GNU Binutils with patches for OS216
Revision | 362beea4b400bcd5aca3bb1215a77e9e749b07fe (tree) |
---|---|
Time | 2015-02-11 22:05:04 |
Author | Nick Clifton <nickc@redh...> |
Commiter | Nick Clifton |
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.
@@ -1,3 +1,12 @@ | ||
1 | +2015-02-11 Nick Clifton <nickc@redhat.com> | |
2 | + | |
3 | + PR binutils/17531 | |
4 | + * dwarf.c (display_debug_pubnames_worker): Work around compiler | |
5 | + bug checking address ranges. | |
6 | + (display_debug_frames): Likewise. | |
7 | + (display_gdb_index): Likewise. | |
8 | + (process_cu_tu_index): Add range check on the ncols value. | |
9 | + | |
1 | 10 | 2015-02-10 Nick Clifton <nickc@redhat.com> |
2 | 11 | |
3 | 12 | PR binutils/17512 |
@@ -3725,6 +3725,7 @@ display_debug_pubnames_worker (struct dwarf_section *section, | ||
3725 | 3725 | while (start < end) |
3726 | 3726 | { |
3727 | 3727 | unsigned char *data; |
3728 | + unsigned char *adr; | |
3728 | 3729 | dwarf_vma offset; |
3729 | 3730 | unsigned int offset_size, initial_length_size; |
3730 | 3731 |
@@ -3754,17 +3755,18 @@ display_debug_pubnames_worker (struct dwarf_section *section, | ||
3754 | 3755 | |
3755 | 3756 | SAFE_BYTE_GET_AND_INC (names.pn_size, data, offset_size, end); |
3756 | 3757 | |
3758 | + adr = start + names.pn_length + initial_length_size; | |
3757 | 3759 | /* PR 17531: file: 7615b6b2. */ |
3758 | 3760 | if ((dwarf_signed_vma) names.pn_length < 0 |
3759 | 3761 | /* PR 17531: file: a5dbeaa7. */ |
3760 | - || start + names.pn_length + initial_length_size < start) | |
3762 | + || adr < start) | |
3761 | 3763 | { |
3762 | 3764 | warn (_("Negative length for public name: 0x%lx\n"), (long) names.pn_length); |
3763 | 3765 | start = end; |
3764 | 3766 | } |
3765 | 3767 | else |
3766 | - start += names.pn_length + initial_length_size; | |
3767 | - | |
3768 | + start = adr; | |
3769 | + | |
3768 | 3770 | printf (_(" Length: %ld\n"), |
3769 | 3771 | (long) names.pn_length); |
3770 | 3772 | printf (_(" Version: %d\n"), |
@@ -6111,6 +6113,7 @@ display_debug_frames (struct dwarf_section *section, | ||
6111 | 6113 | |
6112 | 6114 | while (start < block_end) |
6113 | 6115 | { |
6116 | + unsigned char * tmp; | |
6114 | 6117 | unsigned op, opa; |
6115 | 6118 | unsigned long ul, reg, roffs; |
6116 | 6119 | long l; |
@@ -6412,7 +6415,8 @@ display_debug_frames (struct dwarf_section *section, | ||
6412 | 6415 | reg_prefix = bad_reg; |
6413 | 6416 | /* PR 17512: file: 069-133014-0.006. */ |
6414 | 6417 | /* PR 17512: file: 98c02eb4. */ |
6415 | - if (start >= block_end || start + ul > block_end || start + ul < start) | |
6418 | + tmp = start + ul; | |
6419 | + if (start >= block_end || tmp > block_end || tmp < start) | |
6416 | 6420 | { |
6417 | 6421 | printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul); |
6418 | 6422 | break; |
@@ -6427,7 +6431,7 @@ display_debug_frames (struct dwarf_section *section, | ||
6427 | 6431 | } |
6428 | 6432 | if (*reg_prefix == '\0') |
6429 | 6433 | fc->col_type[reg] = DW_CFA_expression; |
6430 | - start += ul; | |
6434 | + start = tmp; | |
6431 | 6435 | break; |
6432 | 6436 | |
6433 | 6437 | case DW_CFA_val_expression: |
@@ -6435,7 +6439,8 @@ display_debug_frames (struct dwarf_section *section, | ||
6435 | 6439 | ul = LEB (); |
6436 | 6440 | if (reg >= (unsigned int) fc->ncols) |
6437 | 6441 | reg_prefix = bad_reg; |
6438 | - if (start >= block_end || start + ul > block_end || start + ul < start) | |
6442 | + tmp = start + ul; | |
6443 | + if (start >= block_end || tmp > block_end || tmp < start) | |
6439 | 6444 | { |
6440 | 6445 | printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul); |
6441 | 6446 | break; |
@@ -6450,7 +6455,7 @@ display_debug_frames (struct dwarf_section *section, | ||
6450 | 6455 | } |
6451 | 6456 | if (*reg_prefix == '\0') |
6452 | 6457 | fc->col_type[reg] = DW_CFA_val_expression; |
6453 | - start += ul; | |
6458 | + start = tmp; | |
6454 | 6459 | break; |
6455 | 6460 | |
6456 | 6461 | case DW_CFA_offset_extended_sf: |
@@ -6729,10 +6734,11 @@ display_gdb_index (struct dwarf_section *section, | ||
6729 | 6734 | || cu_vector_offset != 0) |
6730 | 6735 | { |
6731 | 6736 | unsigned int j; |
6737 | + unsigned char * adr; | |
6732 | 6738 | |
6739 | + adr = constant_pool + name_offset; | |
6733 | 6740 | /* PR 17531: file: 5b7b07ad. */ |
6734 | - if (constant_pool + name_offset < constant_pool | |
6735 | - || constant_pool + name_offset >= section->start + section->size) | |
6741 | + if (adr < constant_pool || adr >= section->start + section->size) | |
6736 | 6742 | { |
6737 | 6743 | printf (_("[%3u] <corrupt offset: %x>"), i, name_offset); |
6738 | 6744 | 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, | ||
6743 | 6749 | (int) (section->size - (constant_pool_offset + name_offset)), |
6744 | 6750 | constant_pool + name_offset); |
6745 | 6751 | |
6746 | - if (constant_pool + cu_vector_offset < constant_pool | |
6747 | - || constant_pool + cu_vector_offset >= section->start + section->size - 3) | |
6752 | + adr = constant_pool + cu_vector_offset; | |
6753 | + if (adr < constant_pool || adr >= section->start + section->size - 3) | |
6748 | 6754 | { |
6749 | 6755 | printf (_("<invalid CU vector offset: %x>\n"), cu_vector_offset); |
6750 | 6756 | 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, | ||
6752 | 6758 | continue; |
6753 | 6759 | } |
6754 | 6760 | |
6755 | - num_cus = byte_get_little_endian (constant_pool + cu_vector_offset, 4); | |
6761 | + num_cus = byte_get_little_endian (adr, 4); | |
6756 | 6762 | |
6763 | + adr = constant_pool + cu_vector_offset + 4 + num_cus * 4; | |
6757 | 6764 | if (num_cus * 4 < num_cus |
6758 | - || constant_pool + cu_vector_offset + 4 + num_cus * 4 | |
6759 | - >= section->start + section->size | |
6760 | - || (constant_pool + cu_vector_offset + 4 + num_cus * 4) < constant_pool) | |
6765 | + || adr >= section->start + section->size | |
6766 | + || adr < constant_pool) | |
6761 | 6767 | { |
6762 | 6768 | printf ("<invalid number of CUs: %d>\n", num_cus); |
6763 | 6769 | 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) | ||
7011 | 7017 | |
7012 | 7018 | is_tu_index = strcmp (section->name, ".debug_tu_index") == 0; |
7013 | 7019 | |
7020 | + /* PR 17531: file: 0dd159bf. | |
7021 | + Check for wraparound with an overlarge ncols value. */ | |
7022 | + if ((unsigned int) ((poffsets - ppool) / 4) != ncols) | |
7023 | + { | |
7024 | + warn (_("Overlarge number of columns: %x\n"), ncols); | |
7025 | + return 0; | |
7026 | + } | |
7027 | + | |
7014 | 7028 | if (pend > limit) |
7015 | 7029 | { |
7016 | 7030 | warn (_("Section %s too small for offset and size tables\n"), |