Module: wine Branch: master Commit: a71998d0a60fb3c67aefe1938cc794f8263a7591 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a71998d0a60fb3c67aefe1938c...
Author: Alexandre Julliard julliard@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; }