[PATCH] Increase closure buffer size and fail gracefully for too big closures.

Laszlo Agocs laszlo.p.agocs at nokia.com
Fri Dec 16 00:29:36 PST 2011


Buffer size changed from 256 to 1024 bytes. Marshalling will now stop
if the buffer is not big enough.
---
 src/connection.c     |   31 ++++++++++++++++++++++++++-----
 src/wayland-client.c |    7 ++++++-
 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)
-- 
1.7.4.1


--------------030503050907070405020702--


More information about the wayland-devel mailing list