summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2013-02-04 07:07:17 -0500
committerKristian Høgsberg <krh@bitplanet.net>2013-02-04 07:07:17 -0500
commitf02f82ef7802c4961c784121c4475e8958c8e41f (patch)
tree8debfbaa177194c1a5a068d37ab383084c87e4aa
parent9d2db599e7c7359cc2b79b073d92d910aa02fb74 (diff)
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.
-rw-r--r--src/connection.c22
1 files changed, 18 insertions, 4 deletions
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;