Alexandre Julliard : winex11: Fix X11DRV_CLIPBOARD_ReadProperty to read data in larger chunks and to properly null-terminate the buffer .

Alexandre Julliard julliard at winehq.org
Wed Mar 26 09:16:12 CDT 2008


Module: wine
Branch: master
Commit: a71998d0a60fb3c67aefe1938cc794f8263a7591
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a71998d0a60fb3c67aefe1938cc794f8263a7591

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Mar 26 12:14:41 2008 +0100

winex11: Fix X11DRV_CLIPBOARD_ReadProperty to read data in larger chunks and to properly null-terminate the buffer.

---

 dlls/winex11.drv/clipboard.c |   87 +++++++++++++++++------------------------
 1 files changed, 36 insertions(+), 51 deletions(-)

diff --git a/dlls/winex11.drv/clipboard.c b/dlls/winex11.drv/clipboard.c
index 0dba308..2996857 100644
--- a/dlls/winex11.drv/clipboard.c
+++ b/dlls/winex11.drv/clipboard.c
@@ -72,6 +72,7 @@
 # include <unistd.h>
 #endif
 #include <fcntl.h>
+#include <limits.h>
 #include <time.h>
 #include <assert.h>
 
@@ -2006,71 +2007,55 @@ static BOOL X11DRV_CLIPBOARD_ReadProperty(Window w, Atom prop,
     Display *display = thread_display();
     Atom atype = AnyPropertyType;
     int aformat;
-    unsigned long total, nitems, remain, val_cnt;
-    long  reqlen, bwc;
-    unsigned char* val;
-    unsigned char* buffer;
+    unsigned long pos = 0, nitems, remain, count;
+    unsigned char *val = NULL, *buffer;
 
     if (prop == None)
         return FALSE;
 
-    TRACE("Reading property %d from X window %d\n",
-        (unsigned int)prop, (unsigned int)w);
+    TRACE("Reading property %lu from X window %lx\n", prop, w);
 
-    /*
-     * First request a zero length in order to figure out the request size.
-     */
-    wine_tsx11_lock();
-    if(XGetWindowProperty(display,w,prop,0,0,False, AnyPropertyType,
-        &atype, &aformat, &nitems, &remain, &buffer) != Success)
-    {
-        wine_tsx11_unlock();
-        WARN("Failed to get property size\n");
-        return FALSE;
-    }
-
-    /* Free zero length return data if any */
-    if (buffer)
+    for (;;)
     {
-       XFree(buffer);
-       buffer = NULL;
-    }
-
-    bwc = aformat/8;
-    reqlen = remain * bwc;
-
-    TRACE("Retrieving %ld bytes\n", reqlen);
-
-    val = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, reqlen);
+        wine_tsx11_lock();
+        if (XGetWindowProperty(display, w, prop, pos, INT_MAX / 4, False,
+                               AnyPropertyType, &atype, &aformat, &nitems, &remain, &buffer) != Success)
+        {
+            wine_tsx11_unlock();
+            WARN("Failed to read property\n");
+            HeapFree( GetProcessHeap(), 0, val );
+            return FALSE;
+        }
 
-    /* Read property in 4K blocks */
-    for (total = 0, val_cnt = 0; remain;)
-    {
-       if (XGetWindowProperty(display, w, prop, (total / 4), 4096, False,
-           AnyPropertyType, &atype, &aformat, &nitems, &remain, &buffer) != Success)
-       {
-           wine_tsx11_unlock();
-           WARN("Failed to read property\n");
-           HeapFree(GetProcessHeap(), 0, val);
-           return FALSE;
-       }
+        count = nitems * (aformat / 8);
+        if (!val) *data = HeapAlloc( GetProcessHeap(), 0, pos * sizeof(int) + count + 1 );
+        else *data = HeapReAlloc( GetProcessHeap(), 0, val, pos * sizeof(int) + count + 1 );
 
-       bwc = aformat/8;
-       memcpy(&val[val_cnt], buffer, nitems * bwc);
-       val_cnt += nitems * bwc;
-       total += nitems*bwc;
-       XFree(buffer);
+        if (!*data)
+        {
+            XFree( buffer );
+            wine_tsx11_unlock();
+            HeapFree( GetProcessHeap(), 0, val );
+            return FALSE;
+        }
+        val = *data;
+        memcpy( (int *)val + pos, buffer, count );
+        XFree( buffer );
+        wine_tsx11_unlock();
+        if (!remain)
+        {
+            *datasize = pos * sizeof(int) + count;
+            val[*datasize] = 0;
+            break;
+        }
+        pos += count / sizeof(int);
     }
 
     /* Delete the property on the window now that we are done
      * This will send a PropertyNotify event to the selection owner. */
+    wine_tsx11_lock();
     XDeleteProperty(display, w, prop);
-
     wine_tsx11_unlock();
-
-    *data = val;
-    *datasize = total;
-
     return TRUE;
 }
 




More information about the wine-cvs mailing list