_bfd_mul_overflow
authorAlan Modra <amodra@gmail.com>
Wed, 19 Feb 2020 02:45:06 +0000 (13:15 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 19 Feb 2020 02:45:06 +0000 (13:15 +1030)
This patch removes the bfd_alloc2 series of memory allocation functions,
replacing them with __builtin_mul_overflow followed by bfd_alloc.  Why
do that?  Well, a followup patch will implement _bfd_alloc_and_read
and I don't want to implement alloc2 variants as well.

* coffcode.h (buy_and_read, coff_slurp_line_table),
(coff_slurp_symbol_table, coff_slurp_reloc_table): Replace
bfd_[z][m]alloc2 calls with _bfd_mul_overflow followed by the
corresponding bfd_alloc call.  Adjust variables to suit.
* coffgen.c (_bfd_coff_get_external_symbols): Likewise.
* ecoff.c (_bfd_ecoff_slurp_symbolic_info),
(_bfd_ecoff_slurp_symbol_table, READ): Likewise.
* elf.c (bfd_elf_get_elf_syms, setup_group, bfd_section_from_shdr),
(swap_out_syms, _bfd_elf_slurp_version_tables): Likewise.
* elf32-m32c.c (m32c_elf_relax_section): Likewise.
* elf32-rl78.c (rl78_elf_relax_section): Likewise.
* elf32-rx.c (elf32_rx_relax_section): Likewise.
* elf64-alpha.c (READ): Likewise.
* elfcode.h (elf_object_p, elf_write_relocs, elf_write_shdrs_and_ehdr),
(elf_slurp_symbol_table, elf_slurp_reloc_table),
(bfd_from_remote_memory): Likewise.
* elfcore.h (core_find_build_id): Likewise.
* elfxx-mips.c (READ): Likewise.
* mach-o.c (bfd_mach_o_mangle_sections),
(bfd_mach_o_read_symtab_symbols, bfd_mach_o_read_thread),
(bfd_mach_o_read_dysymtab, bfd_mach_o_flatten_sections),
(bfd_mach_o_scan, bfd_mach_o_fat_archive_p): Likewise.
* som.c (setup_sections, som_prep_for_fixups)
(som_build_and_write_symbol_table, som_slurp_symbol_table),
(som_slurp_reloc_table, som_bfd_count_ar_symbols),
(som_bfd_fill_in_ar_symbols, som_slurp_armap),
(som_bfd_ar_write_symbol_stuff): Likewise.
* vms-alpha.c (vector_grow1): Likewise.
* vms-lib.c (vms_add_index): Likewise.
* wasm-module.c (wasm_scan_name_function_section): Likewise.
* libbfd.c (bfd_malloc2, bfd_realloc2, bfd_zmalloc2): Delete.
* opncls.c (bfd_alloc2, bfd_zalloc2): Delete.
* libbfd-in.h (bfd_malloc2, bfd_realloc2, bfd_zmalloc2),
(bfd_alloc2, bfd_zalloc2): Delete.
(_bfd_mul_overflow): Define.
* libbfd.h: Regenerate.

21 files changed:
bfd/ChangeLog
bfd/coffcode.h
bfd/coffgen.c
bfd/ecoff.c
bfd/elf.c
bfd/elf32-m32c.c
bfd/elf32-rl78.c
bfd/elf32-rx.c
bfd/elf64-alpha.c
bfd/elfcode.h
bfd/elfcore.h
bfd/elfxx-mips.c
bfd/libbfd-in.h
bfd/libbfd.c
bfd/libbfd.h
bfd/mach-o.c
bfd/opncls.c
bfd/som.c
bfd/vms-alpha.c
bfd/vms-lib.c
bfd/wasm-module.c

index a1ef28c035fee66f7547cbec60cadabca8db249d..a9e3f6729c150ef94632f4aeaec9cf2018c71b7a 100644 (file)
@@ -1,3 +1,42 @@
+2020-02-19  Alan Modra  <amodra@gmail.com>
+
+       * coffcode.h (buy_and_read, coff_slurp_line_table),
+       (coff_slurp_symbol_table, coff_slurp_reloc_table): Replace
+       bfd_[z][m]alloc2 calls with _bfd_mul_overflow followed by the
+       corresponding bfd_alloc call.  Adjust variables to suit.
+       * coffgen.c (_bfd_coff_get_external_symbols): Likewise.
+       * ecoff.c (_bfd_ecoff_slurp_symbolic_info),
+       (_bfd_ecoff_slurp_symbol_table, READ): Likewise.
+       * elf.c (bfd_elf_get_elf_syms, setup_group, bfd_section_from_shdr),
+       (swap_out_syms, _bfd_elf_slurp_version_tables): Likewise.
+       * elf32-m32c.c (m32c_elf_relax_section): Likewise.
+       * elf32-rl78.c (rl78_elf_relax_section): Likewise.
+       * elf32-rx.c (elf32_rx_relax_section): Likewise.
+       * elf64-alpha.c (READ): Likewise.
+       * elfcode.h (elf_object_p, elf_write_relocs, elf_write_shdrs_and_ehdr),
+       (elf_slurp_symbol_table, elf_slurp_reloc_table),
+       (bfd_from_remote_memory): Likewise.
+       * elfcore.h (core_find_build_id): Likewise.
+       * elfxx-mips.c (READ): Likewise.
+       * mach-o.c (bfd_mach_o_mangle_sections),
+       (bfd_mach_o_read_symtab_symbols, bfd_mach_o_read_thread),
+       (bfd_mach_o_read_dysymtab, bfd_mach_o_flatten_sections),
+       (bfd_mach_o_scan, bfd_mach_o_fat_archive_p): Likewise.
+       * som.c (setup_sections, som_prep_for_fixups)
+       (som_build_and_write_symbol_table, som_slurp_symbol_table),
+       (som_slurp_reloc_table, som_bfd_count_ar_symbols),
+       (som_bfd_fill_in_ar_symbols, som_slurp_armap),
+       (som_bfd_ar_write_symbol_stuff): Likewise.
+       * vms-alpha.c (vector_grow1): Likewise.
+       * vms-lib.c (vms_add_index): Likewise.
+       * wasm-module.c (wasm_scan_name_function_section): Likewise.
+       * libbfd.c (bfd_malloc2, bfd_realloc2, bfd_zmalloc2): Delete.
+       * opncls.c (bfd_alloc2, bfd_zalloc2): Delete.
+       * libbfd-in.h (bfd_malloc2, bfd_realloc2, bfd_zmalloc2),
+       (bfd_alloc2, bfd_zalloc2): Delete.
+       (_bfd_mul_overflow): Define.
+       * libbfd.h: Regenerate.
+
 2020-02-19  Alan Modra  <amodra@gmail.com>
 
        * elf.c (bfd_section_from_shdr): Use bfd_zalloc rather than
index 3311b9f813050b256c9db387839bb4fa317a2f7a..551105dfb3a111936e0cdfd5c9de0b64c18a343f 100644 (file)
@@ -4200,13 +4200,19 @@ static void *
 buy_and_read (bfd *abfd, file_ptr where,
              bfd_size_type nmemb, bfd_size_type size)
 {
-  void *area = bfd_alloc2 (abfd, nmemb, size);
+  void *area;
+  size_t amt;
 
+  if (_bfd_mul_overflow (nmemb, size, &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return NULL;
+    }
+  area = bfd_alloc (abfd, amt);
   if (!area)
     return NULL;
-  size *= nmemb;
   if (bfd_seek (abfd, where, SEEK_SET) != 0
-      || bfd_bread (area, size, abfd) != size)
+      || bfd_bread (area, amt, abfd) != amt)
     return NULL;
   return area;
 }
@@ -4265,6 +4271,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
   LINENO *src;
   bfd_boolean have_func;
   bfd_boolean ret = TRUE;
+  size_t amt;
 
   if (asect->lineno_count == 0)
     return TRUE;
@@ -4279,9 +4286,12 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
       return FALSE;
     }
 
-  lineno_cache = (alent *) bfd_alloc2 (abfd,
-                                      (bfd_size_type) asect->lineno_count + 1,
-                                      sizeof (alent));
+  if (_bfd_mul_overflow (asect->lineno_count + 1, sizeof (alent), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  lineno_cache = (alent *) bfd_alloc (abfd, amt);
   if (lineno_cache == NULL)
     return FALSE;
 
@@ -4395,8 +4405,12 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
       alent *n_lineno_cache;
 
       /* Create a table of functions.  */
-      func_table = (alent **) bfd_alloc2 (abfd, nbr_func, sizeof (alent *));
-      if (func_table != NULL)
+      if (_bfd_mul_overflow (nbr_func, sizeof (alent *), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         ret = FALSE;
+       }
+      else if ((func_table = (alent **) bfd_alloc (abfd, amt)) != NULL)
        {
          alent **p = func_table;
          unsigned int i;
@@ -4411,9 +4425,12 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
          qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent);
 
          /* Create the new sorted table.  */
-         n_lineno_cache = (alent *) bfd_alloc2 (abfd, asect->lineno_count,
-                                                sizeof (alent));
-         if (n_lineno_cache != NULL)
+         if (_bfd_mul_overflow (asect->lineno_count, sizeof (alent), &amt))
+           {
+             bfd_set_error (bfd_error_file_too_big);
+             ret = FALSE;
+           }
+         else if ((n_lineno_cache = (alent *) bfd_alloc (abfd, amt)) != NULL)
            {
              alent *n_cache_ptr = n_lineno_cache;
 
@@ -4459,6 +4476,7 @@ coff_slurp_symbol_table (bfd * abfd)
   unsigned int *table_ptr;
   unsigned int number_of_symbols = 0;
   bfd_boolean ret = TRUE;
+  size_t amt;
 
   if (obj_symbols (abfd))
     return TRUE;
@@ -4468,15 +4486,23 @@ coff_slurp_symbol_table (bfd * abfd)
     return FALSE;
 
   /* Allocate enough room for all the symbols in cached form.  */
-  cached_area = (coff_symbol_type *) bfd_alloc2 (abfd,
-                                                obj_raw_syment_count (abfd),
-                                                sizeof (coff_symbol_type));
+  if (_bfd_mul_overflow (obj_raw_syment_count (abfd),
+                        sizeof (*cached_area), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  cached_area = (coff_symbol_type *) bfd_alloc (abfd, amt);
   if (cached_area == NULL)
     return FALSE;
 
-  table_ptr = (unsigned int *) bfd_zalloc2 (abfd, obj_raw_syment_count (abfd),
-                                           sizeof (unsigned int));
-
+  if (_bfd_mul_overflow (obj_raw_syment_count (abfd),
+                        sizeof (*table_ptr), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  table_ptr = (unsigned int *) bfd_zalloc (abfd, amt);
   if (table_ptr == NULL)
     return FALSE;
   else
@@ -4963,6 +4989,7 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols)
   arelent *reloc_cache;
   arelent *cache_ptr;
   unsigned int idx;
+  size_t amt;
 
   if (asect->relocation)
     return TRUE;
@@ -4976,9 +5003,12 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols)
   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 (_bfd_mul_overflow (asect->reloc_count, sizeof (arelent), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  reloc_cache = (arelent *) bfd_alloc (abfd, amt);
   if (reloc_cache == NULL || native_relocs == NULL)
     return FALSE;
 
index 5287130490ecd7b869da0c0c47594ddd9d38d0d8..20cee0a74c584281cdac0fb21617702c68d8486d 100644 (file)
@@ -1639,30 +1639,29 @@ copy_name (bfd *abfd, char *name, size_t maxlen)
 bfd_boolean
 _bfd_coff_get_external_symbols (bfd *abfd)
 {
-  bfd_size_type symesz;
-  bfd_size_type size;
+  size_t symesz;
+  size_t size;
   void * syms;
   ufile_ptr filesize;
 
   if (obj_coff_external_syms (abfd) != NULL)
     return TRUE;
 
-  symesz = bfd_coff_symesz (abfd);
-  size = obj_raw_syment_count (abfd) * symesz;
-  if (size == 0)
-    return TRUE;
-
   /* Check for integer overflow and for unreasonable symbol counts.  */
   filesize = bfd_get_file_size (abfd);
-  if (size < obj_raw_syment_count (abfd)
+  symesz = bfd_coff_symesz (abfd);
+  if (_bfd_mul_overflow (obj_raw_syment_count (abfd), symesz, &size)
       || (filesize != 0 && size > filesize))
-
     {
+      bfd_set_error (bfd_error_file_truncated);
       _bfd_error_handler (_("%pB: corrupt symbol count: %#" PRIx64 ""),
                          abfd, (uint64_t) obj_raw_syment_count (abfd));
       return FALSE;
     }
 
+  if (size == 0)
+    return TRUE;
+
   syms = bfd_malloc (size);
   if (syms == NULL)
     {
index e8ccbd45df7a55bbd4abd6c6083345b4db83007a..15c18aca76d937990b387dda59d453cd38c2339b 100644 (file)
@@ -514,6 +514,7 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd,
   bfd_size_type raw_end;
   bfd_size_type cb_end;
   file_ptr pos;
+  size_t amt;
 
   BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info);
 
@@ -615,8 +616,13 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd,
 
      We need to look at the fdr to deal with a lot of information in
      the symbols, so we swap them here.  */
-  debug->fdr = (FDR *) bfd_alloc2 (abfd, internal_symhdr->ifdMax,
-                                  sizeof (struct fdr));
+  if (_bfd_mul_overflow ((unsigned long) internal_symhdr->ifdMax,
+                        sizeof (struct fdr), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  debug->fdr = (FDR *) bfd_alloc (abfd, amt);
   if (debug->fdr == NULL)
     return FALSE;
   external_fdr_size = backend->debug_swap.external_fdr_size;
@@ -872,6 +878,7 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd)
   char *eraw_end;
   FDR *fdr_ptr;
   FDR *fdr_end;
+  size_t amt;
 
   /* If we've already read in the symbol table, do nothing.  */
   if (ecoff_data (abfd)->canonical_symbols != NULL)
@@ -884,8 +891,13 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd)
   if (bfd_get_symcount (abfd) == 0)
     return TRUE;
 
-  internal = (ecoff_symbol_type *) bfd_alloc2 (abfd, bfd_get_symcount (abfd),
-                                              sizeof (ecoff_symbol_type));
+  if (_bfd_mul_overflow (bfd_get_symcount (abfd),
+                        sizeof (ecoff_symbol_type), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  internal = (ecoff_symbol_type *) bfd_alloc (abfd, amt);
   if (internal == NULL)
     return FALSE;
 
@@ -3745,25 +3757,32 @@ ecoff_final_link_debug_accumulate (bfd *output_bfd,
   HDRR *symhdr = &debug->symbolic_header;
   bfd_boolean ret;
 
-#define READ(ptr, offset, count, size, type)                            \
-  if (symhdr->count == 0)                                               \
-    debug->ptr = NULL;                                                  \
-  else                                                                  \
-    {                                                                   \
-      bfd_size_type amt = (bfd_size_type) size * symhdr->count;                 \
-      debug->ptr = (type) bfd_malloc (amt);                             \
-      if (debug->ptr == NULL)                                           \
-       {                                                                \
-         ret = FALSE;                                                   \
-         goto return_something;                                         \
-       }                                                                \
-      if (bfd_seek (input_bfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \
-         || bfd_bread (debug->ptr, amt, input_bfd) != amt)              \
-       {                                                                \
-         ret = FALSE;                                                   \
-         goto return_something;                                         \
-       }                                                                \
-    }
+#define READ(ptr, offset, count, size, type)                           \
+  do                                                                   \
+    {                                                                  \
+      size_t amt;                                                      \
+      debug->ptr = NULL;                                               \
+      if (symhdr->count == 0)                                          \
+       break;                                                          \
+      if (_bfd_mul_overflow (size, symhdr->count, &amt))               \
+       {                                                               \
+         bfd_set_error (bfd_error_file_too_big);                       \
+         ret = FALSE;                                                  \
+         goto return_something;                                        \
+       }                                                               \
+      debug->ptr = (type) bfd_malloc (amt);                            \
+      if (debug->ptr == NULL)                                          \
+       {                                                               \
+         ret = FALSE;                                                  \
+         goto return_something;                                        \
+       }                                                               \
+      if (bfd_seek (input_bfd, symhdr->offset, SEEK_SET) != 0          \
+         || bfd_bread (debug->ptr, amt, input_bfd) != amt)             \
+       {                                                               \
+         ret = FALSE;                                                  \
+         goto return_something;                                        \
+       }                                                               \
+    } while (0)
 
   /* If raw_syments is not NULL, then the data was already by read by
      _bfd_ecoff_slurp_symbolic_info.  */
index 8f18daf687c27bbb64e9ab91d8b49dd803d05824..a3af7ef2af7b6d93bab1ab14fde141093959ec66 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -402,7 +402,7 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   Elf_Internal_Sym *isymend;
   const struct elf_backend_data *bed;
   size_t extsym_size;
-  bfd_size_type amt;
+  size_t amt;
   file_ptr pos;
 
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
@@ -448,11 +448,16 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   alloc_intsym = NULL;
   bed = get_elf_backend_data (ibfd);
   extsym_size = bed->s->sizeof_sym;
-  amt = (bfd_size_type) symcount * extsym_size;
+  if (_bfd_mul_overflow (symcount, extsym_size, &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      intsym_buf = NULL;
+      goto out;
+    }
   pos = symtab_hdr->sh_offset + symoffset * extsym_size;
   if (extsym_buf == NULL)
     {
-      alloc_ext = bfd_malloc2 (symcount, extsym_size);
+      alloc_ext = bfd_malloc (amt);
       extsym_buf = alloc_ext;
     }
   if (extsym_buf == NULL
@@ -467,12 +472,16 @@ bfd_elf_get_elf_syms (bfd *ibfd,
     extshndx_buf = NULL;
   else
     {
-      amt = (bfd_size_type) symcount * sizeof (Elf_External_Sym_Shndx);
+      if (_bfd_mul_overflow (symcount, sizeof (Elf_External_Sym_Shndx), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         intsym_buf = NULL;
+         goto out;
+       }
       pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
       if (extshndx_buf == NULL)
        {
-         alloc_extshndx = (Elf_External_Sym_Shndx *)
-             bfd_malloc2 (symcount, sizeof (Elf_External_Sym_Shndx));
+         alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
          extshndx_buf = alloc_extshndx;
        }
       if (extshndx_buf == NULL
@@ -486,8 +495,12 @@ bfd_elf_get_elf_syms (bfd *ibfd,
 
   if (intsym_buf == NULL)
     {
-      alloc_intsym = (Elf_Internal_Sym *)
-         bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
+      if (_bfd_mul_overflow (symcount, sizeof (Elf_Internal_Sym), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         goto out;
+       }
+      alloc_intsym = (Elf_Internal_Sym *) bfd_malloc (amt);
       intsym_buf = alloc_intsym;
       if (intsym_buf == NULL)
        goto out;
@@ -629,15 +642,14 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
        {
          /* We keep a list of elf section headers for group sections,
             so we can find them quickly.  */
-         bfd_size_type amt;
+         size_t amt;
 
          elf_tdata (abfd)->num_group = num_group;
-         elf_tdata (abfd)->group_sect_ptr = (Elf_Internal_Shdr **)
-             bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
+         amt = num_group * sizeof (Elf_Internal_Shdr *);
+         elf_tdata (abfd)->group_sect_ptr
+           = (Elf_Internal_Shdr **) bfd_zalloc (abfd, amt);
          if (elf_tdata (abfd)->group_sect_ptr == NULL)
            return FALSE;
-         memset (elf_tdata (abfd)->group_sect_ptr, 0,
-                 num_group * sizeof (Elf_Internal_Shdr *));
          num_group = 0;
 
          for (i = 0; i < shnum; i++)
@@ -659,24 +671,12 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                  num_group += 1;
 
                  /* Read the raw contents.  */
-                 BFD_ASSERT (sizeof (*dest) >= 4);
-                 amt = shdr->sh_size * sizeof (*dest) / 4;
-                 shdr->contents = (unsigned char *)
-                   bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4);
-                 /* PR binutils/4110: Handle corrupt group headers.  */
-                 if (shdr->contents == NULL)
-                   {
-                     _bfd_error_handler
-                       /* xgettext:c-format */
-                       (_("%pB: corrupt size field in group section"
-                          " header: %#" PRIx64),
-                        abfd, (uint64_t) shdr->sh_size);
-                     bfd_set_error (bfd_error_bad_value);
-                     -- num_group;
-                     continue;
-                   }
-
-                 if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
+                 BFD_ASSERT (sizeof (*dest) >= 4 && sizeof (*dest) % 4 == 0);
+                 shdr->contents = NULL;
+                 if (_bfd_mul_overflow (shdr->sh_size,
+                                        sizeof (*dest) / 4, &amt)
+                     || (shdr->contents = bfd_alloc (abfd, amt)) == NULL
+                     || bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
                      || (bfd_bread (shdr->contents, shdr->sh_size, abfd)
                          != shdr->sh_size))
                    {
@@ -690,8 +690,11 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                      /* PR 17510: If the group contents are even
                         partially corrupt, do not allow any of the
                         contents to be used.  */
-                     bfd_release (abfd, shdr->contents);
-                     shdr->contents = NULL;
+                     if (shdr->contents != NULL)
+                       {
+                         bfd_release (abfd, shdr->contents);
+                         shdr->contents = NULL;
+                       }
                      continue;
                    }
 
@@ -8015,7 +8018,7 @@ swap_out_syms (bfd *abfd,
               int relocatable_p)
 {
   const struct elf_backend_data *bed;
-  int symcount;
+  unsigned int symcount;
   asymbol **syms;
   struct elf_strtab_hash *stt;
   Elf_Internal_Shdr *symtab_hdr;
@@ -8026,9 +8029,9 @@ swap_out_syms (bfd *abfd,
   bfd_byte *outbound_shndx;
   unsigned long outbound_syms_index;
   unsigned long outbound_shndx_index;
-  int idx;
+  unsigned int idx;
   unsigned int num_locals;
-  bfd_size_type amt;
+  size_t amt;
   bfd_boolean name_local_sections;
 
   if (!elf_map_symbols (abfd, &num_locals))
@@ -8052,21 +8055,22 @@ 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_malloc2 (symcount + 1,
-                                                    sizeof (*symstrtab));
-  if (symstrtab == NULL)
+  if (_bfd_mul_overflow (symcount + 1, sizeof (*symstrtab), &amt)
+      || (symstrtab = (struct elf_sym_strtab *) bfd_malloc (amt)) == NULL)
     {
+      bfd_set_error (bfd_error_no_memory);
       _bfd_elf_strtab_free (stt);
       return FALSE;
     }
 
-  outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount,
-                                          bed->s->sizeof_sym);
-  if (outbound_syms == NULL)
+  if (_bfd_mul_overflow (symcount + 1, bed->s->sizeof_sym, &amt)
+      || (outbound_syms = (bfd_byte *) bfd_alloc (abfd, amt)) == NULL)
     {
-error_return:
-      _bfd_elf_strtab_free (stt);
+    error_no_mem:
+      bfd_set_error (bfd_error_no_memory);
+    error_return:
       free (symstrtab);
+      _bfd_elf_strtab_free (stt);
       return FALSE;
     }
   symtab_hdr->contents = outbound_syms;
@@ -8080,9 +8084,10 @@ error_return:
       symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
       if (symtab_shndx_hdr->sh_name != 0)
        {
-         amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
-         outbound_shndx =  (bfd_byte *)
-           bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx));
+         if (_bfd_mul_overflow (symcount + 1,
+                                sizeof (Elf_External_Sym_Shndx), &amt))
+           goto error_no_mem;
+         outbound_shndx =  (bfd_byte *) bfd_zalloc (abfd, amt);
          if (outbound_shndx == NULL)
            goto error_return;
 
@@ -8570,6 +8575,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
 {
   bfd_byte *contents = NULL;
   unsigned int freeidx = 0;
+  size_t amt;
 
   if (elf_dynverref (abfd) != 0)
     {
@@ -8614,9 +8620,12 @@ error_return_verref:
          || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
        goto error_return_verref;
 
-      elf_tdata (abfd)->verref = (Elf_Internal_Verneed *)
-       bfd_alloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
-
+      if (_bfd_mul_overflow (hdr->sh_info, sizeof (Elf_Internal_Verneed), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         goto error_return_verref;
+       }
+      elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) bfd_alloc (abfd, amt);
       if (elf_tdata (abfd)->verref == NULL)
        goto error_return_verref;
 
@@ -8645,9 +8654,14 @@ error_return_verref:
            iverneed->vn_auxptr = NULL;
          else
            {
+             if (_bfd_mul_overflow (iverneed->vn_cnt,
+                                    sizeof (Elf_Internal_Vernaux), &amt))
+               {
+                 bfd_set_error (bfd_error_file_too_big);
+                 goto error_return_verref;
+               }
              iverneed->vn_auxptr = (struct elf_internal_vernaux *)
-                 bfd_alloc2 (abfd, iverneed->vn_cnt,
-                             sizeof (Elf_Internal_Vernaux));
+               bfd_alloc (abfd, amt);
              if (iverneed->vn_auxptr == NULL)
                goto error_return_verref;
            }
@@ -8779,9 +8793,12 @@ error_return_verref:
          else
            freeidx = ++maxidx;
        }
-
-      elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
-       bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef));
+      if (_bfd_mul_overflow (maxidx, sizeof (Elf_Internal_Verdef), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         goto error_return_verdef;
+       }
+      elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc (abfd, amt);
       if (elf_tdata (abfd)->verdef == NULL)
        goto error_return_verdef;
 
@@ -8809,9 +8826,14 @@ error_return_verref:
            iverdef->vd_auxptr = NULL;
          else
            {
+             if (_bfd_mul_overflow (iverdef->vd_cnt,
+                                    sizeof (Elf_Internal_Verdaux), &amt))
+               {
+                 bfd_set_error (bfd_error_file_too_big);
+                 goto error_return_verdef;
+               }
              iverdef->vd_auxptr = (struct elf_internal_verdaux *)
-                 bfd_alloc2 (abfd, iverdef->vd_cnt,
-                             sizeof (Elf_Internal_Verdaux));
+               bfd_alloc (abfd, amt);
              if (iverdef->vd_auxptr == NULL)
                goto error_return_verdef;
            }
@@ -8874,8 +8896,12 @@ error_return_verref:
       else
        freeidx++;
 
-      elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
-         bfd_zalloc2 (abfd, freeidx, sizeof (Elf_Internal_Verdef));
+      if (_bfd_mul_overflow (freeidx, sizeof (Elf_Internal_Verdef), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         goto error_return;
+       }
+      elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc (abfd, amt);
       if (elf_tdata (abfd)->verdef == NULL)
        goto error_return;
 
index 70ccd6203abdc6acabc70a6fa5bc875031bcfd0f..89bdccacd062cf3c1dd035f3b6058847e9154e6e 100644 (file)
@@ -1491,10 +1491,14 @@ m32c_elf_relax_section
 
   if (shndx_hdr && shndx_hdr->sh_size != 0)
     {
-      bfd_size_type amt;
+      size_t amt;
 
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf_External_Sym_Shndx);
+      if (_bfd_mul_overflow (symtab_hdr->sh_info,
+                            sizeof (Elf_External_Sym_Shndx), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         goto error_return;
+       }
       shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
       if (shndx_buf == NULL)
        goto error_return;
index b7e3464c6f1e43293db7a728d5e57ce97ddff03a..f4abf0425e8f55a7fd0300a594f9edefc76416fa 100644 (file)
@@ -2121,10 +2121,14 @@ rl78_elf_relax_section
 
   if (shndx_hdr && shndx_hdr->sh_size != 0)
     {
-      bfd_size_type amt;
+      size_t amt;
 
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf_External_Sym_Shndx);
+      if (_bfd_mul_overflow (symtab_hdr->sh_info,
+                            sizeof (Elf_External_Sym_Shndx), &amt))
+       {
+         bfd_set_error (bfd_error_no_memory);
+         goto error_return;
+       }
       shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
       if (shndx_buf == NULL)
        goto error_return;
index 744bbf24d52c67bee353a24460c315a78e72794f..a94aee729cfb3b8204847aa258bc98aaeb8fab6e 100644 (file)
@@ -2058,10 +2058,14 @@ elf32_rx_relax_section (bfd *                  abfd,
 
   if (shndx_hdr && shndx_hdr->sh_size != 0)
     {
-      bfd_size_type amt;
+      size_t amt;
 
-      amt = symtab_hdr->sh_info;
-      amt *= sizeof (Elf_External_Sym_Shndx);
+      if (_bfd_mul_overflow (symtab_hdr->sh_info,
+                            sizeof (Elf_External_Sym_Shndx), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         goto error_return;
+       }
       shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
       if (shndx_buf == NULL)
        goto error_return;
index 96ce158b55adf6e53922727e9fef9ad50467085d..ae4be9f07464051950724a0867d410566b2c1a38 100644 (file)
@@ -1387,18 +1387,24 @@ elf64_alpha_read_ecoff_info (bfd *abfd, asection *section,
   /* The symbolic header contains absolute file offsets and sizes to
      read.  */
 #define READ(ptr, offset, count, size, type)                           \
-  if (symhdr->count == 0)                                              \
-    debug->ptr = NULL;                                                 \
-  else                                                                 \
+  do                                                                   \
     {                                                                  \
-      bfd_size_type amt = (bfd_size_type) size * symhdr->count;                \
+      size_t amt;                                                      \
+      debug->ptr = NULL;                                               \
+      if (symhdr->count == 0)                                          \
+       break;                                                          \
+      if (_bfd_mul_overflow (size, symhdr->count, &amt))               \
+       {                                                               \
+         bfd_set_error (bfd_error_file_too_big);                       \
+         goto error_return;                                            \
+       }                                                               \
       debug->ptr = (type) bfd_malloc (amt);                            \
       if (debug->ptr == NULL)                                          \
        goto error_return;                                              \
       if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0    \
          || bfd_bread (debug->ptr, amt, abfd) != amt)                  \
        goto error_return;                                              \
-    }
+    } while (0)
 
   READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
   READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
index a6b0c613ba24df7be8d96f8113861ef1db2598e7..e7dfdee95e9c7e6672dbdd14379206837df1ef26 100644 (file)
@@ -687,19 +687,18 @@ elf_object_p (bfd *abfd)
     {
       Elf_Internal_Shdr *shdrp;
       unsigned int num_sec;
+      size_t amt;
 
-#ifndef BFD64
-      if (i_ehdrp->e_shnum > ((bfd_size_type) -1) / sizeof (*i_shdrp))
+      if (_bfd_mul_overflow (i_ehdrp->e_shnum, sizeof (*i_shdrp), &amt))
        goto got_wrong_format_error;
-#endif
-      i_shdrp = (Elf_Internal_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum,
-                                                 sizeof (*i_shdrp));
+      i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
       if (!i_shdrp)
        goto got_no_match;
       num_sec = i_ehdrp->e_shnum;
       elf_numsections (abfd) = num_sec;
-      elf_elfsections (abfd)
-       = (Elf_Internal_Shdr **) bfd_alloc2 (abfd, num_sec, sizeof (i_shdrp));
+      if (_bfd_mul_overflow (num_sec, sizeof (i_shdrp), &amt))
+       goto got_wrong_format_error;
+      elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
       if (!elf_elfsections (abfd))
        goto got_no_match;
 
@@ -781,20 +780,18 @@ elf_object_p (bfd *abfd)
       Elf_Internal_Phdr *i_phdr;
       unsigned int i;
       ufile_ptr filesize;
+      size_t amt;
 
-#ifndef BFD64
-      if (i_ehdrp->e_phnum > ((bfd_size_type) -1) / sizeof (*i_phdr))
-       goto got_wrong_format_error;
-#endif
       /* Check for a corrupt input file with an impossibly large number
         of program headers.  */
       filesize = bfd_get_file_size (abfd);
       if (filesize != 0
          && i_ehdrp->e_phnum > filesize / sizeof (Elf_External_Phdr))
        goto got_wrong_format_error;
+      if (_bfd_mul_overflow (i_ehdrp->e_phnum, sizeof (*i_phdr), &amt))
+       goto got_wrong_format_error;
       elf_tdata (abfd)->phdr
-       = (Elf_Internal_Phdr *) bfd_alloc2 (abfd, i_ehdrp->e_phnum,
-                                           sizeof (*i_phdr));
+       = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
       if (elf_tdata (abfd)->phdr == NULL)
        goto got_no_match;
       if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
@@ -881,6 +878,7 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data)
   unsigned int idx;
   asymbol *last_sym;
   int last_sym_idx;
+  size_t amt;
 
   /* If we have already failed, don't do anything.  */
   if (*failedp)
@@ -907,10 +905,10 @@ 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_alloc2 (abfd, sec->reloc_count,
-                                                    rela_hdr->sh_entsize);
-  if (rela_hdr->contents == NULL)
+  if (_bfd_mul_overflow (sec->reloc_count, rela_hdr->sh_entsize, &amt)
+      || (rela_hdr->contents = bfd_alloc (abfd, amt)) == NULL)
     {
+      bfd_set_error (bfd_error_no_memory);
       *failedp = TRUE;
       return;
     }
@@ -1019,7 +1017,7 @@ elf_write_shdrs_and_ehdr (bfd *abfd)
   Elf_External_Shdr *x_shdrp;  /* Section header table, external form */
   Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
   unsigned int count;
-  bfd_size_type amt;
+  size_t amt;
 
   i_ehdrp = elf_elfheader (abfd);
   i_shdrp = elf_elfsections (abfd);
@@ -1045,8 +1043,12 @@ 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...  */
-  x_shdrp = (Elf_External_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum,
-                                             sizeof (*x_shdrp));
+  if (_bfd_mul_overflow (i_ehdrp->e_shnum, sizeof (*x_shdrp), &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return FALSE;
+    }
+  x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt);
   if (!x_shdrp)
     return FALSE;
 
@@ -1157,6 +1159,7 @@ 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;
+  size_t amt;
 
   /* Read each raw ELF symbol, converting from external ELF form to
      internal ELF form, and then using the information to create a
@@ -1201,8 +1204,12 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
       if (isymbuf == NULL)
        return -1;
 
-      symbase = (elf_symbol_type *) bfd_zalloc2 (abfd, symcount,
-                                                sizeof (elf_symbol_type));
+      if (_bfd_mul_overflow (symcount, sizeof (elf_symbol_type), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         goto error_return;
+       }
+      symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
       if (symbase == (elf_symbol_type *) NULL)
        goto error_return;
 
@@ -1522,6 +1529,7 @@ elf_slurp_reloc_table (bfd *abfd,
   bfd_size_type reloc_count;
   bfd_size_type reloc_count2;
   arelent *relents;
+  size_t amt;
 
   if (asect->relocation != NULL)
     return TRUE;
@@ -1559,8 +1567,12 @@ elf_slurp_reloc_table (bfd *abfd,
       reloc_count2 = 0;
     }
 
-  relents = (arelent *) bfd_alloc2 (abfd, reloc_count + reloc_count2,
-                                   sizeof (arelent));
+  if (_bfd_mul_overflow (reloc_count + reloc_count2, sizeof (arelent), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  relents = (arelent *) bfd_alloc (abfd, amt);
   if (relents == NULL)
     return FALSE;
 
@@ -1660,6 +1672,7 @@ NAME(_bfd_elf,bfd_from_remote_memory)
   bfd_vma shdr_end;
   bfd_vma loadbase;
   char *filename;
+  size_t amt;
 
   /* Read in the ELF header in external format.  */
   err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr);
@@ -1716,9 +1729,13 @@ NAME(_bfd_elf,bfd_from_remote_memory)
       return NULL;
     }
 
-  x_phdrs
-    = (Elf_External_Phdr *) bfd_malloc2 (i_ehdr.e_phnum,
-                                        sizeof (*x_phdrs) + sizeof (*i_phdrs));
+  if (_bfd_mul_overflow (i_ehdr.e_phnum,
+                        sizeof (*x_phdrs) + sizeof (*i_phdrs), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return NULL;
+    }
+  x_phdrs = (Elf_External_Phdr *) bfd_malloc (amt);
   if (x_phdrs == NULL)
     return NULL;
   err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs,
index 60339bc65f31dd9db9efcd79428a22d2ce256f72..eaf40f24cc9b0183b5f89c646752babdf5b397dd 100644 (file)
@@ -335,6 +335,7 @@ NAME(_bfd_elf, core_find_build_id)
   Elf_Internal_Ehdr i_ehdr;    /* Elf file header, internal form.   */
   Elf_Internal_Phdr *i_phdr;
   unsigned int i;
+  size_t amt;
 
   /* Seek to the position of the segment at OFFSET.  */
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
@@ -384,8 +385,12 @@ NAME(_bfd_elf, core_find_build_id)
     goto fail;
 
   /* Read in program headers.  */
-  i_phdr = (Elf_Internal_Phdr *) bfd_alloc2 (abfd, i_ehdr.e_phnum,
-                                            sizeof (*i_phdr));
+  if (_bfd_mul_overflow (i_ehdr.e_phnum, sizeof (*i_phdr), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto fail;
+    }
+  i_phdr = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
   if (i_phdr == NULL)
     goto fail;
 
index a05c67154cff3ac54df54127113ac8280b8a7aef..81ed9b390a041d069163f0be00e84b91a686adee 100644 (file)
@@ -1413,18 +1413,24 @@ _bfd_mips_elf_read_ecoff_info (bfd *abfd, asection *section,
   /* The symbolic header contains absolute file offsets and sizes to
      read.  */
 #define READ(ptr, offset, count, size, type)                           \
-  if (symhdr->count == 0)                                              \
-    debug->ptr = NULL;                                                 \
-  else                                                                 \
+  do                                                                   \
     {                                                                  \
-      bfd_size_type amt = (bfd_size_type) size * symhdr->count;                \
+      size_t amt;                                                      \
+      debug->ptr = NULL;                                               \
+      if (symhdr->count == 0)                                          \
+       break;                                                          \
+      if (_bfd_mul_overflow (size, symhdr->count, &amt))               \
+       {                                                               \
+         bfd_set_error (bfd_error_file_too_big);                       \
+         goto error_return;                                            \
+       }                                                               \
       debug->ptr = bfd_malloc (amt);                                   \
       if (debug->ptr == NULL)                                          \
        goto error_return;                                              \
       if (bfd_seek (abfd, symhdr->offset, SEEK_SET) != 0               \
          || bfd_bread (debug->ptr, amt, abfd) != amt)                  \
        goto error_return;                                              \
-    }
+    } while (0)
 
   READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *);
   READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, void *);
index 20bf85cc0c4ba1740955d023201faa59364e006f..00650c3c86d13bbd6e453fff0701e0c8b48e64ba 100644 (file)
@@ -116,12 +116,6 @@ extern void *bfd_realloc_or_free
   (void *, bfd_size_type) ATTRIBUTE_HIDDEN;
 extern void *bfd_zmalloc
   (bfd_size_type) ATTRIBUTE_HIDDEN;
-extern void *bfd_malloc2
-  (bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
-extern void *bfd_realloc2
-  (void *, bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
-extern void *bfd_zmalloc2
-  (bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
 
 static inline char *
 bfd_strdup (const char *str)
@@ -134,10 +128,6 @@ bfd_strdup (const char *str)
 }
 /* These routines allocate and free things on the BFD's objalloc.  */
 
-extern void *bfd_alloc2
-  (bfd *, bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
-extern void *bfd_zalloc2
-  (bfd *, bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
 extern void bfd_release
   (bfd *, void *) ATTRIBUTE_HIDDEN;
 
@@ -905,3 +895,11 @@ extern bfd_signed_vma _bfd_read_signed_leb128
 extern bfd_vma _bfd_safe_read_leb128
   (bfd *, bfd_byte *, unsigned int *, bfd_boolean, const bfd_byte * const)
   ATTRIBUTE_HIDDEN;
+
+#if GCC_VERSION >= 7000
+#define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res)
+#else
+/* Assumes unsigned values.  Careful!  Args evaluated multiple times.  */
+#define _bfd_mul_overflow(a, b, res) \
+  ((*res) = (a), (*res) *= (b), (b) != 0 && (*res) / (b) != (a))
+#endif
index 84fadb234b623a1c9bd6e6d7020e0056ed6e0b3e..cb7c3b5aba0872bf7666da5db5b054b1bdc76fc5 100644 (file)
@@ -279,24 +279,6 @@ bfd_malloc (bfd_size_type size)
   return ptr;
 }
 
-/* Allocate memory using malloc, nmemb * size with overflow checking.  */
-
-void *
-bfd_malloc2 (bfd_size_type nmemb, bfd_size_type size)
-{
-  if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
-      && size != 0
-      && nmemb > ~(bfd_size_type) 0 / size)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
-
-  return bfd_malloc (size * nmemb);
-}
-
-/* Reallocate memory using realloc.  */
-
 void *
 bfd_realloc (void *ptr, bfd_size_type size)
 {
@@ -322,22 +304,6 @@ bfd_realloc (void *ptr, bfd_size_type size)
   return ret;
 }
 
-/* Reallocate memory using realloc, nmemb * size with overflow checking.  */
-
-void *
-bfd_realloc2 (void *ptr, bfd_size_type nmemb, bfd_size_type size)
-{
-  if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
-      && size != 0
-      && nmemb > ~(bfd_size_type) 0 / size)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
-
-  return bfd_realloc (ptr, size * nmemb);
-}
-
 /* Reallocate memory using realloc.
    If this fails the pointer is freed before returning.  */
 
@@ -365,25 +331,6 @@ bfd_zmalloc (bfd_size_type size)
   return ptr;
 }
 
-/* Allocate memory using malloc (nmemb * size) with overflow checking
-   and clear it.  */
-
-void *
-bfd_zmalloc2 (bfd_size_type nmemb, bfd_size_type size)
-{
-  void *ptr = bfd_malloc2 (nmemb, size);
-
-  if (ptr != NULL)
-    {
-      size_t sz = nmemb * size;
-
-      if (sz > 0)
-       memset (ptr, 0, sz);
-    }
-
-  return ptr;
-}
-
 /*
 INTERNAL_FUNCTION
        bfd_write_bigendian_4byte_int
index a3684a94cc9b104f1f99d8dfa86fa8ad27d57cf8..7fcd46a38a34f1143b0f00ef464b2a7b46661215 100644 (file)
@@ -121,12 +121,6 @@ extern void *bfd_realloc_or_free
   (void *, bfd_size_type) ATTRIBUTE_HIDDEN;
 extern void *bfd_zmalloc
   (bfd_size_type) ATTRIBUTE_HIDDEN;
-extern void *bfd_malloc2
-  (bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
-extern void *bfd_realloc2
-  (void *, bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
-extern void *bfd_zmalloc2
-  (bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
 
 static inline char *
 bfd_strdup (const char *str)
@@ -139,10 +133,6 @@ bfd_strdup (const char *str)
 }
 /* These routines allocate and free things on the BFD's objalloc.  */
 
-extern void *bfd_alloc2
-  (bfd *, bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
-extern void *bfd_zalloc2
-  (bfd *, bfd_size_type, bfd_size_type) ATTRIBUTE_HIDDEN;
 extern void bfd_release
   (bfd *, void *) ATTRIBUTE_HIDDEN;
 
@@ -910,6 +900,14 @@ extern bfd_signed_vma _bfd_read_signed_leb128
 extern bfd_vma _bfd_safe_read_leb128
   (bfd *, bfd_byte *, unsigned int *, bfd_boolean, const bfd_byte * const)
   ATTRIBUTE_HIDDEN;
+
+#if GCC_VERSION >= 7000
+#define _bfd_mul_overflow(a, b, res) __builtin_mul_overflow (a, b, res)
+#else
+/* Assumes unsigned values.  Careful!  Args evaluated multiple times.  */
+#define _bfd_mul_overflow(a, b, res) \
+  ((*res) = (a), (*res) *= (b), (b) != 0 && (*res) / (b) != (a))
+#endif
 /* Extracted from libbfd.c.  */
 bfd_boolean bfd_write_bigendian_4byte_int (bfd *, unsigned int);
 
index a18c68c6d89d2814c7edd4d464f8dcced124b971..1cc9d432503f84eb4ae519271cf7bd92cdc390e1 100644 (file)
@@ -2554,6 +2554,7 @@ bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata)
   asection *sec;
   unsigned target_index;
   unsigned nsect;
+  size_t amt;
 
   nsect = bfd_count_sections (abfd);
 
@@ -2572,8 +2573,12 @@ bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata)
     }
 
   mdata->nsects = nsect;
-  mdata->sections = bfd_alloc2 (abfd,
-                               mdata->nsects, sizeof (bfd_mach_o_section *));
+  if (_bfd_mul_overflow (mdata->nsects, sizeof (bfd_mach_o_section *), &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return FALSE;
+    }
+  mdata->sections = bfd_alloc (abfd, amt);
   if (mdata->sections == NULL)
     return FALSE;
 
@@ -3923,14 +3928,16 @@ bfd_mach_o_read_symtab_symbols (bfd *abfd)
   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
   bfd_mach_o_symtab_command *sym = mdata->symtab;
   unsigned long i;
+  size_t amt;
 
   if (sym == NULL || sym->symbols)
     /* Return now if there are no symbols or if already loaded.  */
     return TRUE;
 
-  sym->symbols = bfd_alloc2 (abfd, sym->nsyms, sizeof (bfd_mach_o_asymbol));
-  if (sym->symbols == NULL)
+  if (_bfd_mul_overflow (sym->nsyms, sizeof (bfd_mach_o_asymbol), &amt)
+      || (sym->symbols = bfd_alloc (abfd, amt)) == NULL)
     {
+      bfd_set_error (bfd_error_no_memory);
       _bfd_error_handler (_("bfd_mach_o_read_symtab_symbols: "
                            "unable to allocate memory for symbols"));
       sym->nsyms = 0;
@@ -4174,6 +4181,7 @@ bfd_mach_o_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
   unsigned int nflavours;
   unsigned int i;
   struct mach_o_thread_command_external raw;
+  size_t amt;
 
   BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD)
              || (command->type == BFD_MACH_O_LC_UNIXTHREAD));
@@ -4200,8 +4208,12 @@ bfd_mach_o_read_thread (bfd *abfd, bfd_mach_o_load_command *command)
     return FALSE;
 
   /* Allocate threads.  */
-  cmd->flavours = bfd_alloc2 (abfd, nflavours,
-                             sizeof (bfd_mach_o_thread_flavour));
+  if (_bfd_mul_overflow (nflavours, sizeof (bfd_mach_o_thread_flavour), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  cmd->flavours = bfd_alloc (abfd, amt);
   if (cmd->flavours == NULL)
     return FALSE;
   cmd->nflavours = nflavours;
@@ -4315,9 +4327,15 @@ bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
       unsigned int i;
       int wide = bfd_mach_o_wide_p (abfd);
       unsigned int module_len = wide ? 56 : 52;
+      size_t amt;
 
-      cmd->dylib_module =
-       bfd_alloc2 (abfd, cmd->nmodtab, sizeof (bfd_mach_o_dylib_module));
+      if (_bfd_mul_overflow (cmd->nmodtab,
+                            sizeof (bfd_mach_o_dylib_module), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         return FALSE;
+       }
+      cmd->dylib_module = bfd_alloc (abfd, amt);
       if (cmd->dylib_module == NULL)
        return FALSE;
 
@@ -4364,9 +4382,15 @@ bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
   if (cmd->ntoc != 0)
     {
       unsigned long i;
+      size_t amt;
 
-      cmd->dylib_toc = bfd_alloc2
-       (abfd, cmd->ntoc, sizeof (bfd_mach_o_dylib_table_of_content));
+      if (_bfd_mul_overflow (cmd->ntoc,
+                            sizeof (bfd_mach_o_dylib_table_of_content), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         return FALSE;
+       }
+      cmd->dylib_toc = bfd_alloc (abfd, amt);
       if (cmd->dylib_toc == NULL)
        return FALSE;
 
@@ -4389,9 +4413,14 @@ bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
   if (cmd->nindirectsyms != 0)
     {
       unsigned int i;
+      size_t amt;
 
-      cmd->indirect_syms = bfd_alloc2
-       (abfd, cmd->nindirectsyms, sizeof (unsigned int));
+      if (_bfd_mul_overflow (cmd->nindirectsyms, sizeof (unsigned int), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         return FALSE;
+       }
+      cmd->indirect_syms = bfd_alloc (abfd, amt);
       if (cmd->indirect_syms == NULL)
        return FALSE;
 
@@ -4414,9 +4443,15 @@ bfd_mach_o_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command)
     {
       unsigned long v;
       unsigned int i;
+      size_t amt;
 
-      cmd->ext_refs = bfd_alloc2
-       (abfd, cmd->nextrefsyms, sizeof (bfd_mach_o_dylib_reference));
+      if (_bfd_mul_overflow (cmd->nextrefsyms,
+                            sizeof (bfd_mach_o_dylib_reference), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         return FALSE;
+       }
+      cmd->ext_refs = bfd_alloc (abfd, amt);
       if (cmd->ext_refs == NULL)
        return FALSE;
 
@@ -5005,6 +5040,7 @@ bfd_mach_o_flatten_sections (bfd *abfd)
   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
   bfd_mach_o_load_command *cmd;
   long csect = 0;
+  size_t amt;
 
   /* Count total number of sections.  */
   mdata->nsects = 0;
@@ -5021,8 +5057,12 @@ bfd_mach_o_flatten_sections (bfd *abfd)
     }
 
   /* Allocate sections array.  */
-  mdata->sections = bfd_alloc2 (abfd,
-                               mdata->nsects, sizeof (bfd_mach_o_section *));
+  if (_bfd_mul_overflow (mdata->nsects, sizeof (bfd_mach_o_section *), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  mdata->sections = bfd_alloc (abfd, amt);
   if (mdata->sections == NULL && mdata->nsects != 0)
     return FALSE;
 
@@ -5195,11 +5235,18 @@ bfd_mach_o_scan (bfd *abfd,
   if (header->ncmds != 0)
     {
       bfd_mach_o_load_command *cmd;
+      size_t amt;
 
       mdata->first_command = NULL;
       mdata->last_command = NULL;
 
-      cmd = bfd_alloc2 (abfd, header->ncmds, sizeof (bfd_mach_o_load_command));
+      if (_bfd_mul_overflow (header->ncmds,
+                            sizeof (bfd_mach_o_load_command), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         return FALSE;
+       }
+      cmd = bfd_alloc (abfd, amt);
       if (cmd == NULL)
        return FALSE;
 
@@ -5418,6 +5465,7 @@ bfd_mach_o_fat_archive_p (bfd *abfd)
   mach_o_fat_data_struct *adata = NULL;
   struct mach_o_fat_header_external hdr;
   unsigned long i;
+  size_t amt;
 
   if (bfd_seek (abfd, 0, SEEK_SET) != 0
       || bfd_bread (&hdr, sizeof (hdr), abfd) != sizeof (hdr))
@@ -5437,8 +5485,13 @@ bfd_mach_o_fat_archive_p (bfd *abfd)
   if (adata->nfat_arch > 30)
     goto error;
 
-  adata->archentries =
-    bfd_alloc2 (abfd, adata->nfat_arch, sizeof (mach_o_fat_archentry));
+  if (_bfd_mul_overflow (adata->nfat_arch,
+                        sizeof (mach_o_fat_archentry), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error;
+    }
+  adata->archentries = bfd_alloc (abfd, amt);
   if (adata->archentries == NULL)
     goto error;
 
index 796202d31a581bcab7992681ab74bd9f51e812ea..99097a9e39989e377af70e9450a970b009439e70 100644 (file)
@@ -981,32 +981,6 @@ bfd_alloc (bfd *abfd, bfd_size_type size)
   return ret;
 }
 
-/*
-INTERNAL_FUNCTION
-       bfd_alloc2
-
-SYNOPSIS
-       void *bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size);
-
-DESCRIPTION
-       Allocate a block of @var{nmemb} elements of @var{size} bytes each
-       of memory attached to <<abfd>> and return a pointer to it.
-*/
-
-void *
-bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size)
-{
-  if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
-      && size != 0
-      && nmemb > ~(bfd_size_type) 0 / size)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
-
-  return bfd_alloc (abfd, size * nmemb);
-}
-
 /*
 FUNCTION
        bfd_zalloc
@@ -1030,39 +1004,6 @@ bfd_zalloc (bfd *abfd, bfd_size_type size)
   return res;
 }
 
-/*
-INTERNAL_FUNCTION
-       bfd_zalloc2
-
-SYNOPSIS
-       void *bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size);
-
-DESCRIPTION
-       Allocate a block of @var{nmemb} elements of @var{size} bytes each
-       of zeroed memory attached to <<abfd>> and return a pointer to it.
-*/
-
-void *
-bfd_zalloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size)
-{
-  void *res;
-
-  if ((nmemb | size) >= HALF_BFD_SIZE_TYPE
-      && size != 0
-      && nmemb > ~(bfd_size_type) 0 / size)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return NULL;
-    }
-
-  size *= nmemb;
-
-  res = bfd_alloc (abfd, size);
-  if (res)
-    memset (res, 0, (size_t) size);
-  return res;
-}
-
 /* Free a block allocated for a BFD.
    Note:  Also frees all more recently allocated blocks!  */
 
index 9c29230ece1fc89674d58425f5ca7e2522695799..d7d4d8f845f37938a7aa7519ae82738a4ac82992 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -2079,17 +2079,17 @@ setup_sections (bfd *abfd,
   unsigned int total_subspaces = 0;
   asection **subspace_sections = NULL;
   asection *section;
-  bfd_size_type amt;
+  size_t amt;
 
   /* First, read in space names.  */
   amt = file_hdr->space_strings_size;
-  if (amt == (bfd_size_type) -1)
+  if (amt == (size_t) -1)
     {
       bfd_set_error (bfd_error_no_memory);
       goto error_return;
     }
   space_strings = bfd_malloc (amt + 1);
-  if (space_strings == NULL && amt != 0)
+  if (space_strings == NULL)
     goto error_return;
 
   if (bfd_seek (abfd, current_offset + file_hdr->space_strings_location,
@@ -2344,7 +2344,12 @@ setup_sections (bfd *abfd,
     }
   /* Now that we've read in all the subspace records, we need to assign
      a target index to each subspace.  */
-  subspace_sections = bfd_malloc2 (total_subspaces, sizeof (asection *));
+  if (_bfd_mul_overflow (total_subspaces, sizeof (asection *), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
+  subspace_sections = bfd_malloc (amt);
   if (subspace_sections == NULL)
     goto error_return;
 
@@ -2804,6 +2809,7 @@ som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms)
   unsigned long i;
   asection *section;
   asymbol **sorted_syms;
+  size_t amt;
 
   /* Most SOM relocations involving a symbol have a length which is
      dependent on the index of the symbol.  So symbols which are
@@ -2875,7 +2881,12 @@ som_prep_for_fixups (bfd *abfd, asymbol **syms, unsigned long num_syms)
 
   /* Sort a copy of the symbol table, rather than the canonical
      output symbol table.  */
-  sorted_syms = bfd_zalloc2 (abfd, num_syms, sizeof (asymbol *));
+  if (_bfd_mul_overflow (num_syms, sizeof (asymbol *), &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return FALSE;
+    }
+  sorted_syms = bfd_zalloc (abfd, amt);
   if (sorted_syms == NULL)
     return FALSE;
   memcpy (sorted_syms, syms, num_syms * sizeof (asymbol *));
@@ -4460,12 +4471,18 @@ som_build_and_write_symbol_table (bfd *abfd)
   struct som_external_symbol_dictionary_record *som_symtab = NULL;
   unsigned int i;
   bfd_size_type symtab_size;
+  size_t amt;
 
   /* Compute total symbol table size and allocate a chunk of memory
      to hold the symbol table as we build it.  */
-  som_symtab
-    = bfd_zmalloc2 (num_syms,
-                   sizeof (struct som_external_symbol_dictionary_record));
+  if (_bfd_mul_overflow (num_syms,
+                        sizeof (struct som_external_symbol_dictionary_record),
+                        &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return FALSE;
+    }
+  som_symtab = bfd_zmalloc (amt);
   if (som_symtab == NULL && num_syms != 0)
     goto error_return;
 
@@ -4638,12 +4655,12 @@ bfd_section_from_som_symbol
 static unsigned int
 som_slurp_symbol_table (bfd *abfd)
 {
-  int symbol_count = bfd_get_symcount (abfd);
-  int symsize = sizeof (struct som_external_symbol_dictionary_record);
+  unsigned int symbol_count = bfd_get_symcount (abfd);
+  size_t symsize = sizeof (struct som_external_symbol_dictionary_record);
   char *stringtab;
   struct som_external_symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
   som_symbol_type *sym, *symbase;
-  bfd_size_type amt;
+  size_t amt;
 
   /* Return saved value if it exists.  */
   if (obj_som_symtab (abfd) != NULL)
@@ -4658,18 +4675,26 @@ som_slurp_symbol_table (bfd *abfd)
 
   stringtab = obj_som_stringtab (abfd);
 
-  symbase = bfd_zmalloc2 (symbol_count, sizeof (som_symbol_type));
+  if (_bfd_mul_overflow (symbol_count, sizeof (som_symbol_type), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
+  symbase = bfd_zmalloc (amt);
   if (symbase == NULL)
     goto error_return;
 
   /* Read in the external SOM representation.  */
-  buf = bfd_malloc2 (symbol_count, symsize);
+  if (_bfd_mul_overflow (symbol_count, symsize, &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
+  buf = bfd_malloc (amt);
   if (buf == NULL)
     goto error_return;
   if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) != 0)
     goto error_return;
-  amt = symbol_count;
-  amt *= symsize;
   if (bfd_bread (buf, amt, abfd) != amt)
     goto error_return;
 
@@ -5259,7 +5284,7 @@ som_slurp_reloc_table (bfd *abfd,
   unsigned int fixup_stream_size;
   arelent *internal_relocs;
   unsigned int num_relocs;
-  bfd_size_type amt;
+  size_t amt;
 
   fixup_stream_size = som_section_data (section)->reloc_size;
   /* If there were no relocations, then there is nothing to do.  */
@@ -5303,7 +5328,12 @@ som_slurp_reloc_table (bfd *abfd,
   if (section->relocation != NULL)
     return TRUE;
 
-  internal_relocs = bfd_zalloc2 (abfd, num_relocs, sizeof (arelent));
+  if (_bfd_mul_overflow (num_relocs, sizeof (arelent), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  internal_relocs = bfd_zalloc (abfd, amt);
   if (internal_relocs == NULL)
     return FALSE;
 
@@ -5884,12 +5914,17 @@ som_bfd_count_ar_symbols (bfd *abfd,
 {
   unsigned int i;
   unsigned char *hash_table;
-  bfd_size_type amt;
+  size_t amt;
   file_ptr lst_filepos;
 
   lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
 
-  hash_table = bfd_malloc2 (lst_header->hash_size, 4);
+  if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  hash_table = bfd_malloc (amt);
   if (hash_table == NULL && lst_header->hash_size != 0)
     goto error_return;
 
@@ -5898,7 +5933,6 @@ som_bfd_count_ar_symbols (bfd *abfd,
 
   /* Read in the hash table.  The hash table is an array of 32-bit
      file offsets which point to the hash chains.  */
-  amt = (bfd_size_type) lst_header->hash_size * 4;
   if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
     goto error_return;
 
@@ -5975,18 +6009,22 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
   carsym *set = syms[0];
   unsigned char *hash_table;
   struct som_external_som_entry *som_dict = NULL;
-  bfd_size_type amt;
+  size_t amt;
   file_ptr lst_filepos;
   unsigned int string_loc;
 
   lst_filepos = bfd_tell (abfd) - sizeof (struct som_external_lst_header);
-  hash_table = bfd_malloc2 (lst_header->hash_size, 4);
+  if (_bfd_mul_overflow (lst_header->hash_size, 4, &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  hash_table = bfd_malloc (amt);
   if (hash_table == NULL && lst_header->hash_size != 0)
     goto error_return;
 
   /* Read in the hash table.  The has table is an array of 32bit file offsets
      which point to the hash chains.  */
-  amt = (bfd_size_type) lst_header->hash_size * 4;
   if (bfd_bread ((void *) hash_table, amt, abfd) != amt)
     goto error_return;
 
@@ -5995,13 +6033,16 @@ som_bfd_fill_in_ar_symbols (bfd *abfd,
   if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) != 0)
     goto error_return;
 
-  som_dict = bfd_malloc2 (lst_header->module_count,
-                         sizeof (struct som_external_som_entry));
+  if (_bfd_mul_overflow (lst_header->module_count,
+                        sizeof (struct som_external_som_entry), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      goto error_return;
+    }
+  som_dict = bfd_malloc (amt);
   if (som_dict == NULL && lst_header->module_count != 0)
     goto error_return;
 
-  amt = lst_header->module_count;
-  amt *= sizeof (struct som_external_som_entry);
   if (bfd_bread ((void *) som_dict, amt, abfd) != amt)
     goto error_return;
 
@@ -6156,7 +6197,7 @@ som_slurp_armap (bfd *abfd)
   unsigned int parsed_size;
   struct artdata *ardata = bfd_ardata (abfd);
   char nextname[17];
-  bfd_size_type amt = 16;
+  size_t amt = 16;
   int i = bfd_bread ((void *) nextname, amt, abfd);
 
   /* Special cases.  */
@@ -6225,7 +6266,12 @@ som_slurp_armap (bfd *abfd)
 
   /* Initialize the cache and allocate space for the library symbols.  */
   ardata->cache = 0;
-  ardata->symdefs = bfd_alloc2 (abfd, ardata->symdef_count, sizeof (carsym));
+  if (_bfd_mul_overflow (ardata->symdef_count, sizeof (carsym), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  ardata->symdefs = bfd_alloc (abfd, amt);
   if (!ardata->symdefs)
     return FALSE;
 
@@ -6352,22 +6398,39 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd,
   struct som_external_som_entry *som_dict = NULL;
   struct som_external_lst_symbol_record **last_hash_entry = NULL;
   unsigned int curr_som_offset, som_index = 0;
-  bfd_size_type amt;
+  size_t amt;
   unsigned int module_count;
   unsigned int hash_size;
 
   hash_size = bfd_getb32 (lst.hash_size);
-  hash_table = bfd_zmalloc2 (hash_size, 4);
+  if (_bfd_mul_overflow (hash_size, 4, &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return FALSE;
+    }
+  hash_table = bfd_zmalloc (amt);
   if (hash_table == NULL && hash_size != 0)
     goto error_return;
 
   module_count = bfd_getb32 (lst.module_count);
-  som_dict = bfd_zmalloc2 (module_count, sizeof (struct som_external_som_entry));
+  if (_bfd_mul_overflow (module_count,
+                        sizeof (struct som_external_som_entry), &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
+  som_dict = bfd_zmalloc (amt);
   if (som_dict == NULL && module_count != 0)
     goto error_return;
 
-  last_hash_entry
-    = bfd_zmalloc2 (hash_size, sizeof (struct som_external_lst_symbol_record *));
+  if (_bfd_mul_overflow (hash_size,
+                        sizeof (struct som_external_lst_symbol_record *),
+                        &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
+  last_hash_entry = bfd_zmalloc (amt);
   if (last_hash_entry == NULL && hash_size != 0)
     goto error_return;
 
@@ -6395,10 +6458,16 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd,
   curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
 
   /* FIXME should be done with buffers just like everything else...  */
-  lst_syms = bfd_malloc2 (nsyms, sizeof (struct som_external_lst_symbol_record));
+  if (_bfd_mul_overflow (nsyms,
+                        sizeof (struct som_external_lst_symbol_record), &amt))
+    {
+      bfd_set_error (bfd_error_no_memory);
+      goto error_return;
+    }
+  lst_syms = bfd_malloc (amt);
   if (lst_syms == NULL && nsyms != 0)
     goto error_return;
-  strings = bfd_malloc ((bfd_size_type) string_size);
+  strings = bfd_malloc (string_size);
   if (strings == NULL && string_size != 0)
     goto error_return;
 
@@ -6543,17 +6612,17 @@ som_bfd_ar_write_symbol_stuff (bfd *abfd,
     }
 
   /* Now scribble out the hash table.  */
-  amt = (bfd_size_type) hash_size * 4;
+  amt = (size_t) hash_size * 4;
   if (bfd_bwrite ((void *) hash_table, amt, abfd) != amt)
     goto error_return;
 
   /* Then the SOM dictionary.  */
-  amt = (bfd_size_type) module_count * sizeof (struct som_external_som_entry);
+  amt = (size_t) module_count * sizeof (struct som_external_som_entry);
   if (bfd_bwrite ((void *) som_dict, amt, abfd) != amt)
     goto error_return;
 
   /* The library symbols.  */
-  amt = (bfd_size_type) nsyms * sizeof (struct som_external_lst_symbol_record);
+  amt = (size_t) nsyms * sizeof (struct som_external_lst_symbol_record);
   if (bfd_bwrite ((void *) lst_syms, amt, abfd) != amt)
     goto error_return;
 
index ac01c4dac8a69e008897d72fbf95fbdda5286397..24842780b6d1c09da332d0b20ffbd4c43ebda294 100644 (file)
@@ -2963,17 +2963,23 @@ vector_grow1 (struct vector_type *vec, size_t elsz)
       if (vec->max_el == 0)
        {
          vec->max_el = 16;
-         vec->els = bfd_malloc2 (vec->max_el, elsz);
+         vec->els = bfd_malloc (vec->max_el * elsz);
        }
       else
        {
+         size_t amt;
          if (vec->max_el > -1u / 2)
            {
              bfd_set_error (bfd_error_file_too_big);
              return NULL;
            }
          vec->max_el *= 2;
-         vec->els = bfd_realloc2 (vec->els, vec->max_el, elsz);
+         if (_bfd_mul_overflow (vec->max_el, elsz, &amt))
+           {
+             bfd_set_error (bfd_error_file_too_big);
+             return NULL;
+           }
+         vec->els = bfd_realloc (vec->els, amt);
        }
     }
   if (vec->els == NULL)
index 3d14a461857f399a68f35dc1e975a8af79351881..dc07e79710c39624cc93b4c7130bf6287f0cb48d 100644 (file)
@@ -134,12 +134,23 @@ vms_add_index (struct carsym_mem *cs, char *name,
   if (cs->nbr == cs->max)
     {
       struct carsym *n;
+      size_t amt;
 
+      if (cs->max > -33u / 2)
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         return FALSE;
+       }
       cs->max = 2 * cs->max + 32;
+      if (_bfd_mul_overflow (cs->max, sizeof (struct carsym), &amt))
+       {
+         bfd_set_error (bfd_error_file_too_big);
+         return FALSE;
+       }
 
       if (!cs->realloced)
        {
-         n = bfd_malloc2 (cs->max, sizeof (struct carsym));
+         n = bfd_malloc (amt);
          if (n == NULL)
            return FALSE;
          memcpy (n, cs->idx, cs->nbr * sizeof (struct carsym));
@@ -147,7 +158,7 @@ vms_add_index (struct carsym_mem *cs, char *name,
        }
       else
        {
-         n = bfd_realloc_or_free (cs->idx, cs->nbr * sizeof (struct carsym));
+         n = bfd_realloc_or_free (cs->idx, amt);
          if (n == NULL)
            return FALSE;
        }
index dfd3d873b22435a7077af69be448dcf04ebede3f..315d3effb8db4dd554440cd396c224216a2a2c75 100644 (file)
@@ -245,6 +245,7 @@ wasm_scan_name_function_section (bfd *abfd, sec_ptr asect)
   tdata_type *tdata = abfd->tdata.any;
   asymbol *symbols = NULL;
   sec_ptr space_function_index;
+  size_t amt;
 
   p = asect->contents;
   end = asect->contents + asect->size;
@@ -301,7 +302,12 @@ wasm_scan_name_function_section (bfd *abfd, sec_ptr asect)
   if (!space_function_index)
     return FALSE;
 
-  symbols = bfd_alloc2 (abfd, tdata->symcount, sizeof (asymbol));
+  if (_bfd_mul_overflow (tdata->symcount, sizeof (asymbol), &amt))
+    {
+      bfd_set_error (bfd_error_file_too_big);
+      return FALSE;
+    }
+  symbols = bfd_alloc (abfd, amt);
   if (!symbols)
     return FALSE;