Alignment error in libXi

Matthieu Herrb matthieu.herrb at laas.fr
Sun Mar 27 13:42:14 PDT 2011


On Thu, Mar 24, 2011 at 11:51:32PM -0700, Jeremy Huddleston wrote:
> Don't feel too bad.  I missed it too and bugged Peter about it
> before I pushed the release ;)  


Unfortunatly, as Peter forsaid it, there are other issues. I'm
currently fighting with the code for XISelectEvents(). 

It uses Data32() to send a xXIEventMask structure. This is very wrong
and fails miserablily on sparc64, for at least 2 reasons: 

1. Data32() suffers from the infamous 'use unsigned long for 32 bits
   data' API mis-design, so on 64 bits machines one can't pass a
   pointer to a 32 bit only data to Data32(): it has one chance over 2
   to be mis-aligned, and will read 4 extra random bytes on the stack.
2. since xXIEventMask contains two uint_16 values, which are not
   properly swapped, this will not work across client/server with
   different endianness.

This can all be seen whil trying Gtk+3's gtk3-demo on an
OpenBSD/sparc64 machine, but probably on other 64 bits big endian
machines too.

For now I have the ugly patch below. Any better suggestion ?

And there are other issues...

--- src/XISelEv.c	4 Sep 2010 10:17:03 -0000	1.2
+++ src/XISelEv.c	27 Mar 2011 15:09:31 -0000
@@ -32,6 +32,7 @@ in this Software without prior written a
 
 
 #include <stdint.h>
+#include <X11/Xarch.h>
 #include <X11/Xlibint.h>
 #include <X11/extensions/XI2proto.h>
 #include <X11/extensions/XInput2.h>
@@ -46,6 +47,7 @@ XISelectEvents(Display* dpy, Window win,
     XIEventMask  *current;
     xXISelectEventsReq  *req;
     xXIEventMask mask;
+    unsigned long long_mask;
     int i;
     int len = 0;
     int r = Success;
@@ -83,7 +85,12 @@ XISelectEvents(Display* dpy, Window win,
          * and they need to be padded with 0 */
         buff = calloc(1, mask.mask_len * 4);
         memcpy(buff, current->mask, current->mask_len);
-        Data32(dpy, &mask, sizeof(xXIEventMask));
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+	long_mask = mask.deviceid << 16 | mask.mask_len;
+#else
+	long_mask = mask.mask_len << 16 | mask.deviceid;
+#endif
+	Data32(dpy, &long_mask, sizeof(xXIEventMask));
         Data(dpy, buff, mask.mask_len * 4);
         free(buff);
     }

-- 
Matthieu Herrb


More information about the xorg-devel mailing list