emacs-diffs
[Top][All Lists]
Advanced

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

master 0bf5463f81: Fix junk data being returned with incremental selecti


From: Po Lu
Subject: master 0bf5463f81: Fix junk data being returned with incremental selection transfers
Date: Tue, 30 Aug 2022 07:28:13 -0400 (EDT)

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

    Fix junk data being returned with incremental selection transfers
    
    * src/xselect.c (receive_incremental_selection): New arg
    REAL_BYTES_RET.  Set it to the actual size instead of using the
    size of the array after it was grown by xpalloc.
    (x_get_window_property_as_lisp_data): Adjust call to
    receive_incremental_selection.
---
 src/xselect.c | 34 +++++++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/src/xselect.c b/src/xselect.c
index bab0400540..74d762f305 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -1567,7 +1567,8 @@ receive_incremental_selection (struct x_display_info 
*dpyinfo,
                               unsigned char **data_ret,
                               ptrdiff_t *size_bytes_ret,
                               Atom *type_ret, int *format_ret,
-                              unsigned long *size_ret)
+                              unsigned long *size_ret,
+                              ptrdiff_t *real_bytes_ret)
 {
   ptrdiff_t offset = 0;
   struct prop_location *wait_object;
@@ -1622,7 +1623,8 @@ receive_incremental_selection (struct x_display_info 
*dpyinfo,
 
       if (tmp_size_bytes == 0) /* we're done */
        {
-         TRACE0 ("Done reading incrementally");
+         TRACE1 ("Done reading incrementally; total bytes: %"pD"d",
+                 *size_bytes_ret);
 
          if (! waiting_for_other_props_on_window (display, window))
            XSelectInput (display, window, STANDARD_EVENT_SET);
@@ -1652,6 +1654,19 @@ receive_incremental_selection (struct x_display_info 
*dpyinfo,
       memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes);
       offset += tmp_size_bytes;
 
+      /* *size_bytes_ret is not really the size of the data inside the
+        buffer; it is the size of the buffer allocated by xpalloc.
+
+        This matters when the cardinal specified in the INCR property
+        (a _lower bound_ on the size of the selection data) is
+        smaller than the actual selection contents, which can happen
+        when programs are streaming selection data from a file
+        descriptor.  In that case, we used to return junk if xpalloc
+        decided to grow the buffer by more than the provided
+        increment; to avoid that, store the actual size of the
+        selection data in *real_bytes_ret.  */
+      *real_bytes_ret += tmp_size_bytes;
+
       /* Use xfree, not XFree, because x_get_window_property
         calls xmalloc itself.  */
       xfree (tmp_data);
@@ -1674,10 +1689,14 @@ x_get_window_property_as_lisp_data (struct 
x_display_info *dpyinfo,
   int actual_format;
   unsigned long actual_size;
   unsigned char *data = 0;
-  ptrdiff_t bytes = 0;
+  ptrdiff_t bytes = 0, array_bytes;
   Lisp_Object val;
   Display *display = dpyinfo->display;
 
+  /* array_bytes is only used as an argument to xpalloc.  The actual
+     size of the data inside the buffer is inside bytes.  */
+  array_bytes = 0;
+
   TRACE0 ("Reading selection data");
 
   x_get_window_property (display, window, property, &data, &bytes,
@@ -1718,10 +1737,15 @@ x_get_window_property_as_lisp_data (struct 
x_display_info *dpyinfo,
         calls xmalloc itself.  */
       xfree (data);
       unblock_input ();
+
+      /* Clear bytes again.  Previously, receive_incremental_selection
+        would set this to min_size_bytes, but that is now done to
+        array_bytes instead.  */
+      bytes = 0;
       receive_incremental_selection (dpyinfo, window, property, target_type,
-                                    min_size_bytes, &data, &bytes,
+                                    min_size_bytes, &data, &array_bytes,
                                     &actual_type, &actual_format,
-                                    &actual_size);
+                                    &actual_size, &bytes);
     }
 
   if (!for_multiple)



reply via email to

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