summaryrefslogtreecommitdiff
path: root/binutils/dwarf.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2015-02-10 14:11:00 +0000
committerNick Clifton <nickc@redhat.com>2015-02-10 14:11:00 +0000
commit77ef86547510cee3a2bff27bea9f19f0b2715bae (patch)
treecf37b63c2505ce132ac49d286340751c4caebe7f /binutils/dwarf.c
parentb677c4562dea82ffaf413e7e9311ca4b9c1c6ec6 (diff)
Fix memory access violations triggered by running objdump compiled with out-of-bounds sanitization checking.
PR binutils/17512 * dwarf.c (eh_addr_size): Use an unsigned type. (size_of_encoded_value): Return an unsigned type. (read_leb128): Break if the shift becomes too big. (process_extended_line_op): Do not read the address if the length is too long. (read_cie): Warn and fail if the pointer size or segment size are too big. * dwarf.h (DWARF2_External_LineInfo): Delete unused and incorrect structure definition. (DWARF2_External_PubNames): Likewise. (DWARF2_External_CompUnit): Likewise. (DWARF2_External_ARange): Likewise. (DWARF2_Internal_LineInfo): Use dwarf_vma type for li_prologue_length. (eh_addr_size): Update prototype. * coffcode.h (styp_to_sec_flags): Use an unsigned long type to hold the flag bits. * peXXigen.c (pe_print_reloc): Use unsigned types to hold the size and number of relocs. (pe_print_debugdata): Use a 32-bit aligned buffer to store the codeview record. * versados.c (process_otr): Check the esdid value before using it to access the EDATA.
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r--binutils/dwarf.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index e93a757287..9daf31579a 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -44,7 +44,7 @@ static debug_info *debug_information = NULL;
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;
@@ -105,7 +105,7 @@ static void load_cu_tu_indexes (void *file);
#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)
@@ -281,6 +281,11 @@ read_leb128 (unsigned char *data,
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)
@@ -446,9 +451,13 @@ process_extended_line_op (unsigned char * data,
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;
@@ -2860,7 +2869,7 @@ display_debug_lines_raw (struct dwarf_section *section,
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);
@@ -2875,7 +2884,7 @@ display_debug_lines_raw (struct dwarf_section *section,
warn (_("Line range of 0 is invalid, using 1 instead\n"));
linfo.li_line_range = 1;
}
-
+
reset_state_machine (linfo.li_default_is_stmt);
/* Display the contents of the Opcodes table. */
@@ -5542,7 +5551,20 @@ read_cie (unsigned char *start, unsigned char *end,
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
@@ -5634,7 +5656,7 @@ display_debug_frames (struct dwarf_section *section,
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);