Don't use bfd_get_file_size in objdump
authorAlan Modra <amodra@gmail.com>
Tue, 12 Mar 2019 05:49:25 +0000 (16:19 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 12 Mar 2019 13:24:09 +0000 (23:54 +1030)
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.

bfd/ChangeLog
bfd/coffcode.h
bfd/coffgen.c
bfd/elf.c
bfd/elf64-sparc.c
bfd/elfcode.h
bfd/mach-o.c
bfd/pdp11.c
binutils/ChangeLog
binutils/objdump.c

index 18f180453d452153f8ccec4a9ed4075ba4219c1b..3e7d68343aa918c78bd162603cce219a1e5c33f7 100644 (file)
@@ -1,3 +1,31 @@
+2019-03-12  Alan Modra  <amodra@gmail.com>
+
+       * 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.
+
 2019-03-08  Alan Modra  <amodra@gmail.com>
 
        PR 24311
index 2cea9988dee33b76b70cd4718831c68ad5c44d07..f4bfea0ceb706b20c33600b36a32c8c89b810d03 100644 (file)
@@ -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;
index 5f5c5f67a455549ffd26da535aac19f4e394e497..5db35c7ddf13bdfa9b05883e0aa783c2e53a1e92 100644 (file)
@@ -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)
index 852b966efbe7ed9b2d246ab1e04676c2b90d3f63..73fb86971f3dcc0461ba17d5d24d3cf7add41761 100644 (file)
--- 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;
index bd29be3a93cde357cb2106846df2615e373230c5..f523ce7f84688b5cfb74150bd1c8643bc335e0a9 100644 (file)
@@ -19,6 +19,7 @@
    MA 02110-1301, USA.  */
 
 #include "sysdep.h"
+#include <limits.h>
 #include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
    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
index ec5ea766de48182bd2ae8a8fd332e330f8e92f8d..a0487b0843cdbdbe640de536e6caefc7a2e5cbae 100644 (file)
@@ -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,
index 917335d86e8c8cfe7219412c07ec27fc6ab8fd07..a9ca313501e5f447ef99e79950d6a7a72b8b36d4 100644 (file)
@@ -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.  */
index b16c78f9399b606c975d55fea7a6c91cfbc648e1..1d34047fdc06ebe3a4bdbc5eabe5be7ed40ea0f8 100644 (file)
@@ -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 *);
 }
 
 \f
index 605a7b349b33ce871b45a2237a5cb7a73a8af7b7..d62f94a47cc6a8208c24fdd996c23b0c3e26f68b 100644 (file)
@@ -1,3 +1,10 @@
+2019-03-12  Alan Modra  <amodra@gmail.com>
+
+       * 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.
+
 2019-03-05  Nick Clifton  <nickc@redhat.com>
 
        PR 24295
index ab091c10d4bfcffef991026ab2b9469d2362965c..3ef2716b198b7cb5da5d2c65a4c9012248ca5b6f 100644 (file)
@@ -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)