aboutsummaryrefslogtreecommitdiff
path: root/binutils/dwarf.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-05-11 17:57:59 +0930
committerAlan Modra <amodra@gmail.com>2021-05-11 19:07:02 +0930
commitf2f9554bf0d15a5b93289ebfef7e04d0aeb51a60 (patch)
tree9b5c2f55a9402ff12ebbde7f3da756918ae4ed4f /binutils/dwarf.c
parent2005aa0281fccd53ad867ead783aa417516cf39c (diff)
downloadgdb-f2f9554bf0d15a5b93289ebfef7e04d0aeb51a60.zip
gdb-f2f9554bf0d15a5b93289ebfef7e04d0aeb51a60.tar.gz
gdb-f2f9554bf0d15a5b93289ebfef7e04d0aeb51a60.tar.bz2
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.
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r--binutils/dwarf.c80
1 files changed, 42 insertions, 38 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index c584f5b..aa48f69 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -1059,10 +1059,34 @@ add_abbrev_attr (unsigned long attribute,
an abbreviation set was found. */
static unsigned char *
-process_abbrev_set (unsigned char * start,
- const unsigned char * end,
- abbrev_list * list)
+process_abbrev_set (struct dwarf_section *section,
+ dwarf_vma abbrev_base,
+ 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)
{
unsigned long entry;
@@ -3679,12 +3703,9 @@ process_debug_info (struct dwarf_section * section,
list = new_abbrev_list (abbrev_base,
compunit.cu_abbrev_offset);
- next = process_abbrev_set
- (((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + compunit.cu_abbrev_offset),
- ((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + abbrev_size),
- list);
+ next = process_abbrev_set (&debug_displays[abbrev_sec].section,
+ abbrev_base, abbrev_size,
+ compunit.cu_abbrev_offset, list);
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. */
- if (compunit.cu_abbrev_offset >= abbrev_size)
- warn (_("Debug info is corrupted, abbrev offset (%lx) is larger than abbrev section size (%lx)\n"),
- (unsigned long) compunit.cu_abbrev_offset,
- (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,
+ compunit.cu_abbrev_offset);
+ if (list == NULL)
{
- list = find_abbrev_list_by_abbrev_offset (abbrev_base,
- compunit.cu_abbrev_offset);
- if (list == NULL)
- {
- unsigned char * next;
-
- list = new_abbrev_list (abbrev_base,
- compunit.cu_abbrev_offset);
- next = process_abbrev_set
- (((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + compunit.cu_abbrev_offset),
- ((unsigned char *) debug_displays [abbrev_sec].section.start
- + abbrev_base + abbrev_size),
- list);
- list->start_of_next_abbrevs = next;
- }
+ unsigned char *next;
+
+ list = new_abbrev_list (abbrev_base,
+ compunit.cu_abbrev_offset);
+ next = process_abbrev_set (&debug_displays[abbrev_sec].section,
+ abbrev_base, abbrev_size,
+ compunit.cu_abbrev_offset, list);
+ list->start_of_next_abbrevs = next;
}
level = 0;
@@ -6326,7 +6331,6 @@ display_debug_abbrev (struct dwarf_section *section,
{
abbrev_entry *entry;
unsigned char *start = section->start;
- const unsigned char *end = start + section->size;
introduce (section, false);
@@ -6340,7 +6344,7 @@ display_debug_abbrev (struct dwarf_section *section,
if (list == NULL)
{
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;
}
else