From 0a9d414aa114b7b7e609cbcbc285f79031bbe608 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 21 Nov 2014 21:44:04 +0000 Subject: [PATCH 1/1] Fixes for memory access violations exposed by fuzzinf various binaries. PR binutils/17512 * dwarf.c (get_encoded_value): Check for an encoded size of 0. (display_debug_lines_raw): Check for an invalid line range value. (display_debug_frames): Check for corrupt augmentation data. * coffgen.c (coff_get_normalized_symtab): Check for an excessive number of auxillary entries. * ieee.c (next_byte): Convert to a function. Return FALSE if the next byte is beyond the end of the buffer. (parse_int): Test the return value of next_byte. (parse_expression): Convert to boolean. Return FALSE if the parsing failed. Test the return value of next_byte. (ieee_seek): Convert to a function. Return FALSE if the seek goes beyond the end of the buffer. (ieee_slurp_external_symbols): Test the return value of ieee_seek and next_byte. (ieee_slurp_sections): Convert to boolean. Return FALSE if the operation failed. Test the return value of ieee_seek and next_byte. (ieee_archive_p): Test the return value of ieee_seek and next_byte. (do_one): Likewise. (ieee_slurp_section_data): Likewise. (ieee_object_p): Likewise. Store the size of the buffer in the total_amt field in the header. * libieee.h (common_header_type): Add amt field. * mach-o.c (bfd_mach_o_canonicalize_one_reloc): Check that the reloc's value is within range. (bfd_mach_o_read_symtab_symbols): Nullify the symbols field if the operation fails. * pei-x86_64.c (pex64_xdata_print_uwd_codes): Replace abort with an error message. (pex64_dump_xdata): Check for buffer overflows. * versados.c (process_otr): Check that the section exists before taking its size. (versados_object_p): Make sure that enough data was read for the header to be checked. * vms-alpha.c (vms_get_remaining_object_record): Change read_so_far parameter to an unsigned int. Check that the amount read is in range. --- bfd/ChangeLog | 39 +++++++ bfd/coffgen.c | 17 ++- bfd/ieee.c | 261 ++++++++++++++++++++++++++++++--------------- bfd/libieee.h | 1 + bfd/mach-o.c | 22 ++-- bfd/pei-x86_64.c | 37 +++++-- bfd/versados.c | 21 +++- bfd/vms-alpha.c | 15 +-- binutils/ChangeLog | 7 ++ binutils/dwarf.c | 24 +++++ 10 files changed, 333 insertions(+), 111 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1f5ad55990..5700c51cbf 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,42 @@ +2014-11-21 Nick Clifton + + PR binutils/17512 + * coffgen.c (coff_get_normalized_symtab): Check for an excessive + number of auxillary entries. + * ieee.c (next_byte): Convert to a function. Return FALSE if the + next byte is beyond the end of the buffer. + (parse_int): Test the return value of next_byte. + (parse_expression): Convert to boolean. Return FALSE if the + parsing failed. Test the return value of next_byte. + (ieee_seek): Convert to a function. Return FALSE if the seek goes + beyond the end of the buffer. + (ieee_slurp_external_symbols): Test the return value of ieee_seek + and next_byte. + (ieee_slurp_sections): Convert to boolean. Return FALSE if the + operation failed. Test the return value of ieee_seek and + next_byte. + (ieee_archive_p): Test the return value of ieee_seek and + next_byte. + (do_one): Likewise. + (ieee_slurp_section_data): Likewise. + (ieee_object_p): Likewise. Store the size of the buffer in the + total_amt field in the header. + * libieee.h (common_header_type): Add amt field. + * mach-o.c (bfd_mach_o_canonicalize_one_reloc): Check that the + reloc's value is within range. + (bfd_mach_o_read_symtab_symbols): Nullify the symbols field if the + operation fails. + * pei-x86_64.c (pex64_xdata_print_uwd_codes): Replace abort with + an error message. + (pex64_dump_xdata): Check for buffer overflows. + * versados.c (process_otr): Check that the section exists before + taking its size. + (versados_object_p): Make sure that enough data was read for the + header to be checked. + * vms-alpha.c (vms_get_remaining_object_record): Change + read_so_far parameter to an unsigned int. Check that the amount + read is in range. + 2014-11-21 H.J. Lu * elf64-x86-64.c (elf_x86_64_finish_dynamic_symbol): Optimize diff --git a/bfd/coffgen.c b/bfd/coffgen.c index f19efc3aff..4f3f86219c 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -1808,6 +1808,16 @@ coff_get_normalized_symtab (bfd *abfd) symbol_ptr = internal_ptr; internal_ptr->is_sym = TRUE; + /* PR 17512: file: 1353-1166-0.004. */ + if (symbol_ptr->u.syment.n_sclass == C_FILE + && symbol_ptr->u.syment.n_numaux > 0 + && raw_src + symesz + symbol_ptr->u.syment.n_numaux + * sizeof (union internal_auxent) >= raw_end) + { + bfd_release (abfd, internal); + return NULL; + } + for (i = 0; i < symbol_ptr->u.syment.n_numaux; i++) @@ -1815,14 +1825,19 @@ coff_get_normalized_symtab (bfd *abfd) internal_ptr++; /* PR 17512: Prevent buffer overrun. */ if (internal_ptr >= internal_end) - return NULL; + { + bfd_release (abfd, internal); + return NULL; + } raw_src += symesz; + bfd_coff_swap_aux_in (abfd, (void *) raw_src, symbol_ptr->u.syment.n_type, symbol_ptr->u.syment.n_sclass, (int) i, symbol_ptr->u.syment.n_numaux, &(internal_ptr->u.auxent)); + internal_ptr->is_sym = FALSE; coff_pointerize_aux (abfd, internal, symbol_ptr, i, internal_ptr); diff --git a/bfd/ieee.c b/bfd/ieee.c index 313834e7f7..70ce4c5cc0 100644 --- a/bfd/ieee.c +++ b/bfd/ieee.c @@ -170,9 +170,16 @@ ieee_write_id (bfd *abfd, const char *id) standard requires. */ #define this_byte(ieee) *((ieee)->input_p) -#define next_byte(ieee) ((ieee)->input_p++) #define this_byte_and_next(ieee) (*((ieee)->input_p++)) +static bfd_boolean +next_byte (common_header_type * ieee) +{ + ieee->input_p++; + + return ieee->input_p < ieee->last_byte; +} + static unsigned short read_2bytes (common_header_type *ieee) { @@ -348,15 +355,15 @@ parse_int (common_header_type *ieee, bfd_vma *value_ptr) if (value >= 0 && value <= 127) { *value_ptr = value; - next_byte (ieee); - return TRUE; + return next_byte (ieee); } else if (value >= 0x80 && value <= 0x88) { unsigned int count = value & 0xf; result = 0; - next_byte (ieee); + if (! next_byte (ieee)) + return FALSE; while (count) { result = (result << 8) | this_byte_and_next (ieee); @@ -496,7 +503,7 @@ static reloc_howto_type rel8_howto = static ieee_symbol_index_type NOSYMBOL = {0, 0}; -static void +static bfd_boolean parse_expression (ieee_data_type *ieee, bfd_vma *value, ieee_symbol_index_type *symbol, @@ -529,68 +536,83 @@ parse_expression (ieee_data_type *ieee, { int section_n; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; *pcrel = TRUE; section_n = must_parse_int (&(ieee->h)); (void) section_n; PUSH (NOSYMBOL, bfd_abs_section_ptr, 0); break; } + case ieee_variable_L_enum: /* L variable address of section N. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0); break; + case ieee_variable_R_enum: /* R variable, logical address of section module. */ /* FIXME, this should be different to L. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0); break; + case ieee_variable_S_enum: /* S variable, size in MAUS of section module. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; PUSH (NOSYMBOL, 0, ieee->section_table[must_parse_int (&(ieee->h))]->size); break; + case ieee_variable_I_enum: /* Push the address of variable n. */ { ieee_symbol_index_type sy; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; sy.index = (int) must_parse_int (&(ieee->h)); sy.letter = 'I'; PUSH (sy, bfd_abs_section_ptr, 0); } break; + case ieee_variable_X_enum: /* Push the address of external variable n. */ { ieee_symbol_index_type sy; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; + sy.index = (int) (must_parse_int (&(ieee->h))); sy.letter = 'X'; PUSH (sy, bfd_und_section_ptr, 0); } break; + case ieee_function_minus_enum: { bfd_vma value1, value2; asection *section1, *section_dummy; ieee_symbol_index_type sy; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; POP (sy, section1, value1); POP (sy, section_dummy, value2); PUSH (sy, section1 ? section1 : section_dummy, value2 - value1); } break; + case ieee_function_plus_enum: { bfd_vma value1, value2; @@ -599,7 +621,8 @@ parse_expression (ieee_data_type *ieee, ieee_symbol_index_type sy1; ieee_symbol_index_type sy2; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; POP (sy1, section1, value1); POP (sy2, section2, value2); @@ -608,6 +631,7 @@ parse_expression (ieee_data_type *ieee, value1 + value2); } break; + default: { bfd_vma va; @@ -644,17 +668,9 @@ parse_expression (ieee_data_type *ieee, POP (*symbol, dummy, *value); if (section) *section = dummy; -} - -#define ieee_seek(ieee, offset) \ - do \ - { \ - ieee->h.input_p = ieee->h.first_byte + offset; \ - ieee->h.last_byte = (ieee->h.first_byte \ - + ieee_part_after (ieee, offset)); \ - } \ - while (0) + return TRUE; +} #define ieee_pos(ieee) \ (ieee->h.input_p - ieee->h.first_byte) @@ -676,6 +692,22 @@ ieee_part_after (ieee_data_type *ieee, file_ptr here) return after; } +static bfd_boolean +ieee_seek (ieee_data_type * ieee, file_ptr offset) +{ + /* PR 17512: file: 017-1157-0.004. */ + if (offset < 0 || (bfd_size_type) offset >= ieee->h.total_amt) + { + ieee->h.input_p = ieee->h.first_byte + ieee->h.total_amt; + ieee->h.last_byte = ieee->h.input_p; + return FALSE; + } + + ieee->h.input_p = ieee->h.first_byte + offset; + ieee->h.last_byte = (ieee->h.first_byte + ieee_part_after (ieee, offset)); + return TRUE; +} + static unsigned int last_index; static char last_type; /* Is the index for an X or a D. */ @@ -730,14 +762,16 @@ ieee_slurp_external_symbols (bfd *abfd) last_index = 0xffffff; ieee->symbol_table_full = TRUE; - ieee_seek (ieee, offset); + if (! ieee_seek (ieee, offset)) + return FALSE; while (loop) { switch (this_byte (&(ieee->h))) { case ieee_nn_record: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; symbol = get_symbol (abfd, ieee, symbol, &symbol_count, & prev_symbols_ptr, @@ -750,8 +784,10 @@ ieee_slurp_external_symbols (bfd *abfd) symbol->symbol.udata.p = NULL; symbol->symbol.flags = BSF_NO_FLAGS; break; + case ieee_external_symbol_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; symbol = get_symbol (abfd, ieee, symbol, &symbol_count, &prev_symbols_ptr, @@ -842,6 +878,7 @@ ieee_slurp_external_symbols (bfd *abfd) } } break; + case ieee_value_record_enum >> 8: { unsigned int symbol_name_index; @@ -849,17 +886,20 @@ ieee_slurp_external_symbols (bfd *abfd) bfd_boolean pcrel_ignore; unsigned int extra; - next_byte (&(ieee->h)); - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; + if (! next_byte (&(ieee->h))) + return FALSE; symbol_name_index = must_parse_int (&(ieee->h)); (void) symbol_name_index; - parse_expression (ieee, - &symbol->symbol.value, - &symbol_ignore, - &pcrel_ignore, - &extra, - &symbol->symbol.section); + if (! parse_expression (ieee, + &symbol->symbol.value, + &symbol_ignore, + &pcrel_ignore, + &extra, + &symbol->symbol.section)) + return FALSE; /* Fully linked IEEE-695 files tend to give every symbol an absolute value. Try to convert that back into a @@ -892,7 +932,9 @@ ieee_slurp_external_symbols (bfd *abfd) bfd_vma size; bfd_vma value; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; + /* Throw away the external reference index. */ (void) must_parse_int (&(ieee->h)); /* Fetch the default size if not resolved. */ @@ -907,7 +949,8 @@ ieee_slurp_external_symbols (bfd *abfd) break; case ieee_external_reference_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; symbol = get_symbol (abfd, ieee, symbol, &symbol_count, &prev_reference_ptr, @@ -1092,7 +1135,7 @@ get_section_entry (bfd *abfd, ieee_data_type *ieee, unsigned int sindex) return ieee->section_table[sindex]; } -static void +static bfd_boolean ieee_slurp_sections (bfd *abfd) { ieee_data_type *ieee = IEEE_DATA (abfd); @@ -1103,7 +1146,9 @@ ieee_slurp_sections (bfd *abfd) { bfd_byte section_type[3]; - ieee_seek (ieee, offset); + if (! ieee_seek (ieee, offset)) + return FALSE; + while (TRUE) { switch (this_byte (&(ieee->h))) @@ -1113,7 +1158,8 @@ ieee_slurp_sections (bfd *abfd) asection *section; unsigned int section_index; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section_index = must_parse_int (&(ieee->h)); section = get_section_entry (abfd, ieee, section_index); @@ -1132,22 +1178,26 @@ ieee_slurp_sections (bfd *abfd) { /* AS Absolute section attributes. */ case 0xD3: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section_type[2] = this_byte (&(ieee->h)); switch (section_type[2]) { case 0xD0: /* Normal code. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_CODE; break; case 0xC4: /* Normal data. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_DATA; break; case 0xD2: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; /* Normal rom data. */ section->flags |= SEC_ROM | SEC_DATA; break; @@ -1164,15 +1214,18 @@ ieee_slurp_sections (bfd *abfd) switch (section_type[1]) { case 0xD0: /* Normal code (CP). */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_CODE; break; case 0xC4: /* Normal data (CD). */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_DATA; break; case 0xD2: /* Normal rom data (CR). */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_ROM | SEC_DATA; break; default: @@ -1201,7 +1254,8 @@ ieee_slurp_sections (bfd *abfd) bfd_vma value; asection *section; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section_index = must_parse_int (&ieee->h); section = get_section_entry (abfd, ieee, section_index); if (section_index > ieee->section_count) @@ -1251,15 +1305,17 @@ ieee_slurp_sections (bfd *abfd) (void) must_parse_int (&(ieee->h)); break; default: - return; + return TRUE; } } break; default: - return; + return TRUE; } } } + + return TRUE; } /* Make a section for the debugging information, if any. We don't try @@ -1323,7 +1379,8 @@ ieee_archive_p (bfd *abfd) if (this_byte (&(ieee->h)) != Module_Beginning) goto got_wrong_format_error; - next_byte (&(ieee->h)); + (void) next_byte (&(ieee->h)); + library = read_id (&(ieee->h)); if (strcmp (library, "LIBRARY") != 0) goto got_wrong_format_error; @@ -1334,7 +1391,7 @@ ieee_archive_p (bfd *abfd) ieee->element_count = 0; ieee->element_index = 0; - next_byte (&(ieee->h)); /* Drop the ad part. */ + (void) next_byte (&(ieee->h)); /* Drop the ad part. */ must_parse_int (&(ieee->h)); /* And the two dummy numbers. */ must_parse_int (&(ieee->h)); @@ -1407,8 +1464,9 @@ ieee_archive_p (bfd *abfd) ieee->h.first_byte = buffer; ieee->h.input_p = buffer; - next_byte (&(ieee->h)); /* Drop F8. */ - next_byte (&(ieee->h)); /* Drop 14. */ + (void) next_byte (&(ieee->h)); /* Drop F8. */ + if (! next_byte (&(ieee->h))) /* Drop 14. */ + goto error_return; must_parse_int (&(ieee->h)); /* Drop size of block. */ if (must_parse_int (&(ieee->h)) != 0) @@ -1467,7 +1525,8 @@ do_one (ieee_data_type *ieee, unsigned int number_of_maus; unsigned int i; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; number_of_maus = must_parse_int (&(ieee->h)); for (i = 0; i < number_of_maus; i++) @@ -1482,7 +1541,8 @@ do_one (ieee_data_type *ieee, { bfd_boolean loop = TRUE; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; while (loop) { switch (this_byte (&(ieee->h))) @@ -1505,13 +1565,16 @@ do_one (ieee_data_type *ieee, *(current_map->reloc_tail_ptr) = r; current_map->reloc_tail_ptr = &r->next; r->next = (ieee_reloc_type *) NULL; - next_byte (&(ieee->h)); -/* abort();*/ + if (! next_byte (&(ieee->h))) + return FALSE; + r->relent.sym_ptr_ptr = 0; - parse_expression (ieee, - &r->relent.addend, - &r->symbol, - &pcrel, &extra, §ion); + if (! parse_expression (ieee, + &r->relent.addend, + &r->symbol, + &pcrel, &extra, §ion)) + return FALSE; + r->relent.address = current_map->pc; s->flags |= SEC_RELOC; s->owner->flags |= HAS_RELOC; @@ -1521,7 +1584,8 @@ do_one (ieee_data_type *ieee, if (this_byte (&(ieee->h)) == (int) ieee_comma) { - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; /* Fetch number of bytes to pad. */ extra = must_parse_int (&(ieee->h)); }; @@ -1529,13 +1593,16 @@ do_one (ieee_data_type *ieee, switch (this_byte (&(ieee->h))) { case ieee_function_signed_close_b_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; break; case ieee_function_unsigned_close_b_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; break; case ieee_function_either_close_b_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; break; default: break; @@ -1634,7 +1701,8 @@ do_one (ieee_data_type *ieee, for (i = 0; i < this_size; i++) { location_ptr[current_map->pc++] = this_byte (&(ieee->h)); - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; } } else @@ -1667,7 +1735,9 @@ ieee_slurp_section_data (bfd *abfd) if (ieee->read_data) return TRUE; ieee->read_data = TRUE; - ieee_seek (ieee, ieee->w.r.data_part); + + if (! ieee_seek (ieee, ieee->w.r.data_part)) + return FALSE; /* Allocate enough space for all the section contents. */ for (s = abfd->sections; s != (asection *) NULL; s = s->next) @@ -1693,7 +1763,8 @@ ieee_slurp_section_data (bfd *abfd) return TRUE; case ieee_set_current_section_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section_number = must_parse_int (&(ieee->h)); s = ieee->section_table[section_number]; s->flags |= SEC_LOAD | SEC_HAS_CONTENTS; @@ -1706,7 +1777,8 @@ ieee_slurp_section_data (bfd *abfd) break; case ieee_e2_first_byte_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; switch (this_byte (&(ieee->h))) { case ieee_set_current_pc_enum & 0xff: @@ -1716,21 +1788,28 @@ ieee_slurp_section_data (bfd *abfd) unsigned int extra; bfd_boolean pcrel; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; must_parse_int (&(ieee->h)); /* Throw away section #. */ - parse_expression (ieee, &value, - &symbol, - &pcrel, &extra, - 0); + if (! parse_expression (ieee, &value, + &symbol, + &pcrel, &extra, + 0)) + return FALSE; + current_map->pc = value; BFD_ASSERT ((unsigned) (value - s->vma) <= s->size); } break; case ieee_value_starting_address_enum & 0xff: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; if (this_byte (&(ieee->h)) == ieee_function_either_open_b_enum) - next_byte (&(ieee->h)); + { + if (! next_byte (&(ieee->h))) + return FALSE; + } abfd->start_address = must_parse_int (&(ieee->h)); /* We've got to the end of the data now - */ return TRUE; @@ -1748,7 +1827,8 @@ ieee_slurp_section_data (bfd *abfd) unsigned int iterations; unsigned char *start; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; iterations = must_parse_int (&(ieee->h)); start = ieee->h.input_p; if (start[0] == (int) ieee_load_constant_bytes_enum @@ -1759,9 +1839,10 @@ ieee_slurp_section_data (bfd *abfd) location_ptr[current_map->pc++] = start[2]; iterations--; } - next_byte (&(ieee->h)); - next_byte (&(ieee->h)); - next_byte (&(ieee->h)); + (void) next_byte (&(ieee->h)); + (void) next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; } else { @@ -1806,6 +1887,7 @@ ieee_object_p (bfd *abfd) goto got_wrong_format; ieee->h.input_p = buffer; + ieee->h.total_amt = sizeof (buffer); if (this_byte_and_next (&(ieee->h)) != Module_Beginning) goto got_wrong_format; @@ -1901,7 +1983,8 @@ ieee_object_p (bfd *abfd) if (this_byte (&(ieee->h)) != (int) ieee_address_descriptor_enum) goto fail; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + goto fail; if (! parse_int (&(ieee->h), &ieee->ad.number_of_bits_mau)) goto fail; @@ -1912,7 +1995,10 @@ ieee_object_p (bfd *abfd) /* If there is a byte order info, take it. */ if (this_byte (&(ieee->h)) == (int) ieee_variable_L_enum || this_byte (&(ieee->h)) == (int) ieee_variable_M_enum) - next_byte (&(ieee->h)); + { + if (! next_byte (&(ieee->h))) + goto fail; + } for (part = 0; part < N_W_VARIABLES; part++) { @@ -1943,12 +2029,17 @@ ieee_object_p (bfd *abfd) goto fail; if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) goto fail; + /* FIXME: Check return value. I'm not sure whether it needs to read the entire buffer or not. */ - bfd_bread ((void *) (IEEE_DATA (abfd)->h.first_byte), - (bfd_size_type) ieee->w.r.me_record + 1, abfd); + amt = bfd_bread ((void *) (IEEE_DATA (abfd)->h.first_byte), + (bfd_size_type) ieee->w.r.me_record + 1, abfd); + if (amt <= 0) + goto fail; - ieee_slurp_sections (abfd); + IEEE_DATA (abfd)->h.total_amt = amt; + if (ieee_slurp_sections (abfd)) + goto fail; if (! ieee_slurp_debug (abfd)) goto fail; diff --git a/bfd/libieee.h b/bfd/libieee.h index 7026b85f8d..27fd467dd7 100644 --- a/bfd/libieee.h +++ b/bfd/libieee.h @@ -66,6 +66,7 @@ typedef struct { unsigned char *input_p; unsigned char *first_byte; unsigned char *last_byte; + bfd_size_type total_amt; bfd *abfd; } common_header_type ; diff --git a/bfd/mach-o.c b/bfd/mach-o.c index 39526898d5..c13fff3353 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -1363,9 +1363,11 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd, } else { + /* PR 17512: file: 006-2964-0.004. */ + if (num >= mdata->nsects) + return -1; + /* A section number. */ - BFD_ASSERT (num <= mdata->nsects); - sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr; /* For a symbol defined in section S, the addend (stored in the binary) contains the address of the section. To comply with @@ -3660,10 +3662,8 @@ bfd_mach_o_read_symtab_symbols (bfd *abfd) unsigned long i; if (sym == NULL || sym->symbols) - { - /* Return now if there are no symbols or if already loaded. */ - return TRUE; - } + /* Return now if there are no symbols or if already loaded. */ + return TRUE; sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (bfd_mach_o_asymbol)); @@ -3674,12 +3674,18 @@ bfd_mach_o_read_symtab_symbols (bfd *abfd) } if (!bfd_mach_o_read_symtab_strtab (abfd)) - return FALSE; + { + sym->symbols = NULL; + return FALSE; + } for (i = 0; i < sym->nsyms; i++) { if (!bfd_mach_o_read_symtab_symbol (abfd, sym, &sym->symbols[i], i)) - return FALSE; + { + sym->symbols = NULL; + return FALSE; + } } return TRUE; diff --git a/bfd/pei-x86_64.c b/bfd/pei-x86_64.c index 11ee73a2de..ccb5774f3a 100644 --- a/bfd/pei-x86_64.c +++ b/bfd/pei-x86_64.c @@ -276,8 +276,9 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd, fprintf (file, ", unknown(%u))", info); break; default: - /* Already caught by the previous scan. */ - abort (); + /* PR 17512: file: 2245-7442-0.004. */ + fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1])); + break; } if (unexpected) fprintf (file, " [Unexpected!]"); @@ -317,20 +318,34 @@ pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma vaddr; bfd_vma end_addr; bfd_vma addr = rf->rva_UnwindData; + bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size; struct pex64_unwind_info ui; vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase; addr -= vaddr; + /* PR 17512: file: 2245-7442-0.004. */ + if (addr >= sec_size) + { + fprintf (file, _("warning: xdata section corrupt\n")); + return; + } + if (endx) - end_addr = endx[0] - vaddr; + { + end_addr = endx[0] - vaddr; + /* PR 17512: file: 2245-7442-0.004. */ + if (end_addr > sec_size) + { + fprintf (file, _("warning: xdata section corrupt")); + end_addr = sec_size; + } + } else - end_addr = (xdata_section->rawsize != 0 ? - xdata_section->rawsize : xdata_section->size); - + end_addr = sec_size; pex64_get_unwind_info (abfd, &ui, &xdata[addr]); - + if (ui.Version != 1 && ui.Version != 2) { unsigned int i; @@ -380,7 +395,11 @@ pex64_dump_xdata (FILE *file, bfd *abfd, ui.FrameRegister == 0 ? "none" : pex_regs[(unsigned int) ui.FrameRegister]); - pex64_xdata_print_uwd_codes (file, abfd, &ui, rf); + /* PR 17512: file: 2245-7442-0.004. */ + if (ui.CountOfCodes * 2 + ui.rawUnwindCodes + addr >= xdata + xdata_section->size) + fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes); + else + pex64_xdata_print_uwd_codes (file, abfd, &ui, rf); switch (ui.Flags) { @@ -573,6 +592,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) if (i + PDATA_ROW_SIZE > stop) break; + pex64_get_runtime_function (abfd, &rf, &pdata[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 @@ -642,6 +662,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) identical pointers in the array; advance past all of them. */ while (p[0] <= rf.rva_UnwindData) ++p; + if (p[0] == ~((bfd_vma) 0)) p = NULL; diff --git a/bfd/versados.c b/bfd/versados.c index 42bf36c9cd..5bafcb1d7c 100644 --- a/bfd/versados.c +++ b/bfd/versados.c @@ -430,7 +430,8 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass) else { need_contents = 1; - if (dst_idx < esdid->section->size) + + if (esdid->section && dst_idx < esdid->section->size) if (pass == 2) { /* Absolute code, comes in 16 bit lumps. */ @@ -445,8 +446,15 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass) if (!contents && need_contents) { - bfd_size_type size = esdid->section->size; - esdid->contents = bfd_alloc (abfd, size); + if (esdid->section) + { + bfd_size_type size; + + size = esdid->section->size; + esdid->contents = bfd_alloc (abfd, size); + } + else + esdid->contents = NULL; } } @@ -585,6 +593,13 @@ versados_object_p (bfd *abfd) return NULL; } + /* PR 17512: file: 726-2128-0.004. */ + if (len < 13) + { + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + if (bfd_bread (&ext.type, (bfd_size_type) len, abfd) != len) { if (bfd_get_error () != bfd_error_system_call) diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c index 5ff5bfd4ea..3789f794de 100644 --- a/bfd/vms-alpha.c +++ b/bfd/vms-alpha.c @@ -364,9 +364,9 @@ struct vms_section_data_struct ((struct vms_section_data_struct *)sec->used_by_bfd) /* To be called from the debugger. */ -struct vms_private_data_struct *bfd_vms_get_data (bfd *abfd); +struct vms_private_data_struct *bfd_vms_get_data (bfd *); -static int vms_get_remaining_object_record (bfd *abfd, int read_so_far); +static int vms_get_remaining_object_record (bfd *, unsigned int); static bfd_boolean _bfd_vms_slurp_object_records (bfd * abfd); static void alpha_vms_add_fixup_lp (struct bfd_link_info *, bfd *, bfd *); static void alpha_vms_add_fixup_ca (struct bfd_link_info *, bfd *, bfd *); @@ -374,8 +374,8 @@ static void alpha_vms_add_fixup_qr (struct bfd_link_info *, bfd *, bfd *, bfd_vma); static void alpha_vms_add_fixup_lr (struct bfd_link_info *, unsigned int, bfd_vma); -static void alpha_vms_add_lw_reloc (struct bfd_link_info *info); -static void alpha_vms_add_qw_reloc (struct bfd_link_info *info); +static void alpha_vms_add_lw_reloc (struct bfd_link_info *); +static void alpha_vms_add_qw_reloc (struct bfd_link_info *); struct vector_type { @@ -788,7 +788,7 @@ _bfd_vms_get_object_record (bfd *abfd) Return the size of the record or 0 on failure. */ static int -vms_get_remaining_object_record (bfd *abfd, int read_so_far) +vms_get_remaining_object_record (bfd *abfd, unsigned int read_so_far) { unsigned int to_read; @@ -824,7 +824,10 @@ vms_get_remaining_object_record (bfd *abfd, int read_so_far) return 0; PRIV (recrd.buf_size) = to_read; } - + /* PR 17512: file: 025-1974-0.004. */ + else if (to_read <= read_so_far) + return 0; + /* Read the remaining record. */ to_read -= read_so_far; diff --git a/binutils/ChangeLog b/binutils/ChangeLog index cc4590af37..dbf07f9ca6 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2014-11-21 Nick Clifton + + PR binutils/17512 + * dwarf.c (get_encoded_value): Check for an encoded size of 0. + (display_debug_lines_raw): Check for an invalid line range value. + (display_debug_frames): Check for corrupt augmentation data. + 2014-11-21 Nick Clifton PR binutils/17531 diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 7f3a568e81..8213f4dc9e 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -142,6 +142,14 @@ get_encoded_value (unsigned char **pdata, return 0; } + /* PR 17512: file: 1085-5603-0.004. */ + if (size == 0) + { + warn (_("Encoded size of 0 is too small to read\n")); + * pdata = end; + return 0; + } + if (encoding & DW_EH_PE_signed) val = byte_get_signed (data, size); else @@ -2786,6 +2794,13 @@ display_debug_lines_raw (struct dwarf_section *section, printf (_(" Line Range: %d\n"), linfo.li_line_range); printf (_(" Opcode Base: %d\n"), linfo.li_opcode_base); + /* PR 17512: file: 1665-6428-0.004. */ + 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); /* Display the contents of the Opcodes table. */ @@ -5697,6 +5712,15 @@ display_debug_frames (struct dwarf_section *section, augmentation_data_len = LEB (); augmentation_data = start; start += augmentation_data_len; + /* PR 17512: file: 722-8446-0.004. */ + if (start >= end) + { + warn (_("Corrupt augmentation data length: %lx\n"), + augmentation_data_len); + start = end; + augmentation_data = NULL; + augmentation_data_len = 0; + } } printf ("\n%08lx %s %s FDE cie=%08lx pc=", -- 2.34.1