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

Peter Hutterer peter.hutterer at who-t.net
Wed Feb 22 17:25:17 PST 2012


On Tue, Feb 21, 2012 at 08:54:40PM +0100, Michał Masłowski wrote:
> XIValuatorClassInfo and XIScrollClassInfo might have an address
> of 4 bytes modulo 8, while they contain doubles which need 8 byte
> alignment.  This is fixed by adding extra padding after each structure
> or array in sizeDeviceClassType and adding helper functions to
> determine sizes and padding only in one place.
> 
> Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=38331
> Signed-off-by: Michał Masłowski <mtjm at mtjm.eu>
> ---
>  src/XExtInt.c |  131 +++++++++++++++++++++++++++++++++++++++++----------------
>  1 files changed, 95 insertions(+), 36 deletions(-)
> 
> diff --git a/src/XExtInt.c b/src/XExtInt.c
> index b12886d..0dcb352 100644
> --- a/src/XExtInt.c
> +++ b/src/XExtInt.c
> @@ -1036,6 +1036,48 @@ sizeDeviceEvent(int buttons_len, int valuators_len,
>      return len;
>  }
>  
> +/* 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 int
> +pad_to_double(int size)
> +{
> +#if !defined(__i386__) && !defined(__sh__)
> +  if (size % sizeof(double) != 0)
> +    size += sizeof(double) - size % sizeof(double);
> +#endif
> +  return size;
> +}
> +
> +/* Set structure and atoms to size in bytes of XIButtonClassInfo, its
> +   button state mask and labels array. */
> +static void
> +sizeXIButtonClassType(int num_buttons, int* structure, int* state, int* atoms)
> +{
> +  int size;
> +  int labels;
> +  *structure = pad_to_double(sizeof(XIButtonClassInfo));
> +  size = ((((num_buttons + 7)/8) + 3)/4);
> +  /* Force mask alignment with longs to avoid unaligned
> +   * access when accessing the atoms. */
> +  *state = pad_to_double(size * 4);
> +  labels = num_buttons * sizeof(Atom);
> +  /* Force mask alignment with longs to avoid
> +   * unaligned access when accessing the atoms. */
> +  labels += ((((num_buttons + 7)/8) + 3)/4) * sizeof(Atom);
> +  *atoms = pad_to_double(labels);
> +}
> +
> +/* Set structure and keycodes to size in bytes of XIKeyClassInfo and
> +   its keycodes array. */
> +static void
> +sizeXIKeyClassType(int num_keycodes, int* structure, int* keycodes)
> +{
> +  *structure = pad_to_double(sizeof(XIKeyClassInfo));
> +  *keycodes = pad_to_double(num_keycodes * sizeof(int));
> +}
> +

I've fixed up the whitespace/indentation to match the rest of the file,
applied otherwise. thanks.

   34964b0..c1a5a70  master -> master


Cheers,
  Peter
>  /**
>   * Return the size in bytes required to store the matching class type
>   * num_elements is num_buttons for XIButtonClass or num_keycodes for
> @@ -1047,27 +1089,26 @@ static int
>  sizeDeviceClassType(int type, int num_elements)
>  {
>      int l = 0;
> +    int extra1 = 0;
> +    int extra2 = 0;
>      switch(type)
>      {
>          case XIButtonClass:
> -            l = sizeof(XIButtonClassInfo);
> -            l += num_elements * sizeof(Atom);
> -            /* Force mask alignment with longs to avoid
> -             * unaligned access when accessing the atoms. */
> -            l += ((((num_elements + 7)/8) + 3)/4) * sizeof(Atom);
> +            sizeXIButtonClassType(num_elements, &l, &extra1, &extra2);
> +            l += extra1 + extra2;
>              break;
>          case XIKeyClass:
> -            l = sizeof(XIKeyClassInfo);
> -            l += num_elements * sizeof(int);
> +            sizeXIKeyClassType(num_elements, &l, &extra1);
> +            l += extra1;
>              break;
>          case XIValuatorClass:
> -            l = sizeof(XIValuatorClassInfo);
> +            l = pad_to_double(sizeof(XIValuatorClassInfo));
>              break;
>          case XIScrollClass:
> -            l = sizeof(XIScrollClassInfo);
> +            l = pad_to_double(sizeof(XIScrollClassInfo));
>              break;
>          case XITouchClass:
> -            l = sizeof(XITouchClassInfo);
> +            l = pad_to_double(sizeof(XITouchClassInfo));
>              break;
>          default:
>              printf("sizeDeviceClassType: unknown type %d\n", type);
> @@ -1156,20 +1197,21 @@ copyDeviceChangedEvent(XGenericEventCookie *in_cookie,
>          {
>              case XIButtonClass:
>                  {
> -                    int size;
> +                    int struct_size;
> +                    int state_size;
> +                    int labels_size;
>                      XIButtonClassInfo *bin, *bout;
>                      bin = (XIButtonClassInfo*)any;
> -                    bout = next_block(&ptr, sizeof(XIButtonClass));
> +                    sizeXIButtonClassType(bin->num_buttons, &struct_size,
> +                                          &state_size, &labels_size);
> +                    bout = next_block(&ptr, struct_size);
>  
>                      *bout = *bin;
> -                    /* 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);
> +                    bout->state.mask = next_block(&ptr, state_size);
>                      memcpy(bout->state.mask, bin->state.mask,
>                              bout->state.mask_len);
>  
> -                    bout->labels = next_block(&ptr, bout->num_buttons * sizeof(Atom));
> +                    bout->labels = next_block(&ptr, labels_size);
>                      memcpy(bout->labels, bin->labels, bout->num_buttons * sizeof(Atom));
>                      out->classes[i] = (XIAnyClassInfo*)bout;
>                      break;
> @@ -1177,11 +1219,15 @@ copyDeviceChangedEvent(XGenericEventCookie *in_cookie,
>              case XIKeyClass:
>                  {
>                      XIKeyClassInfo *kin, *kout;
> +                    int struct_size;
> +                    int keycodes_size;
>                      kin = (XIKeyClassInfo*)any;
> +                    sizeXIKeyClassType(kin->num_keycodes, &struct_size,
> +                                       &keycodes_size);
>  
> -                    kout = next_block(&ptr, sizeof(XIKeyClass));
> +                    kout = next_block(&ptr, struct_size);
>                      *kout = *kin;
> -                    kout->keycodes = next_block(&ptr, kout->num_keycodes * sizeof(int));
> +                    kout->keycodes = next_block(&ptr, keycodes_size);
>                      memcpy(kout->keycodes, kin->keycodes, kout->num_keycodes * sizeof(int));
>                      out->classes[i] = (XIAnyClassInfo*)kout;
>                      break;
> @@ -1190,7 +1236,8 @@ copyDeviceChangedEvent(XGenericEventCookie *in_cookie,
>                  {
>                      XIValuatorClassInfo *vin, *vout;
>                      vin = (XIValuatorClassInfo*)any;
> -                    vout = next_block(&ptr, sizeof(XIValuatorClass));
> +                    vout = next_block(&ptr,
> +                                      sizeDeviceClassType(XIValuatorClass, 0));
>                      *vout = *vin;
>                      out->classes[i] = (XIAnyClassInfo*)vout;
>                      break;
> @@ -1199,7 +1246,8 @@ copyDeviceChangedEvent(XGenericEventCookie *in_cookie,
>                  {
>                      XIScrollClassInfo *sin, *sout;
>                      sin = (XIScrollClassInfo*)any;
> -                    sout = next_block(&ptr, sizeof(XIScrollClassInfo));
> +                    sout = next_block(&ptr,
> +                                      sizeDeviceClassType(XIScrollClass, 0));
>                      *sout = *sin;
>                      out->classes[i] = (XIAnyClassInfo*)sout;
>                      break;
> @@ -1478,7 +1526,8 @@ size_classes(xXIAnyInfo* from, int nclasses)
>      xXIAnyInfo *any_wire;
>      char *ptr_wire;
>  
> -    len = nclasses * sizeof(XIAnyClassInfo*); /* len for to->classes */
> +    /* len for to->classes */
> +    len = pad_to_double(nclasses * sizeof(XIAnyClassInfo*));
>      ptr_wire = (char*)from;
>      for (i = 0; i < nclasses; i++)
>      {
> @@ -1533,7 +1582,8 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
>  
>      ptr_wire = (char*)from;
>      ptr_lib = to->classes;
> -    to->classes = next_block(&ptr_lib, (*nclasses) * sizeof(XIAnyClassInfo*));
> +    to->classes = next_block(&ptr_lib,
> +                             pad_to_double((*nclasses) * sizeof(XIAnyClassInfo*)));
>      memset(to->classes, 0, (*nclasses) * sizeof(XIAnyClassInfo*));
>      len = 0; /* count wire length */
>  
> @@ -1549,24 +1599,26 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
>                      XIButtonClassInfo *cls_lib;
>                      xXIButtonInfo *cls_wire;
>                      uint32_t *atoms;
> -                    int size;
>                      int j;
> +                    int struct_size;
> +                    int state_size;
> +                    int labels_size;
>  
> -                    cls_lib = next_block(&ptr_lib, sizeof(XIButtonClassInfo));
>                      cls_wire = (xXIButtonInfo*)any_wire;
> +                    sizeXIButtonClassType(cls_wire->num_buttons,
> +                                          &struct_size, &state_size,
> +                                          &labels_size);
> +                    cls_lib = next_block(&ptr_lib, struct_size);
>  
>                      cls_lib->type = cls_wire->type;
>                      cls_lib->sourceid = cls_wire->sourceid;
>                      cls_lib->num_buttons = cls_wire->num_buttons;
> -                    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));
> +                    cls_lib->state.mask_len = state_size;
> +                    cls_lib->state.mask = next_block(&ptr_lib, state_size);
>                      memcpy(cls_lib->state.mask, &cls_wire[1],
>                             cls_lib->state.mask_len);
>  
> -                    cls_lib->labels = next_block(&ptr_lib, cls_lib->num_buttons * sizeof(Atom));
> +                    cls_lib->labels = next_block(&ptr_lib, labels_size);
>                      atoms =(uint32_t*)((char*)&cls_wire[1] + cls_lib->state.mask_len);
>                      for (j = 0; j < cls_lib->num_buttons; j++)
>                          cls_lib->labels[j] = *atoms++;
> @@ -1578,15 +1630,18 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
>                  {
>                      XIKeyClassInfo *cls_lib;
>                      xXIKeyInfo *cls_wire;
> +                    int struct_size;
> +                    int keycodes_size;
>  
> -                    cls_lib = next_block(&ptr_lib, sizeof(XIKeyClassInfo));
>                      cls_wire = (xXIKeyInfo*)any_wire;
> +                    sizeXIKeyClassType(cls_wire->num_keycodes,
> +                                       &struct_size, &keycodes_size);
> +                    cls_lib = next_block(&ptr_lib, struct_size);
>  
>                      cls_lib->type = cls_wire->type;
>                      cls_lib->sourceid = cls_wire->sourceid;
>                      cls_lib->num_keycodes = cls_wire->num_keycodes;
> -                    cls_lib->keycodes = next_block(&ptr_lib,
> -                            cls_lib->num_keycodes * sizeof(int));
> +                    cls_lib->keycodes = next_block(&ptr_lib, keycodes_size);
>                      memcpy(cls_lib->keycodes, &cls_wire[1],
>                              cls_lib->num_keycodes);
>  
> @@ -1598,7 +1653,9 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
>                      XIValuatorClassInfo *cls_lib;
>                      xXIValuatorInfo *cls_wire;
>  
> -                    cls_lib = next_block(&ptr_lib, sizeof(XIValuatorClassInfo));
> +                    cls_lib =
> +                      next_block(&ptr_lib,
> +                                 sizeDeviceClassType(XIValuatorClass, 0));
>                      cls_wire = (xXIValuatorInfo*)any_wire;
>  
>                      cls_lib->type = cls_wire->type;
> @@ -1620,7 +1677,9 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int *nclasses)
>                      XIScrollClassInfo *cls_lib;
>                      xXIScrollInfo *cls_wire;
>  
> -                    cls_lib = next_block(&ptr_lib, sizeof(XIScrollClassInfo));
> +                    cls_lib =
> +                      next_block(&ptr_lib,
> +                                 sizeDeviceClassType(XIScrollClass, 0));
>                      cls_wire = (xXIScrollInfo*)any_wire;
>  
>                      cls_lib->type = cls_wire->type;
> -- 
> 1.7.9.1
 


More information about the xorg-devel mailing list