mirror of
https://github.com/libretro/RetroArch
synced 2025-02-19 12:41:00 +00:00
(nested_list) Fix heap-use-after-free errors due to pointer invalidation when resizing internal RBUF arrays
This commit is contained in:
parent
406c8bee7b
commit
f58c7f69d9
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user