[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