diff --git a/src/wayland-private.h b/src/wayland-private.h index 210451e..9274f1b 100644 --- a/src/wayland-private.h +++ b/src/wayland-private.h @@ -45,6 +45,7 @@ #define WL_MAP_SERVER_SIDE 0 #define WL_MAP_CLIENT_SIDE 1 #define WL_SERVER_ID_START 0xff000000 +#define WL_MAP_MAX_OBJECTS 0x00f00000 #define WL_CLOSURE_MAX_ARGS 20 struct wl_object { diff --git a/src/wayland-util.c b/src/wayland-util.c index e82b7d2..41f0986 100644 --- a/src/wayland-util.c +++ b/src/wayland-util.c @@ -198,6 +198,7 @@ wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data) union map_entry *start, *entry; struct wl_array *entries; uint32_t base; + uint32_t count; if (map->side == WL_MAP_CLIENT_SIDE) { entries = &map->client_entries; @@ -218,10 +219,25 @@ wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data) start = entries->data; } + /* wl_array only grows, so if we have too many objects at + * this point there's no way to clean up. We could be more + * pro-active about trying to avoid this allocation, but + * it doesn't really matter because at this point there is + * nothing to be done but disconnect the client and delete + * the whole array either way. + */ + count = entry - start; + if (count > WL_MAP_MAX_OBJECTS) { + /* entry->data is freshly malloced garbage, so we'd + * better make it a NULL so wl_map_for_each doesn't + * dereference it later. */ + entry->data = NULL; + return 0; + } entry->data = data; entry->next |= (flags & 0x1) << 1; - return (entry - start) + base; + return count + base; } int @@ -238,6 +254,9 @@ wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data) i -= WL_SERVER_ID_START; } + if (i > WL_MAP_MAX_OBJECTS) + return -1; + count = entries->size / sizeof *start; if (count < i) { errno = EINVAL; @@ -280,8 +299,10 @@ wl_map_reserve_new(struct wl_map *map, uint32_t i) i -= WL_SERVER_ID_START; } - count = entries->size / sizeof *start; + if (i > WL_MAP_MAX_OBJECTS) + return -1; + count = entries->size / sizeof *start; if (count < i) { errno = EINVAL; return -1;