mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-06 13:30:01 -05:00
map: fix free_list corruption when re-using removed ids
Re-using an id after removing it is a bug in the caller but there are two cases where we corrupt the free list without warning: Removing an object twice: id = pw_map_insert_new(object); pw_map_remove(map, id); pw_map_remove(map, id); And inserting an element at an index previously removed: id = pw_map_insert_new(object); pw_map_remove(map, id); pw_map_insert_at(map, id, new_object); The latter is arguably valid code, or at least it'll look like it's valid code. For both cases, check if the id to remove/insert at is a free item and handle that accordingly.
This commit is contained in:
parent
5b9447c2a4
commit
626d30e4bd
2 changed files with 109 additions and 2 deletions
|
|
@ -142,8 +142,20 @@ static inline int pw_map_insert_at(struct pw_map *map, uint32_t id, void *data)
|
|||
item = (union pw_map_item *) pw_array_add(&map->items, sizeof(union pw_map_item));
|
||||
if (item == NULL)
|
||||
return -errno;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (pw_map_id_is_free(map, id)) {
|
||||
uint32_t *current = &map->free_list;
|
||||
while (*current != SPA_ID_INVALID) {
|
||||
uint32_t current_id = (*current) >> 1;
|
||||
uint32_t *next = &pw_map_get_item(map, current_id)->next;
|
||||
|
||||
if (current_id == id) {
|
||||
*current = *next;
|
||||
break;
|
||||
}
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
item = pw_map_get_item(map, id);
|
||||
}
|
||||
item->data = data;
|
||||
|
|
@ -156,6 +168,9 @@ static inline int pw_map_insert_at(struct pw_map *map, uint32_t id, void *data)
|
|||
*/
|
||||
static inline void pw_map_remove(struct pw_map *map, uint32_t id)
|
||||
{
|
||||
if (pw_map_id_is_free(map, id))
|
||||
return;
|
||||
|
||||
pw_map_get_item(map, id)->next = map->free_list;
|
||||
map->free_list = (id << 1) | 1;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue