[PATCH libXi] Fix bus error on MIPS N32 for bug #38331.

Peter Hutterer peter.hutterer at who-t.net
Mon Feb 20 19:25:12 PST 2012


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 <mtjm at mtjm.eu>
> ---
>  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


More information about the xorg-devel mailing list