commit f02f82ef7802c4961c784121c4475e8958c8e41f Author: Kristian Høgsberg Date: Mon Feb 4 07:07:17 2013 -0500 connection.c: Align pointer extra storage correctly Most extra data are just pointers, but in case of fds we store an int in the extra space. That can cause un-aligned access to pointers on 64 bit architectures. Make sure we always align pointer storage correctly. diff --git a/src/connection.c b/src/connection.c index 141875e..8707d40 100644 --- a/src/connection.c +++ b/src/connection.c @@ -378,23 +378,28 @@ wl_connection_queue(struct wl_connection *connection, return 0; } +#define ALIGN(p, s) (void *) ( ((intptr_t) (p) + ((s) - 1)) & ~((s) - 1) ) + static int wl_message_size_extra(const struct wl_message *message) { - int i, extra; - - for (i = 0, extra = 0; message->signature[i]; i++) { + char *extra; + int i; + for (i = 0, extra = NULL; message->signature[i]; i++) { switch (message->signature[i]) { case 's': case 'o': case 'n': + extra = ALIGN(extra, sizeof (void *)); extra += sizeof (void *); break; case 'a': + extra = ALIGN(extra, sizeof (void *)); extra += sizeof (void *) + sizeof (struct wl_array); break; case 'h': + extra = ALIGN(extra, sizeof (int)); extra += sizeof (int); break; default: @@ -402,7 +407,7 @@ wl_message_size_extra(const struct wl_message *message) } } - return extra; + return (intptr_t) extra; } static int @@ -501,6 +506,7 @@ wl_closure_vmarshal(struct wl_object *sender, *p++ = va_arg(ap, int32_t); break; case 's': + extra = ALIGN(extra, sizeof (void *)); closure->types[i] = &ffi_type_pointer; closure->args[i] = extra; sp = (const char **) extra; @@ -527,6 +533,7 @@ wl_closure_vmarshal(struct wl_object *sender, p += aligned / sizeof *p; break; case 'o': + extra = ALIGN(extra, sizeof (void *)); closure->types[i] = &ffi_type_pointer; closure->args[i] = extra; objectp = (struct wl_object **) extra; @@ -557,6 +564,7 @@ wl_closure_vmarshal(struct wl_object *sender, break; case 'a': + extra = ALIGN(extra, sizeof (void *)); closure->types[i] = &ffi_type_pointer; closure->args[i] = extra; arrayp = (struct wl_array **) extra; @@ -589,6 +597,7 @@ wl_closure_vmarshal(struct wl_object *sender, break; case 'h': + extra = ALIGN(extra, sizeof (int)); closure->types[i] = &ffi_type_sint; closure->args[i] = extra; fd_ptr = (int *) extra; @@ -715,6 +724,7 @@ wl_connection_demarshal(struct wl_connection *connection, goto err; } + extra = ALIGN(extra, sizeof (void *)); s = (char **) extra; extra += sizeof *s; closure->args[i] = s; @@ -736,6 +746,7 @@ wl_connection_demarshal(struct wl_connection *connection, break; case 'o': closure->types[i] = &ffi_type_pointer; + extra = ALIGN(extra, sizeof (void *)); id = (uint32_t **) extra; extra += sizeof *id; closure->args[i] = id; @@ -753,6 +764,7 @@ wl_connection_demarshal(struct wl_connection *connection, break; case 'n': closure->types[i] = &ffi_type_pointer; + extra = ALIGN(extra, sizeof (void *)); id = (uint32_t **) extra; extra += sizeof *id; closure->args[i] = id; @@ -789,6 +801,7 @@ wl_connection_demarshal(struct wl_connection *connection, goto err; } + extra = ALIGN(extra, sizeof (void *)); array = (struct wl_array **) extra; extra += sizeof *array; closure->args[i] = array; @@ -804,6 +817,7 @@ wl_connection_demarshal(struct wl_connection *connection, case 'h': closure->types[i] = &ffi_type_sint; + extra = ALIGN(extra, sizeof (int)); fd = (int *) extra; extra += sizeof *fd; closure->args[i] = fd;