(nested_list) Fix heap-use-after-free errors due to pointer invalidation when resizing internal RBUF arrays

This commit is contained in:
jdgleaver 2021-08-09 23:08:17 +01:00
parent 406c8bee7b
commit f58c7f69d9

View File

@ -38,7 +38,7 @@ struct nested_list_item
struct nested_list struct nested_list
{ {
nested_list_item_t *items; nested_list_item_t **items;
nested_list_item_t **item_map; nested_list_item_t **item_map;
}; };
@ -62,7 +62,6 @@ static void nested_list_free_item(nested_list_item_t *item)
if (item->children) if (item->children)
{ {
nested_list_free_list(item->children); nested_list_free_list(item->children);
free(item->children);
item->children = NULL; item->children = NULL;
} }
@ -73,6 +72,7 @@ static void nested_list_free_item(nested_list_item_t *item)
} }
item->value = NULL; item->value = NULL;
free(item);
} }
/* Frees contents of a nested list */ /* Frees contents of a nested list */
@ -84,10 +84,11 @@ static void nested_list_free_list(nested_list_t *list)
return; return;
for (i = 0; i < RBUF_LEN(list->items); i++) for (i = 0; i < RBUF_LEN(list->items); i++)
nested_list_free_item(&list->items[i]); nested_list_free_item(list->items[i]);
RBUF_FREE(list->items); RBUF_FREE(list->items);
RHMAP_FREE(list->item_map); RHMAP_FREE(list->item_map);
free(list);
} }
/** /**
@ -123,7 +124,6 @@ nested_list_t *nested_list_init(void)
void nested_list_free(nested_list_t *list) void nested_list_free(nested_list_t *list)
{ {
nested_list_free_list(list); nested_list_free_list(list);
free(list);
} }
/***********/ /***********/
@ -149,20 +149,23 @@ static nested_list_item_t *nested_list_add_item_to_list(nested_list_t *list,
if (RHMAP_HAS_STR(list->item_map, id)) if (RHMAP_HAS_STR(list->item_map, id))
goto end; goto end;
/* Attempt to allocate a buffer slot for the
* new item */
if (!RBUF_TRYFIT(list->items, num_items + 1))
goto end;
/* Create new empty child list */ /* Create new empty child list */
child_list = nested_list_init(); child_list = nested_list_init();
if (!child_list) if (!child_list)
goto end; goto end;
/* Attempt to allocate memory for new item */ /* Create new list item */
if (!RBUF_TRYFIT(list->items, num_items + 1)) new_item = (nested_list_item_t*)malloc(sizeof(*new_item));
if (!new_item)
{
nested_list_free(child_list);
goto end; goto end;
}
/* Allocation successful - increment array size */
RBUF_RESIZE(list->items, num_items + 1);
/* Get handle of new entry at end of list */
new_item = &list->items[num_items];
/* Assign members */ /* Assign members */
new_item->parent_item = parent_item; new_item->parent_item = parent_item;
@ -171,6 +174,12 @@ static nested_list_item_t *nested_list_add_item_to_list(nested_list_t *list,
new_item->id = strdup(id); new_item->id = strdup(id);
new_item->value = value; new_item->value = value;
/* Increment item buffer size */
RBUF_RESIZE(list->items, num_items + 1);
/* Add new item to buffer */
list->items[num_items] = new_item;
/* Update map */ /* Update map */
RHMAP_SET_STR(list->item_map, id, new_item); RHMAP_SET_STR(list->item_map, id, new_item);
end: end:
@ -418,7 +427,7 @@ nested_list_item_t *nested_list_get_item_idx(nested_list_t *list,
if (!list || (idx >= RBUF_LEN(list->items))) if (!list || (idx >= RBUF_LEN(list->items)))
return NULL; return NULL;
return &list->items[idx]; return list->items[idx];
} }
/** /**