/* dwarf.c -- display DWARF contents of a BFD binary file
- Copyright (C) 2005-2014 Free Software Foundation, Inc.
+ Copyright (C) 2005-2015 Free Software Foundation, Inc.
This file is part of GNU Binutils.
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. */
#define DEBUG_INFO_UNAVAILABLE (unsigned int) -1
-int eh_addr_size;
+unsigned int eh_addr_size;
int do_debug_info;
int do_debug_abbrevs;
#define FLAG_DEBUG_LINES_RAW 1
#define FLAG_DEBUG_LINES_DECODED 2
-static int
+static unsigned int
size_of_encoded_value (int encoding)
{
switch (encoding & 0x7)
return val;
}
-#if __STDC_VERSION__ >= 199901L || (defined(__GNUC__) && __GNUC__ >= 2)
-#ifndef __MINGW32__
-#define DWARF_VMA_FMT "ll"
-#define DWARF_VMA_FMT_LONG "%16.16llx"
+#if defined HAVE_LONG_LONG && SIZEOF_LONG_LONG > SIZEOF_LONG
+# ifndef __MINGW32__
+# define DWARF_VMA_FMT "ll"
+# define DWARF_VMA_FMT_LONG "%16.16llx"
+# else
+# define DWARF_VMA_FMT "I64"
+# define DWARF_VMA_FMT_LONG "%016I64x"
+# endif
#else
-#define DWARF_VMA_FMT "I64"
-#define DWARF_VMA_FMT_LONG "%016I64x"
-#endif
-#else
-#define DWARF_VMA_FMT "l"
-#define DWARF_VMA_FMT_LONG "%16.16lx"
+# define DWARF_VMA_FMT "l"
+# define DWARF_VMA_FMT_LONG "%16.16lx"
#endif
/* Convert a dwarf vma value into a string. Returns a pointer to a static
shift += 7;
if ((byte & 0x80) == 0)
break;
+
+ /* PR 17512: file: 0ca183b8.
+ FIXME: Should we signal this error somehow ? */
+ if (shift >= sizeof (result))
+ break;
}
if (length_return != NULL)
case DW_LNE_set_address:
/* PR 17512: file: 002-100480-0.004. */
if (len - bytes_read - 1 > 8)
- warn (_("Length (%d) of DW_LNE_set_address op is too long\n"),
- len - bytes_read - 1);
- SAFE_BYTE_GET (adr, data, len - bytes_read - 1, end);
+ {
+ warn (_("Length (%d) of DW_LNE_set_address op is too long\n"),
+ len - bytes_read - 1);
+ adr = 0;
+ }
+ else
+ SAFE_BYTE_GET (adr, data, len - bytes_read - 1, end);
printf (_("set Address to 0x%s\n"), dwarf_vmatoa ("x", adr));
state_machine_regs.address = adr;
state_machine_regs.op_index = 0;
case DW_OP_GNU_entry_value:
uvalue = read_uleb128 (data, &bytes_read, end);
data += bytes_read;
+ /* PR 17531: file: 0cc9cd00. */
+ if (uvalue > (dwarf_vma) (end - data))
+ uvalue = end - data;
printf ("DW_OP_GNU_entry_value: (");
if (decode_location_expression (data, pointer_size, offset_size,
dwarf_version, uvalue,
uvalue = 0;
block_start = end;
}
+ /* FIXME: Testing "(block_start + uvalue) < block_start" miscompiles with
+ gcc 4.8.3 running on an x86_64 host in 32-bit mode. So we pre-compute
+ block_start + uvalue here. */
+ data = block_start + uvalue;
/* PR 17512: file: 008-103549-0.001:0.1. */
- if (block_start + uvalue > end)
+ if (block_start + uvalue > end || data < block_start)
{
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
uvalue = end - block_start;
uvalue = 0;
block_start = end;
}
- if (block_start + uvalue > end)
+ data = block_start + uvalue;
+ if (block_start + uvalue > end || data < block_start)
{
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
uvalue = end - block_start;
uvalue = 0;
block_start = end;
}
- if (block_start + uvalue > end)
+ data = block_start + uvalue;
+ if (block_start + uvalue > end || data < block_start)
{
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
uvalue = end - block_start;
uvalue = 0;
block_start = end;
}
- if (block_start + uvalue > end)
+ data = block_start + uvalue;
+ if (block_start + uvalue > end
+ /* PR 17531: file: 5b5f0592. */
+ || data < block_start)
{
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
uvalue = end - block_start;
/* DWARF 5 values. */
case DW_LANG_Go: printf ("(Go)"); break;
case DW_LANG_C_plus_plus_11: printf ("(C++11)"); break;
- case DW_LANG_C11: printf ("(ANSI C11)"); break;
+ case DW_LANG_C11: printf ("(C11)"); break;
case DW_LANG_C_plus_plus_14: printf ("(C++14)"); break;
+ case DW_LANG_Fortran03: printf ("(Fortran 03)"); break;
+ case DW_LANG_Fortran08: printf ("(Fortran 08)"); break;
/* MIPS extension. */
case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
/* UPC extension. */
uvalue += cu_offset;
if (uvalue >= section->size)
- warn (_("Offset %s used as value for DW_AT_import attribute of DIE at offset %lx is too big.\n"),
+ warn (_("Offset %s used as value for DW_AT_import attribute of DIE at offset 0x%lx is too big.\n"),
dwarf_vmatoa ("x", uvalue),
(unsigned long) (orig_data - section->start));
else
/* Negative values are illegal, they may even cause infinite
looping. This can happen if we can't accurately apply
- relocations to an object file. */
- if ((signed long) length <= 0)
+ relocations to an object file, or if the file is corrupt. */
+ if ((signed long) length <= 0 || section_begin < start)
{
warn (_("Corrupt unit length (0x%s) found in section %s\n"),
dwarf_vmatoa ("x", length), section->name);
/* Then allocate an array to hold the information. */
debug_information = (debug_info *) cmalloc (num_units,
- sizeof (* debug_information));
+ sizeof (* debug_information));
if (debug_information == NULL)
{
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)
" extends beyond end of section (length = %s)\n"),
dwarf_vmatoa ("x", cu_offset),
dwarf_vmatoa ("x", compunit.cu_length));
+ num_units = unit;
break;
}
tags = hdrptr;
start += compunit.cu_length + initial_length_size;
+ if (start > end)
+ {
+ warn (_("Debug info is corrupt. CU at %s extends beyond end of section"),
+ dwarf_vmatoa ("x", cu_offset));
+ start = end;
+ }
+
if (compunit.cu_version != 2
&& compunit.cu_version != 3
&& compunit.cu_version != 4)
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
process_abbrev_section
(((unsigned char *) debug_displays [abbrev_sec].section.start
printf ("\n");
fflush (stdout);
}
- warn (_("DIE at offset %lx refers to abbreviation number %lu which does not exist\n"),
+ warn (_("DIE at offset 0x%lx refers to abbreviation number %lu which does not exist\n"),
die_offset, abbrev_number);
return 0;
}
/* 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,
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");
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;
/* PR 17512: file:002-117414-0.004. */
if (* end_of_sequence > end)
{
- warn (_("Line length %lld extends beyond end of section\n"), linfo->li_length);
+ warn (_("Line length %s extends beyond end of section\n"),
+ dwarf_vmatoa ("u", linfo->li_length));
* end_of_sequence = end;
return NULL;
}
end_of_sequence = end;
standard_opcodes = NULL;
linfo = saved_linfo;
+ /* PR 17531: file: 0522b371. */
+ if (linfo.li_line_range == 0)
+ {
+ warn (_("Partial .debug_line. section encountered without a prior full .debug_line section\n"));
+ return 0;
+ }
reset_state_machine (linfo.li_default_is_stmt);
}
else
printf (_(" Offset: 0x%lx\n"), (long)(data - start));
printf (_(" Length: %ld\n"), (long) linfo.li_length);
printf (_(" DWARF Version: %d\n"), linfo.li_version);
- printf (_(" Prologue Length: %d\n"), linfo.li_prologue_length);
+ printf (_(" Prologue Length: %d\n"), (int) linfo.li_prologue_length);
printf (_(" Minimum Instruction Length: %d\n"), linfo.li_min_insn_length);
if (linfo.li_version >= 4)
printf (_(" Maximum Ops per Instruction: %d\n"), linfo.li_max_ops_per_insn);
end_of_sequence = end;
standard_opcodes = NULL;
linfo = saved_linfo;
+ /* PR 17531: file: 0522b371. */
+ if (linfo.li_line_range == 0)
+ {
+ warn (_("Partial .debug_line. section encountered without a prior full .debug_line section\n"));
+ return 0;
+ }
reset_state_machine (linfo.li_default_is_stmt);
}
else
& end_of_sequence)) == NULL)
return 0;
+ /* PR 17531: file: 0522b371. */
+ if (linfo.li_line_range == 0)
+ {
+ warn (_("Line range of 0 is invalid, using 1 instead\n"));
+ linfo.li_line_range = 1;
+ }
reset_state_machine (linfo.li_default_is_stmt);
/* Save a pointer to the contents of the Opcodes table. */
SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, end);
- start += names.pn_length + initial_length_size;
+ /* PR 17531: file: 7615b6b2. */
+ if ((dwarf_signed_vma) names.pn_length < 0
+ /* PR 17531: file: a5dbeaa7. */
+ || start + names.pn_length + initial_length_size < start)
+ {
+ warn (_("Negative length for public name: 0x%lx\n"), (long) names.pn_length);
+ start = end;
+ }
+ else
+ start += names.pn_length + initial_length_size;
+
+ printf (_(" Length: %ld\n"),
+ (long) names.pn_length);
+ printf (_(" Version: %d\n"),
+ names.pn_version);
+ printf (_(" Offset into .debug_info section: 0x%lx\n"),
+ (unsigned long) names.pn_offset);
+ printf (_(" Size of area in .debug_info section: %ld\n"),
+ (long) names.pn_size);
if (names.pn_version != 2 && names.pn_version != 3)
{
continue;
}
- printf (_(" Length: %ld\n"),
- (long) names.pn_length);
- printf (_(" Version: %d\n"),
- names.pn_version);
- printf (_(" Offset into .debug_info section: 0x%lx\n"),
- (unsigned long) names.pn_offset);
- printf (_(" Size of area in .debug_info section: %ld\n"),
- (long) names.pn_size);
-
if (is_gnu)
printf (_("\n Offset Kind Name\n"));
else
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"),
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"),
printf (_("Contents of the %s section:\n\n"), section->name);
- debug_addr_info = (debug_info **) xmalloc ((num_debug_info_entries + 1)
- * sizeof (debug_info *));
+ /* PR 17531: file: cf38d01b.
+ We use xcalloc because a corrupt file may not have initialised all of the
+ fields in the debug_info structure, which means that the sort below might
+ try to move uninitialised data. */
+ debug_addr_info = (debug_info **) xcalloc ((num_debug_info_entries + 1),
+ sizeof (debug_info *));
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)
+ {
+ /* PR 17531: file: cf38d01b. */
+ if (debug_information[i].addr_base >= section->size)
+ warn (_("Corrupt address base (%lx) found in debug section %u\n"),
+ (unsigned long) debug_information[i].addr_base, i);
+ else
+ debug_addr_info [count++] = debug_information + i;
+ }
/* Add a sentinel to make iteration convenient. */
debug_addr_info [count] = (debug_info *) xmalloc (sizeof (debug_info));
debug_addr_info [count]->addr_base = section->size;
-
qsort (debug_addr_info, count, sizeof (debug_info *), comp_addr_base);
+
for (i = 0; i < count; i++)
{
unsigned int idx;
if (version >= 4)
{
GET (fc->ptr_size, 1);
+ if (fc->ptr_size < 1 || fc->ptr_size > 8)
+ {
+ warn (_("Invalid pointer size (%d) in CIE data\n"), fc->ptr_size);
+ return end;
+ }
+
GET (fc->segment_size, 1);
+ /* PR 17512: file: e99d2804. */
+ if (fc->segment_size > 8 || fc->segment_size + fc->ptr_size > 8)
+ {
+ warn (_("Invalid segment size (%d) in CIE data\n"), fc->segment_size);
+ return end;
+ }
+
eh_addr_size = fc->ptr_size;
}
else
/* PR 17512: file: 11042-2589-0.004. */
if (start > end)
{
- warn (_("Augmentation data too long: 0x%lx"), augmentation_data_len);
+ warn (_("Augmentation data too long: 0x%lx\n"), augmentation_data_len);
return end;
}
}
if (augmentation_data_len)
{
- unsigned char *p, *q;
+ unsigned char *p;
+ unsigned char *q;
+ unsigned char *qend;
+
p = (unsigned char *) fc->augmentation + 1;
q = augmentation_data;
+ qend = q + augmentation_data_len;
+
+ /* PR 17531: file: 015adfaa. */
+ if (qend < q)
+ {
+ warn (_("Negative augmentation data length: 0x%lx"), augmentation_data_len);
+ augmentation_data_len = 0;
+ }
while (p < end && q < augmentation_data + augmentation_data_len)
{
break;
p++;
}
+ /* Note - it is OK if this loop terminates with q < qend.
+ Padding may have been inserted to align the end of the CIE. */
}
*p_cie = fc;
unsigned int length_return;
unsigned int max_regs = 0;
const char *bad_reg = _("bad register: ");
- int saved_eh_addr_size = eh_addr_size;
+ unsigned int saved_eh_addr_size = eh_addr_size;
printf (_("Contents of the %s section:\n"), section->name);
augmentation_data = start;
start += augmentation_data_len;
/* PR 17512: file: 722-8446-0.004. */
- if (start >= end)
+ if (start >= end || ((signed long) augmentation_data_len) < 0)
{
warn (_("Corrupt augmentation data length: %lx\n"),
augmentation_data_len);
{
unsigned int reg, op, opa;
unsigned long temp;
+ unsigned char * new_start;
op = *start++;
opa = op & 0x3f;
break;
case DW_CFA_def_cfa_expression:
temp = LEB ();
- if (start + temp < start)
+ new_start = start + temp;
+ if (new_start < start)
{
warn (_("Corrupt CFA_def expression value: %lu\n"), temp);
start = block_end;
}
else
- start += temp;
+ start = new_start;
break;
case DW_CFA_expression:
case DW_CFA_val_expression:
reg = LEB ();
temp = LEB ();
- if (start + temp < start)
+ new_start = start + temp;
+ if (new_start < start)
{
/* PR 17512: file:306-192417-0.005. */
warn (_("Corrupt CFA expression value: %lu\n"), temp);
start = block_end;
}
else
- start += temp;
+ start = new_start;
if (frame_need_space (fc, reg) >= 0)
fc->col_type[reg] = DW_CFA_undefined;
break;
fc->cfa_exp = rs->cfa_exp;
if (frame_need_space (fc, rs->ncols - 1) < 0)
{
- warn (_("Invalid column number in saved frame state"));
+ warn (_("Invalid column number in saved frame state\n"));
fc->ncols = 0;
break;
}
return 0;
}
+ /* PR 17531: file: 418d0a8a. */
+ if (tu_list_offset < cu_list_offset)
+ {
+ warn (_("TU offset (%x) is less than CU offset (%x)\n"),
+ tu_list_offset, cu_list_offset);
+ return 0;
+ }
+
cu_list_elements = (tu_list_offset - cu_list_offset) / 8;
+
+ if (address_table_offset < tu_list_offset)
+ {
+ warn (_("Address table offset (%x) is less than TU offset (%x)\n"),
+ address_table_offset, tu_list_offset);
+ return 0;
+ }
+
tu_list_elements = (address_table_offset - tu_list_offset) / 8;
+
+ /* PR 17531: file: 18a47d3d. */
+ if (symbol_table_offset < address_table_offset)
+ {
+ warn (_("Symbol table offset (%xl) is less then Address table offset (%x)\n"),
+ symbol_table_offset, address_table_offset);
+ return 0;
+ }
+
address_table_size = symbol_table_offset - address_table_offset;
+
+ if (constant_pool_offset < symbol_table_offset)
+ {
+ warn (_("Constant pool offset (%x) is less than symbol table offset (%x)\n"),
+ constant_pool_offset, symbol_table_offset);
+ return 0;
+ }
+
symbol_table_slots = (constant_pool_offset - symbol_table_offset) / 8;
cu_list = start + cu_list_offset;
symbol_table = start + symbol_table_offset;
constant_pool = start + constant_pool_offset;
+ if (address_table + address_table_size * (2 + 8 + 4) > section->start + section->size)
+ {
+ warn (_("Address table extends beyond end of section.\n"));
+ return 0;
+ }
+
printf (_("\nCU table:\n"));
for (i = 0; i < cu_list_elements; i += 2)
{
}
printf (_("\nAddress table:\n"));
- for (i = 0; i < address_table_size; i += 2 * 8 + 4)
+ for (i = 0; i < address_table_size && i <= address_table_size - (2 * 8 + 4);
+ i += 2 * 8 + 4)
{
uint64_t low = byte_get_little_endian (address_table + i, 8);
uint64_t high = byte_get_little_endian (address_table + i + 8, 8);
{
unsigned int j;
- printf ("[%3u] %s:", i, constant_pool + name_offset);
+ /* PR 17531: file: 5b7b07ad. */
+ if (constant_pool + name_offset < constant_pool
+ || constant_pool + name_offset >= section->start + section->size)
+ {
+ printf (_("[%3u] <corrupt offset: %x>"), i, name_offset);
+ warn (_("Corrupt name offset of 0x%x found for symbol table slot %d\n"),
+ name_offset, i);
+ }
+ else
+ printf ("[%3u] %.*s:", i,
+ (int) (section->size - (constant_pool_offset + name_offset)),
+ constant_pool + name_offset);
+
+ if (constant_pool + cu_vector_offset < constant_pool
+ || constant_pool + cu_vector_offset >= section->start + section->size - 3)
+ {
+ printf (_("<invalid CU vector offset: %x>\n"), cu_vector_offset);
+ warn (_("Corrupt CU vector offset of 0x%x found for symbol table slot %d\n"),
+ cu_vector_offset, i);
+ continue;
+ }
+
num_cus = byte_get_little_endian (constant_pool + cu_vector_offset, 4);
+
+ if (num_cus * 4 < num_cus
+ || constant_pool + cu_vector_offset + 4 + num_cus * 4
+ >= section->start + section->size
+ || (constant_pool + cu_vector_offset + 4 + num_cus * 4) < constant_pool)
+ {
+ printf ("<invalid number of CUs: %d>\n", num_cus);
+ warn (_("Invalid number of CUs (0x%x) for symbol table slot %d\n"),
+ num_cus, i);
+ continue;
+ }
+
if (num_cus > 1)
printf ("\n");
+
for (j = 0; j < num_cus; ++j)
{
int is_static;
/* PR 17512: file: 002-376-0.004. */
if (section->size < 24)
{
- warn (_("Section %s is too small to contain a CU/TU header"),
+ warn (_("Section %s is too small to contain a CU/TU header\n"),
section->name);
return 0;
}
pindex = phash + nslots * 8;
ppool = pindex + nslots * 4;
+ /* PR 17531: file: 45d69832. */
+ if (pindex < phash || ppool < phdr)
+ {
+ warn (_("Section %s is too small for %d slots\n"),
+ section->name, nslots);
+ return 0;
+ }
+
if (do_display)
{
printf (_("Contents of the %s section:\n\n"), section->name);
{
SAFE_BYTE_GET (j, pindex, 4, limit);
shndx_list = ppool + j * 4;
+ /* PR 17531: file: 705e010d. */
+ if (shndx_list < ppool)
+ {
+ warn (_("Section index pool located before start of section\n"));
+ return 0;
+ }
+
if (do_display)
printf (_(" [%3d] Signature: 0x%s Sections: "),
i, dwarf_vmatoa64 (signature_high, signature_low,
if (is_tu_index)
{
tu_count = nused;
- tu_sets = xcmalloc (nused, sizeof (struct cu_tu_set));
+ tu_sets = xcalloc2 (nused, sizeof (struct cu_tu_set));
this_set = tu_sets;
}
else
{
cu_count = nused;
- cu_sets = xcmalloc (nused, sizeof (struct cu_tu_set));
+ cu_sets = xcalloc2 (nused, sizeof (struct cu_tu_set));
this_set = cu_sets;
}
}
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;
}
}
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;
}
}
return 1;
}
+/* Like malloc, but takes two parameters like calloc.
+ Verifies that the first parameter is not too large.
+ 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 like calloc.
+ Verifies that the first parameter is not too large.
+ 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);
+ {
+ fprintf (stderr,
+ _("Attempt to allocate an array with an excessive number of elements: 0x%lx\n"),
+ (long) nmemb);
+ xexit (1);
+ }
+
+ return xmalloc (nmemb * size);
}
+/* Like xrealloc, but takes three parameters.
+ Verifies that the second parameter is not too large.
+ 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);
+ {
+ fprintf (stderr,
+ _("Attempt to re-allocate an array with an excessive number of elements: 0x%lx\n"),
+ (long) nmemb);
+ xexit (1);
+ }
+
+ return xrealloc (ptr, nmemb * size);
+}
+
+/* Like xcalloc, but verifies that the first parameter is not too large. */
+void *
+xcalloc2 (size_t nmemb, size_t size)
+{
+ /* Check for overflow. */
+ if (nmemb >= ~(size_t) 0 / size)
+ {
+ fprintf (stderr,
+ _("Attempt to allocate a zero'ed array with an excessive number of elements: 0x%lx\n"),
+ (long) nmemb);
+ xexit (1);
+ }
+
+ return xcalloc (nmemb, size);
}
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;
}
}
break;
default:
- warn (_("Unrecognized debug option '%s'\n"), optarg);
+ warn (_("Unrecognized debug option '%s'\n"), letters);
break;
}
}