emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master d679f9e388c: Fix leak when quit arrives during incremental select


From: Po Lu
Subject: master d679f9e388c: Fix leak when quit arrives during incremental selection transfer
Date: Sun, 2 Jul 2023 23:45:36 -0400 (EDT)

branch: master
commit d679f9e388cde367d8d0c2e438b62a16ec1aca67
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix leak when quit arrives during incremental selection transfer
    
    * src/xselect.c (x_free_selection_data): New function.
    (x_get_window_property_as_lisp_data): Free `data' reliably
    if receive_incremental_selection quits.
---
 src/xselect.c | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/src/xselect.c b/src/xselect.c
index 40be6d4c00c..c38a1f8b6a9 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -1989,9 +1989,22 @@ receive_incremental_selection (struct x_display_info 
*dpyinfo,
 }
 
 
+
+/* Free the selection data allocated inside *DATA, which is actually a
+   pointer to unsigned char *.  */
+
+static void
+x_free_selection_data (void *data)
+{
+  unsigned char **ptr;
+
+  ptr = data;
+  xfree (*ptr);
+}
+
 /* Fetch a value from property PROPERTY of X window WINDOW on display
-   DISPLAY.  TARGET_TYPE and SELECTION_ATOM are used in error message
-   if this fails.  */
+   DISPLAY.  TARGET_TYPE and SELECTION_ATOM are used in the error
+   message signaled if this fails.  */
 
 static Lisp_Object
 x_get_window_property_as_lisp_data (struct x_display_info *dpyinfo,
@@ -2007,6 +2020,7 @@ x_get_window_property_as_lisp_data (struct x_display_info 
*dpyinfo,
   ptrdiff_t bytes = 0, array_bytes;
   Lisp_Object val;
   Display *display = dpyinfo->display;
+  specpdl_ref count;
 
   /* array_bytes is only used as an argument to xpalloc.  The actual
      size of the data inside the buffer is inside bytes.  */
@@ -2042,6 +2056,13 @@ x_get_window_property_as_lisp_data (struct 
x_display_info *dpyinfo,
        }
     }
 
+  /* Make sure DATA is freed even if `receive_incremental_connection'
+     quits. Use xfree, not XFree, because x_get_window_property calls
+     xmalloc itself.  */
+
+  count = SPECPDL_INDEX ();
+  record_unwind_protect_ptr (x_free_selection_data, &data);
+
   if (!for_multiple && actual_type == dpyinfo->Xatom_INCR)
     {
       /* That wasn't really the data, just the beginning.  */
@@ -2051,6 +2072,9 @@ x_get_window_property_as_lisp_data (struct x_display_info 
*dpyinfo,
       /* Use xfree, not XFree, because x_get_window_property
         calls xmalloc itself.  */
       xfree (data);
+
+      /* In case quitting happens below.  */
+      data = NULL;
       unblock_input ();
 
       /* Clear bytes again.  Previously, receive_incremental_selection
@@ -2077,10 +2101,8 @@ x_get_window_property_as_lisp_data (struct 
x_display_info *dpyinfo,
   val = selection_data_to_lisp_data (dpyinfo, data, bytes,
                                     actual_type, actual_format);
 
-  /* Use xfree, not XFree, because x_get_window_property
-     calls xmalloc itself.  */
-  xfree (data);
-  return val;
+  /* This will also free `data'.  */
+  return unbind_to (count, val);
 }
 
 /* These functions convert from the selection data read from the server into



reply via email to

[Prev in Thread] Current Thread [Next in Thread]