* libbfd-in.h (bfd_malloc2, bfd_realloc2, bfd_zmalloc2, bfd_alloc2,
authorJakub Jelinek <jakub@redhat.com>
Tue, 5 Jul 2005 09:44:20 +0000 (09:44 +0000)
committerJakub Jelinek <jakub@redhat.com>
Tue, 5 Jul 2005 09:44:20 +0000 (09:44 +0000)
bfd_zalloc2): New prototypes.
* bfd-in.h (HALF_BFD_SIZE_TYPE): Define.
* libbfd.c (bfd_malloc2, bfd_realloc2, bfd_zmalloc2): New functions.
* opncls.c (bfd_alloc2, bfd_zalloc2): New functions.
* elf.c (bfd_elf_get_elf_syms, setup_group, assign_section_numbers,
elf_map_symbols, map_sections_to_segments,
assign_file_positions_for_segments, copy_private_bfd_data,
swap_out_syms, _bfd_elf_slurp_version_tables): Use bfd_*alloc2
where appropriate.
* bfd-in2.h: Rebuilt.
* libbfd.h: Rebuilt.

* elf.c (_bfd_elf_print_private_bfd_data): Don't crash on bogus
verdef or verneed section.
(_bfd_elf_slurp_version_tables): Handle corrupt verdef and/or
verneed sections gracefully.
* elfxx-sparc.c (_bfd_sparc_elf_info_to_howto_ptr): Don't crash on
bogus relocation values.
* elf64-ppc.c (ppc64_elf_info_to_howto): Likewise.
* elf64-s390.c (elf_s390_info_to_howto): Likewise.
* elf32-s390.c (elf_s390_info_to_howto): Likewise.
* elf64-x86-64.c (elf64_x86_64_info_to_howto): Likewise.
* elfxx-ia64.c (lookup_howto): Likewise.

14 files changed:
bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elf.c
bfd/elf32-s390.c
bfd/elf64-ppc.c
bfd/elf64-s390.c
bfd/elf64-x86-64.c
bfd/elfxx-ia64.c
bfd/elfxx-sparc.c
bfd/libbfd-in.h
bfd/libbfd.c
bfd/libbfd.h
bfd/opncls.c

index 3bd8f0b8ae0cdcadd36375b816710c384d2b50d2..c91ffab182d3a699617c29545bc274ac519ea897 100644 (file)
@@ -1,5 +1,30 @@
 2005-07-05  Jakub Jelinek  <jakub@redhat.com>
 
+       * libbfd-in.h (bfd_malloc2, bfd_realloc2, bfd_zmalloc2, bfd_alloc2,
+       bfd_zalloc2): New prototypes.
+       * bfd-in.h (HALF_BFD_SIZE_TYPE): Define.
+       * libbfd.c (bfd_malloc2, bfd_realloc2, bfd_zmalloc2): New functions.
+       * opncls.c (bfd_alloc2, bfd_zalloc2): New functions.
+       * elf.c (bfd_elf_get_elf_syms, setup_group, assign_section_numbers,
+       elf_map_symbols, map_sections_to_segments,
+       assign_file_positions_for_segments, copy_private_bfd_data,
+       swap_out_syms, _bfd_elf_slurp_version_tables): Use bfd_*alloc2
+       where appropriate.
+       * bfd-in2.h: Rebuilt.
+       * libbfd.h: Rebuilt.
+
+       * elf.c (_bfd_elf_print_private_bfd_data): Don't crash on bogus
+       verdef or verneed section.
+       (_bfd_elf_slurp_version_tables): Handle corrupt verdef and/or
+       verneed sections gracefully.
+       * elfxx-sparc.c (_bfd_sparc_elf_info_to_howto_ptr): Don't crash on
+       bogus relocation values.
+       * elf64-ppc.c (ppc64_elf_info_to_howto): Likewise.
+       * elf64-s390.c (elf_s390_info_to_howto): Likewise.
+       * elf32-s390.c (elf_s390_info_to_howto): Likewise.
+       * elf64-x86-64.c (elf64_x86_64_info_to_howto): Likewise.
+       * elfxx-ia64.c (lookup_howto): Likewise.
+
        * elf.c (bfd_elf_get_str_section): Allocate an extra byte after
        the end of strtab and clear it.
        (elf_read): Remove.
index b8c4ef89ebaeb61c7d7760e3ab8a634258ccdd9c..4d999b9f1d06c95025e39a2f3ae97195186d6edc 100644 (file)
@@ -136,6 +136,9 @@ typedef unsigned long bfd_size_type;
 
 #endif /* not BFD64  */
 
+#define HALF_BFD_SIZE_TYPE \
+  (((bfd_size_type) 1) << (8 * sizeof (bfd_size_type) / 2))
+
 #ifndef BFD_HOST_64_BIT
 /* Fall back on a 32 bit type.  The idea is to make these types always
    available for function return types, but in the case that
index 7d16049c82aed0bd300a1d803e7cab857a46e33a..ada5e0ebf8ce6501ec26bef11ed0c6d755f21da5 100644 (file)
@@ -143,6 +143,9 @@ typedef unsigned long bfd_size_type;
 
 #endif /* not BFD64  */
 
+#define HALF_BFD_SIZE_TYPE \
+  (((bfd_size_type) 1) << (8 * sizeof (bfd_size_type) / 2))
+
 #ifndef BFD_HOST_64_BIT
 /* Fall back on a 32 bit type.  The idea is to make these types always
    available for function return types, but in the case that
index 447074426976789ce850af664db428ffcbe0df3f..130ec7a71d028b6b3091e4a85dd550c5509cacd2 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -340,7 +340,7 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   pos = symtab_hdr->sh_offset + symoffset * extsym_size;
   if (extsym_buf == NULL)
     {
-      alloc_ext = bfd_malloc (amt);
+      alloc_ext = bfd_malloc2 (symcount, extsym_size);
       extsym_buf = alloc_ext;
     }
   if (extsym_buf == NULL
@@ -359,7 +359,8 @@ bfd_elf_get_elf_syms (bfd *ibfd,
       pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
       if (extshndx_buf == NULL)
        {
-         alloc_extshndx = bfd_malloc (amt);
+         alloc_extshndx = bfd_malloc2 (symcount,
+                                       sizeof (Elf_External_Sym_Shndx));
          extshndx_buf = alloc_extshndx;
        }
       if (extshndx_buf == NULL
@@ -373,8 +374,7 @@ bfd_elf_get_elf_syms (bfd *ibfd,
 
   if (intsym_buf == NULL)
     {
-      bfd_size_type amt = symcount * sizeof (Elf_Internal_Sym);
-      intsym_buf = bfd_malloc (amt);
+      intsym_buf = bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
       if (intsym_buf == NULL)
        goto out;
     }
@@ -494,10 +494,10 @@ 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;
-         
+
          elf_tdata (abfd)->num_group = num_group;
-         amt = num_group * sizeof (Elf_Internal_Shdr *);
-         elf_tdata (abfd)->group_sect_ptr = bfd_alloc (abfd, amt);
+         elf_tdata (abfd)->group_sect_ptr
+           = bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
          if (elf_tdata (abfd)->group_sect_ptr == NULL)
            return FALSE;
 
@@ -517,7 +517,8 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                  /* Read the raw contents.  */
                  BFD_ASSERT (sizeof (*dest) >= 4);
                  amt = shdr->sh_size * sizeof (*dest) / 4;
-                 shdr->contents = bfd_alloc (abfd, amt);
+                 shdr->contents = bfd_alloc2 (abfd, shdr->sh_size,
+                                              sizeof (*dest) / 4);
                  if (shdr->contents == NULL
                      || bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
                      || (bfd_bread (shdr->contents, shdr->sh_size, abfd)
@@ -1219,8 +1220,9 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
       for (t = elf_tdata (abfd)->verdef; t != NULL; t = t->vd_nextdef)
        {
          fprintf (f, "%d 0x%2.2x 0x%8.8lx %s\n", t->vd_ndx,
-                  t->vd_flags, t->vd_hash, t->vd_nodename);
-         if (t->vd_auxptr->vda_nextptr != NULL)
+                  t->vd_flags, t->vd_hash,
+                  t->vd_nodename ? t->vd_nodename : "<corrupt>");
+         if (t->vd_auxptr != NULL && t->vd_auxptr->vda_nextptr != NULL)
            {
              Elf_Internal_Verdaux *a;
 
@@ -1228,7 +1230,8 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
              for (a = t->vd_auxptr->vda_nextptr;
                   a != NULL;
                   a = a->vda_nextptr)
-               fprintf (f, "%s ", a->vda_nodename);
+               fprintf (f, "%s ",
+                        a->vda_nodename ? a->vda_nodename : "<corrupt>");
              fprintf (f, "\n");
            }
        }
@@ -1243,10 +1246,12 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
        {
          Elf_Internal_Vernaux *a;
 
-         fprintf (f, _("  required from %s:\n"), t->vn_filename);
+         fprintf (f, _("  required from %s:\n"),
+                  t->vn_filename ? t->vn_filename : "<corrupt>");
          for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
            fprintf (f, "    0x%8.8lx 0x%2.2x %2.2d %s\n", a->vna_hash,
-                    a->vna_flags, a->vna_other, a->vna_nodename);
+                    a->vna_flags, a->vna_other,
+                    a->vna_nodename ? a->vna_nodename : "<corrupt>");
        }
     }
 
@@ -2883,7 +2888,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   asection *sec;
   unsigned int section_number, secn;
   Elf_Internal_Shdr **i_shdrp;
-  bfd_size_type amt;
   struct bfd_elf_section_data *d;
 
   section_number = 1;
@@ -2987,13 +2991,11 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 
   /* Set up the list of section header pointers, in agreement with the
      indices.  */
-  amt = section_number * sizeof (Elf_Internal_Shdr *);
-  i_shdrp = bfd_zalloc (abfd, amt);
+  i_shdrp = bfd_zalloc2 (abfd, section_number, sizeof (Elf_Internal_Shdr *));
   if (i_shdrp == NULL)
     return FALSE;
 
-  amt = sizeof (Elf_Internal_Shdr);
-  i_shdrp[0] = bfd_zalloc (abfd, amt);
+  i_shdrp[0] = bfd_zalloc (abfd, sizeof (Elf_Internal_Shdr));
   if (i_shdrp[0] == NULL)
     {
       bfd_release (abfd, i_shdrp);
@@ -3244,7 +3246,6 @@ elf_map_symbols (bfd *abfd)
   unsigned int idx;
   asection *asect;
   asymbol **new_syms;
-  bfd_size_type amt;
 
 #ifdef DEBUG
   fprintf (stderr, "elf_map_symbols\n");
@@ -3258,8 +3259,7 @@ elf_map_symbols (bfd *abfd)
     }
 
   max_index++;
-  amt = max_index * sizeof (asymbol *);
-  sect_syms = bfd_zalloc (abfd, amt);
+  sect_syms = bfd_zalloc2 (abfd, max_index, sizeof (asymbol *));
   if (sect_syms == NULL)
     return FALSE;
   elf_section_syms (abfd) = sect_syms;
@@ -3332,8 +3332,7 @@ elf_map_symbols (bfd *abfd)
     }
 
   /* Now sort the symbols so the local symbols are first.  */
-  amt = (num_locals + num_globals) * sizeof (asymbol *);
-  new_syms = bfd_alloc (abfd, amt);
+  new_syms = bfd_alloc2 (abfd, num_locals + num_globals, sizeof (asymbol *));
 
   if (new_syms == NULL)
     return FALSE;
@@ -3592,8 +3591,7 @@ map_sections_to_segments (bfd *abfd)
 
   /* Select the allocated sections, and sort them.  */
 
-  amt = bfd_count_sections (abfd) * sizeof (asection *);
-  sections = bfd_malloc (amt);
+  sections = bfd_malloc2 (bfd_count_sections (abfd), sizeof (asection *));
   if (sections == NULL)
     goto error_return;
 
@@ -4025,7 +4023,6 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
   bfd_vma filehdr_vaddr, filehdr_paddr;
   bfd_vma phdrs_vaddr, phdrs_paddr;
   Elf_Internal_Phdr *p;
-  bfd_size_type amt;
 
   if (elf_tdata (abfd)->segment_map == NULL)
     {
@@ -4100,8 +4097,7 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
   if (alloc == 0)
     alloc = count;
 
-  amt = alloc * sizeof (Elf_Internal_Phdr);
-  phdrs = bfd_alloc (abfd, amt);
+  phdrs = bfd_alloc2 (abfd, alloc, sizeof (Elf_Internal_Phdr));
   if (phdrs == NULL)
     return FALSE;
 
@@ -5361,8 +5357,7 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd)
 
       /* Gcc 2.96 miscompiles this code on mips. Don't do casting here
         to work around this long long bug.  */
-      amt = section_count * sizeof (asection *);
-      sections = bfd_malloc (amt);
+      sections = bfd_malloc2 (section_count, sizeof (asection *));
       if (sections == NULL)
        return FALSE;
 
@@ -5784,8 +5779,7 @@ swap_out_syms (bfd *abfd,
   symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
   symstrtab_hdr->sh_type = SHT_STRTAB;
 
-  amt = (bfd_size_type) (1 + symcount) * bed->s->sizeof_sym;
-  outbound_syms = bfd_alloc (abfd, amt);
+  outbound_syms = bfd_alloc2 (abfd, 1 + symcount, bed->s->sizeof_sym);
   if (outbound_syms == NULL)
     {
       _bfd_stringtab_free (stt);
@@ -5798,7 +5792,8 @@ swap_out_syms (bfd *abfd,
   if (symtab_shndx_hdr->sh_name != 0)
     {
       amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
-      outbound_shndx = bfd_zalloc (abfd, amt);
+      outbound_shndx = bfd_zalloc2 (abfd, 1 + symcount,
+                                   sizeof (Elf_External_Sym_Shndx));
       if (outbound_shndx == NULL)
        {
          _bfd_stringtab_free (stt);
@@ -6211,7 +6206,6 @@ bfd_boolean
 _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
 {
   bfd_byte *contents = NULL;
-  bfd_size_type amt;
   unsigned int freeidx = 0;
 
   if (elf_dynverref (abfd) != 0)
@@ -6220,11 +6214,12 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
       Elf_External_Verneed *everneed;
       Elf_Internal_Verneed *iverneed;
       unsigned int i;
+      bfd_byte *contents_end;
 
       hdr = &elf_tdata (abfd)->dynverref_hdr;
 
-      amt = (bfd_size_type) hdr->sh_info * sizeof (Elf_Internal_Verneed);
-      elf_tdata (abfd)->verref = bfd_zalloc (abfd, amt);
+      elf_tdata (abfd)->verref = bfd_zalloc2 (abfd, hdr->sh_info,
+                                             sizeof (Elf_Internal_Verneed));
       if (elf_tdata (abfd)->verref == NULL)
        goto error_return;
 
@@ -6232,11 +6227,22 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
 
       contents = bfd_malloc (hdr->sh_size);
       if (contents == NULL)
-       goto error_return;
+       {
+error_return_verref:
+         elf_tdata (abfd)->verref = NULL;
+         elf_tdata (abfd)->cverrefs = 0;
+         goto error_return;
+       }
       if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
          || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
-       goto error_return;
+       goto error_return_verref;
 
+      if (hdr->sh_info && hdr->sh_size < sizeof (Elf_External_Verneed))
+       goto error_return_verref;
+
+      BFD_ASSERT (sizeof (Elf_External_Verneed)
+                 == sizeof (Elf_External_Vernaux));
+      contents_end = contents + hdr->sh_size - sizeof (Elf_External_Verneed);
       everneed = (Elf_External_Verneed *) contents;
       iverneed = elf_tdata (abfd)->verref;
       for (i = 0; i < hdr->sh_info; i++, iverneed++)
@@ -6253,11 +6259,21 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
            bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
                                             iverneed->vn_file);
          if (iverneed->vn_filename == NULL)
-           goto error_return;
+           goto error_return_verref;
 
-         amt = iverneed->vn_cnt;
-         amt *= sizeof (Elf_Internal_Vernaux);
-         iverneed->vn_auxptr = bfd_alloc (abfd, amt);
+         if (iverneed->vn_cnt == 0)
+           iverneed->vn_auxptr = NULL;
+         else
+           {
+             iverneed->vn_auxptr = bfd_alloc2 (abfd, iverneed->vn_cnt,
+                                               sizeof (Elf_Internal_Vernaux));
+             if (iverneed->vn_auxptr == NULL)
+               goto error_return_verref;
+           }
+
+         if (iverneed->vn_aux
+             > (size_t) (contents_end - (bfd_byte *) everneed))
+           goto error_return_verref;
 
          evernaux = ((Elf_External_Vernaux *)
                      ((bfd_byte *) everneed + iverneed->vn_aux));
@@ -6270,13 +6286,17 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
                bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
                                                 ivernaux->vna_name);
              if (ivernaux->vna_nodename == NULL)
-               goto error_return;
+               goto error_return_verref;
 
              if (j + 1 < iverneed->vn_cnt)
                ivernaux->vna_nextptr = ivernaux + 1;
              else
                ivernaux->vna_nextptr = NULL;
 
+             if (ivernaux->vna_next
+                 > (size_t) (contents_end - (bfd_byte *) evernaux))
+               goto error_return_verref;
+
              evernaux = ((Elf_External_Vernaux *)
                          ((bfd_byte *) evernaux + ivernaux->vna_next));
 
@@ -6289,6 +6309,10 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
          else
            iverneed->vn_nextref = NULL;
 
+         if (iverneed->vn_next
+             > (size_t) (contents_end - (bfd_byte *) everneed))
+           goto error_return_verref;
+
          everneed = ((Elf_External_Verneed *)
                      ((bfd_byte *) everneed + iverneed->vn_next));
        }
@@ -6306,6 +6330,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
       Elf_Internal_Verdef iverdefmem;
       unsigned int i;
       unsigned int maxidx;
+      bfd_byte *contents_end_def, *contents_end_aux;
 
       hdr = &elf_tdata (abfd)->dynverdef_hdr;
 
@@ -6316,6 +6341,16 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
          || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
        goto error_return;
 
+      if (hdr->sh_info && hdr->sh_size < sizeof (Elf_External_Verdef))
+       goto error_return;
+
+      BFD_ASSERT (sizeof (Elf_External_Verdef)
+                 >= sizeof (Elf_External_Verdaux));
+      contents_end_def = contents + hdr->sh_size
+                        - sizeof (Elf_External_Verdef);
+      contents_end_aux = contents + hdr->sh_size
+                        - sizeof (Elf_External_Verdaux);
+
       /* We know the number of entries in the section but not the maximum
         index.  Therefore we have to run through all entries and find
         the maximum.  */
@@ -6328,6 +6363,10 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
          if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) > maxidx)
            maxidx = iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION);
 
+         if (iverdefmem.vd_next
+             > (size_t) (contents_end_def - (bfd_byte *) everdef))
+           goto error_return;
+
          everdef = ((Elf_External_Verdef *)
                     ((bfd_byte *) everdef + iverdefmem.vd_next));
        }
@@ -6339,8 +6378,8 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
          else
            freeidx = ++maxidx;
        }
-      amt = (bfd_size_type) maxidx * sizeof (Elf_Internal_Verdef);
-      elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
+      elf_tdata (abfd)->verdef = bfd_zalloc2 (abfd, maxidx,
+                                             sizeof (Elf_Internal_Verdef));
       if (elf_tdata (abfd)->verdef == NULL)
        goto error_return;
 
@@ -6356,15 +6395,32 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
 
          _bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
 
+         if ((iverdefmem.vd_ndx & VERSYM_VERSION) == 0)
+           {
+error_return_verdef:
+             elf_tdata (abfd)->verdef = NULL;
+             elf_tdata (abfd)->cverdefs = 0;
+             goto error_return;
+           }
+
          iverdef = &iverdefarr[(iverdefmem.vd_ndx & VERSYM_VERSION) - 1];
          memcpy (iverdef, &iverdefmem, sizeof (Elf_Internal_Verdef));
 
          iverdef->vd_bfd = abfd;
 
-         amt = (bfd_size_type) iverdef->vd_cnt * sizeof (Elf_Internal_Verdaux);
-         iverdef->vd_auxptr = bfd_alloc (abfd, amt);
-         if (iverdef->vd_auxptr == NULL)
-           goto error_return;
+         if (iverdef->vd_cnt == 0)
+           iverdef->vd_auxptr = NULL;
+         else
+           {
+             iverdef->vd_auxptr = bfd_alloc2 (abfd, iverdef->vd_cnt,
+                                              sizeof (Elf_Internal_Verdaux));
+             if (iverdef->vd_auxptr == NULL)
+               goto error_return_verdef;
+           }
+
+         if (iverdef->vd_aux
+             > (size_t) (contents_end_aux - (bfd_byte *) everdef))
+           goto error_return_verdef;
 
          everdaux = ((Elf_External_Verdaux *)
                      ((bfd_byte *) everdef + iverdef->vd_aux));
@@ -6377,20 +6433,25 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
                bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
                                                 iverdaux->vda_name);
              if (iverdaux->vda_nodename == NULL)
-               goto error_return;
+               goto error_return_verdef;
 
              if (j + 1 < iverdef->vd_cnt)
                iverdaux->vda_nextptr = iverdaux + 1;
              else
                iverdaux->vda_nextptr = NULL;
 
+             if (iverdaux->vda_next
+                 > (size_t) (contents_end_aux - (bfd_byte *) everdaux))
+               goto error_return_verdef;
+
              everdaux = ((Elf_External_Verdaux *)
                          ((bfd_byte *) everdaux + iverdaux->vda_next));
            }
 
-         iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename;
+         if (iverdef->vd_cnt)
+           iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename;
 
-         if (i + 1 < hdr->sh_info)
+         if ((size_t) (iverdef - iverdefarr) + 1 < maxidx)
            iverdef->vd_nextdef = iverdef + 1;
          else
            iverdef->vd_nextdef = NULL;
@@ -6409,8 +6470,8 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
       else
        freeidx++;
 
-      amt = (bfd_size_type) freeidx * sizeof (Elf_Internal_Verdef);
-      elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
+      elf_tdata (abfd)->verdef = bfd_zalloc2 (abfd, freeidx,
+                                             sizeof (Elf_Internal_Verdef));
       if (elf_tdata (abfd)->verdef == NULL)
        goto error_return;
 
@@ -6434,10 +6495,11 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
 
       iverdef->vd_nodename = bfd_elf_get_dt_soname (abfd);
       if (iverdef->vd_nodename == NULL)
-       goto error_return;
+       goto error_return_verdef;
       iverdef->vd_nextdef = NULL;
-      amt = (bfd_size_type) sizeof (Elf_Internal_Verdaux);
-      iverdef->vd_auxptr = bfd_alloc (abfd, amt);
+      iverdef->vd_auxptr = bfd_alloc (abfd, sizeof (Elf_Internal_Verdaux));
+      if (iverdef->vd_auxptr == NULL)
+       goto error_return_verdef;
 
       iverdaux = iverdef->vd_auxptr;
       iverdaux->vda_nodename = iverdef->vd_nodename;
index dc4e5b0fbd42fa8d28fae1912a539cc1a38fd7ea..61f4d65e52ba248da32b440f56855f831b118f30 100644 (file)
@@ -351,7 +351,8 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst)
      arelent *cache_ptr;
      Elf_Internal_Rela *dst;
 {
-  switch (ELF32_R_TYPE(dst->r_info))
+  unsigned int r_type = ELF32_R_TYPE(dst->r_info);
+  switch (r_type)
     {
     case R_390_GNU_VTINHERIT:
       cache_ptr->howto = &elf32_s390_vtinherit_howto;
@@ -362,8 +363,13 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst)
       break;
 
     default:
-      BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_390_max);
-      cache_ptr->howto = &elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+      if (r_type >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0]))
+       {
+         (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+                                abfd, (int) r_type);
+         r_type = R_390_NONE;
+       }
+      cache_ptr->howto = &elf_howto_table[r_type];
     }
 }
 
index 99bbe187e8e67319a6f46508f23d4e7b2bcf1ccb..656e8227552cab86e2c4ba67890971dd2ccbfe93 100644 (file)
@@ -2117,8 +2117,13 @@ ppc64_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
     ppc_howto_init ();
 
   type = ELF64_R_TYPE (dst->r_info);
-  BFD_ASSERT (type < (sizeof (ppc64_elf_howto_table)
-                     / sizeof (ppc64_elf_howto_table[0])));
+  if (type >= (sizeof (ppc64_elf_howto_table)
+              / sizeof (ppc64_elf_howto_table[0])))
+    {
+      (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+                            abfd, (int) r_type);
+      r_type = R_PPC64_NONE;
+    }
   cache_ptr->howto = ppc64_elf_howto_table[type];
 }
 
index c88b0a29811ba1b68aad59a29decff884aba3796..0df3c283fa3cd140d1d276e597b8d9c800cc7f5a 100644 (file)
@@ -373,7 +373,8 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst)
      arelent *cache_ptr;
      Elf_Internal_Rela *dst;
 {
-  switch (ELF64_R_TYPE(dst->r_info))
+  unsigned int r_type = ELF64_R_TYPE(dst->r_info);
+  switch (r_type)
     {
     case R_390_GNU_VTINHERIT:
       cache_ptr->howto = &elf64_s390_vtinherit_howto;
@@ -384,8 +385,13 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst)
       break;
 
     default:
-      BFD_ASSERT (ELF64_R_TYPE(dst->r_info) < (unsigned int) R_390_max);
-      cache_ptr->howto = &elf_howto_table[ELF64_R_TYPE(dst->r_info)];
+      if (r_type >= sizeof (elf_howto_table) / sizeof (elf_howto_table[0]))
+       {
+         (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+                                abfd, (int) r_type);
+         r_type = R_390_NONE;
+       }
+      cache_ptr->howto = &elf_howto_table[r_type];
     }
 }
 
index aaf13083bdf82566a909f70a4862c21af1ded0dd..055f626566fc95d62d0bc9dee04d8b07316da3dc 100644 (file)
@@ -189,16 +189,19 @@ elf64_x86_64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
   unsigned r_type, i;
 
   r_type = ELF64_R_TYPE (dst->r_info);
-  if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT)
+  if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT
+      || r_type >= (unsigned int) R_X86_64_max)
     {
-      BFD_ASSERT (r_type <= (unsigned int) R_X86_64_GOTPC32);
+      if (r_type > (unsigned int) R_X86_64_GOTPC32)
+       {
+         (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+                                abfd, (int) r_type);
+         r_type = R_X86_64_NONE;
+       }
       i = r_type;
     }
   else
-    {
-      BFD_ASSERT (r_type < (unsigned int) R_X86_64_max);
-      i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_GOTPC32 - 1);
-    }
+    i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_GOTPC32 - 1);
   cache_ptr->howto = &x86_64_elf_howto_table[i];
   BFD_ASSERT (r_type == cache_ptr->howto->type);
 }
index ab59a1c3ff6ababba79f31fb267268c27fd645b2..d016cf0fd3bf2b96506b81c6dc2e6206d2a2d7e9 100644 (file)
@@ -487,7 +487,8 @@ lookup_howto (rtype)
        elf_code_to_howto_index[ia64_howto_table[i].type] = i;
     }
 
-  BFD_ASSERT (rtype <= R_IA64_MAX_RELOC_CODE);
+  if (rtype > R_IA64_MAX_RELOC_CODE)
+    return 0;
   i = elf_code_to_howto_index[rtype];
   if (i >= NELEMS (ia64_howto_table))
     return 0;
index c34b8bec8d3e3fed8a7248fd356b65661304fcc6..c967e820951eb64d1b0cc8609b33bff180cda8f8 100644 (file)
@@ -397,7 +397,12 @@ _bfd_sparc_elf_info_to_howto_ptr (unsigned int r_type)
       return &sparc_rev32_howto;
 
     default:
-      BFD_ASSERT (r_type < (unsigned int) R_SPARC_max_std);
+      if (r_type >= (unsigned int) R_SPARC_max_std)
+       {
+         (*_bfd_error_handler) (_("invalid relocation type %d"),
+                                (int) r_type);
+         r_type = R_SPARC_NONE;
+       }
       return &_bfd_sparc_elf_howto_table[r_type];
     }
 }
index 2c690a4bcc3920f0e710df0c9c76ce9c3b1bc636..ac7274c8ebdf09b9730b9d53afacf9174e63df66 100644 (file)
@@ -93,6 +93,12 @@ extern void *bfd_realloc
   (void *, bfd_size_type);
 extern void *bfd_zmalloc
   (bfd_size_type);
+extern void *bfd_malloc2
+  (bfd_size_type, bfd_size_type);
+extern void *bfd_realloc2
+  (void *, bfd_size_type, bfd_size_type);
+extern void *bfd_zmalloc2
+  (bfd_size_type, bfd_size_type);
 
 extern void _bfd_default_error_handler (const char *s, ...);
 extern bfd_error_handler_type _bfd_error_handler;
@@ -103,6 +109,10 @@ extern void *bfd_alloc
   (bfd *, bfd_size_type);
 extern void *bfd_zalloc
   (bfd *, bfd_size_type);
+extern void *bfd_alloc2
+  (bfd *, bfd_size_type, bfd_size_type);
+extern void *bfd_zalloc2
+  (bfd *, bfd_size_type, bfd_size_type);
 extern void bfd_release
   (bfd *, void *);
 
index 92f0089898cc7b5412b9945e8428a7a54ed9fbea..df41787c08d4dbb74aa5519ff26cfd0292885780 100644 (file)
@@ -156,6 +156,36 @@ 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)
+{
+  void *ptr;
+
+  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;
+
+  if (size != (size_t) size)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
+
+  ptr = malloc ((size_t) size);
+  if (ptr == NULL && (size_t) size != 0)
+    bfd_set_error (bfd_error_no_memory);
+
+  return ptr;
+}
+
 /* Reallocate memory using realloc.  */
 
 void *
@@ -180,6 +210,40 @@ 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)
+{
+  void *ret;
+
+  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;
+
+  if (size != (size_t) size)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
+
+  if (ptr == NULL)
+    ret = malloc ((size_t) size);
+  else
+    ret = realloc (ptr, (size_t) size);
+
+  if (ret == NULL && (size_t) size != 0)
+    bfd_set_error (bfd_error_no_memory);
+
+  return ret;
+}
+
 /* Allocate memory using malloc and clear it.  */
 
 void *
@@ -205,6 +269,44 @@ 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;
+
+  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;
+
+  if (size != (size_t) size)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
+
+  ptr = malloc ((size_t) size);
+
+  if ((size_t) size != 0)
+    {
+      if (ptr == NULL)
+       bfd_set_error (bfd_error_no_memory);
+      else
+       memset (ptr, 0, (size_t) size);
+    }
+
+  return ptr;
+}
+
 /*
 INTERNAL_FUNCTION
        bfd_write_bigendian_4byte_int
index df2fbcab91aa8c6930a1c9cca5f92c1d0b8facd4..b05ef1423747a97ace1550dad6cca062b0ba20b5 100644 (file)
@@ -98,6 +98,12 @@ extern void *bfd_realloc
   (void *, bfd_size_type);
 extern void *bfd_zmalloc
   (bfd_size_type);
+extern void *bfd_malloc2
+  (bfd_size_type, bfd_size_type);
+extern void *bfd_realloc2
+  (void *, bfd_size_type, bfd_size_type);
+extern void *bfd_zmalloc2
+  (bfd_size_type, bfd_size_type);
 
 extern void _bfd_default_error_handler (const char *s, ...);
 extern bfd_error_handler_type _bfd_error_handler;
@@ -108,6 +114,10 @@ extern void *bfd_alloc
   (bfd *, bfd_size_type);
 extern void *bfd_zalloc
   (bfd *, bfd_size_type);
+extern void *bfd_alloc2
+  (bfd *, bfd_size_type, bfd_size_type);
+extern void *bfd_zalloc2
+  (bfd *, bfd_size_type, bfd_size_type);
 extern void bfd_release
   (bfd *, void *);
 
index 56b5925cd6be0fbbe432c441f544a645da192505..c5cc252c66bdc4dc2cf8f9f44934374b5500f1b1 100644 (file)
@@ -856,6 +856,45 @@ 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)
+{
+  void *ret;
+
+  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;
+
+  if (size != (unsigned long) size)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
+
+  ret = objalloc_alloc (abfd->memory, (unsigned long) size);
+  if (ret == NULL)
+    bfd_set_error (bfd_error_no_memory);
+  return ret;
+}
+
 /*
 INTERNAL_FUNCTION
        bfd_zalloc
@@ -879,6 +918,39 @@ 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!  */