diff options
-rw-r--r-- | bfd/ChangeLog | 25 | ||||
-rw-r--r-- | bfd/bfd-in.h | 3 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 3 | ||||
-rw-r--r-- | bfd/elf.c | 176 | ||||
-rw-r--r-- | bfd/elf32-s390.c | 12 | ||||
-rw-r--r-- | bfd/elf64-ppc.c | 9 | ||||
-rw-r--r-- | bfd/elf64-s390.c | 12 | ||||
-rw-r--r-- | bfd/elf64-x86-64.c | 15 | ||||
-rw-r--r-- | bfd/elfxx-ia64.c | 3 | ||||
-rw-r--r-- | bfd/elfxx-sparc.c | 7 | ||||
-rw-r--r-- | bfd/libbfd-in.h | 10 | ||||
-rw-r--r-- | bfd/libbfd.c | 102 | ||||
-rw-r--r-- | bfd/libbfd.h | 10 | ||||
-rw-r--r-- | bfd/opncls.c | 72 |
14 files changed, 386 insertions, 73 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3bd8f0b..c91ffab 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 b8c4ef8..4d999b9 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 7d16049..ada5e0e 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 @@ -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 dc4e5b0..61f4d65 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 99bbe18..656e822 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 c88b0a2..0df3c28 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 aaf1308..055f626 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 ab59a1c..d016cf0 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 c34b8be..c967e82 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 2c690a4..ac7274c 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 92f0089..df41787 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 df2fbca..b05ef14 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 56b5925..c5cc252 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! */ |