PR27845, readelf heap-buffer-overflow

PR 27845
	* dwarf.c (process_abbrev_set): Replace start and end parameters
	with section, abbrev_base, abbrev_size, abbrev_offset.  Update
	all callers.  Sanity check parameters correctly and emit warnings
	here rather than..
	(process_debug_info): ..here.
This commit is contained in:
Alan Modra
2021-05-11 17:57:59 +09:30
parent 2005aa0281
commit f2f9554bf0
2 changed files with 50 additions and 37 deletions

View File

@ -1,3 +1,12 @@
2021-05-11 Alan Modra <amodra@gmail.com>
PR 27845
* dwarf.c (process_abbrev_set): Replace start and end parameters
with section, abbrev_base, abbrev_size, abbrev_offset. Update
all callers. Sanity check parameters correctly and emit warnings
here rather than..
(process_debug_info): ..here.
2021-05-10 Thomas Wolff <towo@towo.net> 2021-05-10 Thomas Wolff <towo@towo.net>
PR 4356 PR 4356

View File

@ -1059,10 +1059,34 @@ add_abbrev_attr (unsigned long attribute,
an abbreviation set was found. */ an abbreviation set was found. */
static unsigned char * static unsigned char *
process_abbrev_set (unsigned char * start, process_abbrev_set (struct dwarf_section *section,
const unsigned char * end, dwarf_vma abbrev_base,
abbrev_list * list) dwarf_vma abbrev_size,
dwarf_vma abbrev_offset,
abbrev_list *list)
{ {
if (abbrev_base >= section->size
|| abbrev_size > section->size - abbrev_base)
{
/* PR 17531: file:4bcd9ce9. */
warn (_("Debug info is corrupted, abbrev size (%lx) is larger than "
"abbrev section size (%lx)\n"),
(unsigned long) abbrev_base + abbrev_size,
(unsigned long) section->size);
return NULL;
}
if (abbrev_offset >= abbrev_size)
{
warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than "
"abbrev section size (%lx)\n"),
(unsigned long) abbrev_offset,
(unsigned long) abbrev_size);
return NULL;
}
unsigned char *start = section->start + abbrev_base;
unsigned char *end = start + abbrev_size;
start += abbrev_offset;
while (start < end) while (start < end)
{ {
unsigned long entry; unsigned long entry;
@ -3679,12 +3703,9 @@ process_debug_info (struct dwarf_section * section,
list = new_abbrev_list (abbrev_base, list = new_abbrev_list (abbrev_base,
compunit.cu_abbrev_offset); compunit.cu_abbrev_offset);
next = process_abbrev_set next = process_abbrev_set (&debug_displays[abbrev_sec].section,
(((unsigned char *) debug_displays [abbrev_sec].section.start abbrev_base, abbrev_size,
+ abbrev_base + compunit.cu_abbrev_offset), compunit.cu_abbrev_offset, list);
((unsigned char *) debug_displays [abbrev_sec].section.start
+ abbrev_base + abbrev_size),
list);
list->start_of_next_abbrevs = next; list->start_of_next_abbrevs = next;
} }
@ -3905,34 +3926,18 @@ process_debug_info (struct dwarf_section * section,
} }
/* Process the abbrevs used by this compilation unit. */ /* Process the abbrevs used by this compilation unit. */
if (compunit.cu_abbrev_offset >= abbrev_size) list = find_abbrev_list_by_abbrev_offset (abbrev_base,
warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than abbrev section size (%lx)\n"), compunit.cu_abbrev_offset);
(unsigned long) compunit.cu_abbrev_offset, if (list == NULL)
(unsigned long) abbrev_size);
/* PR 17531: file:4bcd9ce9. */
else if ((abbrev_base + abbrev_size)
> debug_displays [abbrev_sec].section.size)
warn (_("Debug info is corrupted, abbrev size (%lx) is larger than abbrev section size (%lx)\n"),
(unsigned long) abbrev_base + abbrev_size,
(unsigned long) debug_displays [abbrev_sec].section.size);
else
{ {
list = find_abbrev_list_by_abbrev_offset (abbrev_base, unsigned char *next;
compunit.cu_abbrev_offset);
if (list == NULL)
{
unsigned char * next;
list = new_abbrev_list (abbrev_base, list = new_abbrev_list (abbrev_base,
compunit.cu_abbrev_offset); compunit.cu_abbrev_offset);
next = process_abbrev_set next = process_abbrev_set (&debug_displays[abbrev_sec].section,
(((unsigned char *) debug_displays [abbrev_sec].section.start abbrev_base, abbrev_size,
+ abbrev_base + compunit.cu_abbrev_offset), compunit.cu_abbrev_offset, list);
((unsigned char *) debug_displays [abbrev_sec].section.start list->start_of_next_abbrevs = next;
+ abbrev_base + abbrev_size),
list);
list->start_of_next_abbrevs = next;
}
} }
level = 0; level = 0;
@ -6326,7 +6331,6 @@ display_debug_abbrev (struct dwarf_section *section,
{ {
abbrev_entry *entry; abbrev_entry *entry;
unsigned char *start = section->start; unsigned char *start = section->start;
const unsigned char *end = start + section->size;
introduce (section, false); introduce (section, false);
@ -6340,7 +6344,7 @@ display_debug_abbrev (struct dwarf_section *section,
if (list == NULL) if (list == NULL)
{ {
list = new_abbrev_list (0, offset); list = new_abbrev_list (0, offset);
start = process_abbrev_set (start, end, list); start = process_abbrev_set (section, 0, section->size, offset, list);
list->start_of_next_abbrevs = start; list->start_of_next_abbrevs = start;
} }
else else