diff --git a/doc/publican/Protocol.xml b/doc/publican/Protocol.xml index e4087e9f..e297569a 100644 --- a/doc/publican/Protocol.xml +++ b/doc/publican/Protocol.xml @@ -112,8 +112,11 @@ - The second has 2 parts of 16-bit. The upper 16-bits are the message - size in bytes, starting at the header (i.e. it has a minimum value of 8).The lower is the request/event opcode. + The second has 2 parts of 16 bits each. The upper 16 bits are the message + size in bytes, starting at the header (i.e. it has a minimum value of 8). + The lower is the request/event opcode. The size must be a multiple of 4. + Messages must be sent using the fewest bytes possible, so padding after + the end of a message is not permitted. diff --git a/src/connection.c b/src/connection.c index 2d1e8d1d..b78e4a46 100644 --- a/src/connection.c +++ b/src/connection.c @@ -904,7 +904,14 @@ wl_connection_demarshal(struct wl_connection *connection, /* Space for sender_id and opcode */ if (size < 2 * sizeof *p) { - wl_log("message too short, invalid header\n"); + wl_log("message length %" PRIu32 " too short, invalid header\n", size); + wl_connection_consume(connection, size); + errno = EINVAL; + return NULL; + } + + if (size % sizeof *p) { + wl_log("message length %" PRIu32 " invalid, not multiple of 4 bytes", size); wl_connection_consume(connection, size); errno = EINVAL; return NULL; @@ -1072,6 +1079,12 @@ wl_connection_demarshal(struct wl_connection *connection, } } + if (p != end) { + wl_log("trailing junk\n"); + errno = EINVAL; + goto err; + } + wl_connection_consume(connection, size); return closure; diff --git a/src/wayland-server.c b/src/wayland-server.c index c81d98f1..62c1a892 100644 --- a/src/wayland-server.c +++ b/src/wayland-server.c @@ -424,6 +424,15 @@ wl_client_connection_data(int fd, uint32_t mask, void *data) if (len < size) break; + if ((size & 3) != 0) { + /* Post a better error than "invalid arguments" */ + wl_resource_post_error(client->display_resource, + WL_DISPLAY_ERROR_INVALID_METHOD, + "message length %u is not multiple of 4", + size); + break; + } + resource = wl_map_lookup(&client->objects, p[0]); resource_flags = wl_map_lookup_flags(&client->objects, p[0]); if (resource == NULL) {