summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-07-05 09:44:20 +0000
committerJakub Jelinek <jakub@redhat.com>2005-07-05 09:44:20 +0000
commitd0fb9a8d03cc6b0e81f50d601ab361704e3dedb7 (patch)
treea05d1da0ddc4c02099d393a412d04b4ae40dc00d /bfd
parentc6c60d09fdd84b45d78a750a5d526faafe6f33a3 (diff)
downloadbinutils-d0fb9a8d03cc6b0e81f50d601ab361704e3dedb7.tar.gz
binutils-d0fb9a8d03cc6b0e81f50d601ab361704e3dedb7.tar.bz2
binutils-d0fb9a8d03cc6b0e81f50d601ab361704e3dedb7.zip
* 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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog25
-rw-r--r--bfd/bfd-in.h3
-rw-r--r--bfd/bfd-in2.h3
-rw-r--r--bfd/elf.c176
-rw-r--r--bfd/elf32-s390.c12
-rw-r--r--bfd/elf64-ppc.c9
-rw-r--r--bfd/elf64-s390.c12
-rw-r--r--bfd/elf64-x86-64.c15
-rw-r--r--bfd/elfxx-ia64.c3
-rw-r--r--bfd/elfxx-sparc.c7
-rw-r--r--bfd/libbfd-in.h10
-rw-r--r--bfd/libbfd.c102
-rw-r--r--bfd/libbfd.h10
-rw-r--r--bfd/opncls.c72
14 files changed, 386 insertions, 73 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 3bd8f0b8ae0..c91ffab182d 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index b8c4ef89eba..4d999b9f1d0 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -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
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 7d16049c82a..ada5e0ebf8c 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -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
diff --git a/bfd/elf.c b/bfd/elf.c
index 44707442697..130ec7a71d0 100644
--- 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;
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index dc4e5b0fbd4..61f4d65e52b 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -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];
}
}
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 99bbe187e8e..656e8227552 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -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];
}
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index c88b0a29811..0df3c283fa3 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -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];
}
}
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index aaf13083bdf..055f626566f 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -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);
}
diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c
index ab59a1c3ff6..d016cf0fd3b 100644
--- a/bfd/elfxx-ia64.c
+++ b/bfd/elfxx-ia64.c
@@ -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;
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index c34b8bec8d3..c967e820951 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -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];
}
}
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 2c690a4bcc3..ac7274c8ebd 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -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 *);
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index 92f0089898c..df41787c08d 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -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
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index df2fbcab91a..b05ef142374 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -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 *);
diff --git a/bfd/opncls.c b/bfd/opncls.c
index 56b5925cd6b..c5cc252c66b 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -858,6 +858,45 @@ bfd_alloc (bfd *abfd, bfd_size_type size)
/*
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
SYNOPSIS
@@ -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! */