Increase closure buffer size and fail gracefully for too big closures.
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>
Fri, 16 Dec 2011 08:29:36 +0000 (10:29 +0200)
committerKristian Høgsberg <krh@bitplanet.net>
Sat, 17 Dec 2011 21:02:05 +0000 (16:02 -0500)
Buffer size changed from 256 to 1024 bytes. Marshalling will now stop
if the buffer is not big enough.

src/connection.c
src/wayland-client.c
src/wayland-server.c

index f19280a..06b6130 100644 (file)
@@ -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;
index e4f2c99..bbfc035 100644 (file)
@@ -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();
        }
 
index 421c3f0..87e4ed5 100644 (file)
@@ -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)