[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