This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: binutils pr 17531 for 2.25?


Hi Matthias, Hi Tristan,

I have now committed the rest of the changes to the binutils sub-directory. Now on to bfd...

Cheers
  Nick

binutils/ChangeLog

	Apply from master:
	2015-02-26  Nick Clifton  <nickc@redhat.com>

	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  <nickc@redhat.com>

	PR binutils/17512
	* resrc.c (write_rc_messagetable): Tighten check for invalid
	message lengths.

	2015-02-13  Nick Clifton  <nickc@redhat.com>

	* 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  <nickc@redhat.com>

	PR binutils/17512
	* objdump.c (display_any_bfd): Fail if archives nest too deeply.

	2015-01-27  Nick Clifton  <nickc@redhat.com>

	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  <nickc@redhat.com>

	* 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  <nickc@redhat.com>

	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  <nickc@redhat.com>

	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  <nickc@redhat.com>

	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  <nickc@redhat.com>

	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  <nickc@redhat.com>

	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  <nickc@redhat.com>

	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 a4bb426..9f3d3b1 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -4,6 +4,138 @@
 	2015-02-26  Nick Clifton  <nickc@redhat.com>
 
 	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  <nickc@redhat.com>
+
+	PR binutils/17512
+	* resrc.c (write_rc_messagetable): Tighten check for invalid
+	message lengths.
+
+	2015-02-13  Nick Clifton  <nickc@redhat.com>
+
+	* 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  <nickc@redhat.com>
+
+	PR binutils/17512
+	* objdump.c (display_any_bfd): Fail if archives nest too deeply.
+
+	2015-01-27  Nick Clifton  <nickc@redhat.com>
+
+	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  <nickc@redhat.com>
+
+	* 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  <nickc@redhat.com>
+
+	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  <nickc@redhat.com>
+
+	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  <nickc@redhat.com>
+
+	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  <nickc@redhat.com>
+
+	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  <nickc@redhat.com>
+
+	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  <nickc@redhat.com>
+
+	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  <nickc@redhat.com>
+
+	Apply from master:
+	2015-02-26  Nick Clifton  <nickc@redhat.com>
+
+	PR binutils/17512
 	* dwarf.c (display_debug_loc): Pacify the undefined behaviour
 	sanitizer by simplifying address difference calculation.
 	(struct Frame_Chunk): Change type of cfa_offset to dwarf_vma in
diff --git a/binutils/addr2line.c b/binutils/addr2line.c
index f88e745..7cabb8b 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 117826d..7c3c869 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 b4c8415..bf62915 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 ? _("<no sym>") : 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 f37f266..e2d520e 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 75e0824..830da39 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 157ebe0..391eb29 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 8b013f0..4d77b02 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 f1502b9..063662a 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 d834753..f7f7544 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 0513f29..fecb110 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 ecd147e..ed1ed12 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 07794cb..da429f5 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 da68f39..44107cf 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, &section->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 2d17909..23bd69f 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 607c823..dadc683 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 65f1c11..4126abd 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 e727165..8edd7f9 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 13119b4..1bda313 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 7346f55..224f870 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 5ae324f..b8dfec8 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 01785db..9364e20 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 7fa90fc..5750490 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);
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]