>From c7f566225ac055a3fc30b1b9a97eef5481a516c0 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs <laszlo.p.ag...@nokia.com> Date: Fri, 16 Dec 2011 10:29:36 +0200 Subject: [PATCH] Increase closure buffer size and fail gracefully for too big closures.
Buffer size changed from 256 to 1024 bytes. Marshalling will now calculate the total size in advance and will stop if the buffer is not big enough. --- src/connection.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++-- src/wayland-client.c | 7 ++++- src/wayland-server.c | 6 ++++ 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/connection.c b/src/connection.c index f19280a..4acb1a3 100644 --- a/src/connection.c +++ b/src/connection.c @@ -54,7 +54,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; }; @@ -384,6 +384,60 @@ wl_message_size_extra(const struct wl_message *message) return extra; } +static int +wl_message_size(const struct wl_message *message, va_list ap) +{ + int i, size, length; + const char *s; + struct wl_array *array; + + for (i = 0, size = 0; message->signature[i]; i++) { + + switch (message->signature[i]) { + case 'u': + va_arg(ap, uint32_t); + size += sizeof (uint32_t); + break; + + case 'i': + va_arg(ap, int32_t); + size += sizeof (uint32_t); + break; + + case 'o': + va_arg(ap, struct wl_object *); + size += sizeof (uint32_t); + break; + + case 'n': + va_arg(ap, struct wl_object *); + size += sizeof (uint32_t); + break; + + case 's': + s = va_arg(ap, const char *); + length = s ? strlen(s) + 1: 0; + size += sizeof (uint32_t) + ALIGN(length, sizeof (uint32_t)); + break; + + case 'a': + array = va_arg(ap, struct wl_array *); + length = array ? array->size : 0; + size += sizeof (uint32_t) + ALIGN(length, sizeof (uint32_t)); + break; + + case 'h': + va_arg(ap, int); + break; + + default: + break; + } + } + + return size + 2 * sizeof (uint32_t); +} + struct wl_closure * wl_connection_vmarshal(struct wl_connection *connection, struct wl_object *sender, @@ -397,13 +451,24 @@ wl_connection_vmarshal(struct wl_connection *connection, struct wl_array **arrayp, *array; const char **sp, *s; char *extra; - int i, count, fd, extra_size, *fd_ptr; + int i, count, fd, extra_size, *fd_ptr, total_size; + va_list size_ap; extra_size = wl_message_size_extra(message); count = strlen(message->signature) + 2; extra = (char *) closure->buffer; start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)]; p = &start[2]; + + va_copy(size_ap, ap); + total_size = wl_message_size(message, size_ap) + ALIGN(extra_size, sizeof(*p)); + if (sizeof closure->buffer < total_size) { + printf("request too big to marshal, maximum %d actual %d\n", + sizeof closure->buffer, total_size); + errno = ENOMEM; + return NULL; + } + for (i = 2; i < count; i++) { switch (message->signature[i - 2]) { case 'u': @@ -501,6 +566,7 @@ wl_connection_vmarshal(struct wl_connection *connection, } size = (p - start) * sizeof *p; + assert(size + ALIGN(extra_size, sizeof(*p)) == total_size); start[0] = sender->id; start[1] = opcode | (size << 16); @@ -535,7 +601,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) -- 1.7.4.1
_______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel