mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-21 18:39:34 +08:00
PR29370, infinite loop in display_debug_abbrev
The PR29370 testcase is a fuzzed object file with multiple .trace_abbrev sections. Multiple .trace_abbrev or .debug_abbrev sections are not a violation of the DWARF standard. The DWARF5 standard even gives an example of multiple .debug_abbrev sections contained in groups. Caching and lookup of processed abbrevs thus needs to be done by section and offset rather than base and offset. (Why base anyway?) Or, since section contents are kept, by a pointer into the contents. PR 29370 * dwarf.c (struct abbrev_list): Replace abbrev_base and abbrev_offset with raw field. (find_abbrev_list_by_abbrev_offset): Delete. (find_abbrev_list_by_raw_abbrev): New function. (process_abbrev_set): Set list->raw and list->next. (find_and_process_abbrev_set): Replace abbrev list lookup with new function. Don't set list abbrev_base, abbrev_offset or next.
This commit is contained in:
@ -856,8 +856,7 @@ typedef struct abbrev_list
|
|||||||
{
|
{
|
||||||
abbrev_entry * first_abbrev;
|
abbrev_entry * first_abbrev;
|
||||||
abbrev_entry * last_abbrev;
|
abbrev_entry * last_abbrev;
|
||||||
dwarf_vma abbrev_base;
|
unsigned char * raw;
|
||||||
dwarf_vma abbrev_offset;
|
|
||||||
struct abbrev_list * next;
|
struct abbrev_list * next;
|
||||||
unsigned char * start_of_next_abbrevs;
|
unsigned char * start_of_next_abbrevs;
|
||||||
}
|
}
|
||||||
@ -946,14 +945,12 @@ free_all_abbrevs (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static abbrev_list *
|
static abbrev_list *
|
||||||
find_abbrev_list_by_abbrev_offset (dwarf_vma abbrev_base,
|
find_abbrev_list_by_raw_abbrev (unsigned char *raw)
|
||||||
dwarf_vma abbrev_offset)
|
|
||||||
{
|
{
|
||||||
abbrev_list * list;
|
abbrev_list * list;
|
||||||
|
|
||||||
for (list = abbrev_lists; list != NULL; list = list->next)
|
for (list = abbrev_lists; list != NULL; list = list->next)
|
||||||
if (list->abbrev_base == abbrev_base
|
if (list->raw == raw)
|
||||||
&& list->abbrev_offset == abbrev_offset)
|
|
||||||
return list;
|
return list;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1040,6 +1037,7 @@ process_abbrev_set (struct dwarf_section *section,
|
|||||||
abbrev_list *list = xmalloc (sizeof (*list));
|
abbrev_list *list = xmalloc (sizeof (*list));
|
||||||
list->first_abbrev = NULL;
|
list->first_abbrev = NULL;
|
||||||
list->last_abbrev = NULL;
|
list->last_abbrev = NULL;
|
||||||
|
list->raw = start;
|
||||||
|
|
||||||
while (start < end)
|
while (start < end)
|
||||||
{
|
{
|
||||||
@ -1055,6 +1053,7 @@ process_abbrev_set (struct dwarf_section *section,
|
|||||||
the caller. */
|
the caller. */
|
||||||
if (start == end || entry == 0)
|
if (start == end || entry == 0)
|
||||||
{
|
{
|
||||||
|
list->next = NULL;
|
||||||
list->start_of_next_abbrevs = start != end ? start : NULL;
|
list->start_of_next_abbrevs = start != end ? start : NULL;
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@ -1144,16 +1143,10 @@ find_and_process_abbrev_set (struct dwarf_section *section,
|
|||||||
unsigned char *end = section->start + abbrev_base + abbrev_size;
|
unsigned char *end = section->start + abbrev_base + abbrev_size;
|
||||||
abbrev_list *list = NULL;
|
abbrev_list *list = NULL;
|
||||||
if (free_list)
|
if (free_list)
|
||||||
list = find_abbrev_list_by_abbrev_offset (abbrev_base, abbrev_offset);
|
list = find_abbrev_list_by_raw_abbrev (start);
|
||||||
if (list == NULL)
|
if (list == NULL)
|
||||||
{
|
{
|
||||||
list = process_abbrev_set (section, start, end);
|
list = process_abbrev_set (section, start, end);
|
||||||
if (list)
|
|
||||||
{
|
|
||||||
list->abbrev_base = abbrev_base;
|
|
||||||
list->abbrev_offset = abbrev_offset;
|
|
||||||
list->next = NULL;
|
|
||||||
}
|
|
||||||
if (free_list)
|
if (free_list)
|
||||||
*free_list = list;
|
*free_list = list;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user