aboutsummaryrefslogtreecommitdiff
path: root/binutils/dwarf.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-01-05 13:54:22 +0000
committerNick Clifton <nickc@redhat.com>2015-01-05 13:54:22 +0000
commit82b1b41bcdc6d01fdbd94b246e24a8a8f8c2bddd (patch)
tree757eaffeeb7a220f257326d6d7e366d0713187be /binutils/dwarf.c
parentc1724c7fd39d85ccc1f94a0cd7bc25b19aa43ffd (diff)
downloadgdb-82b1b41bcdc6d01fdbd94b246e24a8a8f8c2bddd.zip
gdb-82b1b41bcdc6d01fdbd94b246e24a8a8f8c2bddd.tar.gz
gdb-82b1b41bcdc6d01fdbd94b246e24a8a8f8c2bddd.tar.bz2
More fixes for invalid memory accesses triggered by fuzzed binaries.
PR binutils/17531 * dwarf.c (alloc_num_debug_info_entries): New variable. (process_debug_info): Set it. Use it to avoid displaying attributes for which there is no info. (display_debug_abbrev): Check that the debug_info_entry index is valid before using it. (display_loc_list_dwo): Likewise. (process_cu_tu_index): Add range check for an overlarge dw_sect value. (free_debug_memory): Reset alloc_num_debug_info_entries. * readelf.c (slurp_ia64_unwind_table): Warn if the reloc could not be indentified. (dynamic_section_mips_val): Warn if the timestamp is invalid. (print_mips_got_entry): Add a data_end parameter. Warn if a read would go beyond the end of the data, and return an error value. (process_mips_specific): Do not read options from beyond the end of the section. Correct code to display optional data at the end of an option. Warn if there are too many GOT symbols. Update calls to print_mips_got_entry, and handle error returns.
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r--binutils/dwarf.c107
1 files changed, 76 insertions, 31 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 3d3f4cc..2500a49 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -38,6 +38,7 @@ static unsigned int last_pointer_size = 0;
static int warned_about_missing_comp_units = FALSE;
static unsigned int num_debug_info_entries = 0;
+static unsigned int alloc_num_debug_info_entries = 0;
static debug_info *debug_information = NULL;
/* Special value for num_debug_info_entries to indicate
that the .debug_info section could not be loaded/parsed. */
@@ -2280,8 +2281,10 @@ process_debug_info (struct dwarf_section *section,
{
error (_("Not enough memory for a debug info array of %u entries\n"),
num_units);
+ alloc_num_debug_info_entries = num_debug_info_entries = 0;
return 0;
}
+ alloc_num_debug_info_entries = num_units;
}
if (!do_loc)
@@ -2596,10 +2599,11 @@ process_debug_info (struct dwarf_section *section,
/* Show the offset from where the tag was extracted. */
printf (" <%lx>", (unsigned long)(tags - section_begin));
- arg = debug_information;
- if (debug_information)
- arg += unit;
-
+ if (debug_information && unit < alloc_num_debug_info_entries)
+ arg = debug_information + unit;
+ else
+ arg = NULL;
+
tags = read_and_display_attr (attr->attribute,
attr->form,
tags,
@@ -2624,7 +2628,12 @@ process_debug_info (struct dwarf_section *section,
if ((do_loc || do_debug_loc || do_debug_ranges)
&& num_debug_info_entries == 0
&& ! do_types)
- num_debug_info_entries = num_units;
+ {
+ if (num_units > alloc_num_debug_info_entries)
+ num_debug_info_entries = alloc_num_debug_info_entries;
+ else
+ num_debug_info_entries = num_units;
+ }
if (!do_loc)
printf ("\n");
@@ -2661,9 +2670,10 @@ load_debug_info (void * file)
if (load_debug_section (info, file)
&& process_debug_info (&debug_displays [info].section, file, abbrev, 1, 0))
return num_debug_info_entries;
- else if (load_debug_section (info_dwo, file)
- && process_debug_info (&debug_displays [info_dwo].section, file,
- abbrev_dwo, 1, 0))
+
+ if (load_debug_section (info_dwo, file)
+ && process_debug_info (&debug_displays [info_dwo].section, file,
+ abbrev_dwo, 1, 0))
return num_debug_info_entries;
num_debug_info_entries = DEBUG_INFO_UNAVAILABLE;
@@ -4271,23 +4281,35 @@ display_debug_abbrev (struct dwarf_section *section,
static void
display_loc_list (struct dwarf_section *section,
unsigned char **start_ptr,
- int debug_info_entry,
+ unsigned int debug_info_entry,
unsigned long offset,
unsigned long base_address,
int has_frame_base)
{
unsigned char *start = *start_ptr;
unsigned char *section_end = section->start + section->size;
- unsigned long cu_offset = debug_information [debug_info_entry].cu_offset;
- unsigned int pointer_size = debug_information [debug_info_entry].pointer_size;
- unsigned int offset_size = debug_information [debug_info_entry].offset_size;
- int dwarf_version = debug_information [debug_info_entry].dwarf_version;
+ unsigned long cu_offset;
+ unsigned int pointer_size;
+ unsigned int offset_size;
+ int dwarf_version;
dwarf_vma begin;
dwarf_vma end;
unsigned short length;
int need_frame_base;
+ if (debug_info_entry >= num_debug_info_entries)
+ {
+ warn (_("No debug information available for loc lists of entry: %u\n"),
+ debug_info_entry);
+ return;
+ }
+
+ cu_offset = debug_information [debug_info_entry].cu_offset;
+ pointer_size = debug_information [debug_info_entry].pointer_size;
+ offset_size = debug_information [debug_info_entry].offset_size;
+ dwarf_version = debug_information [debug_info_entry].dwarf_version;
+
if (pointer_size < 2 || pointer_size > 8)
{
warn (_("Invalid pointer size (%d) in debug info for entry %d\n"),
@@ -4391,22 +4413,34 @@ print_addr_index (unsigned int idx, unsigned int len)
static void
display_loc_list_dwo (struct dwarf_section *section,
unsigned char **start_ptr,
- int debug_info_entry,
+ unsigned int debug_info_entry,
unsigned long offset,
int has_frame_base)
{
unsigned char *start = *start_ptr;
unsigned char *section_end = section->start + section->size;
- unsigned long cu_offset = debug_information [debug_info_entry].cu_offset;
- unsigned int pointer_size = debug_information [debug_info_entry].pointer_size;
- unsigned int offset_size = debug_information [debug_info_entry].offset_size;
- int dwarf_version = debug_information [debug_info_entry].dwarf_version;
+ unsigned long cu_offset;
+ unsigned int pointer_size;
+ unsigned int offset_size;
+ int dwarf_version;
int entry_type;
unsigned short length;
int need_frame_base;
unsigned int idx;
unsigned int bytes_read;
+ if (debug_info_entry >= num_debug_info_entries)
+ {
+ warn (_("No debug information for loc lists of entry: %u\n"),
+ debug_info_entry);
+ return;
+ }
+
+ cu_offset = debug_information [debug_info_entry].cu_offset;
+ pointer_size = debug_information [debug_info_entry].pointer_size;
+ offset_size = debug_information [debug_info_entry].offset_size;
+ dwarf_version = debug_information [debug_info_entry].dwarf_version;
+
if (pointer_size < 2 || pointer_size > 8)
{
warn (_("Invalid pointer size (%d) in debug info for entry %d\n"),
@@ -4902,10 +4936,8 @@ display_debug_addr (struct dwarf_section *section,
count = 0;
for (i = 0; i < num_debug_info_entries; i++)
- {
- if (debug_information [i].addr_base != DEBUG_INFO_UNAVAILABLE)
- debug_addr_info [count++] = &debug_information [i];
- }
+ if (debug_information [i].addr_base != DEBUG_INFO_UNAVAILABLE)
+ debug_addr_info [count++] = debug_information + i;
/* Add a sentinel to make iteration convenient. */
debug_addr_info [count] = (debug_info *) xmalloc (sizeof (debug_info));
@@ -6963,7 +6995,12 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
else
{
SAFE_BYTE_GET (dw_sect, ppool + j * 4, 4, limit);
- this_set [row - 1].section_offsets [dw_sect] = val;
+
+ /* PR 17531: file: 10796eb3. */
+ if (dw_sect >= DW_SECT_MAX)
+ warn (_("Overlarge Dwarf section index detected: %u\n"), dw_sect);
+ else
+ this_set [row - 1].section_offsets [dw_sect] = val;
}
}
@@ -7016,6 +7053,9 @@ process_cu_tu_index (struct dwarf_section *section, int do_display)
else
{
SAFE_BYTE_GET (dw_sect, ppool + j * 4, 4, limit);
+ if (dw_sect >= DW_SECT_MAX)
+ warn (_("Overlarge Dwarf section index detected: %u\n"), dw_sect);
+ else
this_set [row - 1].section_sizes [dw_sect] = val;
}
}
@@ -7100,34 +7140,40 @@ display_debug_not_supported (struct dwarf_section *section,
return 1;
}
+/* Like malloc, but takes two parameters.
+ Note: does *not* initialise the allocated memory to zero. */
void *
cmalloc (size_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
return NULL;
- else
- return malloc (nmemb * size);
+
+ return xmalloc (nmemb * size);
}
+/* Like xmalloc, but takes two parameters.
+ Note: does *not* initialise the allocated memory to zero. */
void *
xcmalloc (size_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
return NULL;
- else
- return xmalloc (nmemb * size);
+
+ return xmalloc (nmemb * size);
}
+/* Like xrealloc, but takes three parameters.
+ Note: does *not* initialise any new memory to zero. */
void *
xcrealloc (void *ptr, size_t nmemb, size_t size)
{
/* Check for overflow. */
if (nmemb >= ~(size_t) 0 / size)
return NULL;
- else
- return xrealloc (ptr, nmemb * size);
+
+ return xrealloc (ptr, nmemb * size);
}
void
@@ -7155,10 +7201,9 @@ free_debug_memory (void)
free (debug_information [i].range_lists);
}
}
-
free (debug_information);
debug_information = NULL;
- num_debug_info_entries = 0;
+ alloc_num_debug_info_entries = num_debug_info_entries = 0;
}
}