diff options
author | Nick Clifton <nickc@redhat.com> | 2015-02-11 13:05:04 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2015-02-11 13:05:04 +0000 |
commit | 362beea4b400bcd5aca3bb1215a77e9e749b07fe (patch) | |
tree | e5f2090255d9e4ada3bdefc45ca76012e47bcbb7 | |
parent | 439b7f41b5fee5ec5902aecc8f3fd105be6270b3 (diff) | |
download | fsf-binutils-gdb-362beea4b400bcd5aca3bb1215a77e9e749b07fe.zip fsf-binutils-gdb-362beea4b400bcd5aca3bb1215a77e9e749b07fe.tar.gz fsf-binutils-gdb-362beea4b400bcd5aca3bb1215a77e9e749b07fe.tar.bz2 |
Fixes for invalid memory accesses triggered by running readelf on fuzzed binaries.
PR binutils/17531
* dwarf.c (display_debug_pubnames_worker): Work around compiler
bug checking address ranges.
(display_debug_frames): Likewise.
(display_gdb_index): Likewise.
(process_cu_tu_index): Add range check on the ncols value.
-rw-r--r-- | binutils/ChangeLog | 9 | ||||
-rw-r--r-- | binutils/dwarf.c | 44 |
2 files changed, 38 insertions, 15 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index a5b227e..3ffebb7 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,12 @@ +2015-02-11 Nick Clifton <nickc@redhat.com> + + PR binutils/17531 + * dwarf.c (display_debug_pubnames_worker): Work around compiler + bug checking address ranges. + (display_debug_frames): Likewise. + (display_gdb_index): Likewise. + (process_cu_tu_index): Add range check on the ncols value. + 2015-02-10 Nick Clifton <nickc@redhat.com> PR binutils/17512 diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 74a5e7a..1b0ab70 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -3725,6 +3725,7 @@ display_debug_pubnames_worker (struct dwarf_section *section, while (start < end) { unsigned char *data; + unsigned char *adr; dwarf_vma offset; unsigned int offset_size, initial_length_size; @@ -3754,17 +3755,18 @@ display_debug_pubnames_worker (struct dwarf_section *section, SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, end); + adr = 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) + || adr < start) { warn (_("Negative length for public name: 0x%lx\n"), (long) names.pn_length); start = end; } else - start += names.pn_length + initial_length_size; - + start = adr; + printf (_(" Length: %ld\n"), (long) names.pn_length); printf (_(" Version: %d\n"), @@ -6111,6 +6113,7 @@ display_debug_frames (struct dwarf_section *section, while (start < block_end) { + unsigned char * tmp; unsigned op, opa; unsigned long ul, reg, roffs; long l; @@ -6412,7 +6415,8 @@ display_debug_frames (struct dwarf_section *section, reg_prefix = bad_reg; /* PR 17512: file: 069-133014-0.006. */ /* PR 17512: file: 98c02eb4. */ - if (start >= block_end || start + ul > block_end || start + ul < start) + tmp = start + ul; + if (start >= block_end || tmp > block_end || tmp < start) { printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul); break; @@ -6427,7 +6431,7 @@ display_debug_frames (struct dwarf_section *section, } if (*reg_prefix == '\0') fc->col_type[reg] = DW_CFA_expression; - start += ul; + start = tmp; break; case DW_CFA_val_expression: @@ -6435,7 +6439,8 @@ display_debug_frames (struct dwarf_section *section, ul = LEB (); if (reg >= (unsigned int) fc->ncols) reg_prefix = bad_reg; - if (start >= block_end || start + ul > block_end || start + ul < start) + tmp = start + ul; + if (start >= block_end || tmp > block_end || tmp < start) { printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul); break; @@ -6450,7 +6455,7 @@ display_debug_frames (struct dwarf_section *section, } if (*reg_prefix == '\0') fc->col_type[reg] = DW_CFA_val_expression; - start += ul; + start = tmp; break; case DW_CFA_offset_extended_sf: @@ -6729,10 +6734,11 @@ display_gdb_index (struct dwarf_section *section, || cu_vector_offset != 0) { unsigned int j; + unsigned char * adr; + adr = constant_pool + name_offset; /* PR 17531: file: 5b7b07ad. */ - if (constant_pool + name_offset < constant_pool - || constant_pool + name_offset >= section->start + section->size) + if (adr < constant_pool || adr >= 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"), @@ -6743,8 +6749,8 @@ display_gdb_index (struct dwarf_section *section, (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) + adr = constant_pool + cu_vector_offset; + if (adr < constant_pool || adr >= 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"), @@ -6752,12 +6758,12 @@ display_gdb_index (struct dwarf_section *section, continue; } - num_cus = byte_get_little_endian (constant_pool + cu_vector_offset, 4); + num_cus = byte_get_little_endian (adr, 4); + adr = constant_pool + cu_vector_offset + 4 + num_cus * 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) + || adr >= section->start + section->size + || adr < constant_pool) { printf ("<invalid number of CUs: %d>\n", num_cus); warn (_("Invalid number of CUs (0x%x) for symbol table slot %d\n"), @@ -7011,6 +7017,14 @@ process_cu_tu_index (struct dwarf_section *section, int do_display) is_tu_index = strcmp (section->name, ".debug_tu_index") == 0; + /* PR 17531: file: 0dd159bf. + Check for wraparound with an overlarge ncols value. */ + if ((unsigned int) ((poffsets - ppool) / 4) != ncols) + { + warn (_("Overlarge number of columns: %x\n"), ncols); + return 0; + } + if (pend > limit) { warn (_("Section %s too small for offset and size tables\n"), |