diff options
author | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-12-16 10:29:36 +0200 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2011-12-17 16:02:05 -0500 |
commit | 34901868b8d037c3ec230a6828aa75c79ffae59c (patch) | |
tree | f073b42d28ae5816b1f647b1059a3a3dd1746c63 | |
parent | f598691831db779aab1f5dd17ace5992a0928960 (diff) |
Increase closure buffer size and fail gracefully for too big closures.
Buffer size changed from 256 to 1024 bytes. Marshalling will now stop
if the buffer is not big enough.
-rw-r--r-- | src/connection.c | 31 | ||||
-rw-r--r-- | src/wayland-client.c | 7 | ||||
-rw-r--r-- | src/wayland-server.c | 6 |
3 files changed, 38 insertions, 6 deletions
diff --git a/src/connection.c b/src/connection.c index f19280a..06b6130 100644 --- a/src/connection.c +++ b/src/connection.c @@ -39,8 +39,6 @@ #include "wayland-util.h" #include "wayland-private.h" -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - struct wl_buffer { char data[4096]; int head, tail; @@ -54,7 +52,7 @@ struct wl_closure { ffi_type *types[20]; ffi_cif cif; void *args[20]; - uint32_t buffer[64]; + uint32_t buffer[256]; uint32_t *start; }; @@ -392,7 +390,7 @@ wl_connection_vmarshal(struct wl_connection *connection, { struct wl_closure *closure = &connection->send_closure; struct wl_object **objectp, *object; - uint32_t length, *p, *start, size; + uint32_t length, *p, *start, size, *end; int dup_fd; struct wl_array **arrayp, *array; const char **sp, *s; @@ -403,17 +401,23 @@ wl_connection_vmarshal(struct wl_connection *connection, count = strlen(message->signature) + 2; extra = (char *) closure->buffer; start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)]; + end = &closure->buffer[ARRAY_LENGTH(closure->buffer)]; p = &start[2]; + for (i = 2; i < count; i++) { switch (message->signature[i - 2]) { case 'u': closure->types[i] = &ffi_type_uint32; closure->args[i] = p; + if (end - p < 1) + goto err; *p++ = va_arg(ap, uint32_t); break; case 'i': closure->types[i] = &ffi_type_sint32; closure->args[i] = p; + if (end - p < 1) + goto err; *p++ = va_arg(ap, int32_t); break; case 's': @@ -424,6 +428,8 @@ wl_connection_vmarshal(struct wl_connection *connection, s = va_arg(ap, const char *); length = s ? strlen(s) + 1: 0; + if (end - p < DIV_ROUNDUP(length, sizeof *p) + 1) + goto err; *p++ = length; if (length > 0) @@ -442,6 +448,8 @@ wl_connection_vmarshal(struct wl_connection *connection, object = va_arg(ap, struct wl_object *); *objectp = object; + if (end - p < 1) + goto err; *p++ = object ? object->id : 0; break; @@ -449,6 +457,8 @@ wl_connection_vmarshal(struct wl_connection *connection, closure->types[i] = &ffi_type_uint32; closure->args[i] = p; object = va_arg(ap, struct wl_object *); + if (end - p < 1) + goto err; *p++ = object ? object->id : 0; break; @@ -463,9 +473,13 @@ wl_connection_vmarshal(struct wl_connection *connection, array = va_arg(ap, struct wl_array *); if (array == NULL || array->size == 0) { + if (end - p < 1) + goto err; *p++ = 0; break; } + if (end - p < DIV_ROUNDUP(array->size, sizeof *p) + 1) + goto err; *p++ = array->size; memcpy(p, array->data, array->size); @@ -509,6 +523,12 @@ wl_connection_vmarshal(struct wl_connection *connection, closure->count = count; return closure; + +err: + printf("request too big to marshal, maximum size is %d\n", + sizeof closure->buffer); + errno = ENOMEM; + return NULL; } struct wl_closure * @@ -535,7 +555,8 @@ wl_connection_demarshal(struct wl_connection *connection, extra_space = wl_message_size_extra(message); if (sizeof closure->buffer < size + extra_space) { - printf("request too big, should malloc tmp buffer here\n"); + printf("request too big to demarshal, maximum %d actual %d\n", + sizeof closure->buffer, size + extra_space); errno = ENOMEM; wl_connection_consume(connection, size); return NULL; diff --git a/src/wayland-client.c b/src/wayland-client.c index e4f2c99..bbfc035 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -198,6 +198,11 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...) &proxy->object.interface->methods[opcode]); va_end(ap); + if (closure == NULL) { + fprintf(stderr, "Error marshalling request\n"); + abort(); + } + wl_closure_send(closure, proxy->display->connection); if (wl_debug) @@ -473,7 +478,7 @@ handle_event(struct wl_display *display, size, &display->objects, message); if (closure == NULL) { - fprintf(stderr, "Error demarshalling event: %m\n"); + fprintf(stderr, "Error demarshalling event\n"); abort(); } diff --git a/src/wayland-server.c b/src/wayland-server.c index 421c3f0..87e4ed5 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -100,6 +100,9 @@ wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...) &object->interface->events[opcode]); va_end(ap); + if (closure == NULL) + return; + wl_closure_send(closure, resource->client->connection); if (wl_debug) @@ -122,6 +125,9 @@ wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...) &object->interface->events[opcode]); va_end(ap); + if (closure == NULL) + return; + wl_closure_queue(closure, resource->client->connection); if (wl_debug) |