[PATCH] wayland-util: fix wrap-back of wl_map->free_list when client id >= 0x80000000

Chang Liu cl91tp at gmail.com
Sun Sep 8 04:11:28 PDT 2013


The current implementation of wl_map uses uint32_t for free_list.
When removing client id >= 0x80000000, shifting said id by 1 bit left
will cause free_list to wrap back to 0x0. Bump both wl_map->free_list
and union_entry->next to uint64_t to fix this problem.
---
The relavent lines are:
In wl_map_remove:
	start[i].next = map->free_list;
	map->free_list = (i << 1) | 1;
If we are removing a client id i >= 0x80000000, the MSB of i will be lost
when we perform i << 1, and this causes free_list to wrap back to 0x0.
In wl_map_insert_new:
	if (map->free_list) {
		entry = &start[map->free_list >> 1];
		map->free_list = entry->next;
	}
With free_list wrapped back to 0x0, we are longer able to recover the missing
MSB in the client id even if we perform a right-shift to free_list.

 src/wayland-private.h | 2 +-
 src/wayland-util.c    | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/wayland-private.h b/src/wayland-private.h
index 67e8783..5b3715d 100644
--- a/src/wayland-private.h
+++ b/src/wayland-private.h
@@ -63,7 +63,7 @@ struct wl_map {
 	struct wl_array client_entries;
 	struct wl_array server_entries;
 	uint32_t side;
-	uint32_t free_list;
+	uint64_t free_list;
 };
 
 typedef void (*wl_iterator_func_t)(void *element, void *data);
diff --git a/src/wayland-util.c b/src/wayland-util.c
index 4fe9c81..1798fd6 100644
--- a/src/wayland-util.c
+++ b/src/wayland-util.c
@@ -149,12 +149,12 @@ wl_array_copy(struct wl_array *array, struct wl_array *source)
 }
 
 union map_entry {
-	uintptr_t next;
+	uint64_t next;
 	void *data;
 };
 
 #define map_entry_is_free(entry) ((entry).next & 0x1)
-#define map_entry_get_data(entry) ((void *)((entry).next & ~(uintptr_t)0x3))
+#define map_entry_get_data(entry) ((void *)((entry).next & ~0x3))
 #define map_entry_get_flags(entry) (((entry).next >> 1) & 0x1)
 
 WL_EXPORT void
@@ -291,7 +291,7 @@ wl_map_remove(struct wl_map *map, uint32_t i)
 
 	start = entries->data;
 	start[i].next = map->free_list;
-	map->free_list = (i << 1) | 1;
+	map->free_list = ((uint64_t)i << 1) | 1;
 }
 
 WL_EXPORT void *
-- 
1.8.3.4



More information about the wayland-devel mailing list