On Mon, Feb 20, 2012 at 11:47:33PM +0100, Michał Masłowski wrote: > XIValuatorClassInfo and XIScrollClassInfo might have an address > of 4 bytes modulo 8, while they contain doubles which needs 8 byte > alignment. This is fixed by adding extra padding before instances of > these structure in size_classes and copy_classes. > > Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=38331 > Signed-off-by: Michał Masłowski <[email protected]> > --- > src/XExtInt.c | 28 ++++++++++++++++++++++++++++ > 1 files changed, 28 insertions(+), 0 deletions(-) > > diff --git a/src/XExtInt.c b/src/XExtInt.c > index b12886d..b537730 100644 > --- a/src/XExtInt.c > +++ b/src/XExtInt.c > @@ -1471,6 +1471,30 @@ wireToDeviceEvent(xXIDeviceEvent *in, > XGenericEventCookie* cookie) > return 1; > } > > +/* Return the size with added padding so next element would be > + double-aligned unless the architecture is known to allow unaligned > + data accesses. Not doing this can cause a bus error on > + MIPS N32. */ > +static size_t > +pad_to_double(size_t size) > +{ > +#if !defined(__i386__) && !defined(__sh__) > + if (size % sizeof(double) != 0) > + size += sizeof(double) - size % sizeof(double); > +#endif > + return size; > +} > + > +static void* > +pad_ptr_to_double(void* ptr) > +{ > +#if !defined(__i386__) && !defined(__sh__) > + if (((size_t) ptr) % sizeof(double) != 0) > + *(unsigned char**) &ptr += sizeof(double) - ((size_t) ptr) % > sizeof(double); > +#endif > + return ptr; > +} > + > _X_HIDDEN int > size_classes(xXIAnyInfo* from, int nclasses) > { > @@ -1495,9 +1519,11 @@ size_classes(xXIAnyInfo* from, int nclasses) > ((xXIKeyInfo*)any_wire)->num_keycodes); > break; > case XIValuatorClass: > + len = pad_to_double(len); > l = sizeDeviceClassType(XIValuatorClass, 0); > break; > case XIScrollClass: > + len = pad_to_double(len); > l = sizeDeviceClassType(XIScrollClass, 0); > break; > case XITouchClass: > @@ -1598,6 +1624,7 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int > *nclasses) > XIValuatorClassInfo *cls_lib; > xXIValuatorInfo *cls_wire; > > + ptr_lib = pad_ptr_to_double(ptr_lib); > cls_lib = next_block(&ptr_lib, > sizeof(XIValuatorClassInfo)); > cls_wire = (xXIValuatorInfo*)any_wire; > > @@ -1620,6 +1647,7 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int > *nclasses) > XIScrollClassInfo *cls_lib; > xXIScrollInfo *cls_wire; > > + ptr_lib = pad_ptr_to_double(ptr_lib); > cls_lib = next_block(&ptr_lib, > sizeof(XIScrollClassInfo)); > cls_wire = (xXIScrollInfo*)any_wire; > > -- > 1.7.9.1
i think you need the same code in copyDeviceChangedEvent. looking at this in more detail, I have a few more comments though: - adding new classes may make this bug appear again. you could just fix this in sizeDeviceClassType() to ensure we only ever return double-aligned sizes (which would cover copyDeviceChangedEvent as well then). - likewise, you could adjust ptr_lib before the switch statement in copy_classes and so something similar in copyDeviceChangedEvent. that too should then future-proof us for new device classes. Cheers, Peter _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
