From: Nick Clifton Date: Tue, 24 Mar 2015 12:25:25 +0000 (+0000) Subject: Import fixes from trunk sources to correct invalid memory access issues with various... X-Git-Tag: binutils-2_25_1~165 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4f9583e9c45482e111d30f94df650a3f2cf36b99;p=thirdparty%2Fbinutils-gdb.git Import fixes from trunk sources to correct invalid memory access issues with various binutils programs. Apply from master: 2015-02-26 Nick Clifton PR binutils/17512 * coffgrok.c (do_type): Check for an out of range tag index. Check for integer overflow computing array dimension. (do_define): Likewise. 2015-02-26 Nick Clifton PR binutils/17512 * resrc.c (write_rc_messagetable): Tighten check for invalid message lengths. 2015-02-13 Nick Clifton * coffgrok.c (do_define): Add check for type size overflow. * srconv.c (walk_tree_sfile): Check that enough sections are available before parsing. (prescan): Likewise. 2015-02-03 Nick Clifton PR binutils/17512 * objdump.c (display_any_bfd): Fail if archives nest too deeply. 2015-01-27 Nick Clifton PR binutils/17512 * dlltool.c (identify_search_archive): If the last archive was the same as the current archive, terminate the loop. * addr2line.c (slurp_symtab): If the symcount is zero, free the symbol table pointer. * rcparse.y: Add checks to avoid integer divide by zero. * rescoff.c (read_coff_rsrc): Add check on the size of the resource section. (read_coff_res_dir): Add check on the nesting level. Check for resource names overrunning the buffer. * resrc.c (write_rc_messagetable): Update formatting. Add check of 'elen' being zero. 2015-01-23 Nick Clifton * nlmconv.c (powerpc_mangle_relocs): Fix build errors introduced by recent delta, when compiling on for a 32-bit host. 2015-01-21 Nick Clifton PR binutils/17512 * addr2line.c (main): Call bfd_set_error_program_name. * ar.c (main): Likewise. * coffdump.c (main): Likewise. * cxxfilt.c (main): Likewise. * dlltool.c (main): Likewise. * nlmconv.c (main): Likewise. * nm.c (main): Likewise. * objdump.c (main): Likewise. * size.c (main): Likewise. * srconv.c (main): Likewise. * strings.c (main): Likewise. * sysdump.c (main): Likewise. * windmc.c (main): Likewise. * windres.c (main): Likewise. * objcopy.c (main): Likewise. (copy_relocations_in_section): Check for relocs without associated symbol pointers. 2015-01-21 Nick Clifton PR binutils/17512 * coffgrok.c (do_type): Check that computed ref exists. (doit): Add range checks when computing section for scope. 2015-01-08 Nick Clifton PR binutils/17512 * ojcopy.c (copy_object): Free the symbol table if no symbols could be loaded. (copy_file): Use bfd_close_all_done to close files that could not be copied. * sysdump.c (getINT): Fail if reading off the end of the buffer. Replace call to abort with a call to fatal. (getCHARS): Prevetn reading off the end of the buffer. * nlmconv.c (i386_mangle_relocs): Skip relocs without an associated symbol. (powerpc_mangle_relocs): Skip unrecognised relocs. Check address range before applying a reloc. 2015-01-07 Nick Clifton PR binutils/17512 * dlltool.c (scan_obj_file): Break loop if the last archive displayed matches the current archive. * objdump.c (display_any_bfd): Add a depth limit to nested archive display in order to avoid infinite loops. * srconv.c: Replace calls to abort with calls to fatal with an error message. 2015-01-06 Nick Clifton PR binutils/17512 * coffdump.c (dump_coff_section): Check for a symbol being available before printing its name. (main): Check the return value from coff_grok. * coffgrok.c: Reformat and tidy. Add range checks to most functions. (coff_grok): Return NULL if the input bfd is not in a COFF format. * coffgrok.h: Reformat and tidy. (struct coff_section): Change the nrelocs field to unsigned. * srconv.c (main): Check the return value from coff_grok. 2015-01-05 Nick Clifton PR binutils/17512 * nm.c (print_symbol): Add 'is_synthetic' parameter. Use it to help initialize the info.elfinfo field. (print_size_symbols): Add 'synth_count' parameter. Use it to set the is_synthetic parameter when calling print_symbol. (print_symbols): Likewise. (display_rel_file): Pass synth_count to printing function. (display_archive): Break loop if the last archive displayed matches the current archive. --- diff --git a/binutils/ChangeLog b/binutils/ChangeLog index a4bb426f464..9f3d3b13e2f 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,135 @@ +2015-03-24 Nick Clifton + + Apply from master: + 2015-02-26 Nick Clifton + + PR binutils/17512 + * coffgrok.c (do_type): Check for an out of range tag index. + Check for integer overflow computing array dimension. + (do_define): Likewise. + + 2015-02-26 Nick Clifton + + PR binutils/17512 + * resrc.c (write_rc_messagetable): Tighten check for invalid + message lengths. + + 2015-02-13 Nick Clifton + + * coffgrok.c (do_define): Add check for type size overflow. + * srconv.c (walk_tree_sfile): Check that enough sections are + available before parsing. + (prescan): Likewise. + + 2015-02-03 Nick Clifton + + PR binutils/17512 + * objdump.c (display_any_bfd): Fail if archives nest too deeply. + + 2015-01-27 Nick Clifton + + PR binutils/17512 + * dlltool.c (identify_search_archive): If the last archive was the + same as the current archive, terminate the loop. + + * addr2line.c (slurp_symtab): If the symcount is zero, free the + symbol table pointer. + + * rcparse.y: Add checks to avoid integer divide by zero. + * rescoff.c (read_coff_rsrc): Add check on the size of the + resource section. + (read_coff_res_dir): Add check on the nesting level. + Check for resource names overrunning the buffer. + * resrc.c (write_rc_messagetable): Update formatting. + Add check of 'elen' being zero. + + 2015-01-23 Nick Clifton + + * nlmconv.c (powerpc_mangle_relocs): Fix build errors introduced + by recent delta, when compiling on for a 32-bit host. + + 2015-01-21 Nick Clifton + + PR binutils/17512 + * addr2line.c (main): Call bfd_set_error_program_name. + * ar.c (main): Likewise. + * coffdump.c (main): Likewise. + * cxxfilt.c (main): Likewise. + * dlltool.c (main): Likewise. + * nlmconv.c (main): Likewise. + * nm.c (main): Likewise. + * objdump.c (main): Likewise. + * size.c (main): Likewise. + * srconv.c (main): Likewise. + * strings.c (main): Likewise. + * sysdump.c (main): Likewise. + * windmc.c (main): Likewise. + * windres.c (main): Likewise. + * objcopy.c (main): Likewise. + (copy_relocations_in_section): Check for relocs without associated + symbol pointers. + + 2015-01-21 Nick Clifton + + PR binutils/17512 + * coffgrok.c (do_type): Check that computed ref exists. + (doit): Add range checks when computing section for scope. + + 2015-01-08 Nick Clifton + + PR binutils/17512 + * ojcopy.c (copy_object): Free the symbol table if no symbols + could be loaded. + (copy_file): Use bfd_close_all_done to close files that could not + be copied. + + * sysdump.c (getINT): Fail if reading off the end of the buffer. + Replace call to abort with a call to fatal. + (getCHARS): Prevetn reading off the end of the buffer. + + * nlmconv.c (i386_mangle_relocs): Skip relocs without an + associated symbol. + (powerpc_mangle_relocs): Skip unrecognised relocs. Check address + range before applying a reloc. + + 2015-01-07 Nick Clifton + + PR binutils/17512 + * dlltool.c (scan_obj_file): Break loop if the last archive + displayed matches the current archive. + + * objdump.c (display_any_bfd): Add a depth limit to nested archive + display in order to avoid infinite loops. + * srconv.c: Replace calls to abort with calls to fatal with an + error message. + + 2015-01-06 Nick Clifton + + PR binutils/17512 + * coffdump.c (dump_coff_section): Check for a symbol being + available before printing its name. + (main): Check the return value from coff_grok. + * coffgrok.c: Reformat and tidy. + Add range checks to most functions. + (coff_grok): Return NULL if the input bfd is not in a COFF + format. + * coffgrok.h: Reformat and tidy. + (struct coff_section): Change the nrelocs field to unsigned. + * srconv.c (main): Check the return value from coff_grok. + + 2015-01-05 Nick Clifton + + PR binutils/17512 + * nm.c (print_symbol): Add 'is_synthetic' parameter. Use it to + help initialize the info.elfinfo field. + (print_size_symbols): Add 'synth_count' parameter. Use it to set + the is_synthetic parameter when calling print_symbol. + (print_symbols): Likewise. + (display_rel_file): Pass synth_count to printing function. + (display_archive): Break loop if the last archive displayed + matches the current archive. + * size.c (display_archive): Likewise. + 2015-03-24 Nick Clifton Apply from master: diff --git a/binutils/addr2line.c b/binutils/addr2line.c index f88e7458cdb..7cabb8bdbb5 100644 --- a/binutils/addr2line.c +++ b/binutils/addr2line.c @@ -140,6 +140,14 @@ slurp_symtab (bfd *abfd) syms = xmalloc (storage); symcount = bfd_canonicalize_dynamic_symtab (abfd, syms); } + + /* PR 17512: file: 2a1d3b5b. + Do not pretend that we have some symbols when we don't. */ + if (symcount <= 0) + { + free (syms); + syms = NULL; + } } /* These global variables are used to pass information between @@ -423,6 +431,7 @@ main (int argc, char **argv) program_name = *argv; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&argc, &argv); diff --git a/binutils/ar.c b/binutils/ar.c index 117826d18e8..7c3c86974ae 100644 --- a/binutils/ar.c +++ b/binutils/ar.c @@ -691,6 +691,7 @@ main (int argc, char **argv) program_name = argv[0]; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); #if BFD_SUPPORTS_PLUGINS bfd_plugin_set_program_name (program_name); #endif diff --git a/binutils/coffdump.c b/binutils/coffdump.c index b4c84155f19..bf629155417 100644 --- a/binutils/coffdump.c +++ b/binutils/coffdump.c @@ -417,21 +417,23 @@ dump_coff_sfile (struct coff_sfile *p) static void dump_coff_section (struct coff_section *ptr) { - int i; + unsigned int i; tab (1); - printf (_("section %s %d %d address %x size %x number %d nrelocs %d"), + printf (_("section %s %d %d address %x size %x number %d nrelocs %u"), ptr->name, ptr->code, ptr->data, ptr->address,ptr->size, ptr->number, ptr->nrelocs); nl (); for (i = 0; i < ptr->nrelocs; i++) { + struct coff_reloc * r = ptr->relocs + i; tab (0); printf ("(%x %s %x)", - ptr->relocs[i].offset, - ptr->relocs[i].symbol->name, - ptr->relocs[i].addend); + r->offset, + /* PR 17512: file: 0a38fb7c. */ + r->symbol == NULL ? _("") : r->symbol->name, + r->addend); nl (); } @@ -498,6 +500,7 @@ main (int ac, char **av) program_name = av[0]; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&ac, &av); @@ -549,9 +552,11 @@ main (int ac, char **av) } tree = coff_grok (abfd); - - coff_dump (tree); - printf ("\n"); + if (tree) + { + coff_dump (tree); + printf ("\n"); + } return 0; } diff --git a/binutils/coffgrok.c b/binutils/coffgrok.c index f37f266340e..e2d520e3c14 100644 --- a/binutils/coffgrok.c +++ b/binutils/coffgrok.c @@ -122,6 +122,9 @@ push_scope (int slink) static void pop_scope (void) { + /* PR 17512: file: 809933ac. */ + if (top_scope == NULL) + fatal (_("Out of context scope change encountered")); top_scope = top_scope->parent; } @@ -138,10 +141,14 @@ do_sections_p1 (struct coff_ofile *head) for (idx = 0, section = abfd->sections; section; section = section->next, idx++) { long relsize; - int i = section->target_index; + unsigned int i = section->target_index; arelent **relpp; long relcount; + /* PR 17512: file: 2d6effca. */ + if (i > abfd->section_count) + fatal (_("Invalid section target index: %u"), i); + relsize = bfd_get_reloc_upper_bound (abfd, section); if (relsize < 0) bfd_fatal (bfd_get_filename (abfd)); @@ -182,26 +189,51 @@ do_sections_p2 (struct coff_ofile *head) { unsigned int j; + /* PR 17512: file: 7c1a36e8. + A corrupt COFF binary might have a reloc count but no relocs. + Handle this here. */ + if (section->relocation == NULL) + continue; + for (j = 0; j < section->reloc_count; j++) { - int idx; + unsigned int idx; int i = section->target_index; - struct coff_reloc *r = head->sections[i].relocs + j; + struct coff_reloc *r; arelent *sr = section->relocation + j; + + if (i > head->nsections) + fatal (_("Invalid section target index: %d"), i); + /* PR 17512: file: db850ff4. */ + if (j >= head->sections[i].nrelocs) + fatal (_("Target section has insufficient relocs")); + r = head->sections[i].relocs + j; r->offset = sr->address; r->addend = sr->addend; idx = ((coff_symbol_type *) (sr->sym_ptr_ptr[0]))->native - rawsyms; + if (idx >= rawcount) + { + if (rawcount == 0) + fatal (_("Symbol index %u encountered when there are no symbols"), idx); + non_fatal (_("Invalid symbol index %u encountered"), idx); + idx = 0; + } r->symbol = tindex[idx]; } } } static struct coff_where * -do_where (int i) +do_where (unsigned int i) { - struct internal_syment *sym = &rawsyms[i].u.syment; + struct internal_syment *sym; struct coff_where *where = (struct coff_where *) (xmalloc (sizeof (struct coff_where))); + + if (i >= rawcount) + fatal ("Invalid symbol index: %d\n", i); + + sym = &rawsyms[i].u.syment; where->offset = sym->n_value; if (sym->n_scnum == -1) @@ -231,7 +263,16 @@ do_where (int i) case C_EXTDEF: case C_LABEL: where->where = coff_where_memory; - where->section = &ofile->sections[sym->n_scnum]; + /* PR 17512: file: 07a37c40. */ + /* PR 17512: file: 0c2eb101. */ + if (sym->n_scnum >= ofile->nsections || sym->n_scnum < 0) + { + non_fatal (_("Invalid section number (%d) encountered"), + sym->n_scnum); + where->section = ofile->sections; + } + else + where->section = &ofile->sections[sym->n_scnum]; break; case C_REG: case C_REGPARM: @@ -248,47 +289,61 @@ do_where (int i) where->where = coff_where_typedef; break; default: - abort (); + fatal (_("Unrecognized symbol class: %d"), sym->n_sclass); break; } return where; } -static -struct coff_line * +static struct coff_line * do_lines (int i, char *name ATTRIBUTE_UNUSED) { struct coff_line *res = (struct coff_line *) xcalloc (sizeof (struct coff_line), 1); asection *s; unsigned int l; - /* Find out if this function has any line numbers in the table */ + /* Find out if this function has any line numbers in the table. */ for (s = abfd->sections; s; s = s->next) { + /* PR 17512: file: 07a37c40. + A corrupt COFF binary can have a linenumber count in the header + but no line number table. This should be reported elsewhere, but + do not rely upon this. */ + if (s->lineno == NULL) + continue; + for (l = 0; l < s->lineno_count; l++) { if (s->lineno[l].line_number == 0) { if (rawsyms + i == ((coff_symbol_type *) (&(s->lineno[l].u.sym[0])))->native) { - /* These lines are for this function - so count them and stick them on */ + /* These lines are for this function - so count them and stick them on. */ int c = 0; /* Find the linenumber of the top of the function, since coff linenumbers are relative to the start of the function. */ int start_line = rawsyms[i + 3].u.auxent.x_sym.x_misc.x_lnsz.x_lnno; l++; - for (c = 0; s->lineno[l + c + 1].line_number; c++) + for (c = 0; + /* PR 17512: file: c2825452. */ + l + c + 1 < s->lineno_count + && s->lineno[l + c + 1].line_number; + c++) ; - /* Add two extra records, one for the prologue and one for the epilogue */ + /* Add two extra records, one for the prologue and one for the epilogue. */ c += 1; res->nlines = c; res->lines = (int *) (xcalloc (sizeof (int), c)); res->addresses = (int *) (xcalloc (sizeof (int), c)); res->lines[0] = start_line; res->addresses[0] = rawsyms[i].u.syment.n_value - s->vma; - for (c = 0; s->lineno[l + c + 1].line_number; c++) + for (c = 0; + /* PR 17512: file: c2825452. */ + l + c + 1 < s->lineno_count + && s->lineno[l + c + 1].line_number; + c++) { res->lines[c + 1] = s->lineno[l + c].line_number + start_line - 1; res->addresses[c + 1] = s->lineno[l + c].u.offset; @@ -301,18 +356,30 @@ do_lines (int i, char *name ATTRIBUTE_UNUSED) return res; } -static -struct coff_type * -do_type (int i) +static struct coff_type * +do_type (unsigned int i) { - struct internal_syment *sym = &rawsyms[i].u.syment; - union internal_auxent *aux = &rawsyms[i + 1].u.auxent; - struct coff_type *res = - (struct coff_type *) xmalloc (sizeof (struct coff_type)); - int type = sym->n_type; + struct internal_syment *sym; + union internal_auxent *aux; + struct coff_type *res = (struct coff_type *) xmalloc (sizeof (struct coff_type)); + int type; int which_dt = 0; int dimind = 0; + if (i >= rawcount) + fatal (_("Type entry %u does not have enough symbolic information"), i); + + if (!rawsyms[i].is_sym) + fatal (_("Type entry %u does not refer to a symbol"), i); + sym = &rawsyms[i].u.syment; + + if (sym->n_numaux == 0 || i >= rawcount -1 || rawsyms[i + 1].is_sym) + aux = NULL; + else + aux = &rawsyms[i + 1].u.auxent; + + type = sym->n_type; + res->type = coff_basic_type; res->u.basic = type & 0xf; @@ -322,28 +389,33 @@ do_type (int i) case T_VOID: if (sym->n_numaux && sym->n_sclass == C_STAT) { - /* This is probably a section definition */ + /* This is probably a section definition. */ res->type = coff_secdef_type; + if (aux == NULL) + fatal (_("Section definition needs a section length")); res->size = aux->x_scn.x_scnlen; + + /* PR 17512: file: 081c955d. + Fill in the asecdef structure as well. */ + res->u.asecdef.address = 0; + res->u.asecdef.size = 0; } else { if (type == 0) { - /* Don't know what this is, let's make it a simple int */ + /* Don't know what this is, let's make it a simple int. */ res->size = INT_SIZE; res->u.basic = T_UINT; } else { - /* Else it could be a function or pointer to void */ + /* Else it could be a function or pointer to void. */ res->size = 0; } } break; - - break; case T_UCHAR: case T_CHAR: res->size = 1; @@ -370,17 +442,39 @@ do_type (int i) case T_UNION: if (sym->n_numaux) { + if (aux == NULL) + fatal (_("Aggregate definition needs auxillary information")); + if (aux->x_sym.x_tagndx.p) { - /* Referring to a struct defined elsewhere */ + unsigned int idx; + + /* PR 17512: file: e72f3988. */ + if (aux->x_sym.x_tagndx.l < 0 || aux->x_sym.x_tagndx.p < rawsyms) + { + non_fatal (_("Invalid tag index %#lx encountered"), aux->x_sym.x_tagndx.l); + idx = 0; + } + else + idx = INDEXOF (aux->x_sym.x_tagndx.p); + + if (idx >= rawcount) + { + if (rawcount == 0) + fatal (_("Symbol index %u encountered when there are no symbols"), idx); + non_fatal (_("Invalid symbol index %u encountered"), idx); + idx = 0; + } + + /* Referring to a struct defined elsewhere. */ res->type = coff_structref_type; - res->u.astructref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)]; + res->u.astructref.ref = tindex[idx]; res->size = res->u.astructref.ref ? res->u.astructref.ref->type->size : 0; } else { - /* A definition of a struct */ + /* A definition of a struct. */ last_struct = res; res->type = coff_structdef_type; res->u.astructdef.elements = empty_scope (); @@ -391,23 +485,34 @@ do_type (int i) } else { - /* No auxents - it's anonymous */ + /* No auxents - it's anonymous. */ res->type = coff_structref_type; res->u.astructref.ref = 0; res->size = 0; } break; case T_ENUM: + if (aux == NULL) + fatal (_("Enum definition needs auxillary information")); if (aux->x_sym.x_tagndx.p) { - /* Referring to a enum defined elsewhere */ + unsigned int idx = INDEXOF (aux->x_sym.x_tagndx.p); + + /* PR 17512: file: 1ef037c7. */ + if (idx >= rawcount) + fatal (_("Invalid enum symbol index %u encountered"), idx); + /* Referring to a enum defined elsewhere. */ res->type = coff_enumref_type; - res->u.aenumref.ref = tindex[INDEXOF (aux->x_sym.x_tagndx.p)]; - res->size = res->u.aenumref.ref->type->size; + res->u.aenumref.ref = tindex[idx]; + /* PR 17512: file: b85b67e8. */ + if (res->u.aenumref.ref) + res->size = res->u.aenumref.ref->type->size; + else + res->size = 0; } else { - /* A definition of an enum */ + /* A definition of an enum. */ last_enum = res; res->type = coff_enumdef_type; res->u.aenumdef.elements = empty_scope (); @@ -428,12 +533,27 @@ do_type (int i) { struct coff_type *ptr = ((struct coff_type *) xmalloc (sizeof (struct coff_type))); - int els = (dimind < DIMNUM - ? aux->x_sym.x_fcnary.x_ary.x_dimen[dimind] - : 0); + int els; + + if (aux == NULL) + fatal (_("Array definition needs auxillary information")); + els = (dimind < DIMNUM + ? aux->x_sym.x_fcnary.x_ary.x_dimen[dimind] + : 0); + ++dimind; ptr->type = coff_array_type; - ptr->size = els * res->size; + /* PR 17512: file: ae1971e2. + Check for integer overflow. */ + { + long long a, z; + a = els; + z = res->size; + a *= z; + ptr->size = (int) a; + if (ptr->size != a) + non_fatal (_("Out of range sum for els (%#x) * size (%#x)"), els, res->size); + } ptr->u.array.dim = els; ptr->u.array.array_of = res; res = ptr; @@ -443,6 +563,7 @@ do_type (int i) { struct coff_type *ptr = (struct coff_type *) xmalloc (sizeof (struct coff_type)); + ptr->size = PTR_SIZE; ptr->type = coff_pointer_type; ptr->u.pointer.points_to = res; @@ -453,11 +574,12 @@ do_type (int i) { struct coff_type *ptr = (struct coff_type *) xmalloc (sizeof (struct coff_type)); + ptr->size = 0; ptr->type = coff_function_type; ptr->u.function.function_returns = res; ptr->u.function.parameters = empty_scope (); - ptr->u.function.lines = do_lines (i, sym->_n._n_nptr[1]); + ptr->u.function.lines = do_lines (i, N(sym)); ptr->u.function.code = 0; last_function_type = ptr; res = ptr; @@ -475,6 +597,7 @@ do_visible (int i) struct coff_visible *visible = (struct coff_visible *) (xmalloc (sizeof (struct coff_visible))); enum coff_vis_type t; + switch (sym->n_sclass) { case C_MOS: @@ -485,11 +608,9 @@ do_visible (int i) case C_MOE: t = coff_vis_member_of_enum; break; - case C_REGPARM: t = coff_vis_regparam; break; - case C_REG: t = coff_vis_register; break; @@ -504,8 +625,6 @@ do_visible (int i) t = coff_vis_autoparam; break; case C_AUTO: - - t = coff_vis_auto; break; case C_LABEL: @@ -524,27 +643,32 @@ do_visible (int i) t = coff_vis_ext_def; break; default: - abort (); + fatal (_("Unrecognised symbol class: %d"), sym->n_sclass); break; - } visible->type = t; return visible; } +/* Define a symbol and attach to block B. */ + static int -do_define (int i, struct coff_scope *b) +do_define (unsigned int i, struct coff_scope *b) { static int symbol_index; - struct internal_syment *sym = &rawsyms[i].u.syment; - - /* Define a symbol and attach to block b */ + struct internal_syment *sym; struct coff_symbol *s = empty_symbol (); + if (b == NULL) + fatal (_("ICE: do_define called without a block")); + if (i >= rawcount) + fatal (_("Out of range symbol index: %u"), i); + + sym = &rawsyms[i].u.syment; s->number = ++symbol_index; - s->name = sym->_n._n_nptr[1]; + s->name = N(sym); s->sfile = cur_sfile; - /* Glue onto the ofile list */ + /* Glue onto the ofile list. */ if (lofile >= 0) { if (ofile->symbol_list_tail) @@ -552,7 +676,7 @@ do_define (int i, struct coff_scope *b) else ofile->symbol_list_head = s; ofile->symbol_list_tail = s; - /* And the block list */ + /* And the block list. */ } if (b->vars_tail) b->vars_tail->next = s; @@ -567,21 +691,42 @@ do_define (int i, struct coff_scope *b) tindex[i] = s; - /* We remember the lowest address in each section for each source file */ - + /* We remember the lowest address in each section for each source file. */ if (s->where->where == coff_where_memory && s->type->type == coff_secdef_type) { - struct coff_isection *is = cur_sfile->section + s->where->section->number; + struct coff_isection *is; - if (!is->init) + /* PR 17512: file: 4676c97f. */ + if (cur_sfile == NULL) + non_fatal (_("Section referenced before any file is defined")); + else { - is->low = s->where->offset; - is->high = s->where->offset + s->type->size; - is->init = 1; - is->parent = s->where->section; - } + is = cur_sfile->section + s->where->section->number; + if (!is->init) + { + is->low = s->where->offset; + /* PR 17512: file: 37e7a80d. + Check for integer overflow computing low + size. */ + { + long long a, z; + + a = s->where->offset; + z = s->type->size; + a += z; + is->high = (int) a; + if (a != is->high) + non_fatal (_("Out of range sum for offset (%#x) + size (%#x)"), + is->low, s->type->size); + } + /* PR 17512: file: 37e7a80d. */ + if (is->high < s->where->offset) + fatal (_("Out of range type size: %u"), s->type->size); + is->init = 1; + is->parent = s->where->section; + } + } } if (s->type->type == coff_function_type) @@ -590,15 +735,14 @@ do_define (int i, struct coff_scope *b) return i + sym->n_numaux + 1; } - -static -struct coff_ofile * +static struct coff_ofile * doit (void) { - int i; - int infile = 0; + unsigned int i; + bfd_boolean infile = FALSE; struct coff_ofile *head = (struct coff_ofile *) xmalloc (sizeof (struct coff_ofile)); + ofile = head; head->source_head = 0; head->source_tail = 0; @@ -611,23 +755,25 @@ doit (void) for (i = 0; i < rawcount;) { struct internal_syment *sym = &rawsyms[i].u.syment; + switch (sym->n_sclass) { case C_FILE: { - /* new source file announced */ + /* New source file announced. */ struct coff_sfile *n = (struct coff_sfile *) xmalloc (sizeof (struct coff_sfile)); + n->section = (struct coff_isection *) xcalloc (sizeof (struct coff_isection), abfd->section_count + 1); cur_sfile = n; - n->name = sym->_n._n_nptr[1]; + n->name = N(sym); n->next = 0; if (infile) - { - pop_scope (); - } - infile = 1; + pop_scope (); + else + infile = TRUE; + push_scope (1); file_scope = n->scope = top_scope; @@ -642,20 +788,29 @@ doit (void) break; case C_FCN: { - char *name = sym->_n._n_nptr[1]; + char *name = N(sym); + if (name[1] == 'b') { - /* Function start */ + /* Function start. */ push_scope (0); - last_function_type->u.function.code = top_scope; - top_scope->sec = ofile->sections + sym->n_scnum; + /* PR 17512: file: 0ef7fbaf. */ + if (last_function_type) + last_function_type->u.function.code = top_scope; + /* PR 17512: file: 22908266. */ + if (sym->n_scnum < ofile->nsections && sym->n_scnum >= 0) + top_scope->sec = ofile->sections + sym->n_scnum; + else + top_scope->sec = NULL; top_scope->offset = sym->n_value; } else { + /* PR 17512: file: e92e42e1. */ + if (top_scope == NULL) + fatal (_("Function start encountered without a top level scope.")); top_scope->size = sym->n_value - top_scope->offset + 1; pop_scope (); - } i += sym->n_numaux + 1; } @@ -663,17 +818,23 @@ doit (void) case C_BLOCK: { - char *name = sym->_n._n_nptr[1]; + char *name = N(sym); + if (name[1] == 'b') { - /* Block start */ + /* Block start. */ push_scope (1); - top_scope->sec = ofile->sections + sym->n_scnum; + /* PR 17512: file: af7e8e83. */ + if (sym->n_scnum < ofile->nsections && sym->n_scnum >= 0) + top_scope->sec = ofile->sections + sym->n_scnum; + else + top_scope->sec = NULL; top_scope->offset = sym->n_value; - } else { + if (top_scope == NULL) + fatal (_("Block start encountered without a scope for it.")); top_scope->size = sym->n_value - top_scope->offset + 1; pop_scope (); } @@ -682,37 +843,50 @@ doit (void) break; case C_REGPARM: case C_ARG: + if (last_function_symbol == NULL) + fatal (_("Function arguments encountered without a function definition")); i = do_define (i, last_function_symbol->type->u.function.parameters); break; case C_MOS: case C_MOU: case C_FIELD: + /* PR 17512: file: 43ab21f4. */ + if (last_struct == NULL) + fatal (_("Structure element encountered without a structure definition")); i = do_define (i, last_struct->u.astructdef.elements); break; case C_MOE: + if (last_enum == NULL) + fatal (_("Enum element encountered without an enum definition")); i = do_define (i, last_enum->u.aenumdef.elements); break; case C_STRTAG: case C_ENTAG: case C_UNTAG: - /* Various definition */ + /* Various definition. */ + if (top_scope == NULL) + fatal (_("Aggregate defintion encountered without a scope")); i = do_define (i, top_scope); break; case C_EXT: case C_LABEL: + if (file_scope == NULL) + fatal (_("Label defintion encountered without a file scope")); i = do_define (i, file_scope); break; case C_STAT: case C_TPDEF: case C_AUTO: case C_REG: + if (top_scope == NULL) + fatal (_("Variable defintion encountered without a scope")); i = do_define (i, top_scope); break; - default: - abort (); case C_EOS: i += sym->n_numaux + 1; break; + default: + fatal (_("Unrecognised symbol class: %d"), sym->n_sclass); } } do_sections_p2 (head); @@ -725,6 +899,13 @@ coff_grok (bfd *inabfd) long storage; struct coff_ofile *p; abfd = inabfd; + + if (! bfd_family_coff (abfd)) + { + non_fatal (_("%s: is not a COFF format file"), bfd_get_filename (abfd)); + return NULL; + } + storage = bfd_get_symtab_upper_bound (abfd); if (storage < 0) diff --git a/binutils/coffgrok.h b/binutils/coffgrok.h index 75e08241e77..830da39b951 100644 --- a/binutils/coffgrok.h +++ b/binutils/coffgrok.h @@ -19,22 +19,22 @@ MA 02110-1301, USA. */ #define T_NULL 0 -#define T_VOID 1 /* function argument (only used by compiler) */ -#define T_CHAR 2 /* character */ -#define T_SHORT 3 /* short integer */ -#define T_INT 4 /* integer */ -#define T_LONG 5 /* long integer */ -#define T_FLOAT 6 /* floating point */ -#define T_DOUBLE 7 /* double word */ -#define T_STRUCT 8 /* structure */ -#define T_UNION 9 /* union */ -#define T_ENUM 10 /* enumeration */ -#define T_MOE 11 /* member of enumeration*/ -#define T_UCHAR 12 /* unsigned character */ -#define T_USHORT 13 /* unsigned short */ -#define T_UINT 14 /* unsigned integer */ -#define T_ULONG 15 /* unsigned long */ -#define T_LNGDBL 16 /* long double */ +#define T_VOID 1 /* Function argument (only used by compiler). */ +#define T_CHAR 2 /* Character */ +#define T_SHORT 3 /* Short integer */ +#define T_INT 4 /* Integer */ +#define T_LONG 5 /* Long integer */ +#define T_FLOAT 6 /* Floating point */ +#define T_DOUBLE 7 /* Double word */ +#define T_STRUCT 8 /* Structure */ +#define T_UNION 9 /* Union */ +#define T_ENUM 10 /* Enumeration */ +#define T_MOE 11 /* Member of enumeration*/ +#define T_UCHAR 12 /* Unsigned character */ +#define T_USHORT 13 /* Unsigned short */ +#define T_UINT 14 /* Unsigned integer */ +#define T_ULONG 15 /* Unsigned long */ +#define T_LNGDBL 16 /* Long double */ struct coff_reloc @@ -51,7 +51,7 @@ struct coff_section int data; int address; int number; /* 0..n, .text = 0 */ - int nrelocs; + unsigned int nrelocs; int size; struct coff_reloc *relocs; struct bfd_section *bfd_section; @@ -68,7 +68,8 @@ struct coff_ofile struct coff_symbol *symbol_list_tail; }; -struct coff_isection { +struct coff_isection +{ int low; int high; int init; @@ -82,145 +83,139 @@ struct coff_sfile struct coff_sfile *next; /* Vector which maps where in each output section - the input file has it's data */ + the input file has it's data. */ struct coff_isection *section; - }; - - struct coff_type +struct coff_type { int size; enum { coff_pointer_type, coff_function_type, coff_array_type, coff_structdef_type, coff_basic_type, coff_structref_type, coff_enumref_type, coff_enumdef_type, coff_secdef_type - } type; + } type; + union { struct - { + { int address; int size; } asecdef; struct - { - int isstruct; - struct coff_scope *elements; - int idx; - } - astructdef; + { + int isstruct; + struct coff_scope *elements; + int idx; + } astructdef; + struct - { - struct coff_symbol *ref; - } astructref; + { + struct coff_symbol *ref; + } astructref; struct - { - struct coff_scope *elements; - int idx; - } aenumdef; + { + struct coff_scope *elements; + int idx; + } aenumdef; + struct - { - struct coff_symbol *ref; - } aenumref; + { + struct coff_symbol *ref; + } aenumref; struct - { - struct coff_type *points_to; - } pointer; + { + struct coff_type *points_to; + } pointer; + struct - { - int dim; - struct coff_type *array_of; - } array; + { + int dim; + struct coff_type *array_of; + } array; struct - { - struct coff_type *function_returns; - struct coff_scope *parameters; - struct coff_scope *code; - struct coff_line *lines; - } function; + { + struct coff_type * function_returns; + struct coff_scope * parameters; + struct coff_scope * code; + struct coff_line * lines; + } function; + int basic; /* One of T_VOID.. T_UINT */ - } u; + } u; +}; + +struct coff_line +{ + int nlines; + int * lines; + int * addresses; }; +struct coff_scope +{ + struct coff_section * sec; /* Which section. */ + int offset; /* Where. */ + int size; /* How big. */ + struct coff_scope * parent; /* One up. */ + struct coff_scope * next; /* Next along. */ + int nvars; + struct coff_symbol * vars_head; /* Symbols. */ + struct coff_symbol * vars_tail; + struct coff_scope * list_head; /* Children. */ + struct coff_scope * list_tail; +}; + +struct coff_visible +{ + enum coff_vis_type + { + coff_vis_ext_def, + coff_vis_ext_ref, + coff_vis_int_def, + coff_vis_common, + coff_vis_auto, + coff_vis_register, + coff_vis_tag, + coff_vis_member_of_struct, + coff_vis_member_of_enum, + coff_vis_autoparam, + coff_vis_regparam, + } type; +}; + +struct coff_where +{ + enum + { + coff_where_stack, coff_where_memory, coff_where_register, coff_where_unknown, + coff_where_strtag, coff_where_member_of_struct, + coff_where_member_of_enum, coff_where_entag, coff_where_typedef + } where; + + int offset; + int bitoffset; + int bitsize; + struct coff_section *section; +}; + +struct coff_symbol +{ + char * name; + int tag; + struct coff_type * type; + struct coff_where * where; + struct coff_visible * visible; + struct coff_symbol * next; + struct coff_symbol * next_in_ofile_list; /* For the ofile list. */ + int number; + int er_number; + struct coff_sfile * sfile; +}; - struct coff_line - { - int nlines; - int *lines; - int *addresses; - }; - - - struct coff_scope - { - struct coff_section *sec; /* What section */ - int offset; /* where */ - int size; /* How big */ - struct coff_scope *parent; /* one up */ - - struct coff_scope *next; /*next along */ - - int nvars; - - struct coff_symbol *vars_head; /* symbols */ - struct coff_symbol *vars_tail; - - struct coff_scope *list_head; /* children */ - struct coff_scope *list_tail; - - }; - - - struct coff_visible - { - enum coff_vis_type - { - coff_vis_ext_def, - coff_vis_ext_ref, - coff_vis_int_def, - coff_vis_common, - coff_vis_auto, - coff_vis_register, - coff_vis_tag, - coff_vis_member_of_struct, - coff_vis_member_of_enum, - coff_vis_autoparam, - coff_vis_regparam, - } type; - }; - - struct coff_where - { - enum - { - coff_where_stack, coff_where_memory, coff_where_register, coff_where_unknown, - coff_where_strtag, coff_where_member_of_struct, - coff_where_member_of_enum, coff_where_entag, coff_where_typedef - - } where; - int offset; - int bitoffset; - int bitsize; - struct coff_section *section; - }; - - struct coff_symbol - { - char *name; - int tag; - struct coff_type *type; - struct coff_where *where; - struct coff_visible *visible; - struct coff_symbol *next; - struct coff_symbol *next_in_ofile_list; /* For the ofile list */ - int number; - int er_number; - struct coff_sfile *sfile; - }; - -struct coff_ofile *coff_grok (bfd *); +struct coff_ofile * coff_grok (bfd *); diff --git a/binutils/cxxfilt.c b/binutils/cxxfilt.c index 157ebe02d52..391eb297858 100644 --- a/binutils/cxxfilt.c +++ b/binutils/cxxfilt.c @@ -176,6 +176,7 @@ main (int argc, char **argv) program_name = argv[0]; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&argc, &argv); diff --git a/binutils/dlltool.c b/binutils/dlltool.c index 8b013f0e3b0..4d77b021fa8 100644 --- a/binutils/dlltool.c +++ b/binutils/dlltool.c @@ -1699,6 +1699,9 @@ scan_obj_file (const char *filename) scan_open_obj_file (arfile); next = bfd_openr_next_archived_file (f, arfile); bfd_close (arfile); + /* PR 17512: file: 58715298. */ + if (next == arfile) + break; arfile = next; } @@ -1991,6 +1994,31 @@ assemble_file (const char * source, const char * dest) run (as_name, cmd); } +static const char * temp_file_to_remove[5]; +#define TEMP_EXPORT_FILE 0 +#define TEMP_HEAD_FILE 1 +#define TEMP_TAIL_FILE 2 +#define TEMP_HEAD_O_FILE 3 +#define TEMP_TAIL_O_FILE 4 + +static void +unlink_temp_files (void) +{ + unsigned i; + + if (dontdeltemps > 0) + return; + + for (i = 0; i < ARRAY_SIZE (temp_file_to_remove); i++) + { + if (temp_file_to_remove[i]) + { + unlink (temp_file_to_remove[i]); + temp_file_to_remove[i] = NULL; + } + } +} + static void gen_exp_file (void) { @@ -2007,6 +2035,8 @@ gen_exp_file (void) /* xgettext:c-format */ fatal (_("Unable to open temporary assembler file: %s"), TMP_ASM); + temp_file_to_remove[TEMP_EXPORT_FILE] = TMP_ASM; + /* xgettext:c-format */ inform (_("Opened temporary file: %s"), TMP_ASM); @@ -2143,7 +2173,6 @@ gen_exp_file (void) } } - /* Add to the output file a way of getting to the exported names without using the import library. */ if (add_indirect) @@ -2231,7 +2260,10 @@ gen_exp_file (void) assemble_file (TMP_ASM, exp_name); if (dontdeltemps == 0) - unlink (TMP_ASM); + { + temp_file_to_remove[TEMP_EXPORT_FILE] = NULL; + unlink (TMP_ASM); + } inform (_("Generated exports file")); } @@ -2936,6 +2968,8 @@ make_head (void) return NULL; } + temp_file_to_remove[TEMP_HEAD_FILE] = TMP_HEAD_S; + fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C); fprintf (f, "\t.section\t.idata$2\n"); @@ -2997,6 +3031,7 @@ make_head (void) fatal (_("failed to open temporary head file: %s: %s"), TMP_HEAD_O, bfd_get_errmsg ()); + temp_file_to_remove[TEMP_HEAD_O_FILE] = TMP_HEAD_O; return abfd; } @@ -3012,6 +3047,8 @@ make_delay_head (void) return NULL; } + temp_file_to_remove[TEMP_HEAD_FILE] = TMP_HEAD_S; + /* Output the __tailMerge__xxx function */ fprintf (f, "%s Import trampoline\n", ASM_C); fprintf (f, "\t.section\t.text\n"); @@ -3080,6 +3117,7 @@ make_delay_head (void) fatal (_("failed to open temporary head file: %s: %s"), TMP_HEAD_O, bfd_get_errmsg ()); + temp_file_to_remove[TEMP_HEAD_O_FILE] = TMP_HEAD_O; return abfd; } @@ -3095,6 +3133,8 @@ make_tail (void) return NULL; } + temp_file_to_remove[TEMP_TAIL_FILE] = TMP_TAIL_S; + if (!no_idata4) { fprintf (f, "\t.section\t.idata$4\n"); @@ -3151,6 +3191,7 @@ make_tail (void) fatal (_("failed to open temporary tail file: %s: %s"), TMP_TAIL_O, bfd_get_errmsg ()); + temp_file_to_remove[TEMP_TAIL_O_FILE] = TMP_TAIL_O; return abfd; } @@ -3176,6 +3217,8 @@ gen_lib_file (int delay) /* xgettext:c-format */ inform (_("Creating library file: %s"), imp_name); + xatexit (unlink_temp_files); + bfd_set_format (outarch, bfd_archive); outarch->has_armap = 1; outarch->is_thin_archive = 0; @@ -3245,13 +3288,7 @@ gen_lib_file (int delay) } /* Delete all the temp files. */ - if (dontdeltemps == 0) - { - unlink (TMP_HEAD_O); - unlink (TMP_HEAD_S); - unlink (TMP_TAIL_O); - unlink (TMP_TAIL_S); - } + unlink_temp_files (); if (dontdeltemps < 2) { @@ -3586,7 +3623,15 @@ identify_search_archive (bfd * abfd, } if (last_arfile != NULL) - bfd_close (last_arfile); + { + bfd_close (last_arfile); + /* PR 17512: file: 8b2168d4. */ + if (last_arfile == arfile) + { + last_arfile = NULL; + break; + } + } last_arfile = arfile; } @@ -4041,6 +4086,7 @@ main (int ac, char **av) bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); + bfd_set_error_program_name (program_name); expandargv (&ac, &av); while ((c = getopt_long (ac, av, diff --git a/binutils/elfcomm.c b/binutils/elfcomm.c index f1502b9fdf6..063662a9f7f 100644 --- a/binutils/elfcomm.c +++ b/binutils/elfcomm.c @@ -51,7 +51,7 @@ warn (const char *message, ...) /* Try to keep warning messages in sync with the program's normal output. */ fflush (stdout); - + va_start (args, message); fprintf (stderr, _("%s: Warning: "), program_name); vfprintf (stderr, message, args); @@ -386,10 +386,11 @@ byte_get_64 (unsigned char *field, elf_vma *high, elf_vma *low) char * adjust_relative_path (const char *file_name, const char *name, - int name_len) + unsigned long name_len) { char * member_file_name; const char * base_name = lbasename (file_name); + size_t amt; /* This is a proxy entry for a thin archive member. If the extended name table contains an absolute path @@ -399,7 +400,10 @@ adjust_relative_path (const char *file_name, const char *name, archive is located. */ if (IS_ABSOLUTE_PATH (name) || base_name == file_name) { - member_file_name = (char *) malloc (name_len + 1); + amt = name_len + 1; + if (amt == 0) + return NULL; + member_file_name = (char *) malloc (amt); if (member_file_name == NULL) { error (_("Out of memory\n")); @@ -413,7 +417,18 @@ adjust_relative_path (const char *file_name, const char *name, /* Concatenate the path components of the archive file name to the relative path name from the extended name table. */ size_t prefix_len = base_name - file_name; - member_file_name = (char *) malloc (prefix_len + name_len + 1); + + amt = prefix_len + name_len + 1; + /* PR 17531: file: 2896dc8b + Catch wraparound. */ + if (amt < prefix_len || amt < name_len) + { + error (_("Abnormal length of thin archive member name: %lx\n"), + name_len); + return NULL; + } + + member_file_name = (char *) malloc (amt); if (member_file_name == NULL) { error (_("Out of memory\n")); @@ -445,6 +460,14 @@ process_archive_index_and_symbols (struct archive_info * arch, unsigned long size; size = strtoul (arch->arhdr.ar_size, NULL, 10); + /* PR 17531: file: 912bd7de. */ + if ((signed long) size < 0) + { + error (_("%s: invalid archive header size: %ld\n"), + arch->file_name, size); + return FALSE; + } + size = size + (size & 1); arch->next_arhdr_offset += sizeof arch->arhdr + size; @@ -468,7 +491,7 @@ process_archive_index_and_symbols (struct archive_info * arch, unsigned char * index_buffer; assert (sizeof_ar_index <= sizeof integer_buffer); - + /* Check the size of the archive index. */ if (size < sizeof_ar_index) { @@ -487,9 +510,11 @@ process_archive_index_and_symbols (struct archive_info * arch, arch->index_num = byte_get_big_endian (integer_buffer, sizeof_ar_index); size -= sizeof_ar_index; - if (size < arch->index_num * sizeof_ar_index) + if (size < arch->index_num * sizeof_ar_index + /* PR 17531: file: 585515d1. */ + || size < arch->index_num) { - error (_("%s: the archive index is supposed to have %ld entries of %d bytes, but the size is only %ld\n"), + error (_("%s: the archive index is supposed to have 0x%lx entries of %d bytes, but the size is only 0x%lx\n"), arch->file_name, (long) arch->index_num, sizeof_ar_index, size); return FALSE; } @@ -623,9 +648,25 @@ setup_archive (struct archive_info *arch, const char *file_name, { /* This is the archive string table holding long member names. */ arch->longnames_size = strtoul (arch->arhdr.ar_size, NULL, 10); + /* PR 17531: file: 01068045. */ + if (arch->longnames_size < 8) + { + error (_("%s: long name table is too small, (size = %ld)\n"), + file_name, arch->longnames_size); + return 1; + } + /* PR 17531: file: 639d6a26. */ + if ((signed long) arch->longnames_size < 0) + { + error (_("%s: long name table is too big, (size = 0x%lx)\n"), + file_name, arch->longnames_size); + return 1; + } + arch->next_arhdr_offset += sizeof arch->arhdr + arch->longnames_size; - arch->longnames = (char *) malloc (arch->longnames_size); + /* Plus one to allow for a string terminator. */ + arch->longnames = (char *) malloc (arch->longnames_size + 1); if (arch->longnames == NULL) { error (_("Out of memory reading long symbol names in archive\n")); @@ -643,6 +684,8 @@ setup_archive (struct archive_info *arch, const char *file_name, if ((arch->longnames_size & 1) != 0) getc (file); + + arch->longnames[arch->longnames_size] = 0; } return 0; @@ -713,23 +756,37 @@ get_archive_member_name (struct archive_info *arch, error (_("Archive member uses long names, but no longname table found\n")); return NULL; } - + arch->nested_member_origin = 0; k = j = strtoul (arch->arhdr.ar_name + 1, &endp, 10); if (arch->is_thin_archive && endp != NULL && * endp == ':') arch->nested_member_origin = strtoul (endp + 1, NULL, 10); + if (j > arch->longnames_size) + { + error (_("Found long name index (%ld) beyond end of long name table\n"),j); + return NULL; + } while ((j < arch->longnames_size) && (arch->longnames[j] != '\n') && (arch->longnames[j] != '\0')) j++; - if (arch->longnames[j-1] == '/') + if (j > 0 && arch->longnames[j-1] == '/') j--; + if (j > arch->longnames_size) + j = arch->longnames_size; arch->longnames[j] = '\0'; if (!arch->is_thin_archive || arch->nested_member_origin == 0) return arch->longnames + k; + /* PR 17531: file: 2896dc8b. */ + if (k >= j) + { + error (_("Invalid Thin archive member name\n")); + return NULL; + } + /* This is a proxy for a member of a nested archive. Find the name of the member in that archive. */ member_file_name = adjust_relative_path (arch->file_name, diff --git a/binutils/elfcomm.h b/binutils/elfcomm.h index d834753a6c4..f7f7544f4cb 100644 --- a/binutils/elfcomm.h +++ b/binutils/elfcomm.h @@ -77,7 +77,7 @@ struct archive_info }; /* Return the path name for a proxy entry in a thin archive. */ -extern char *adjust_relative_path (const char *, const char *, int); +extern char *adjust_relative_path (const char *, const char *, unsigned long); /* Read the symbol table and long-name table from an archive. */ extern int setup_archive (struct archive_info *, const char *, FILE *, diff --git a/binutils/nlmconv.c b/binutils/nlmconv.c index 0513f291494..fecb110a67d 100644 --- a/binutils/nlmconv.c +++ b/binutils/nlmconv.c @@ -211,6 +211,7 @@ main (int argc, char **argv) program_name = argv[0]; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&argc, &argv); @@ -1415,6 +1416,9 @@ i386_mangle_relocs (bfd *outbfd, asection *insec, arelent ***relocs_ptr, bfd_vma addend; rel = *relocs++; + /* PR 17512: file: 057f89c1. */ + if (rel->sym_ptr_ptr == NULL) + continue; sym = *rel->sym_ptr_ptr; /* We're moving the relocs from the input section to the output @@ -1871,7 +1875,7 @@ powerpc_mangle_relocs (bfd *outbfd, asection *insec, toc_howto = bfd_reloc_type_lookup (insec->owner, BFD_RELOC_PPC_TOC16); if (toc_howto == (reloc_howto_type *) NULL) - abort (); + fatal (_("Unable to locate PPC_TOC16 reloc information")); /* If this is the .got section, clear out all the contents beyond the initial size. We must do this here because copy_sections is @@ -1910,6 +1914,10 @@ powerpc_mangle_relocs (bfd *outbfd, asection *insec, } } + /* PR 17512: file: 70cfde95. */ + if (rel->howto == NULL) + continue; + /* We must be able to resolve all PC relative relocs at this point. If we get a branch to an undefined symbol we build a stub, since NetWare will resolve undefined symbols into a @@ -1927,6 +1935,13 @@ powerpc_mangle_relocs (bfd *outbfd, asection *insec, { bfd_vma val; + if (rel->address > contents_size - 4) + { + non_fatal (_("Out of range relocation: %lx"), + (long) rel->address); + break; + } + assert (rel->howto->size == 2 && rel->howto->pcrel_offset); val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address); val = ((val &~ rel->howto->dst_mask) @@ -1976,6 +1991,13 @@ powerpc_mangle_relocs (bfd *outbfd, asection *insec, switch (rel->howto->size) { case 1: + if (rel->address > contents_size - 2) + { + non_fatal (_("Out of range relocation: %lx"), + (long) rel->address); + break; + } + val = bfd_get_16 (outbfd, (bfd_byte *) contents + rel->address); val = ((val &~ rel->howto->dst_mask) @@ -1991,6 +2013,14 @@ powerpc_mangle_relocs (bfd *outbfd, asection *insec, break; case 2: + /* PR 17512: file: 0455a112. */ + if (rel->address > contents_size - 4) + { + non_fatal (_("Out of range relocation: %lx"), + (long) rel->address); + break; + } + val = bfd_get_32 (outbfd, (bfd_byte *) contents + rel->address); val = ((val &~ rel->howto->dst_mask) @@ -2002,7 +2032,7 @@ powerpc_mangle_relocs (bfd *outbfd, asection *insec, break; default: - abort (); + fatal (_("Unsupported relocation size: %d"), rel->howto->size); } if (! bfd_is_und_section (bfd_get_section (sym))) diff --git a/binutils/nm.c b/binutils/nm.c index ecd147e0400..ed1ed12580b 100644 --- a/binutils/nm.c +++ b/binutils/nm.c @@ -806,7 +806,11 @@ get_relocs (bfd *abfd, asection *sec, void *dataarg) /* Print a single symbol. */ static void -print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd) +print_symbol (bfd * abfd, + asymbol * sym, + bfd_vma ssize, + bfd * archive_bfd, + bfd_boolean is_synthetic) { symbol_info syminfo; struct extended_symbol_info info; @@ -816,12 +820,12 @@ print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd) format->print_symbol_filename (archive_bfd, abfd); bfd_get_symbol_info (abfd, sym, &syminfo); + info.sinfo = &syminfo; info.ssize = ssize; - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - info.elfinfo = (elf_symbol_type *) sym; - else - info.elfinfo = NULL; + /* Synthetic symbols do not have a full elf_symbol_type set of data available. */ + info.elfinfo = is_synthetic ? NULL : elf_symbol_from (abfd, sym); + format->print_symbol_info (&info, abfd); if (line_numbers) @@ -941,12 +945,17 @@ print_symbol (bfd *abfd, asymbol *sym, bfd_vma ssize, bfd *archive_bfd) /* Print the symbols when sorting by size. */ static void -print_size_symbols (bfd *abfd, bfd_boolean is_dynamic, - struct size_sym *symsizes, long symcount, - bfd *archive_bfd) +print_size_symbols (bfd * abfd, + bfd_boolean is_dynamic, + struct size_sym * symsizes, + long symcount, + long synth_count, + bfd * archive_bfd) { asymbol *store; - struct size_sym *from, *fromend; + struct size_sym *from; + struct size_sym *fromend; + struct size_sym *fromsynth; store = bfd_make_empty_symbol (abfd); if (store == NULL) @@ -954,6 +963,8 @@ print_size_symbols (bfd *abfd, bfd_boolean is_dynamic, from = symsizes; fromend = from + symcount; + fromsynth = symsizes + (symcount - synth_count); + for (; from < fromend; from++) { asymbol *sym; @@ -962,20 +973,34 @@ print_size_symbols (bfd *abfd, bfd_boolean is_dynamic, if (sym == NULL) bfd_fatal (bfd_get_filename (abfd)); - print_symbol (abfd, sym, from->size, archive_bfd); + print_symbol (abfd, sym, from->size, archive_bfd, from >= fromsynth); } } -/* Print the symbols. If ARCHIVE_BFD is non-NULL, it is the archive - containing ABFD. */ +/* Print the symbols of ABFD that are held in MINISYMS. + + If ARCHIVE_BFD is non-NULL, it is the archive containing ABFD. + + SYMCOUNT is the number of symbols in MINISYMS and SYNTH_COUNT + is the number of these that are synthetic. Synthetic symbols, + if any are present, always come at the end of the MINISYMS. + + SIZE is the size of a symbol in MINISYMS. */ static void -print_symbols (bfd *abfd, bfd_boolean is_dynamic, void *minisyms, long symcount, - unsigned int size, bfd *archive_bfd) +print_symbols (bfd * abfd, + bfd_boolean is_dynamic, + void * minisyms, + long symcount, + long synth_count, + unsigned int size, + bfd * archive_bfd) { asymbol *store; - bfd_byte *from, *fromend; + bfd_byte *from; + bfd_byte *fromend; + bfd_byte *fromsynth; store = bfd_make_empty_symbol (abfd); if (store == NULL) @@ -983,6 +1008,8 @@ print_symbols (bfd *abfd, bfd_boolean is_dynamic, void *minisyms, long symcount, from = (bfd_byte *) minisyms; fromend = from + symcount * size; + fromsynth = (bfd_byte *) minisyms + ((symcount - synth_count) * size); + for (; from < fromend; from += size) { asymbol *sym; @@ -991,7 +1018,7 @@ print_symbols (bfd *abfd, bfd_boolean is_dynamic, void *minisyms, long symcount, if (sym == NULL) bfd_fatal (bfd_get_filename (abfd)); - print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd); + print_symbol (abfd, sym, (bfd_vma) 0, archive_bfd, from >= fromsynth); } } @@ -1001,6 +1028,7 @@ static void display_rel_file (bfd *abfd, bfd *archive_bfd) { long symcount; + long synth_count = 0; void *minisyms; unsigned int size; struct size_sym *symsizes; @@ -1031,11 +1059,10 @@ display_rel_file (bfd *abfd, bfd *archive_bfd) non_fatal (_("%s: no symbols"), bfd_get_filename (abfd)); return; } - + if (show_synthetic && size == sizeof (asymbol *)) { asymbol *synthsyms; - long synth_count; asymbol **static_syms = NULL; asymbol **dyn_syms = NULL; long static_count = 0; @@ -1061,6 +1088,7 @@ display_rel_file (bfd *abfd, bfd *archive_bfd) bfd_fatal (bfd_get_filename (abfd)); } } + synth_count = bfd_get_synthetic_symtab (abfd, static_count, static_syms, dyn_count, dyn_syms, &synthsyms); if (synth_count > 0) @@ -1106,9 +1134,9 @@ display_rel_file (bfd *abfd, bfd *archive_bfd) } if (! sort_by_size) - print_symbols (abfd, dynamic, minisyms, symcount, size, archive_bfd); + print_symbols (abfd, dynamic, minisyms, symcount, synth_count, size, archive_bfd); else - print_size_symbols (abfd, dynamic, symsizes, symcount, archive_bfd); + print_size_symbols (abfd, dynamic, symsizes, symcount, synth_count, archive_bfd); free (minisyms); free (symsizes); @@ -1181,6 +1209,8 @@ display_archive (bfd *file) bfd_close (last_arfile); lineno_cache_bfd = NULL; lineno_cache_rel_bfd = NULL; + if (arfile == last_arfile) + return; } last_arfile = arfile; } @@ -1434,7 +1464,6 @@ print_symbol_info_bsd (struct extended_symbol_info *info, bfd *abfd) print_value (abfd, SYM_SIZE (info)); else print_value (abfd, SYM_VALUE (info)); - if (print_size && SYM_SIZE (info)) { printf (" "); @@ -1541,6 +1570,7 @@ main (int argc, char **argv) program_name = *argv; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); #if BFD_SUPPORTS_PLUGINS bfd_plugin_set_program_name (program_name); #endif diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 07794cbbf8b..da429f54ea8 100644 --- a/binutils/objcopy.c +++ b/binutils/objcopy.c @@ -1776,6 +1776,14 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch) bfd_nonfatal_message (NULL, ibfd, NULL, NULL); return FALSE; } + /* PR 17512: file: d6323821 + If the symbol table could not be loaded do not pretend that we have + any symbols. This trips us up later on when we load the relocs. */ + if (symcount == 0) + { + free (isympp); + osympp = isympp = NULL; + } /* BFD mandates that all output sections be created and sizes set before any output is done. Thus, we traverse all sections multiple times. */ @@ -2552,7 +2560,11 @@ copy_file (const char *input_filename, const char *output_filename, if (! copy_object (ibfd, obfd, input_arch)) status = 1; - if (!bfd_close (obfd)) + /* PR 17512: file: 0f15796a. + If the file could not be copied it may not be in a writeable + state. So use bfd_close_all_done to avoid the possibility of + writing uninitialised data into the file. */ + if (! (status ? bfd_close_all_done (obfd) : bfd_close (obfd))) { status = 1; bfd_nonfatal_message (output_filename, NULL, NULL, NULL); @@ -2948,9 +2960,13 @@ copy_relocations_in_section (bfd *ibfd, sec_ptr isection, void *obfdarg) temp_relpp = (arelent **) xmalloc (relsize); for (i = 0; i < relcount; i++) - if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr), - keep_specific_htab)) - temp_relpp [temp_relcount++] = relpp [i]; + { + /* PR 17512: file: 9e907e0c. */ + if (relpp[i]->sym_ptr_ptr) + if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr), + keep_specific_htab)) + temp_relpp [temp_relcount++] = relpp [i]; + } relcount = temp_relcount; free (relpp); relpp = temp_relpp; @@ -4399,6 +4415,9 @@ main (int argc, char *argv[]) create_symbol_htabs (); + if (argv != NULL) + bfd_set_error_program_name (argv[0]); + if (is_strip) strip_main (argc, argv); else diff --git a/binutils/objdump.c b/binutils/objdump.c index da68f39a115..44107cf8646 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -2265,6 +2265,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, section->address = bfd_get_section_vma (abfd, sec); section->size = bfd_get_section_size (sec); section->start = NULL; + section->user_data = sec; ret = bfd_get_full_section_contents (abfd, sec, §ion->start); if (! ret) @@ -2331,6 +2332,23 @@ free_debug_section (enum dwarf_section_display_enum debug) if (section->start == NULL) return; + /* PR 17512: file: 0f67f69d. */ + if (section->user_data != NULL) + { + asection * sec = (asection *) section->user_data; + + /* If we are freeing contents that are also pointed to by the BFD + library's section structure then make sure to update those pointers + too. Otherwise, the next time we try to load data for this section + we can end up using a stale pointer. */ + if (section->start == sec->contents) + { + sec->contents = NULL; + sec->flags &= ~ SEC_IN_MEMORY; + sec->compress_status = COMPRESS_SECTION_NONE; + } + } + free ((char *) section->start); section->start = NULL; section->address = 0; @@ -2766,7 +2784,8 @@ dump_section (bfd *abfd, asection *section, void *dummy ATTRIBUTE_UNUSED) if (!bfd_get_full_section_contents (abfd, section, &data)) { - non_fatal (_("Reading section failed")); + non_fatal (_("Reading section %s failed because: %s"), + section->name, bfd_errmsg (bfd_get_error ())); return; } @@ -3375,6 +3394,13 @@ display_any_bfd (bfd *file, int level) if (level == 0) printf (_("In archive %s:\n"), bfd_get_filename (file)); + else if (level > 100) + { + /* Prevent corrupted files from spinning us into an + infinite loop. 100 is an arbitrary heuristic. */ + fatal (_("Archive nesting is too deep")); + return; + } else printf (_("In nested archive %s:\n"), bfd_get_filename (file)); @@ -3393,7 +3419,15 @@ display_any_bfd (bfd *file, int level) display_any_bfd (arfile, level + 1); if (last_arfile != NULL) - bfd_close (last_arfile); + { + bfd_close (last_arfile); + /* PR 17512: file: ac585d01. */ + if (arfile == last_arfile) + { + last_arfile = NULL; + break; + } + } last_arfile = arfile; } @@ -3446,6 +3480,7 @@ main (int argc, char **argv) program_name = *argv; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); START_PROGRESS (program_name, 0); diff --git a/binutils/rcparse.y b/binutils/rcparse.y index 2d179097fc0..23bd69f542d 100644 --- a/binutils/rcparse.y +++ b/binutils/rcparse.y @@ -1887,12 +1887,12 @@ sizednumexpr: } | sizednumexpr '/' sizednumexpr { - $$.val = $1.val / $3.val; + $$.val = $1.val / ($3.val ? $3.val : 1); $$.dword = $1.dword || $3.dword; } | sizednumexpr '%' sizednumexpr { - $$.val = $1.val % $3.val; + $$.val = $1.val % ($3.val ? $3.val : 1); $$.dword = $1.dword || $3.dword; } | sizednumexpr '+' sizednumexpr @@ -1966,12 +1966,13 @@ sizedposnumexpr: } | sizedposnumexpr '/' sizednumexpr { - $$.val = $1.val / $3.val; + $$.val = $1.val / ($3.val ? $3.val : 1); $$.dword = $1.dword || $3.dword; } | sizedposnumexpr '%' sizednumexpr { - $$.val = $1.val % $3.val; + /* PR 17512: file: 89105a25. */ + $$.val = $1.val % ($3.val ? $3.val : 1); $$.dword = $1.dword || $3.dword; } | sizedposnumexpr '+' sizednumexpr diff --git a/binutils/rescoff.c b/binutils/rescoff.c index 607c8231b7d..dadc6833586 100644 --- a/binutils/rescoff.c +++ b/binutils/rescoff.c @@ -142,8 +142,14 @@ read_coff_rsrc (const char *filename, const char *target) set_windres_bfd (&wrbfd, abfd, sec, WR_KIND_BFD); size = bfd_section_size (abfd, sec); - data = (bfd_byte *) res_alloc (size); + /* PR 17512: file: 1b25ba5d + The call to get_file_size here may be expensive + but there is no other way to determine if the section size + is reasonable. */ + if (size > (bfd_size_type) get_file_size (filename)) + fatal (_("%s: .rsrc section is bigger than the file!"), filename); + data = (bfd_byte *) res_alloc (size); get_windres_bfd_content (&wrbfd, data, 0, size); flaginfo.filename = filename; @@ -185,6 +191,13 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, rc_res_entry **pp; const struct extern_res_entry *ere; + /* PR 17512: file: 09d80f53. + Whilst in theory resources can nest to any level, in practice + Microsoft only defines 3 levels. Corrupt files however might + claim to use more. */ + if (level > 4) + overrun (flaginfo, _("Resources nest too deep")); + if ((size_t) (flaginfo->data_end - data) < sizeof (struct extern_res_directory)) overrun (flaginfo, _("directory")); @@ -234,7 +247,12 @@ read_coff_res_dir (windres_bfd *wrbfd, const bfd_byte *data, re->id.u.n.length = length; re->id.u.n.name = (unichar *) res_alloc (length * sizeof (unichar)); for (j = 0; j < length; j++) - re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); + { + /* PR 17512: file: 05dc4a16. */ + if (length < 0 || ers >= (bfd_byte *) ere || ers + j * 2 + 4 >= (bfd_byte *) ere) + overrun (flaginfo, _("resource name")); + re->id.u.n.name[j] = windres_get_16 (wrbfd, ers + j * 2 + 2, 2); + } if (level == 0) type = &re->id; diff --git a/binutils/resrc.c b/binutils/resrc.c index 65f1c1109b0..4126abdd397 100644 --- a/binutils/resrc.c +++ b/binutils/resrc.c @@ -2923,6 +2923,7 @@ write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data) { int has_error = 0; const struct bin_messagetable *mt; + fprintf (e, "BEGIN\n"); write_rc_datablock (e, length, data, 0, 0, 0); @@ -2932,53 +2933,68 @@ write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data) if (length < BIN_MESSAGETABLE_SIZE) has_error = 1; else - do { - rc_uint_type m, i; - mt = (const struct bin_messagetable *) data; - m = windres_get_32 (&wrtarget, mt->cblocks, length); - if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE)) - { - has_error = 1; - break; - } - for (i = 0; i < m; i++) - { - rc_uint_type low, high, offset; - const struct bin_messagetable_item *mti; + do + { + rc_uint_type m, i; + + mt = (const struct bin_messagetable *) data; + m = windres_get_32 (&wrtarget, mt->cblocks, length); + + if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE)) + { + has_error = 1; + break; + } + for (i = 0; i < m; i++) + { + rc_uint_type low, high, offset; + const struct bin_messagetable_item *mti; + + low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4); + high = windres_get_32 (&wrtarget, mt->items[i].highid, 4); + offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4); + + while (low <= high) + { + rc_uint_type elen, flags; + if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length) + { + has_error = 1; + break; + } + mti = (const struct bin_messagetable_item *) &data[offset]; + elen = windres_get_16 (&wrtarget, mti->length, 2); + flags = windres_get_16 (&wrtarget, mti->flags, 2); + if ((offset + elen) > length) + { + has_error = 1; + break; + } + wr_printcomment (e, "MessageId = 0x%x", low); + wr_printcomment (e, ""); + + if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE) + { + /* PR 17512: file: 5c3232dc. */ + if (elen > BIN_MESSAGETABLE_ITEM_SIZE * 2) + unicode_print (e, (const unichar *) mti->data, + (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2); + } + else + { + if (elen > BIN_MESSAGETABLE_ITEM_SIZE) + ascii_print (e, (const char *) mti->data, + (elen - BIN_MESSAGETABLE_ITEM_SIZE)); + } + + wr_printcomment (e,""); + ++low; + offset += elen; + } + } + } + while (0); - low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4); - high = windres_get_32 (&wrtarget, mt->items[i].highid, 4); - offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4); - while (low <= high) - { - rc_uint_type elen, flags; - if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length) - { - has_error = 1; - break; - } - mti = (const struct bin_messagetable_item *) &data[offset]; - elen = windres_get_16 (&wrtarget, mti->length, 2); - flags = windres_get_16 (&wrtarget, mti->flags, 2); - if ((offset + elen) > length) - { - has_error = 1; - break; - } - wr_printcomment (e, "MessageId = 0x%x", low); - wr_printcomment (e, ""); - if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE) - unicode_print (e, (const unichar *) mti->data, - (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2); - else - ascii_print (e, (const char *) mti->data, - (elen - BIN_MESSAGETABLE_ITEM_SIZE)); - wr_printcomment (e,""); - ++low; - offset += elen; - } - } - } while (0); if (has_error) wr_printcomment (e, "Illegal data"); wr_print_flush (e); @@ -2995,7 +3011,7 @@ write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_ fprintf (e, "BEGIN\n"); if (show_comment == -1) - { + { if (test_rc_datablock_text(length, data)) { rc_uint_type i, c; @@ -3008,7 +3024,7 @@ write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_ ; if (i < length && data[i] == '\n') ++i, ++c; - ascii_print (e, (const char *) &data[i - c], c); + ascii_print(e, (const char *) &data[i - c], c); fprintf (e, "\""); if (i < length) fprintf (e, "\n"); diff --git a/binutils/size.c b/binutils/size.c index e727165f019..8edd7f987d9 100644 --- a/binutils/size.c +++ b/binutils/size.c @@ -133,6 +133,7 @@ main (int argc, char **argv) program_name = *argv; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&argc, &argv); @@ -365,7 +366,14 @@ display_archive (bfd *file) display_bfd (arfile); if (last_arfile != NULL) - bfd_close (last_arfile); + { + bfd_close (last_arfile); + + /* PR 17512: file: a244edbc. */ + if (last_arfile == arfile) + return; + } + last_arfile = arfile; } diff --git a/binutils/srconv.c b/binutils/srconv.c index 13119b4f1ea..1bda313fe76 100644 --- a/binutils/srconv.c +++ b/binutils/srconv.c @@ -167,7 +167,8 @@ checksum (FILE *ffile, unsigned char *ptr, int size, int ccode) last = !(ccode & 0xff00); if (size & 0x7) - abort (); + fatal (_("Checksum failure")); + ptr[0] = ccode | (last ? 0x80 : 0); ptr[1] = bytes + 1; @@ -178,7 +179,7 @@ checksum (FILE *ffile, unsigned char *ptr, int size, int ccode) ptr[bytes] = ~sum; if (fwrite (ptr, bytes + 1, 1, ffile) != 1) /* FIXME: Return error status. */ - abort (); + fatal (_("Failed to write checksum")); } @@ -218,7 +219,7 @@ writeINT (int n, unsigned char *ptr, int *idx, int size, FILE *ffile) ptr[byte + 3] = n >> 0; break; default: - abort (); + fatal (_("Unsupported integer write size: %d"), size); } *idx += size * 8; } @@ -304,7 +305,7 @@ wr_tr (void) if (fwrite (b, sizeof (b), 1, file) != 1) /* FIXME: Return error status. */ - abort (); + fatal (_("Failed to write TR block")); } static void @@ -395,7 +396,8 @@ wr_hd (struct coff_ofile *p) toolname = "C_H8/300S"; break; default: - abort(); + fatal (_("Unrecognized H8300 sub-architecture: %ld"), + bfd_get_mach (abfd)); } rnames = rname_h8300; break; @@ -412,7 +414,7 @@ wr_hd (struct coff_ofile *p) rnames = rname_sh; break; default: - abort (); + fatal (_("Unsupported architecture: %d"), bfd_get_arch (abfd)); } if (! (bfd_get_file_flags(abfd) & EXEC_P)) @@ -866,7 +868,7 @@ walk_tree_type_1 (struct coff_sfile *sfile, struct coff_symbol *symbol, break; default: - abort (); + fatal (_("Unrecognised type: %d"), type->type); } } @@ -995,7 +997,7 @@ walk_tree_symbol (struct coff_sfile *sfile, struct coff_section *section ATTRIBU return; default: - abort (); + fatal (_("Unrecognised coff symbol type: %d"), symbol->type->type); } if (symbol->where->where == coff_where_member_of_struct) @@ -1057,7 +1059,7 @@ walk_tree_symbol (struct coff_sfile *sfile, struct coff_section *section ATTRIBU break; default: - abort (); + fatal (_("Unrecognised coff symbol visibility: %d"), symbol->visible->type); } dsy.dlength = symbol->type->size; @@ -1083,7 +1085,7 @@ walk_tree_symbol (struct coff_sfile *sfile, struct coff_section *section ATTRIBU break; default: - abort (); + fatal (_("Unrecognised coff symbol location: %d"), symbol->where->where); } switch (symbol->where->where) @@ -1128,7 +1130,7 @@ walk_tree_symbol (struct coff_sfile *sfile, struct coff_section *section ATTRIBU break; default: - abort (); + fatal (_("Unrecognised coff symbol location: %d"), symbol->where->where); } if (symbol->where->where == coff_where_register) @@ -1157,7 +1159,7 @@ walk_tree_symbol (struct coff_sfile *sfile, struct coff_section *section ATTRIBU break; default: - abort (); + fatal (_("Unrecognised coff symbol visibility: %d"), symbol->visible->type); } dsy.sfn = 0; @@ -1202,6 +1204,8 @@ walk_tree_sfile (struct coff_section *section, struct coff_sfile *sfile) static void wr_program_structure (struct coff_ofile *p, struct coff_sfile *sfile) { + if (p->nsections < 4) + return; walk_tree_sfile (p->sections + 4, sfile); } @@ -1460,7 +1464,7 @@ wr_cs (void) if (fwrite (b, sizeof (b), 1, file) != 1) /* FIXME: Return error status. */ - abort (); + fatal (_("Failed to write CS struct")); } /* Write out the SC records for a unit. Create an SC @@ -1703,6 +1707,9 @@ prescan (struct coff_ofile *otree) struct coff_symbol *s; struct coff_section *common_section; + if (otree->nsections < 3) + return; + /* Find the common section - always section 3. */ common_section = otree->sections + 3; @@ -1772,6 +1779,7 @@ main (int ac, char **av) program_name = av[0]; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&ac, &av); @@ -1883,10 +1891,12 @@ main (int ac, char **av) printf ("ids %d %d\n", base1, base2); tree = coff_grok (abfd); + if (tree) + { + if (!noprescan) + prescan (tree); - if (!noprescan) - prescan (tree); - - wr_module (tree); + wr_module (tree); + } return 0; } diff --git a/binutils/strings.c b/binutils/strings.c index 7346f553e19..224f87085c7 100644 --- a/binutils/strings.c +++ b/binutils/strings.c @@ -164,6 +164,7 @@ main (int argc, char **argv) program_name = argv[0]; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&argc, &argv); diff --git a/binutils/sysdump.c b/binutils/sysdump.c index 5ae324f8806..b8dfec87fd0 100644 --- a/binutils/sysdump.c +++ b/binutils/sysdump.c @@ -66,6 +66,9 @@ getCHARS (unsigned char *ptr, int *idx, int size, int max) if (b == 0) { + /* PR 17512: file: 13caced2. */ + if (oc >= max) + return _("*corrupt*"); /* Got to work out the length of the string from self. */ b = ptr[oc++]; (*idx) += 8; @@ -166,7 +169,12 @@ getINT (unsigned char *ptr, int *idx, int size, int max) int byte = *idx / 8; if (byte >= max) - return 0; + { + /* PR 17512: file: id:000001,src:000002,op:flip1,pos:45. */ + /* Prevent infinite loops re-reading beyond the end of the buffer. */ + fatal (_("ICE: getINT: Out of buffer space")); + return 0; + } if (size == -2) size = addrsize; @@ -188,7 +196,7 @@ getINT (unsigned char *ptr, int *idx, int size, int max) n = (ptr[byte + 0] << 24) + (ptr[byte + 1] << 16) + (ptr[byte + 2] << 8) + (ptr[byte + 3]); break; default: - abort (); + fatal (_("Unsupported read size: %d"), size); } *idx += size * 8; @@ -615,6 +623,8 @@ module (void) do { c = getc (file); + if (c == EOF) + break; ungetc (c, file); c &= 0x7f; @@ -676,6 +686,7 @@ main (int ac, char **av) program_name = av[0]; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&ac, &av); diff --git a/binutils/windmc.c b/binutils/windmc.c index 01785db58dc..9364e2018ed 100644 --- a/binutils/windmc.c +++ b/binutils/windmc.c @@ -952,6 +952,7 @@ main (int argc, char **argv) program_name = argv[0]; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&argc, &argv); diff --git a/binutils/windres.c b/binutils/windres.c index 7fa90fc7f78..57504909b43 100644 --- a/binutils/windres.c +++ b/binutils/windres.c @@ -204,6 +204,7 @@ open_file_search (const char *filename, const char *mode, const char *errmsg, *real_filename = n; return e; } + free (n); if (errno != ENOENT) break; @@ -807,6 +808,7 @@ main (int argc, char **argv) program_name = argv[0]; xmalloc_set_program_name (program_name); + bfd_set_error_program_name (program_name); expandargv (&argc, &argv);