[PATCH libXi] Force alignment with sizeof(Atom) for XIButtonClassInfo

Peter Hutterer peter.hutterer at who-t.net
Mon Mar 14 18:05:37 PDT 2011


The memory layout of an XIButtonClassInfo is
[struct XIButtonClassInfo][mask][labels]

With the mask being currently 4-byte aligned and labels a list of Atoms. On
LP64, Atoms are 8 byte, leading to unaligned access for some mask lengths.
Force the alignment to be sizeof(Atom).

Reported-by: Christian Weisgerber <naddy at mips.inka.de>
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
This should fix the alignment issue but I expect more problems to show up
with other calls. XI2 is 4-byte aligned on the wire and that has been taken
into the lib. So pretty much anywhere where there's a long or Atom involved,
this may cause issues.
Some auditing would be good here. Plus, some more generic approach at fixing
this than calculating the size by hand everywhere.

 src/XExtInt.c |   18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/XExtInt.c b/src/XExtInt.c
index 5a1bca6..d1451cc 100644
--- a/src/XExtInt.c
+++ b/src/XExtInt.c
@@ -1028,7 +1028,9 @@ sizeDeviceClassType(int type, int num_elements)
         case XIButtonClass:
             l = sizeof(XIButtonClassInfo);
             l += num_elements * sizeof(Atom);
-            l += ((((num_elements + 7)/8) + 3)/4) * 4;
+            /* Force mask alignment with longs to avoid
+             * unaligned access when accessing the atoms. */
+            l += ((((num_elements + 7)/8) + 3)/4) * sizeof(Atom);
             break;
         case XIKeyClass:
             l = sizeof(XIKeyClassInfo);
@@ -1121,12 +1123,16 @@ copyDeviceChangedEvent(XGenericEventCookie *in_cookie,
         {
             case XIButtonClass:
                 {
+                    int size;
                     XIButtonClassInfo *bin, *bout;
                     bin = (XIButtonClassInfo*)any;
                     bout = next_block(&ptr, sizeof(XIButtonClass));
 
                     *bout = *bin;
-                    bout->state.mask = next_block(&ptr, bout->state.mask_len);
+                    /* Force mask alignment with longs to avoid unaligned
+                     * access when accessing the atoms. */
+                    size = bout->state.mask_len/4 * sizeof(Atom);
+                    bout->state.mask = next_block(&ptr, size);
                     memcpy(bout->state.mask, bin->state.mask,
                             bout->state.mask_len);
 
@@ -1474,14 +1480,18 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int nclasses)
                     XIButtonClassInfo *cls_lib;
                     xXIButtonInfo *cls_wire;
                     uint32_t *atoms;
+                    int size;
                     int j;
 
                     cls_lib = next_block(&ptr_lib, sizeof(XIButtonClassInfo));
                     cls_wire = (xXIButtonInfo*)any_wire;
 
                     cls_lib->num_buttons = cls_wire->num_buttons;
-                    cls_lib->state.mask_len = ((((cls_wire->num_buttons + 7)/8) + 3)/4) * 4;
-                    cls_lib->state.mask = next_block(&ptr_lib, cls_lib->state.mask_len);
+                    size = ((((cls_wire->num_buttons + 7)/8) + 3)/4);
+                    cls_lib->state.mask_len = size * 4;
+                    /* Force mask alignment with longs to avoid unaligned
+                     * access when accessing the atoms. */
+                    cls_lib->state.mask = next_block(&ptr_lib, size * sizeof(Atom));
                     memcpy(cls_lib->state.mask, &cls_wire[1],
                            cls_lib->state.mask_len);
 
-- 
1.7.4

Cheers,
  Peter


More information about the xorg-devel mailing list