Fix badAtom issues introduced by behavior changes between Xlib and xcb.
authorGatis Paeglis <gatis.paeglis@nokia.com>
Mon, 30 Jul 2012 09:31:54 +0000 (11:31 +0200)
committerQt by Nokia <qt-info@nokia.com>
Thu, 2 Aug 2012 18:38:54 +0000 (20:38 +0200)
In Xlib, the 'length' variable gets updated with the the actual number
of 8-bit, 16-bit, or 32-bit items stored in the returned data, but xcb
returns the actual number of bytes read through xcb_get_property_value_length,
therefore the logic of calculating offset was broken.

Task-number: QTBUG-26709
Change-Id: I04de3b5c5631cfaf9b3c2c3d4513be73c569f61f
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
src/plugins/platforms/xcb/qxcbclipboard.cpp

index 6852d96..85b28ea 100644 (file)
@@ -608,26 +608,9 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
     bytes_left = reply->bytes_after;
     free(reply);
 
-    int  offset = 0, buffer_offset = 0, format_inc = 1, proplen = bytes_left;
-
-    switch (*format) {
-    case 8:
-    default:
-        format_inc = sizeof(char) / 1;
-        break;
-
-    case 16:
-        format_inc = sizeof(short) / 2;
-        proplen *= sizeof(short) / 2;
-        break;
-
-    case 32:
-        format_inc = sizeof(long) / 4;
-        proplen *= sizeof(long) / 4;
-        break;
-    }
+    int  offset = 0, buffer_offset = 0;
 
-    int newSize = proplen;
+    int newSize = bytes_left;
     buffer->resize(newSize);
 
     bool ok = (buffer->size() == newSize);
@@ -650,13 +633,11 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
             char *data = (char *)xcb_get_property_value(reply);
             int length = xcb_get_property_value_length(reply);
 
-            offset += length / (32 / *format);
-            length *= format_inc * (*format) / 8;
-
             // Here we check if we get a buffer overflow and tries to
             // recover -- this shouldn't normally happen, but it doesn't
             // hurt to be defensive
             if ((int)(buffer_offset + length) > buffer->size()) {
+                qWarning("QXcbClipboard: buffer overflow");
                 length = buffer->size() - buffer_offset;
 
                 // escape loop
@@ -666,6 +647,10 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
             memcpy(buffer->data() + buffer_offset, data, length);
             buffer_offset += length;
 
+            if (bytes_left) {
+                // offset is specified in 32-bit multiples
+                offset += length / 4;
+            }
             free(reply);
         }
     }