Miscellaneous memory alloc related fixes
authorAlan Modra <amodra@gmail.com>
Wed, 19 Feb 2020 02:45:20 +0000 (13:15 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 19 Feb 2020 02:45:20 +0000 (13:15 +1030)
Some minor tidies.  Allocating memory for internal relocs and symbols
after reading external relocs is slightly better with fuzzed files.
You can at least do something about silly sizes that way.

* aoutx.h (slurp_reloc_table): Allocate reloc_cache after
reading external relocs.
* ecoff.c (ecoff_slurp_reloc_table): Likewise.
* archive.c (_bfd_write_archive_contents): Don't twiddle bfd_error
after bfd_bread.
* archive64.c (_bfd_archive_64_bit_slurp_armap): Remove unnecessary
bfd_release.
* elf32-m32c.c (m32c_offset_for_reloc): Make shndx_buf a bfd_byte*.
(m32c_elf_relax_section): Likewise.
* elf32-rl78.c (rl78_offset_for_reloc): Likewise.
(rl78_elf_relax_section): Likewise.
* elf32-rx.c (rx_offset_for_reloc): Likewise.
(elf32_rx_relax_section): Likewise.
* mach-o.c (bfd_mach_o_alloc_and_read): Move earlier with better
parameter types and use..
(bfd_mach_o_read_dylinker, bfd_mach_o_read_dylib),
(bfd_mach_o_read_fvmlib, bfd_mach_o_read_str): ..in these functions.
* peicode.h (pe_bfd_object_p): Don't zero the part of opthdr
being read from file, just the extra.
* som.c (som_slurp_symbol_table): Allocate internal symbol buffer
after reading external syms.  Free on failure.

bfd/ChangeLog
bfd/aoutx.h
bfd/archive.c
bfd/archive64.c
bfd/ecoff.c
bfd/elf32-m32c.c
bfd/elf32-rl78.c
bfd/elf32-rx.c
bfd/mach-o.c
bfd/peicode.h
bfd/som.c

index a9e3f6729c150ef94632f4aeaec9cf2018c71b7a..85747ad64f99d1f1391bd9df6f29be41c44f1bc4 100644 (file)
@@ -1,3 +1,27 @@
+2020-02-19  Alan Modra  <amodra@gmail.com>
+
+       * aoutx.h (slurp_reloc_table): Allocate reloc_cache after
+       reading external relocs.
+       * ecoff.c (ecoff_slurp_reloc_table): Likewise.
+       * archive.c (_bfd_write_archive_contents): Don't twiddle bfd_error
+       after bfd_bread.
+       * archive64.c (_bfd_archive_64_bit_slurp_armap): Remove unnecessary
+       bfd_release.
+       * elf32-m32c.c (m32c_offset_for_reloc): Make shndx_buf a bfd_byte*.
+       (m32c_elf_relax_section): Likewise.
+       * elf32-rl78.c (rl78_offset_for_reloc): Likewise.
+       (rl78_elf_relax_section): Likewise.
+       * elf32-rx.c (rx_offset_for_reloc): Likewise.
+       (elf32_rx_relax_section): Likewise.
+       * mach-o.c (bfd_mach_o_alloc_and_read): Move earlier with better
+       parameter types and use..
+       (bfd_mach_o_read_dylinker, bfd_mach_o_read_dylib),
+       (bfd_mach_o_read_fvmlib, bfd_mach_o_read_str): ..in these functions.
+       * peicode.h (pe_bfd_object_p): Don't zero the part of opthdr
+       being read from file, just the extra.
+       * som.c (som_slurp_symbol_table): Allocate internal symbol buffer
+       after reading external syms.  Free on failure.
+
 2020-02-19  Alan Modra  <amodra@gmail.com>
 
        * coffcode.h (buy_and_read, coff_slurp_line_table),
index df04ab2644966398d8834d7c7c0b687ca8a092fe..7cc72b4b67741c7c04677721fecfc3ba1c4a1caa 100644 (file)
@@ -2316,34 +2316,29 @@ NAME (aout, slurp_reloc_table) (bfd *abfd, sec_ptr asect, asymbol **symbols)
       return FALSE;
     }
 
-  if (reloc_size == 0)
-    return TRUE;               /* Nothing to be done.  */
-
-  if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
-    return FALSE;
-
   each_size = obj_reloc_entry_size (abfd);
-
   count = reloc_size / each_size;
   if (count == 0)
     return TRUE;               /* Nothing to be done.  */
 
-  amt = count * sizeof (arelent);
-  reloc_cache = (arelent *) bfd_zmalloc (amt);
-  if (reloc_cache == NULL)
+  if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
     return FALSE;
 
   relocs = bfd_malloc (reloc_size);
   if (relocs == NULL)
+    return FALSE;
+
+  if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
     {
-      free (reloc_cache);
+      free (relocs);
       return FALSE;
     }
 
-  if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
+  amt = count * sizeof (arelent);
+  reloc_cache = (arelent *) bfd_zmalloc (amt);
+  if (reloc_cache == NULL)
     {
       free (relocs);
-      free (reloc_cache);
       return FALSE;
     }
 
index 67d1c9e1534b9794435e2c6e4e6e47568c2f3c45..91127d7e6be6468650947d5ff92e5f97236219f6 100644 (file)
@@ -2193,11 +2193,7 @@ _bfd_write_archive_contents (bfd *arch)
            amt = remaining;
          errno = 0;
          if (bfd_bread (buffer, amt, current) != amt)
-           {
-             if (bfd_get_error () != bfd_error_system_call)
-               bfd_set_error (bfd_error_file_truncated);
-             goto input_err;
-           }
+           goto input_err;
          if (bfd_bwrite (buffer, amt, arch) != amt)
            return FALSE;
          remaining -= amt;
index 59e42c699e78774bc11c5dc976448f8469027b01..c693ff9d0b18d052bfaf58244642a7b9428cc902 100644 (file)
@@ -117,7 +117,7 @@ _bfd_archive_64_bit_slurp_armap (bfd *abfd)
     {
       if (bfd_get_error () != bfd_error_system_call)
        bfd_set_error (bfd_error_malformed_archive);
-      goto release_raw_armap;
+      goto release_symdefs;
     }
 
   stringend = stringbase + stringsize;
@@ -142,8 +142,6 @@ _bfd_archive_64_bit_slurp_armap (bfd *abfd)
 
   return TRUE;
 
-release_raw_armap:
-  bfd_release (abfd, raw_armap);
 release_symdefs:
   bfd_release (abfd, ardata->symdefs);
   return FALSE;
index 15c18aca76d937990b387dda59d453cd38c2339b..1d9e385b2b5b0fdac6e5fa26b5c9c80511649a04 100644 (file)
@@ -1623,20 +1623,25 @@ ecoff_slurp_reloc_table (bfd *abfd,
   if (! _bfd_ecoff_slurp_symbol_table (abfd))
     return FALSE;
 
-  amt = section->reloc_count;
-  amt *= sizeof (arelent);
-  internal_relocs = (arelent *) bfd_alloc (abfd, amt);
-
   external_reloc_size = backend->external_reloc_size;
   amt = external_reloc_size * section->reloc_count;
   external_relocs = (char *) bfd_alloc (abfd, amt);
-  if (internal_relocs == NULL || external_relocs == NULL)
+  if (external_relocs == NULL)
     return FALSE;
   if (bfd_seek (abfd, section->rel_filepos, SEEK_SET) != 0)
     return FALSE;
   if (bfd_bread (external_relocs, amt, abfd) != amt)
     return FALSE;
 
+  amt = section->reloc_count;
+  amt *= sizeof (arelent);
+  internal_relocs = (arelent *) bfd_alloc (abfd, amt);
+  if (internal_relocs == NULL)
+    {
+      bfd_release (abfd, external_relocs);
+      return FALSE;
+    }
+
   for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++)
     {
       struct internal_reloc intern;
index 89bdccacd062cf3c1dd035f3b6058847e9154e6e..a4dfd8d3d4e5c25d65c5addc115549241bacdabb 100644 (file)
@@ -1284,7 +1284,7 @@ static bfd_vma
 m32c_offset_for_reloc (bfd *abfd,
                       Elf_Internal_Rela *rel,
                       Elf_Internal_Shdr *symtab_hdr,
-                      Elf_External_Sym_Shndx *shndx_buf ATTRIBUTE_UNUSED,
+                      bfd_byte *shndx_buf ATTRIBUTE_UNUSED,
                       Elf_Internal_Sym *intsyms)
 {
   bfd_vma symval;
@@ -1442,7 +1442,7 @@ m32c_elf_relax_section
   bfd_byte * free_contents = NULL;
   Elf_Internal_Sym *intsyms = NULL;
   Elf_Internal_Sym *free_intsyms = NULL;
-  Elf_External_Sym_Shndx *shndx_buf = NULL;
+  bfd_byte *shndx_buf = NULL;
   int machine;
 
   if (abfd == elf_hash_table (link_info)->dynobj
@@ -1499,13 +1499,13 @@ m32c_elf_relax_section
          bfd_set_error (bfd_error_file_too_big);
          goto error_return;
        }
-      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+      shndx_buf = bfd_malloc (amt);
       if (shndx_buf == NULL)
        goto error_return;
       if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
          || bfd_bread (shndx_buf, amt, abfd) != amt)
        goto error_return;
-      shndx_hdr->contents = (bfd_byte *) shndx_buf;
+      shndx_hdr->contents = shndx_buf;
     }
 
   /* Get a copy of the native relocations.  */
index f4abf0425e8f55a7fd0300a594f9edefc76416fa..40f8c5881b1d151e933e058127b2c42951b8439c 100644 (file)
@@ -1822,7 +1822,7 @@ static bfd_vma
 rl78_offset_for_reloc (bfd *                   abfd,
                       Elf_Internal_Rela *      rel,
                       Elf_Internal_Shdr *      symtab_hdr,
-                      Elf_External_Sym_Shndx * shndx_buf ATTRIBUTE_UNUSED,
+                      bfd_byte *               shndx_buf ATTRIBUTE_UNUSED,
                       Elf_Internal_Sym *       intsyms,
                       Elf_Internal_Rela **     lrel,
                       bfd *                    input_bfd,
@@ -2068,7 +2068,7 @@ rl78_elf_relax_section
   bfd_byte *         free_contents = NULL;
   Elf_Internal_Sym *  intsyms = NULL;
   Elf_Internal_Sym *  free_intsyms = NULL;
-  Elf_External_Sym_Shndx * shndx_buf = NULL;
+  bfd_byte *         shndx_buf = NULL;
   bfd_vma pc;
   bfd_vma symval ATTRIBUTE_UNUSED = 0;
   int pcrel ATTRIBUTE_UNUSED = 0;
@@ -2129,13 +2129,13 @@ rl78_elf_relax_section
          bfd_set_error (bfd_error_no_memory);
          goto error_return;
        }
-      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+      shndx_buf = bfd_malloc (amt);
       if (shndx_buf == NULL)
        goto error_return;
       if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
          || bfd_bread (shndx_buf, amt, abfd) != amt)
        goto error_return;
-      shndx_hdr->contents = (bfd_byte *) shndx_buf;
+      shndx_hdr->contents = shndx_buf;
     }
 
   /* Get a copy of the native relocations.  */
index a94aee729cfb3b8204847aa258bc98aaeb8fab6e..0a9900ff21bf37c59aea3fabd2fc0bb8031a8763 100644 (file)
@@ -1738,7 +1738,7 @@ static bfd_vma
 rx_offset_for_reloc (bfd *                   abfd,
                     Elf_Internal_Rela *      rel,
                     Elf_Internal_Shdr *      symtab_hdr,
-                    Elf_External_Sym_Shndx * shndx_buf ATTRIBUTE_UNUSED,
+                    bfd_byte *               shndx_buf ATTRIBUTE_UNUSED,
                     Elf_Internal_Sym *       intsyms,
                     Elf_Internal_Rela **     lrel,
                     bfd *                    input_bfd,
@@ -2005,7 +2005,7 @@ elf32_rx_relax_section (bfd *                    abfd,
   bfd_byte *         free_contents = NULL;
   Elf_Internal_Sym *  intsyms = NULL;
   Elf_Internal_Sym *  free_intsyms = NULL;
-  Elf_External_Sym_Shndx * shndx_buf = NULL;
+  bfd_byte *         shndx_buf = NULL;
   bfd_vma pc;
   bfd_vma sec_start;
   bfd_vma symval = 0;
@@ -2066,13 +2066,13 @@ elf32_rx_relax_section (bfd *                  abfd,
          bfd_set_error (bfd_error_file_too_big);
          goto error_return;
        }
-      shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+      shndx_buf = bfd_malloc (amt);
       if (shndx_buf == NULL)
        goto error_return;
       if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
          || bfd_bread (shndx_buf, amt, abfd) != amt)
        goto error_return;
-      shndx_hdr->contents = (bfd_byte *) shndx_buf;
+      shndx_hdr->contents = shndx_buf;
     }
 
   /* Get a copy of the native relocations.  */
index 1cc9d432503f84eb4ae519271cf7bd92cdc390e1..fd9f480245c4597c837cde6d8766b06b541f5319 100644 (file)
@@ -3997,6 +3997,20 @@ bfd_mach_o_ppc_flavour_string (unsigned int flavour)
     }
 }
 
+static unsigned char *
+bfd_mach_o_alloc_and_read (bfd *abfd, file_ptr filepos, size_t size)
+{
+  unsigned char *buf;
+
+  buf = bfd_alloc (abfd, size);
+  if (buf == NULL)
+    return NULL;
+  if (bfd_seek (abfd, filepos, SEEK_SET) != 0
+      || bfd_bread (buf, size, abfd) != size)
+    return NULL;
+  return buf;
+}
+
 static bfd_boolean
 bfd_mach_o_read_dylinker (bfd *abfd, bfd_mach_o_load_command *command)
 {
@@ -4017,13 +4031,8 @@ bfd_mach_o_read_dylinker (bfd *abfd, bfd_mach_o_load_command *command)
   cmd->name_offset = nameoff;
   namelen = command->len - nameoff;
   nameoff += command->offset;
-  cmd->name_str = bfd_alloc (abfd, namelen);
-  if (cmd->name_str == NULL)
-    return FALSE;
-  if (bfd_seek (abfd, nameoff, SEEK_SET) != 0
-      || bfd_bread (cmd->name_str, namelen, abfd) != namelen)
-    return FALSE;
-  return TRUE;
+  cmd->name_str = (char *) bfd_mach_o_alloc_and_read (abfd, nameoff, namelen);
+  return cmd->name_str != NULL;
 }
 
 static bfd_boolean
@@ -4034,6 +4043,7 @@ bfd_mach_o_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
   struct mach_o_dylib_command_external raw;
   unsigned int nameoff;
   unsigned int namelen;
+  file_ptr pos;
 
   if (command->len < sizeof (raw) + 8)
     return FALSE;
@@ -4063,13 +4073,9 @@ bfd_mach_o_read_dylib (bfd *abfd, bfd_mach_o_load_command *command)
 
   cmd->name_offset = command->offset + nameoff;
   namelen = command->len - nameoff;
-  cmd->name_str = bfd_alloc (abfd, namelen);
-  if (cmd->name_str == NULL)
-    return FALSE;
-  if (bfd_seek (abfd, mdata->hdr_offset + cmd->name_offset, SEEK_SET) != 0
-      || bfd_bread (cmd->name_str, namelen, abfd) != namelen)
-    return FALSE;
-  return TRUE;
+  pos = mdata->hdr_offset + cmd->name_offset;
+  cmd->name_str = (char *) bfd_mach_o_alloc_and_read (abfd, pos, namelen);
+  return cmd->name_str != NULL;
 }
 
 static bfd_boolean
@@ -4163,13 +4169,9 @@ bfd_mach_o_read_fvmlib (bfd *abfd, bfd_mach_o_load_command *command)
 
   fvm->name_offset = command->offset + nameoff;
   namelen = command->len - nameoff;
-  fvm->name_str = bfd_alloc (abfd, namelen);
-  if (fvm->name_str == NULL)
-    return FALSE;
-  if (bfd_seek (abfd, fvm->name_offset, SEEK_SET) != 0
-      || bfd_bread (fvm->name_str, namelen, abfd) != namelen)
-    return FALSE;
-  return TRUE;
+  fvm->name_str = (char *) bfd_mach_o_alloc_and_read (abfd, fvm->name_offset,
+                                                     namelen);
+  return fvm->name_str != NULL;
 }
 
 static bfd_boolean
@@ -4568,27 +4570,9 @@ bfd_mach_o_read_str (bfd *abfd, bfd_mach_o_load_command *command)
 
   cmd->stroff = command->offset + off;
   cmd->str_len = command->len - off;
-  cmd->str = bfd_alloc (abfd, cmd->str_len);
-  if (cmd->str == NULL)
-    return FALSE;
-  if (bfd_seek (abfd, cmd->stroff, SEEK_SET) != 0
-      || bfd_bread ((void *) cmd->str, cmd->str_len, abfd) != cmd->str_len)
-    return FALSE;
-  return TRUE;
-}
-
-static unsigned char *
-bfd_mach_o_alloc_and_read (bfd *abfd, unsigned int off, unsigned int size)
-{
-  unsigned char *buf;
-
-  buf = bfd_alloc (abfd, size);
-  if (buf == NULL)
-    return NULL;
-  if (bfd_seek (abfd, off, SEEK_SET) != 0
-      || bfd_bread (buf, size, abfd) != size)
-    return NULL;
-  return buf;
+  cmd->str = (char *) bfd_mach_o_alloc_and_read (abfd, cmd->stroff,
+                                                cmd->str_len);
+  return cmd->str != NULL;
 }
 
 static bfd_boolean
index c1bc81b169aae5fcdc0f5192ba2d8e478fb95bec..3f772a0785a43f886a253d5670690ebe36b685d7 100644 (file)
@@ -1408,7 +1408,7 @@ pe_bfd_object_p (bfd * abfd)
   struct external_PEI_IMAGE_hdr image_hdr;
   struct internal_filehdr internal_f;
   struct internal_aouthdr internal_a;
-  file_ptr opt_hdr_size;
+  bfd_size_type opt_hdr_size;
   file_ptr offset;
   const bfd_target *result;
 
@@ -1494,12 +1494,14 @@ pe_bfd_object_p (bfd * abfd)
       if (amt < sizeof (PEAOUTHDR))
        amt = sizeof (PEAOUTHDR);
 
-      opthdr = bfd_zalloc (abfd, amt);
+      opthdr = bfd_alloc (abfd, amt);
       if (opthdr == NULL)
        return NULL;
       if (bfd_bread (opthdr, opt_hdr_size, abfd)
          != (bfd_size_type) opt_hdr_size)
        return NULL;
+      if (amt > opt_hdr_size)
+       memset (opthdr + opt_hdr_size, 0, amt - opt_hdr_size);
 
       bfd_set_error (bfd_error_no_error);
       bfd_coff_swap_aouthdr_in (abfd, opthdr, & internal_a);
index d7d4d8f845f37938a7aa7519ae82738a4ac82992..bd685920ba76273085fbf7911f5cc26443731ce8 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -4659,7 +4659,7 @@ som_slurp_symbol_table (bfd *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;
+  som_symbol_type *sym, *symbase = NULL;
   size_t amt;
 
   /* Return saved value if it exists.  */
@@ -4675,15 +4675,6 @@ som_slurp_symbol_table (bfd *abfd)
 
   stringtab = obj_som_stringtab (abfd);
 
-  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.  */
   if (_bfd_mul_overflow (symbol_count, symsize, &amt))
     {
@@ -4698,6 +4689,15 @@ som_slurp_symbol_table (bfd *abfd)
   if (bfd_bread (buf, amt, abfd) != amt)
     goto error_return;
 
+  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;
+
   /* Iterate over all the symbols and internalize them.  */
   endbufp = buf + symbol_count;
   for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
@@ -4837,6 +4837,8 @@ som_slurp_symbol_table (bfd *abfd)
   return (TRUE);
 
  error_return:
+  if (symbase != NULL)
+    free (symbase);
   if (buf != NULL)
     free (buf);
   return FALSE;