Don't use bfd_get_file_size in objdump

Compressed debug sections can have uncompressed sizes that exceed the
original file size, so we can't use bfd_get_file_size.  objdump also
used bfd_get_file_size to limit reloc section size, but I believe the
underlying bug causing the PR22508 out of bounds buffer access was
that we had an integer overflow when calculating the reloc buffer
size.  I've fixed that instead in most of the backends, som and
vms-alpha being the exceptions.  SOM and vmd-alpha have rather more
serious bugs in their slurp_relocs routines that would need fixing
first if we want to fuss about making them safe against fuzzed object
files.

The patch also fixes a number of other potential overflows by using
the bfd_alloc2/malloc2/zalloc2 memory allocation functions.

bfd/
	* coffcode.h (buy_and_read): Delete unnecessary forward decl.  Add
	nmemb parameter.  Use bfd_alloc2.
	(coff_slurp_line_table): Use bfd_alloc2.  Update buy_and_read calls.
	Delete assertion.
	(coff_slurp_symbol_table): Use bfd_alloc2 and bfd_zalloc2.
	(coff_slurp_reloc_table): Use bfd_alloc2.  Update buy_and_read calls.
	* coffgen.c (coff_get_reloc_upper_bound): Ensure size calculation
	doesn't overflow.
	* elf.c (bfd_section_from_shdr): Use bfd_zalloc2.  Style fix.
	(assign_section_numbers): Style fix.
	(swap_out_syms): Use bfd_malloc2.
	(_bfd_elf_get_reloc_upper_bound): Ensure size calculation doesn't
	overflow.
	(_bfd_elf_make_empty_symbol): Style fix.
	(elfobj_grok_stapsdt_note_1): Formatting.
	* elfcode.h (elf_object_p): Use bfd_alloc2.
	(elf_write_relocs, elf_write_shdrs_and_ehdr): Likewise.
	(elf_slurp_symbol_table): Use bfd_zalloc2.
	(elf_slurp_reloc_table): Use bfd_alloc2.
	(_bfd_elf_bfd_from_remote_memory): Use bfd_malloc2.
	* elf64-sparc (elf64_sparc_get_reloc_upper_bound): Ensure
	size calculation doesn't overflow.
	(elf64_sparc_get_dynamic_reloc_upper_bound): Likewise.
	* mach-o.c (bfd_mach_o_get_reloc_upper_bound): Likewise.
	* pdp11.c (get_reloc_upper_bound): Copy aoutx.h version.
binutils/
	* objdump.c (load_specific_debug_section): Don't compare section
	size against file size.
	(dump_relocs_in_section): Don't compare reloc size against file size.
	Print "failed to read relocs" on bfd_get_reloc_upper_bound error.
This commit is contained in:
Alan Modra 2019-03-12 16:19:25 +10:30
parent 0919bfe915
commit 7a6e0d89bb
10 changed files with 180 additions and 107 deletions

View File

@ -1,3 +1,31 @@
2019-03-12 Alan Modra <amodra@gmail.com>
* coffcode.h (buy_and_read): Delete unnecessary forward decl. Add
nmemb parameter. Use bfd_alloc2.
(coff_slurp_line_table): Use bfd_alloc2. Update buy_and_read calls.
Delete assertion.
(coff_slurp_symbol_table): Use bfd_alloc2 and bfd_zalloc2.
(coff_slurp_reloc_table): Use bfd_alloc2. Update buy_and_read calls.
* coffgen.c (coff_get_reloc_upper_bound): Ensure size calculation
doesn't overflow.
* elf.c (bfd_section_from_shdr): Use bfd_zalloc2. Style fix.
(assign_section_numbers): Style fix.
(swap_out_syms): Use bfd_malloc2.
(_bfd_elf_get_reloc_upper_bound): Ensure size calculation doesn't
overflow.
(_bfd_elf_make_empty_symbol): Style fix.
(elfobj_grok_stapsdt_note_1): Formatting.
* elfcode.h (elf_object_p): Use bfd_alloc2.
(elf_write_relocs, elf_write_shdrs_and_ehdr): Likewise.
(elf_slurp_symbol_table): Use bfd_zalloc2.
(elf_slurp_reloc_table): Use bfd_alloc2.
(_bfd_elf_bfd_from_remote_memory): Use bfd_malloc2.
* elf64-sparc (elf64_sparc_get_reloc_upper_bound): Ensure
size calculation doesn't overflow.
(elf64_sparc_get_dynamic_reloc_upper_bound): Likewise.
* mach-o.c (bfd_mach_o_get_reloc_upper_bound): Likewise.
* pdp11.c (get_reloc_upper_bound): Copy aoutx.h version.
2019-03-08 Alan Modra <amodra@gmail.com>
PR 24311

View File

@ -423,8 +423,6 @@ static bfd_boolean coff_write_object_contents
(bfd *) ATTRIBUTE_UNUSED;
static bfd_boolean coff_set_section_contents
(bfd *, asection *, const void *, file_ptr, bfd_size_type);
static void * buy_and_read
(bfd *, file_ptr, bfd_size_type);
static bfd_boolean coff_slurp_line_table
(bfd *, asection *);
static bfd_boolean coff_slurp_symbol_table
@ -4197,12 +4195,14 @@ coff_set_section_contents (bfd * abfd,
}
static void *
buy_and_read (bfd *abfd, file_ptr where, bfd_size_type size)
buy_and_read (bfd *abfd, file_ptr where,
bfd_size_type nmemb, bfd_size_type size)
{
void * area = bfd_alloc (abfd, size);
void *area = bfd_alloc2 (abfd, nmemb, size);
if (!area)
return NULL;
size *= nmemb;
if (bfd_seek (abfd, where, SEEK_SET) != 0
|| bfd_bread (area, size, abfd) != size)
return NULL;
@ -4255,7 +4255,6 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
{
LINENO *native_lineno;
alent *lineno_cache;
bfd_size_type amt;
unsigned int counter;
alent *cache_ptr;
bfd_vma prev_offset = 0;
@ -4278,13 +4277,15 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
return FALSE;
}
amt = ((bfd_size_type) asect->lineno_count + 1) * sizeof (alent);
lineno_cache = (alent *) bfd_alloc (abfd, amt);
lineno_cache = (alent *) bfd_alloc2 (abfd,
(bfd_size_type) asect->lineno_count + 1,
sizeof (alent));
if (lineno_cache == NULL)
return FALSE;
amt = (bfd_size_type) bfd_coff_linesz (abfd) * asect->lineno_count;
native_lineno = (LINENO *) buy_and_read (abfd, asect->line_filepos, amt);
native_lineno = (LINENO *) buy_and_read (abfd, asect->line_filepos,
asect->lineno_count,
bfd_coff_linesz (abfd));
if (native_lineno == NULL)
{
_bfd_error_handler
@ -4393,7 +4394,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
alent *n_lineno_cache;
/* Create a table of functions. */
func_table = (alent **) bfd_alloc (abfd, nbr_func * sizeof (alent *));
func_table = (alent **) bfd_alloc2 (abfd, nbr_func, sizeof (alent *));
if (func_table != NULL)
{
alent **p = func_table;
@ -4409,8 +4410,8 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent);
/* Create the new sorted table. */
amt = (bfd_size_type) asect->lineno_count * sizeof (alent);
n_lineno_cache = (alent *) bfd_alloc (abfd, amt);
n_lineno_cache = (alent *) bfd_alloc2 (abfd, asect->lineno_count,
sizeof (alent));
if (n_lineno_cache != NULL)
{
alent *n_cache_ptr = n_lineno_cache;
@ -4430,9 +4431,9 @@ coff_slurp_line_table (bfd *abfd, asection *asect)
*n_cache_ptr++ = *old_ptr++;
while (old_ptr->line_number != 0);
}
BFD_ASSERT ((bfd_size_type) (n_cache_ptr - n_lineno_cache) == (amt / sizeof (alent)));
memcpy (lineno_cache, n_lineno_cache, amt);
memcpy (lineno_cache, n_lineno_cache,
asect->lineno_count * sizeof (alent));
}
else
ret = FALSE;
@ -4455,7 +4456,6 @@ coff_slurp_symbol_table (bfd * abfd)
combined_entry_type *native_symbols;
coff_symbol_type *cached_area;
unsigned int *table_ptr;
bfd_size_type amt;
unsigned int number_of_symbols = 0;
bfd_boolean ret = TRUE;
@ -4467,15 +4467,14 @@ coff_slurp_symbol_table (bfd * abfd)
return FALSE;
/* Allocate enough room for all the symbols in cached form. */
amt = obj_raw_syment_count (abfd);
amt *= sizeof (coff_symbol_type);
cached_area = (coff_symbol_type *) bfd_alloc (abfd, amt);
cached_area = (coff_symbol_type *) bfd_alloc2 (abfd,
obj_raw_syment_count (abfd),
sizeof (coff_symbol_type));
if (cached_area == NULL)
return FALSE;
amt = obj_raw_syment_count (abfd);
amt *= sizeof (unsigned int);
table_ptr = (unsigned int *) bfd_zalloc (abfd, amt);
table_ptr = (unsigned int *) bfd_zalloc2 (abfd, obj_raw_syment_count (abfd),
sizeof (unsigned int));
if (table_ptr == NULL)
return FALSE;
@ -4963,7 +4962,6 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols)
arelent *reloc_cache;
arelent *cache_ptr;
unsigned int idx;
bfd_size_type amt;
if (asect->relocation)
return TRUE;
@ -4974,10 +4972,11 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols)
if (!coff_slurp_symbol_table (abfd))
return FALSE;
amt = (bfd_size_type) bfd_coff_relsz (abfd) * asect->reloc_count;
native_relocs = (RELOC *) buy_and_read (abfd, asect->rel_filepos, amt);
amt = (bfd_size_type) asect->reloc_count * sizeof (arelent);
reloc_cache = (arelent *) bfd_alloc (abfd, amt);
native_relocs = (RELOC *) buy_and_read (abfd, asect->rel_filepos,
asect->reloc_count,
bfd_coff_relsz (abfd));
reloc_cache = (arelent *) bfd_alloc2 (abfd, asect->reloc_count,
sizeof (arelent));
if (reloc_cache == NULL || native_relocs == NULL)
return FALSE;

View File

@ -37,6 +37,7 @@
coff_data (abfd). */
#include "sysdep.h"
#include <limits.h>
#include "bfd.h"
#include "libbfd.h"
#include "coff/internal.h"
@ -2006,6 +2007,10 @@ coff_get_normalized_symtab (bfd *abfd)
return internal;
}
#if GCC_VERSION >= 4003
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
long
coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
{
@ -2014,8 +2019,16 @@ coff_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
return (asect->reloc_count + 1) * sizeof (arelent *);
}
#if GCC_VERSION >= 4003
# pragma GCC diagnostic pop
#endif
asymbol *
coff_make_empty_symbol (bfd *abfd)

View File

@ -2036,9 +2036,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
sections_being_created = NULL;
if (sections_being_created == NULL)
{
/* FIXME: It would be more efficient to attach this array to the bfd somehow. */
sections_being_created = (bfd_boolean *)
bfd_zalloc (abfd, elf_numsections (abfd) * sizeof (bfd_boolean));
bfd_zalloc2 (abfd, elf_numsections (abfd), sizeof (bfd_boolean));
sections_being_created_abfd = abfd;
}
if (sections_being_created [shindex])
@ -2259,7 +2258,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
if (entry->ndx == shindex)
goto success;
entry = bfd_alloc (abfd, sizeof * entry);
entry = bfd_alloc (abfd, sizeof (*entry));
if (entry == NULL)
goto fail;
entry->ndx = shindex;
@ -3737,11 +3736,11 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
{
elf_section_list * entry;
elf_section_list *entry;
BFD_ASSERT (elf_symtab_shndx_list (abfd) == NULL);
entry = bfd_zalloc (abfd, sizeof * entry);
entry = bfd_zalloc (abfd, sizeof (*entry));
entry->ndx = section_number++;
elf_symtab_shndx_list (abfd) = entry;
entry->hdr.sh_name
@ -7901,8 +7900,8 @@ swap_out_syms (bfd *abfd,
symstrtab_hdr->sh_type = SHT_STRTAB;
/* Allocate buffer to swap out the .strtab section. */
symstrtab = (struct elf_sym_strtab *) bfd_malloc ((symcount + 1)
* sizeof (*symstrtab));
symstrtab = (struct elf_sym_strtab *) bfd_malloc2 (symcount + 1,
sizeof (*symstrtab));
if (symstrtab == NULL)
{
_bfd_elf_strtab_free (stt);
@ -8269,12 +8268,25 @@ _bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
return symtab_size;
}
#if GCC_VERSION >= 4003
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
long
_bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
sec_ptr asect)
{
if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
return (asect->reloc_count + 1) * sizeof (arelent *);
}
#if GCC_VERSION >= 4003
# pragma GCC diagnostic pop
#endif
/* Canonicalize the relocs. */
@ -8753,7 +8765,7 @@ _bfd_elf_make_empty_symbol (bfd *abfd)
{
elf_symbol_type *newsym;
newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym);
newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof (*newsym));
if (!newsym)
return NULL;
newsym->symbol.the_bfd = abfd;
@ -10233,8 +10245,8 @@ static bfd_boolean
elfobj_grok_stapsdt_note_1 (bfd *abfd, Elf_Internal_Note *note)
{
struct sdt_note *cur =
(struct sdt_note *) bfd_alloc (abfd, sizeof (struct sdt_note)
+ note->descsz);
(struct sdt_note *) bfd_alloc (abfd,
sizeof (struct sdt_note) + note->descsz);
cur->next = (struct sdt_note *) (elf_tdata (abfd))->sdt_note_head;
cur->size = (bfd_size_type) note->descsz;

View File

@ -19,6 +19,7 @@
MA 02110-1301, USA. */
#include "sysdep.h"
#include <limits.h>
#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
@ -33,16 +34,36 @@
section can represent up to two relocs, we must tell the user to allocate
more space. */
#if GCC_VERSION >= 4003
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
static long
elf64_sparc_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
{
if (sec->reloc_count >= LONG_MAX / 2 / sizeof (arelent *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
return (sec->reloc_count * 2 + 1) * sizeof (arelent *);
}
#if GCC_VERSION >= 4003
# pragma GCC diagnostic pop
#endif
static long
elf64_sparc_get_dynamic_reloc_upper_bound (bfd *abfd)
{
return _bfd_elf_get_dynamic_reloc_upper_bound (abfd) * 2;
long ret = _bfd_elf_get_dynamic_reloc_upper_bound (abfd);
if (ret > LONG_MAX / 2)
{
bfd_set_error (bfd_error_file_too_big);
ret = -1;
}
else if (ret > 0)
ret *= 2;
return ret;
}
/* Read relocations for ASECT from REL_HDR. There are RELOC_COUNT of

View File

@ -503,7 +503,6 @@ elf_object_p (bfd *abfd)
unsigned int shindex;
const struct elf_backend_data *ebd;
asection *s;
bfd_size_type amt;
const bfd_target *target;
/* Read in the ELF header in external format. */
@ -688,14 +687,14 @@ elf_object_p (bfd *abfd)
if (i_ehdrp->e_shnum > ((bfd_size_type) -1) / sizeof (*i_shdrp))
goto got_wrong_format_error;
#endif
amt = sizeof (*i_shdrp) * (bfd_size_type) i_ehdrp->e_shnum;
i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
i_shdrp = (Elf_Internal_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum,
sizeof (*i_shdrp));
if (!i_shdrp)
goto got_no_match;
num_sec = i_ehdrp->e_shnum;
elf_numsections (abfd) = num_sec;
amt = sizeof (i_shdrp) * num_sec;
elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
elf_elfsections (abfd)
= (Elf_Internal_Shdr **) bfd_alloc2 (abfd, num_sec, sizeof (i_shdrp));
if (!elf_elfsections (abfd))
goto got_no_match;
@ -789,8 +788,9 @@ elf_object_p (bfd *abfd)
if (bfd_get_file_size (abfd) > 0
&& i_ehdrp->e_phnum > bfd_get_file_size (abfd))
goto got_no_match;
amt = (bfd_size_type) i_ehdrp->e_phnum * sizeof (*i_phdr);
elf_tdata (abfd)->phdr = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
elf_tdata (abfd)->phdr
= (Elf_Internal_Phdr *) bfd_alloc2 (abfd, i_ehdrp->e_phnum,
sizeof (*i_phdr));
if (elf_tdata (abfd)->phdr == NULL)
goto got_no_match;
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
@ -903,7 +903,8 @@ elf_write_relocs (bfd *abfd, asection *sec, void *data)
rela_hdr = elf_section_data (sec)->rel.hdr;
rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count;
rela_hdr->contents = (unsigned char *) bfd_alloc (abfd, rela_hdr->sh_size);
rela_hdr->contents = (unsigned char *) bfd_alloc2 (abfd, sec->reloc_count,
rela_hdr->sh_entsize);
if (rela_hdr->contents == NULL)
{
*failedp = TRUE;
@ -1040,9 +1041,8 @@ elf_write_shdrs_and_ehdr (bfd *abfd)
i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx;
/* at this point we've concocted all the ELF sections... */
amt = i_ehdrp->e_shnum;
amt *= sizeof (*x_shdrp);
x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt);
x_shdrp = (Elf_External_Shdr *) bfd_alloc2 (abfd, i_ehdrp->e_shnum,
sizeof (*x_shdrp));
if (!x_shdrp)
return FALSE;
@ -1053,6 +1053,7 @@ elf_write_shdrs_and_ehdr (bfd *abfd)
#endif
elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count);
}
amt = (bfd_size_type) i_ehdrp->e_shnum * sizeof (*x_shdrp);
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
|| bfd_bwrite (x_shdrp, amt, abfd) != amt)
return FALSE;
@ -1152,7 +1153,6 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
Elf_External_Versym *xver;
Elf_External_Versym *xverbuf = NULL;
const struct elf_backend_data *ebd;
bfd_size_type amt;
/* Read each raw ELF symbol, converting from external ELF form to
internal ELF form, and then using the information to create a
@ -1197,9 +1197,8 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic)
if (isymbuf == NULL)
return -1;
amt = symcount;
amt *= sizeof (elf_symbol_type);
symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
symbase = (elf_symbol_type *) bfd_zalloc2 (abfd, symcount,
sizeof (elf_symbol_type));
if (symbase == (elf_symbol_type *) NULL)
goto error_return;
@ -1519,7 +1518,6 @@ elf_slurp_reloc_table (bfd *abfd,
bfd_size_type reloc_count;
bfd_size_type reloc_count2;
arelent *relents;
bfd_size_type amt;
if (asect->relocation != NULL)
return TRUE;
@ -1557,8 +1555,8 @@ elf_slurp_reloc_table (bfd *abfd,
reloc_count2 = 0;
}
amt = (reloc_count + reloc_count2) * sizeof (arelent);
relents = (arelent *) bfd_alloc (abfd, amt);
relents = (arelent *) bfd_alloc2 (abfd, reloc_count + reloc_count2,
sizeof (arelent));
if (relents == NULL)
return FALSE;
@ -1713,8 +1711,9 @@ NAME(_bfd_elf,bfd_from_remote_memory)
return NULL;
}
x_phdrs = (Elf_External_Phdr *)
bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs));
x_phdrs
= (Elf_External_Phdr *) bfd_malloc2 (i_ehdr.e_phnum,
sizeof (*x_phdrs) + sizeof (*i_phdrs));
if (x_phdrs == NULL)
return NULL;
err = target_read_memory (ehdr_vma + i_ehdr.e_phoff, (bfd_byte *) x_phdrs,

View File

@ -19,6 +19,7 @@
MA 02110-1301, USA. */
#include "sysdep.h"
#include <limits.h>
#include "bfd.h"
#include "libbfd.h"
#include "libiberty.h"
@ -1416,12 +1417,24 @@ bfd_mach_o_write_dyld_info (bfd *abfd, bfd_mach_o_load_command *command)
return TRUE;
}
#if GCC_VERSION >= 4003
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
long
bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
asection *asect)
{
return (asect->reloc_count + 1) * sizeof (arelent *);
if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
return (asect->reloc_count + 1) * sizeof (arelent *);
}
#if GCC_VERSION >= 4003
# pragma GCC diagnostic pop
#endif
/* In addition to the need to byte-swap the symbol number, the bit positions
of the fields in the relocation information vary per target endian-ness. */

View File

@ -66,6 +66,7 @@
&& N_MAGIC(x) != ZMAGIC)
#include "sysdep.h"
#include <limits.h>
#include "bfd.h"
#define external_exec pdp11_external_exec
@ -1980,6 +1981,8 @@ NAME (aout, canonicalize_reloc) (bfd *abfd,
long
NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
{
bfd_size_type count;
if (bfd_get_format (abfd) != bfd_object)
{
bfd_set_error (bfd_error_invalid_operation);
@ -1987,28 +1990,25 @@ NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
}
if (asect->flags & SEC_CONSTRUCTOR)
return (sizeof (arelent *) * (asect->reloc_count + 1));
count = asect->reloc_count;
else if (asect == obj_datasec (abfd))
count = exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
else if (asect == obj_textsec (abfd))
count = exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
else if (asect == obj_bsssec (abfd))
count = 0;
else
{
bfd_set_error (bfd_error_invalid_operation);
return -1;
}
if (asect == obj_datasec (abfd))
return (sizeof (arelent *)
* ((exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd))
+ 1));
if (asect == obj_textsec (abfd))
return (sizeof (arelent *)
* ((exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd))
+ 1));
/* TODO: why are there two if statements for obj_bsssec()? */
if (asect == obj_bsssec (abfd))
return sizeof (arelent *);
if (asect == obj_bsssec (abfd))
return 0;
bfd_set_error (bfd_error_invalid_operation);
return -1;
if (count >= LONG_MAX / sizeof (arelent *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
return (count + 1) * sizeof (arelent *);
}

View File

@ -1,3 +1,10 @@
2019-03-12 Alan Modra <amodra@gmail.com>
* objdump.c (load_specific_debug_section): Don't compare section
size against file size.
(dump_relocs_in_section): Don't compare reloc size against file size.
Print "failed to read relocs" on bfd_get_reloc_upper_bound error.
2019-03-05 Nick Clifton <nickc@redhat.com>
PR 24295

View File

@ -2695,7 +2695,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
section->user_data = sec;
section->size = bfd_get_section_size (sec);
amt = section->size + 1;
if (amt == 0 || amt > bfd_get_file_size (abfd))
if (amt == 0)
{
section->start = NULL;
free_debug_section (debug);
@ -3640,47 +3640,28 @@ dump_relocs_in_section (bfd *abfd,
|| ((section->flags & SEC_RELOC) == 0))
return;
relsize = bfd_get_reloc_upper_bound (abfd, section);
if (relsize < 0)
bfd_fatal (bfd_get_filename (abfd));
printf ("RELOCATION RECORDS FOR [%s]:", sanitize_string (section->name));
relsize = bfd_get_reloc_upper_bound (abfd, section);
if (relsize == 0)
{
printf (" (none)\n\n");
return;
}
if ((bfd_get_file_flags (abfd) & (BFD_IN_MEMORY | BFD_LINKER_CREATED)) == 0
&& (/* Check that the size of the relocs is reasonable. Note that some
file formats, eg aout, can have relocs whose internal size is
larger than their external size, thus we check the size divided
by four against the file size. See PR 23931 for an example of
this. */
((ufile_ptr) (relsize / 4) > bfd_get_file_size (abfd))
/* Also check the section's reloc count since if this is negative
(or very large) the computation in bfd_get_reloc_upper_bound
may have resulted in returning a small, positive integer.
See PR 22508 for a reproducer.
Note - we check against file size rather than section size as
it is possible for there to be more relocs that apply to a
section than there are bytes in that section. */
|| (section->reloc_count > bfd_get_file_size (abfd))))
if (relsize < 0)
relcount = relsize;
else
{
printf (" (too many: %#x relocs)\n", section->reloc_count);
bfd_set_error (bfd_error_file_truncated);
bfd_fatal (bfd_get_filename (abfd));
relpp = (arelent **) xmalloc (relsize);
relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
}
relpp = (arelent **) xmalloc (relsize);
relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms);
if (relcount < 0)
{
printf ("\n");
non_fatal (_("failed to read relocs in: %s"), sanitize_string (bfd_get_filename (abfd)));
non_fatal (_("failed to read relocs in: %s"),
sanitize_string (bfd_get_filename (abfd)));
bfd_fatal (_("error message was"));
}
else if (relcount == 0)