Don't use bfd_get_file_size in objdump

Message ID 20190312132342.GJ20126@bubble.grove.modra.org
State New
Headers show
Series
  • Don't use bfd_get_file_size in objdump
Related show

Commit Message

Alan Modra March 12, 2019, 1:23 p.m.
Compressed debug sections can have uncompressed sizes that exceed the
original file size, so we can't use bfd_get_file_size.  objdump also
used bfd_get_file_size to limit reloc section size, but I believe the
underlying bug causing the PR22508 out of bounds buffer access was
that we had an integer overflow when calculating the reloc buffer
size.  I've fixed that instead in most of the backends, som and
vms-alpha being the exceptions.  SOM and vmd-alpha have rather more
serious bugs in their slurp_relocs routines that would need fixing
first if we want to fuss about making them safe against fuzzed object
files.

The patch also fixes a number of other potential overflows by using
the bfd_alloc2/malloc2/zalloc2 memory allocation functions.

bfd/
	* coffcode.h (buy_and_read): Delete unnecessary forward decl.  Add
	nmemb parameter.  Use bfd_alloc2.
	(coff_slurp_line_table): Use bfd_alloc2.  Update buy_and_read calls.
	Delete assertion.
	(coff_slurp_symbol_table): Use bfd_alloc2 and bfd_zalloc2.
	(coff_slurp_reloc_table): Use bfd_alloc2.  Update buy_and_read calls.
	* coffgen.c (coff_get_reloc_upper_bound): Ensure size calculation
	doesn't overflow.
	* elf.c (bfd_section_from_shdr): Use bfd_zalloc2.  Style fix.
	(assign_section_numbers): Style fix.
	(swap_out_syms): Use bfd_malloc2.
	(_bfd_elf_get_reloc_upper_bound): Ensure size calculation doesn't
	overflow.
	(_bfd_elf_make_empty_symbol): Style fix.
	(elfobj_grok_stapsdt_note_1): Formatting.
	* elfcode.h (elf_object_p): Use bfd_alloc2.
	(elf_write_relocs, elf_write_shdrs_and_ehdr): Likewise.
	(elf_slurp_symbol_table): Use bfd_zalloc2.
	(elf_slurp_reloc_table): Use bfd_alloc2.
	(_bfd_elf_bfd_from_remote_memory): Use bfd_malloc2.
	* elf64-sparc (elf64_sparc_get_reloc_upper_bound): Ensure
	size calculation doesn't overflow.
	(elf64_sparc_get_dynamic_reloc_upper_bound): Likewise.
	* mach-o.c (bfd_mach_o_get_reloc_upper_bound): Likewise.
	* pdp11.c (get_reloc_upper_bound): Copy aoutx.h version.
binutils/
	* objdump.c (load_specific_debug_section): Don't compare section
	size against file size.
	(dump_relocs_in_section): Don't compare reloc size against file size.
	Print "failed to read relocs" on bfd_get_reloc_upper_bound error.


-- 
Alan Modra
Australia Development Lab, IBM

Patch

diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 2cea9988de..f4bfea0ceb 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -423,8 +423,6 @@  static bfd_boolean coff_write_object_contents
   (bfd *) ATTRIBUTE_UNUSED;
 static bfd_boolean coff_set_section_contents
   (bfd *, asection *, const void *, file_ptr, bfd_size_type);
-static void * buy_and_read
-  (bfd *, file_ptr, bfd_size_type);
 static bfd_boolean coff_slurp_line_table
   (bfd *, asection *);
 static bfd_boolean coff_slurp_symbol_table
@@ -4197,12 +4195,14 @@  coff_set_section_contents (bfd * abfd,
 }
 
 static void *
-buy_and_read (bfd *abfd, file_ptr where, bfd_size_type size)
+buy_and_read (bfd *abfd, file_ptr where,
+	      bfd_size_type nmemb, bfd_size_type size)
 {
-  void * area = bfd_alloc (abfd, size);
+  void *area = bfd_alloc2 (abfd, nmemb, size);
 
   if (!area)
     return NULL;
+  size *= nmemb;
   if (bfd_seek (abfd, where, SEEK_SET) != 0
       || bfd_bread (area, size, abfd) != size)
     return NULL;
@@ -4255,7 +4255,6 @@  coff_slurp_line_table (bfd *abfd, asection *asect)
 {
   LINENO *native_lineno;
   alent *lineno_cache;
-  bfd_size_type amt;
   unsigned int counter;
   alent *cache_ptr;
   bfd_vma prev_offset = 0;
@@ -4278,13 +4277,15 @@  coff_slurp_line_table (bfd *abfd, asection *asect)
       return FALSE;
     }
 
-  amt = ((bfd_size_type) asect->lineno_count + 1) * sizeof (alent);
-  lineno_cache = (alent *) bfd_alloc (abfd, amt);
+  lineno_cache = (alent *) bfd_alloc2 (abfd,
+				       (bfd_size_type) asect->lineno_count + 1,
+				       sizeof (alent));
   if (lineno_cache == NULL)
     return FALSE;
 
-  amt = (bfd_size_type) bfd_coff_linesz (abfd) * asect->lineno_count;
-  native_lineno = (LINENO *) buy_and_read (abfd, asect->line_filepos, amt);
+  native_lineno = (LINENO *) buy_and_read (abfd, asect->line_filepos,
+					   asect->lineno_count,
+					   bfd_coff_linesz (abfd));
   if (native_lineno == NULL)
     {
       _bfd_error_handler
@@ -4393,7 +4394,7 @@  coff_slurp_line_table (bfd *abfd, asection *asect)
       alent *n_lineno_cache;
 
       /* Create a table of functions.  */
-      func_table = (alent **) bfd_alloc (abfd, nbr_func * sizeof (alent *));
+      func_table = (alent **) bfd_alloc2 (abfd, nbr_func, sizeof (alent *));
       if (func_table != NULL)
 	{
 	  alent **p = func_table;
@@ -4409,8 +4410,8 @@  coff_slurp_line_table (bfd *abfd, asection *asect)
 	  qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent);
 
 	  /* Create the new sorted table.  */
-	  amt = (bfd_size_type) asect->lineno_count * sizeof (alent);
-	  n_lineno_cache = (alent *) bfd_alloc (abfd, amt);
+	  n_lineno_cache = (alent *) bfd_alloc2 (abfd, asect->lineno_count,
+						 sizeof (alent));
 	  if (n_lineno_cache != NULL)
 	    {
 	      alent *n_cache_ptr = n_lineno_cache;
@@ -4430,9 +4431,9 @@  coff_slurp_line_table (bfd *abfd, asection *asect)
 		    *n_cache_ptr++ = *old_ptr++;
 		  while (old_ptr->line_number != 0);
 		}
-	      BFD_ASSERT ((bfd_size_type) (n_cache_ptr - n_lineno_cache) == (amt / sizeof (alent)));
 
-	      memcpy (lineno_cache, n_lineno_cache, amt);
+	      memcpy (lineno_cache, n_lineno_cache,
+		      asect->lineno_count * sizeof (alent));
 	    }
 	  else
 	    ret = FALSE;
@@ -4455,7 +4456,6 @@  coff_slurp_symbol_table (bfd * abfd)
   combined_entry_type *native_symbols;
   coff_symbol_type *cached_area;
   unsigned int *table_ptr;
-  bfd_size_type amt;
   unsigned int number_of_symbols = 0;
   bfd_boolean ret = TRUE;
 
@@ -4467,15 +4467,14 @@  coff_slurp_symbol_table (bfd * abfd)
     return FALSE;
 
   /* Allocate enough room for all the symbols in cached form.  */
-  amt = obj_raw_syment_count (abfd);
-  amt *= sizeof (coff_symbol_type);
-  cached_area = (coff_symbol_type *) bfd_alloc (abfd, amt);
+  cached_area = (coff_symbol_type *) bfd_alloc2 (abfd,
+						 obj_raw_syment_count (abfd),
+						 sizeof (coff_symbol_type));
   if (cached_area == NULL)
     return FALSE;
 
-  amt = obj_raw_syment_count (abfd);
-  amt *= sizeof (unsigned int);
-  table_ptr = (unsigned int *) bfd_zalloc (abfd, amt);
+  table_ptr = (unsigned int *) bfd_zalloc2 (abfd, obj_raw_syment_count (abfd),
+					    sizeof (unsigned int));
 
   if (table_ptr == NULL)
     return FALSE;
@@ -4963,7 +4962,6 @@  coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols)
   arelent *reloc_cache;
   arelent *cache_ptr;
   unsigned int idx;
-  bfd_size_type amt;
 
   if (asect->relocation)
     return TRUE;
@@ -4974,10 +4972,11 @@  coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols)
   if (!coff_slurp_symbol_table (abfd))
     return FALSE;
 
-  amt = (bfd_size_type) bfd_coff_relsz (abfd) * asect->reloc_count;
-  native_relocs = (RELOC *) buy_and_read (abfd, asect->rel_filepos, amt);
-  amt = (bfd_size_type) asect->reloc_count * sizeof (arelent);
-  reloc_cache = (arelent *) bfd_alloc (abfd, amt);
+  native_relocs = (RELOC *) buy_and_read (abfd, asect->rel_filepos,
+					  asect->reloc_count,
+					  bfd_coff_relsz (abfd));
+  reloc_cache = (arelent *) bfd_alloc2 (abfd, asect->reloc_count,
+					sizeof (arelent));
 
   if (reloc_cache == NULL || native_relocs == NULL)
     return FALSE;
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index 5f5c5f67a4..5db35c7ddf 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -37,6 +37,7 @@ 
    coff_data (abfd).  */
 
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 #include "libbfd.h"
 #include "coff/internal.h"
@@ -2006,6 +2007,10 @@  coff_get_normalized_symtab (bfd *abfd)
   return internal;
 }
 
+#if GCC_VERSION >= 4003
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
 long
 coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
 {
@@ -2014,8 +2019,16 @@  coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
       bfd_set_error (bfd_error_invalid_operation);
       return -1;
     }
+  if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
   return (asect->reloc_count + 1) * sizeof (arelent *);
 }
+#if GCC_VERSION >= 4003
+# pragma GCC diagnostic pop
+#endif
 
 asymbol *
 coff_make_empty_symbol (bfd *abfd)
diff --git a/bfd/elf.c b/bfd/elf.c
index 852b966efb..73fb86971f 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2036,9 +2036,8 @@  bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 	sections_being_created = NULL;
       if (sections_being_created == NULL)
 	{
-	  /* FIXME: It would be more efficient to attach this array to the bfd somehow.  */
 	  sections_being_created = (bfd_boolean *)
-	    bfd_zalloc (abfd, elf_numsections (abfd) * sizeof (bfd_boolean));
+	    bfd_zalloc2 (abfd, elf_numsections (abfd), sizeof (bfd_boolean));
 	  sections_being_created_abfd = abfd;
 	}
       if (sections_being_created [shindex])
@@ -2259,7 +2258,7 @@  bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 	  if (entry->ndx == shindex)
 	    goto success;
 
-	entry = bfd_alloc (abfd, sizeof * entry);
+	entry = bfd_alloc (abfd, sizeof (*entry));
 	if (entry == NULL)
 	  goto fail;
 	entry->ndx = shindex;
@@ -3737,11 +3736,11 @@  assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
       if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
 	{
-	  elf_section_list * entry;
+	  elf_section_list *entry;
 
 	  BFD_ASSERT (elf_symtab_shndx_list (abfd) == NULL);
 
-	  entry = bfd_zalloc (abfd, sizeof * entry);
+	  entry = bfd_zalloc (abfd, sizeof (*entry));
 	  entry->ndx = section_number++;
 	  elf_symtab_shndx_list (abfd) = entry;
 	  entry->hdr.sh_name
@@ -7901,8 +7900,8 @@  swap_out_syms (bfd *abfd,
   symstrtab_hdr->sh_type = SHT_STRTAB;
 
   /* Allocate buffer to swap out the .strtab section.  */
-  symstrtab = (struct elf_sym_strtab *) bfd_malloc ((symcount + 1)
-						    * sizeof (*symstrtab));
+  symstrtab = (struct elf_sym_strtab *) bfd_malloc2 (symcount + 1,
+						     sizeof (*symstrtab));
   if (symstrtab == NULL)
     {
       _bfd_elf_strtab_free (stt);
@@ -8269,12 +8268,25 @@  _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
   return symtab_size;
 }
 
+#if GCC_VERSION >= 4003
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
 long
 _bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
 				sec_ptr asect)
 {
+
+  if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
   return (asect->reloc_count + 1) * sizeof (arelent *);
 }
+#if GCC_VERSION >= 4003
+# pragma GCC diagnostic pop
+#endif
 
 /* Canonicalize the relocs.  */
 
@@ -8753,7 +8765,7 @@  _bfd_elf_make_empty_symbol (bfd *abfd)
 {
   elf_symbol_type *newsym;
 
-  newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym);
+  newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof (*newsym));
   if (!newsym)
     return NULL;
   newsym->symbol.the_bfd = abfd;
@@ -10233,8 +10245,8 @@  static bfd_boolean
 elfobj_grok_stapsdt_note_1 (bfd *abfd, Elf_Internal_Note *note)
 {
   struct sdt_note *cur =
-    (struct sdt_note *) bfd_alloc (abfd, sizeof (struct sdt_note)
-				   + note->descsz);
+    (struct sdt_note *) bfd_alloc (abfd,
+				   sizeof (struct sdt_note) + note->descsz);
 
   cur->next = (struct sdt_note *) (elf_tdata (abfd))->sdt_note_head;
   cur->size = (bfd_size_type) note->descsz;
diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c
index bd29be3a93..f523ce7f84 100644
--- a/bfd/elf64-sparc.c
+++ b/bfd/elf64-sparc.c
@@ -19,6 +19,7 @@ 
    MA 02110-1301, USA.  */
 
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
@@ -33,16 +34,36 @@ 
    section can represent up to two relocs, we must tell the user to allocate
    more space.  */
 
+#if GCC_VERSION >= 4003
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
 static long
 elf64_sparc_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
 {
+  if (sec->reloc_count >= LONG_MAX / 2 / sizeof (arelent *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
   return (sec->reloc_count * 2 + 1) * sizeof (arelent *);
 }
+#if GCC_VERSION >= 4003
+# pragma GCC diagnostic pop
+#endif
 
 static long
 elf64_sparc_get_dynamic_reloc_upper_bound (bfd *abfd)
 {
-  return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 2;
+  long ret = _bfd_elf_get_dynamic_reloc_upper_bound (abfd);
+  if (ret > LONG_MAX / 2)
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      ret = -1;
+    }
+  else if (ret > 0)
+    ret *= 2;
+  return ret;
 }
 
 /* Read  relocations for ASECT from REL_HDR.  There are RELOC_COUNT of
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index ec5ea766de..a0487b0843 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -503,7 +503,6 @@  elf_object_p (bfd *abfd)
   unsigned int shindex;
   const struct elf_backend_data *ebd;
   asection *s;
-  bfd_size_type amt;
   const bfd_target *target;
 
   /* Read in the ELF header in external format.  */
@@ -688,14 +687,14 @@  elf_object_p (bfd *abfd)
       if (i_ehdrp->e_shnum > ((bfd_size_type) -1) / sizeof (*i_shdrp))
 	goto got_wrong_format_error;
 #endif
-      amt = sizeof (*i_shdrp) * (bfd_size_type) i_ehdrp->e_shnum;
-      i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
+      i_shdrp = (Elf_Internal_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum,
+						  sizeof (*i_shdrp));
       if (!i_shdrp)
 	goto got_no_match;
       num_sec = i_ehdrp->e_shnum;
       elf_numsections (abfd) = num_sec;
-      amt = sizeof (i_shdrp) * num_sec;
-      elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
+      elf_elfsections (abfd)
+	= (Elf_Internal_Shdr **) bfd_alloc2 (abfd, num_sec, sizeof (i_shdrp));
       if (!elf_elfsections (abfd))
 	goto got_no_match;
 
@@ -789,8 +788,9 @@  elf_object_p (bfd *abfd)
       if (bfd_get_file_size (abfd) > 0
 	  && i_ehdrp->e_phnum > bfd_get_file_size (abfd))
 	goto got_no_match;
-      amt = (bfd_size_type) i_ehdrp->e_phnum * sizeof (*i_phdr);
-      elf_tdata (abfd)->phdr = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
+      elf_tdata (abfd)->phdr
+	= (Elf_Internal_Phdr *) bfd_alloc2 (abfd, i_ehdrp->e_phnum,
+					    sizeof (*i_phdr));
       if (elf_tdata (abfd)->phdr == NULL)
 	goto got_no_match;
       if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
@@ -903,7 +903,8 @@  elf_write_relocs (bfd *abfd, asection *sec, void *data)
     rela_hdr = elf_section_data (sec)->rel.hdr;
 
   rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count;
-  rela_hdr->contents = (unsigned char *) bfd_alloc (abfd, rela_hdr->sh_size);
+  rela_hdr->contents = (unsigned char *) bfd_alloc2 (abfd, sec->reloc_count,
+						     rela_hdr->sh_entsize);
   if (rela_hdr->contents == NULL)
     {
       *failedp = TRUE;
@@ -1040,9 +1041,8 @@  elf_write_shdrs_and_ehdr (bfd *abfd)
     i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx;
 
   /* at this point we've concocted all the ELF sections...  */
-  amt = i_ehdrp->e_shnum;
-  amt *= sizeof (*x_shdrp);
-  x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt);
+  x_shdrp = (Elf_External_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum,
+					      sizeof (*x_shdrp));
   if (!x_shdrp)
     return FALSE;
 
@@ -1053,6 +1053,7 @@  elf_write_shdrs_and_ehdr (bfd *abfd)
 #endif
       elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count);
     }
+  amt = (bfd_size_type) i_ehdrp->e_shnum * sizeof (*x_shdrp);
   if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
       || bfd_bwrite (x_shdrp, amt, abfd) != amt)
     return FALSE;
@@ -1152,7 +1153,6 @@  elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
   Elf_External_Versym *xver;
   Elf_External_Versym *xverbuf = NULL;
   const struct elf_backend_data *ebd;
-  bfd_size_type amt;
 
   /* Read each raw ELF symbol, converting from external ELF form to
      internal ELF form, and then using the information to create a
@@ -1197,9 +1197,8 @@  elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
       if (isymbuf == NULL)
 	return -1;
 
-      amt = symcount;
-      amt *= sizeof (elf_symbol_type);
-      symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
+      symbase = (elf_symbol_type *) bfd_zalloc2 (abfd, symcount,
+						 sizeof (elf_symbol_type));
       if (symbase == (elf_symbol_type *) NULL)
 	goto error_return;
 
@@ -1519,7 +1518,6 @@  elf_slurp_reloc_table (bfd *abfd,
   bfd_size_type reloc_count;
   bfd_size_type reloc_count2;
   arelent *relents;
-  bfd_size_type amt;
 
   if (asect->relocation != NULL)
     return TRUE;
@@ -1557,8 +1555,8 @@  elf_slurp_reloc_table (bfd *abfd,
       reloc_count2 = 0;
     }
 
-  amt = (reloc_count + reloc_count2) * sizeof (arelent);
-  relents = (arelent *) bfd_alloc (abfd, amt);
+  relents = (arelent *) bfd_alloc2 (abfd, reloc_count + reloc_count2,
+				    sizeof (arelent));
   if (relents == NULL)
     return FALSE;
 
@@ -1713,8 +1711,9 @@  NAME(_bfd_elf,bfd_from_remote_memory)
       return NULL;
     }
 
-  x_phdrs = (Elf_External_Phdr *)
-      bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs));
+  x_phdrs
+    = (Elf_External_Phdr *) bfd_malloc2 (i_ehdr.e_phnum,
+					 sizeof (*x_phdrs) + sizeof (*i_phdrs));
   if (x_phdrs == NULL)
     return NULL;
   err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs,
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 917335d86e..a9ca313501 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -19,6 +19,7 @@ 
    MA 02110-1301, USA.  */
 
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 #include "libbfd.h"
 #include "libiberty.h"
@@ -1416,12 +1417,24 @@  bfd_mach_o_write_dyld_info (bfd *abfd, bfd_mach_o_load_command *command)
   return TRUE;
 }
 
+#if GCC_VERSION >= 4003
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wtype-limits"
+#endif
 long
 bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
 				  asection *asect)
 {
-  return (asect->reloc_count + 1) * sizeof (arelent *);
+   if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
+ return (asect->reloc_count + 1) * sizeof (arelent *);
 }
+#if GCC_VERSION >= 4003
+# pragma GCC diagnostic pop
+#endif
 
 /* In addition to the need to byte-swap the symbol number, the bit positions
    of the fields in the relocation information vary per target endian-ness.  */
diff --git a/bfd/pdp11.c b/bfd/pdp11.c
index b16c78f939..1d34047fdc 100644
--- a/bfd/pdp11.c
+++ b/bfd/pdp11.c
@@ -66,6 +66,7 @@ 
 		     && N_MAGIC(x) != ZMAGIC)
 
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 
 #define external_exec pdp11_external_exec
@@ -1980,6 +1981,8 @@  NAME (aout, canonicalize_reloc) (bfd *abfd,
 long
 NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
 {
+  bfd_size_type count;
+
   if (bfd_get_format (abfd) != bfd_object)
     {
       bfd_set_error (bfd_error_invalid_operation);
@@ -1987,28 +1990,25 @@  NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
     }
 
   if (asect->flags & SEC_CONSTRUCTOR)
-    return (sizeof (arelent *) * (asect->reloc_count + 1));
-
-  if (asect == obj_datasec (abfd))
-    return (sizeof (arelent *)
-	    * ((exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd))
-	       + 1));
-
-  if (asect == obj_textsec (abfd))
-    return (sizeof (arelent *)
-	    * ((exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd))
-	       + 1));
-
-  /* TODO: why are there two if statements for obj_bsssec()? */
-
-  if (asect == obj_bsssec (abfd))
-    return sizeof (arelent *);
-
-  if (asect == obj_bsssec (abfd))
-    return 0;
+    count = asect->reloc_count;
+  else if (asect == obj_datasec (abfd))
+    count = exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
+  else if (asect == obj_textsec (abfd))
+    count = exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
+  else if (asect == obj_bsssec (abfd))
+    count = 0;
+  else
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return -1;
+    }
 
-  bfd_set_error (bfd_error_invalid_operation);
-  return -1;
+  if (count >= LONG_MAX / sizeof (arelent *))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return -1;
+    }
+  return (count + 1) * sizeof (arelent *);
 }
 
 
diff --git a/binutils/objdump.c b/binutils/objdump.c
index ab091c10d4..3ef2716b19 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -2695,7 +2695,7 @@  load_specific_debug_section (enum dwarf_section_display_enum debug,
   section->user_data = sec;
   section->size = bfd_get_section_size (sec);
   amt = section->size + 1;
-  if (amt == 0 || amt > bfd_get_file_size (abfd))
+  if (amt == 0)
     {
       section->start = NULL;
       free_debug_section (debug);
@@ -3640,47 +3640,28 @@  dump_relocs_in_section (bfd *abfd,
       || ((section->flags & SEC_RELOC) == 0))
     return;
 
-  relsize = bfd_get_reloc_upper_bound (abfd, section);
-  if (relsize < 0)
-    bfd_fatal (bfd_get_filename (abfd));
-
   printf ("RELOCATION RECORDS FOR [%s]:", sanitize_string (section->name));
 
+  relsize = bfd_get_reloc_upper_bound (abfd, section);
   if (relsize == 0)
     {
       printf (" (none)\n\n");
       return;
     }
 
-  if ((bfd_get_file_flags (abfd) & (BFD_IN_MEMORY | BFD_LINKER_CREATED)) == 0
-      && (/* Check that the size of the relocs is reasonable.  Note that some
-	     file formats, eg aout, can have relocs whose internal size is
-	     larger than their external size, thus we check the size divided
-	     by four against the file size.  See PR 23931 for an example of
-	     this.  */
-	  ((ufile_ptr) (relsize / 4) > bfd_get_file_size (abfd))
-	  /* Also check the section's reloc count since if this is negative
-	     (or very large) the computation in bfd_get_reloc_upper_bound
-	     may have resulted in returning a small, positive integer.
-	     See PR 22508 for a reproducer.
-
-	     Note - we check against file size rather than section size as
-	     it is possible for there to be more relocs that apply to a
-	     section than there are bytes in that section.  */
-	  || (section->reloc_count > bfd_get_file_size (abfd))))
+  if (relsize < 0)
+    relcount = relsize;
+  else
     {
-      printf (" (too many: %#x relocs)\n", section->reloc_count);
-      bfd_set_error (bfd_error_file_truncated);
-      bfd_fatal (bfd_get_filename (abfd));
+      relpp = (arelent **) xmalloc (relsize);
+      relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
     }
 
-  relpp = (arelent **) xmalloc (relsize);
-  relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
-
   if (relcount < 0)
     {
       printf ("\n");
-      non_fatal (_("failed to read relocs in: %s"), sanitize_string (bfd_get_filename (abfd)));
+      non_fatal (_("failed to read relocs in: %s"),
+		 sanitize_string (bfd_get_filename (abfd)));
       bfd_fatal (_("error message was"));
     }
   else if (relcount == 0)