More fixes for memory access errors triggered by attemps to examine corrupted binaries.
PR binutils/17512 * dwarf.c (display_block): Do nothing if the block starts after the end of the buffer. (read_and_display_attr_value): Add range checks. (struct Frame_Chunk): Make the ncols and ra fields unsigned. (frame_need_space): Test for an ncols of zero. (read_cie): Fail if the augmentation data extends off the end of the buffer. (display_debug_frames): Add checks for read_cie failing. Add range checks. * coff-h8300.c (rtype2howto): Replace abort with returning a NULL value. * coff-h8500.c (rtype2howto): Likewise. * coff-tic30.c (rtype2howto): Likewise. * coff-z80.c (rtype2howto): Likewise. * coff-z8k.c (rtype2howto): Likewise. * coff-ia64.c (RTYPE2HOWTO): Always return a valid howto. * coff-m68k.c (m68k_rtype2howto): Return a NULL howto if none could be found. * coff-mcore.c (RTYPE2HOWTO): Add range checking. * coff-w65.c (rtype2howto): Likewise. * coff-we32k.c (RTYPE2HOWTO): Likewise. * pe-mips.c (RTYPE2HOWTO): Likewise. * coff-x86_64.c (coff_amd64_reloc): Likewise. Replace abort with an error return. * coffcode.h (coff_slurp_reloc_table): Allow the rel parameter to be unused. * coffgen.c (make_a_section_from_file): Check the length of a section name before testing to see if it is a debug section name. (coff_object_p): Zero out any uninitialised bytes in the opt header. * ecoff.c (_bfd_ecoff_slurp_symbolic_info): Test for the raw source being empty when there are values to be processed. (_bfd_ecoff_slurp_symbol_table): Add range check. * mach-o.c (bfd_mach_o_canonicalize_one_reloc): Likewise. (bfd_mach_o_mangle_sections): Move test for too many sections to before the allocation of the section table. (bfd_mach_o_read_symtab_strtab): If the read fails, free the memory and nullify the symbol pointer. * reloc.c (bfd_generic_get_relocated_section_contents): Add handling of a bfd_reloc_notsupported return value. * versados.c (EDATA): Add range checking. (get_record): Likewise. (process_otr): Check for contents being available before updating them. (versados_canonicalize_reloc): Add range check.
This commit is contained in:
parent
0cfd832fc7
commit
a11652892c
|
@ -1,3 +1,43 @@
|
|||
2014-11-26 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR binutils/17512
|
||||
* coff-h8300.c (rtype2howto): Replace abort with returning a NULL
|
||||
value.
|
||||
* coff-h8500.c (rtype2howto): Likewise.
|
||||
* coff-tic30.c (rtype2howto): Likewise.
|
||||
* coff-z80.c (rtype2howto): Likewise.
|
||||
* coff-z8k.c (rtype2howto): Likewise.
|
||||
* coff-ia64.c (RTYPE2HOWTO): Always return a valid howto.
|
||||
* coff-m68k.c (m68k_rtype2howto): Return a NULL howto if none
|
||||
could be found.
|
||||
* coff-mcore.c (RTYPE2HOWTO): Add range checking.
|
||||
* coff-w65.c (rtype2howto): Likewise.
|
||||
* coff-we32k.c (RTYPE2HOWTO): Likewise.
|
||||
* pe-mips.c (RTYPE2HOWTO): Likewise.
|
||||
* coff-x86_64.c (coff_amd64_reloc): Likewise. Replace abort with
|
||||
an error return.
|
||||
* coffcode.h (coff_slurp_reloc_table): Allow the rel parameter to
|
||||
be unused.
|
||||
* coffgen.c (make_a_section_from_file): Check the length of a
|
||||
section name before testing to see if it is a debug section name.
|
||||
(coff_object_p): Zero out any uninitialised bytes in the opt
|
||||
header.
|
||||
* ecoff.c (_bfd_ecoff_slurp_symbolic_info): Test for the raw
|
||||
source being empty when there are values to be processed.
|
||||
(_bfd_ecoff_slurp_symbol_table): Add range check.
|
||||
* mach-o.c (bfd_mach_o_canonicalize_one_reloc): Likewise.
|
||||
(bfd_mach_o_mangle_sections): Move test for too many sections to
|
||||
before the allocation of the section table.
|
||||
(bfd_mach_o_read_symtab_strtab): If the read fails, free the
|
||||
memory and nullify the symbol pointer.
|
||||
* reloc.c (bfd_generic_get_relocated_section_contents): Add
|
||||
handling of a bfd_reloc_notsupported return value.
|
||||
* versados.c (EDATA): Add range checking.
|
||||
(get_record): Likewise.
|
||||
(process_otr): Check for contents being available before updating
|
||||
them.
|
||||
(versados_canonicalize_reloc): Add range check.
|
||||
|
||||
2014-11-26 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf.c (_bfd_elf_slurp_version_tables): Delay allocation of
|
||||
|
|
|
@ -337,7 +337,7 @@ rtype2howto (arelent *internal, struct internal_reloc *dst)
|
|||
internal->howto = howto_table + 19;
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
internal->howto = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ rtype2howto (arelent * internal, struct internal_reloc *dst)
|
|||
switch (dst->r_type)
|
||||
{
|
||||
default:
|
||||
abort ();
|
||||
internal->howto = NULL;
|
||||
break;
|
||||
case R_H8500_IMM8:
|
||||
internal->howto = &r_imm8;
|
||||
|
|
|
@ -47,7 +47,7 @@ static reloc_howto_type howto_table[] =
|
|||
#endif
|
||||
|
||||
#define RTYPE2HOWTO(cache_ptr, dst) \
|
||||
(cache_ptr)->howto = howto_table + (dst)->r_type;
|
||||
(cache_ptr)->howto = howto_table;
|
||||
|
||||
#ifdef COFF_WITH_PE
|
||||
/* Return TRUE if this relocation should
|
||||
|
|
|
@ -143,6 +143,7 @@ m68k_rtype2howto (arelent *internal, int relocentry)
|
|||
case R_PCRWORD: internal->howto = m68kcoff_howto_table + 4; break;
|
||||
case R_PCRLONG: internal->howto = m68kcoff_howto_table + 5; break;
|
||||
case R_RELLONG_NEG: internal->howto = m68kcoff_howto_table + 6; break;
|
||||
default: internal->howto = NULL; break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -273,16 +273,15 @@ mcore_coff_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
|
|||
}
|
||||
#undef HOW2MAP
|
||||
|
||||
#define NUM_HOWTOS NUM_ELEM (mcore_coff_howto_table)
|
||||
|
||||
static reloc_howto_type *
|
||||
mcore_coff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
const char *r_name)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0;
|
||||
i < (sizeof (mcore_coff_howto_table)
|
||||
/ sizeof (mcore_coff_howto_table[0]));
|
||||
i++)
|
||||
for (i = 0; i < NUM_HOWTOS; i++)
|
||||
if (mcore_coff_howto_table[i].name != NULL
|
||||
&& strcasecmp (mcore_coff_howto_table[i].name, r_name) == 0)
|
||||
return &mcore_coff_howto_table[i];
|
||||
|
@ -290,8 +289,11 @@ mcore_coff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#define RTYPE2HOWTO(cache_ptr, dst) \
|
||||
(cache_ptr)->howto = mcore_coff_howto_table + (dst)->r_type;
|
||||
#define RTYPE2HOWTO(cache_ptr, dst) \
|
||||
((cache_ptr)->howto = \
|
||||
((dst)->r_type < NUM_HOWTOS \
|
||||
? mcore_coff_howto_table + (dst)->r_type \
|
||||
: NULL))
|
||||
|
||||
static reloc_howto_type *
|
||||
coff_mcore_rtype_to_howto (bfd * abfd ATTRIBUTE_UNUSED,
|
||||
|
@ -303,7 +305,7 @@ coff_mcore_rtype_to_howto (bfd * abfd ATTRIBUTE_UNUSED,
|
|||
{
|
||||
reloc_howto_type * howto;
|
||||
|
||||
if (rel->r_type >= NUM_ELEM (mcore_coff_howto_table))
|
||||
if (rel->r_type >= NUM_HOWTOS)
|
||||
return NULL;
|
||||
|
||||
howto = mcore_coff_howto_table + rel->r_type;
|
||||
|
|
|
@ -136,7 +136,7 @@ rtype2howto (arelent *internal, struct internal_reloc *dst)
|
|||
internal->howto = &tic30_coff_howto_table[4];
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
internal->howto = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,16 +31,18 @@
|
|||
static reloc_howto_type howto_table[] =
|
||||
{
|
||||
HOWTO (R_W65_ABS8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
|
||||
HOWTO (R_W65_ABS16, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
|
||||
HOWTO (R_W65_ABS24, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
|
||||
HOWTO (R_W65_ABS8S8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, ">abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
|
||||
HOWTO (R_W65_ABS8S16, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "^abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
|
||||
HOWTO (R_W65_ABS16S8, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, ">abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
|
||||
HOWTO (R_W65_ABS16S16,1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "^abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
|
||||
HOWTO (R_W65_PCR8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "pcrel8", TRUE, 0x000000ff, 0x000000ff, TRUE),
|
||||
HOWTO (R_W65_PCR16, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, TRUE),
|
||||
HOWTO (R_W65_DP, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "dp", TRUE, 0x000000ff, 0x000000ff, FALSE),
|
||||
};
|
||||
HOWTO (R_W65_ABS16, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
|
||||
HOWTO (R_W65_ABS24, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 0, "abs24", TRUE, 0x00ffffff, 0x00ffffff, FALSE),
|
||||
HOWTO (R_W65_ABS8S8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, ">abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
|
||||
HOWTO (R_W65_ABS8S16, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "^abs8", TRUE, 0x000000ff, 0x000000ff, FALSE),
|
||||
HOWTO (R_W65_ABS16S8, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, ">abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
|
||||
HOWTO (R_W65_ABS16S16,1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "^abs16", TRUE, 0x0000ffff, 0x0000ffff, FALSE),
|
||||
HOWTO (R_W65_PCR8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "pcrel8", TRUE, 0x000000ff, 0x000000ff, TRUE),
|
||||
HOWTO (R_W65_PCR16, 1, 0, 16, FALSE, 0, complain_overflow_bitfield, 0, "pcrel16", TRUE, 0x0000ffff, 0x0000ffff, TRUE),
|
||||
HOWTO (R_W65_DP, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 0, "dp", TRUE, 0x000000ff, 0x000000ff, FALSE),
|
||||
};
|
||||
|
||||
#define NUM_HOWTOS (sizeof (howto_table) / sizeof (howto_table[0]))
|
||||
|
||||
/* Turn a howto into a reloc number. */
|
||||
|
||||
|
@ -61,7 +63,7 @@ static reloc_howto_type howto_table[] =
|
|||
static int
|
||||
select_reloc (reloc_howto_type *howto)
|
||||
{
|
||||
return howto->type ;
|
||||
return howto->type;
|
||||
}
|
||||
|
||||
/* Code to turn a r_type into a howto ptr, uses the above howto table. */
|
||||
|
@ -70,7 +72,10 @@ static void
|
|||
rtype2howto (arelent *internal,
|
||||
struct internal_reloc *dst)
|
||||
{
|
||||
internal->howto = howto_table + dst->r_type - 1;
|
||||
if (dst->r_type > 0 && dst->r_type <= NUM_HOWTOS)
|
||||
internal->howto = howto_table + dst->r_type - 1;
|
||||
else
|
||||
internal->howto = NULL;
|
||||
}
|
||||
|
||||
#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
|
||||
|
|
|
@ -53,14 +53,19 @@ static reloc_howto_type howto_table[] =
|
|||
HOWTO(R_PCRLONG, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0, "DISP32", TRUE, 0xffffffff,0xffffffff, FALSE),
|
||||
};
|
||||
|
||||
#define NUM_HOWTOS (sizeof (howto_table) / sizeof (howto_table[0]))
|
||||
|
||||
/* Turn a howto into a reloc nunmber */
|
||||
|
||||
#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
|
||||
#define BADMAG(x) WE32KBADMAG(x)
|
||||
#define WE32K 1
|
||||
|
||||
#define RTYPE2HOWTO(cache_ptr, dst) \
|
||||
(cache_ptr)->howto = howto_table + (dst)->r_type;
|
||||
#define RTYPE2HOWTO(cache_ptr, dst) \
|
||||
((cache_ptr)->howto = \
|
||||
((dst)->r_type < NUM_HOWTOS \
|
||||
? howto_table + (dst)->r_type \
|
||||
: NULL))
|
||||
|
||||
#ifndef bfd_pe_print_pdata
|
||||
#define bfd_pe_print_pdata NULL
|
||||
|
|
|
@ -143,6 +143,16 @@ coff_amd64_reloc (bfd *abfd,
|
|||
reloc_howto_type *howto = reloc_entry->howto;
|
||||
unsigned char *addr = (unsigned char *) data + reloc_entry->address;
|
||||
|
||||
/* FIXME: We do not have an end address for data, so we cannot
|
||||
accurately range check any addresses computed against it.
|
||||
cf: PR binutils/17512: file: 1085-1761-0.004.
|
||||
For now we do the best that we can. */
|
||||
if (addr < (unsigned char *) data || addr > ((unsigned char *) data) + input_section->size)
|
||||
{
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return bfd_reloc_notsupported;
|
||||
}
|
||||
|
||||
switch (howto->size)
|
||||
{
|
||||
case 0:
|
||||
|
@ -177,7 +187,8 @@ coff_amd64_reloc (bfd *abfd,
|
|||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return bfd_reloc_notsupported;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ rtype2howto (arelent *internal, struct internal_reloc *dst)
|
|||
switch (dst->r_type)
|
||||
{
|
||||
default:
|
||||
abort ();
|
||||
internal->howto = NULL;
|
||||
break;
|
||||
case R_IMM8:
|
||||
internal->howto = &r_imm8;
|
||||
|
|
|
@ -85,7 +85,7 @@ rtype2howto (arelent *internal, struct internal_reloc *dst)
|
|||
switch (dst->r_type)
|
||||
{
|
||||
default:
|
||||
abort ();
|
||||
internal->howto = NULL;
|
||||
break;
|
||||
case R_IMM8:
|
||||
internal->howto = &r_imm8;
|
||||
|
|
|
@ -5310,7 +5310,7 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols)
|
|||
static reloc_howto_type *
|
||||
coff_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
asection *sec ATTRIBUTE_UNUSED,
|
||||
struct internal_reloc *rel,
|
||||
struct internal_reloc *rel ATTRIBUTE_UNUSED,
|
||||
struct coff_link_hash_entry *h ATTRIBUTE_UNUSED,
|
||||
struct internal_syment *sym ATTRIBUTE_UNUSED,
|
||||
bfd_vma *addendp ATTRIBUTE_UNUSED)
|
||||
|
|
|
@ -146,8 +146,9 @@ make_a_section_from_file (bfd *abfd,
|
|||
/* Compress/decompress DWARF debug sections with names: .debug_* and
|
||||
.zdebug_*, after the section flags is set. */
|
||||
if ((flags & SEC_DEBUGGING)
|
||||
&& strlen (name) > 7
|
||||
&& ((name[1] == 'd' && name[6] == '_')
|
||||
|| (name[1] == 'z' && name[7] == '_')))
|
||||
|| (strlen (name) > 8 && name[1] == 'z' && name[7] == '_')))
|
||||
{
|
||||
enum { nothing, compress, decompress } action = nothing;
|
||||
char *new_name = NULL;
|
||||
|
@ -365,6 +366,10 @@ coff_object_p (bfd *abfd)
|
|||
bfd_release (abfd, opthdr);
|
||||
return NULL;
|
||||
}
|
||||
/* PR 17512: file: 11056-1136-0.004. */
|
||||
if (internal_f.f_opthdr < aoutsz)
|
||||
memset (((char *) opthdr) + internal_f.f_opthdr, 0, aoutsz - internal_f.f_opthdr);
|
||||
|
||||
bfd_coff_swap_aouthdr_in (abfd, opthdr, (void *) &internal_a);
|
||||
bfd_release (abfd, opthdr);
|
||||
}
|
||||
|
|
|
@ -615,6 +615,9 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd,
|
|||
external_fdr_size = backend->debug_swap.external_fdr_size;
|
||||
fdr_ptr = debug->fdr;
|
||||
fraw_src = (char *) debug->external_fdr;
|
||||
/* PR 17512: file: 3372-1243-0.004. */
|
||||
if (fraw_src == NULL && internal_symhdr->ifdMax > 0)
|
||||
return FALSE;
|
||||
fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size;
|
||||
for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
|
||||
(*backend->debug_swap.swap_fdr_in) (abfd, (void *) fraw_src, fdr_ptr);
|
||||
|
@ -891,6 +894,11 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd)
|
|||
EXTR internal_esym;
|
||||
|
||||
(*swap_ext_in) (abfd, (void *) eraw_src, &internal_esym);
|
||||
|
||||
/* PR 17512: file: 3372-1000-0.004. */
|
||||
if (internal_esym.asym.iss >= ecoff_data (abfd)->debug_info.symbolic_header.issExtMax)
|
||||
return FALSE;
|
||||
|
||||
internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ssext
|
||||
+ internal_esym.asym.iss);
|
||||
if (!ecoff_set_symbol_info (abfd, &internal_esym.asym,
|
||||
|
|
26
bfd/mach-o.c
26
bfd/mach-o.c
|
@ -1349,8 +1349,12 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd,
|
|||
|
||||
if (reloc.r_extern)
|
||||
{
|
||||
/* An external symbol number. */
|
||||
sym = syms + num;
|
||||
/* PR 17512: file: 8396-1185-0.004. */
|
||||
if (num >= bfd_get_symcount (abfd))
|
||||
sym = bfd_und_section_ptr->symbol_ptr_ptr;
|
||||
else
|
||||
/* An external symbol number. */
|
||||
sym = syms + num;
|
||||
}
|
||||
else if (num == 0x00ffffff || num == 0)
|
||||
{
|
||||
|
@ -2336,17 +2340,20 @@ bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata)
|
|||
&& (mdata->nsects == 0 || mdata->sections != NULL))
|
||||
return TRUE;
|
||||
|
||||
/* We need to check that this can be done... */
|
||||
if (nsect > 255)
|
||||
{
|
||||
(*_bfd_error_handler) (_("mach-o: there are too many sections (%u)"
|
||||
" maximum is 255,\n"), nsect);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mdata->nsects = nsect;
|
||||
mdata->sections = bfd_alloc (abfd,
|
||||
mdata->nsects * sizeof (bfd_mach_o_section *));
|
||||
if (mdata->sections == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* We need to check that this can be done... */
|
||||
if (nsect > 255)
|
||||
(*_bfd_error_handler) (_("mach-o: there are too many sections (%d)"
|
||||
" maximum is 255,\n"), nsect);
|
||||
|
||||
/* Create Mach-O sections.
|
||||
Section type, attribute and align should have been set when the
|
||||
section was created - either read in or specified. */
|
||||
|
@ -3646,6 +3653,9 @@ bfd_mach_o_read_symtab_strtab (bfd *abfd)
|
|||
if (bfd_seek (abfd, sym->stroff, SEEK_SET) != 0
|
||||
|| bfd_bread (sym->strtab, sym->strsize, abfd) != sym->strsize)
|
||||
{
|
||||
/* PR 17512: file: 10888-1609-0.004. */
|
||||
bfd_release (abfd, sym->strtab);
|
||||
sym->strtab = NULL;
|
||||
bfd_set_error (bfd_error_file_truncated);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -3675,6 +3685,7 @@ bfd_mach_o_read_symtab_symbols (bfd *abfd)
|
|||
|
||||
if (!bfd_mach_o_read_symtab_strtab (abfd))
|
||||
{
|
||||
bfd_release (abfd, sym->symbols);
|
||||
sym->symbols = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -3683,6 +3694,7 @@ bfd_mach_o_read_symtab_symbols (bfd *abfd)
|
|||
{
|
||||
if (!bfd_mach_o_read_symtab_symbol (abfd, sym, &sym->symbols[i], i))
|
||||
{
|
||||
bfd_release (abfd, sym->symbols);
|
||||
sym->symbols = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -349,8 +349,11 @@ static reloc_howto_type howto_table[] =
|
|||
/* Customize coffcode.h. */
|
||||
#define MIPS 1
|
||||
|
||||
#define RTYPE2HOWTO(cache_ptr, dst) \
|
||||
(cache_ptr)->howto = howto_table + (dst)->r_type;
|
||||
#define RTYPE2HOWTO(cache_ptr, dst) \
|
||||
((cache_ptr)->howto = \
|
||||
((dst)->r_type < NUM_HOWTOS \
|
||||
? howto_table + (dst)->r_type \
|
||||
: NULL))
|
||||
|
||||
/* Compute the addend of a reloc. If the reloc is to a common symbol,
|
||||
the object file contains the value of the common symbol. By the
|
||||
|
|
|
@ -7655,6 +7655,15 @@ bfd_generic_get_relocated_section_contents (bfd *abfd,
|
|||
abfd, input_section, * parent);
|
||||
goto error_return;
|
||||
|
||||
case bfd_reloc_notsupported:
|
||||
/* PR ld/17512
|
||||
This error can result when processing a corrupt binary.
|
||||
Do not abort. Issue an error message instead. */
|
||||
link_info->callbacks->einfo
|
||||
(_("%X%P: %B(%A): relocation \"%R\" is not supported\n"),
|
||||
abfd, input_section, * parent);
|
||||
goto error_return;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
break;
|
||||
|
|
|
@ -85,8 +85,8 @@ typedef struct versados_data_struct
|
|||
tdata_type;
|
||||
|
||||
#define VDATA(abfd) (abfd->tdata.versados_data)
|
||||
#define EDATA(abfd, n) (abfd->tdata.versados_data->e[n])
|
||||
#define RDATA(abfd, n) (abfd->tdata.versados_data->rest[n])
|
||||
#define EDATA(abfd, n) (abfd->tdata.versados_data->e[(n) < 16 ? (n) : 0])
|
||||
#define RDATA(abfd, n) (abfd->tdata.versados_data->rest[(n) < 240 ? (n) : 0])
|
||||
|
||||
struct ext_otr
|
||||
{
|
||||
|
@ -181,14 +181,22 @@ versados_new_symbol (bfd *abfd,
|
|||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
static bfd_boolean
|
||||
get_record (bfd *abfd, union ext_any *ptr)
|
||||
{
|
||||
if (bfd_bread (&ptr->size, (bfd_size_type) 1, abfd) != 1
|
||||
|| (bfd_bread ((char *) ptr + 1, (bfd_size_type) ptr->size, abfd)
|
||||
!= ptr->size))
|
||||
return 0;
|
||||
return 1;
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
bfd_size_type amt = ptr->size + 1;
|
||||
|
||||
if (amt < sizeof (* ptr))
|
||||
memset ((char *) ptr + amt, 0, sizeof (* ptr) - amt);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -366,7 +374,7 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass)
|
|||
|
||||
struct esdid *esdid = &EDATA (abfd, otr->esdid - 1);
|
||||
unsigned char *contents = esdid->contents;
|
||||
int need_contents = 0;
|
||||
bfd_boolean need_contents = FALSE;
|
||||
unsigned int dst_idx = esdid->pc;
|
||||
|
||||
for (shift = ((unsigned long) 1 << 31); shift && srcp < endp; shift >>= 1)
|
||||
|
@ -390,8 +398,8 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass)
|
|||
int val = get_offset (offsetlen, srcp + esdids);
|
||||
|
||||
if (pass == 1)
|
||||
need_contents = 1;
|
||||
else
|
||||
need_contents = TRUE;
|
||||
else if (contents)
|
||||
for (j = 0; j < sizeinwords * 2; j++)
|
||||
{
|
||||
contents[dst_idx + (sizeinwords * 2) - j - 1] = val;
|
||||
|
@ -429,19 +437,21 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass)
|
|||
}
|
||||
else
|
||||
{
|
||||
need_contents = 1;
|
||||
|
||||
if (esdid->section && dst_idx < esdid->section->size)
|
||||
need_contents = TRUE;
|
||||
|
||||
if (esdid->section && contents && dst_idx < esdid->section->size)
|
||||
if (pass == 2)
|
||||
{
|
||||
/* Absolute code, comes in 16 bit lumps. */
|
||||
contents[dst_idx] = srcp[0];
|
||||
contents[dst_idx + 1] = srcp[1];
|
||||
}
|
||||
|
||||
dst_idx += 2;
|
||||
srcp += 2;
|
||||
}
|
||||
}
|
||||
|
||||
EDATA (abfd, otr->esdid - 1).pc = dst_idx;
|
||||
|
||||
if (!contents && need_contents)
|
||||
|
@ -461,7 +471,7 @@ process_otr (bfd *abfd, struct ext_otr *otr, int pass)
|
|||
static bfd_boolean
|
||||
versados_scan (bfd *abfd)
|
||||
{
|
||||
int loop = 1;
|
||||
bfd_boolean loop = TRUE;
|
||||
int i;
|
||||
int j;
|
||||
int nsecs = 0;
|
||||
|
@ -479,13 +489,13 @@ versados_scan (bfd *abfd)
|
|||
union ext_any any;
|
||||
|
||||
if (!get_record (abfd, &any))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
switch (any.header.type)
|
||||
{
|
||||
case VHEADER:
|
||||
break;
|
||||
case VEND:
|
||||
loop = 0;
|
||||
loop = FALSE;
|
||||
break;
|
||||
case VESTDEF:
|
||||
process_esd (abfd, &any.esd, 1);
|
||||
|
@ -512,7 +522,6 @@ versados_scan (bfd *abfd)
|
|||
{
|
||||
amt = (bfd_size_type) esdid->relocs * sizeof (arelent);
|
||||
esdid->section->relocation = bfd_alloc (abfd, amt);
|
||||
|
||||
esdid->pc = 0;
|
||||
|
||||
if (esdid->contents)
|
||||
|
@ -571,7 +580,7 @@ versados_scan (bfd *abfd)
|
|||
|
||||
VDATA (abfd)->ref_idx = 0;
|
||||
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Check whether an existing file is a versados file. */
|
||||
|
@ -773,6 +782,7 @@ versados_canonicalize_reloc (bfd *abfd,
|
|||
|
||||
versados_pass_2 (abfd);
|
||||
src = section->relocation;
|
||||
|
||||
if (!EDATA (abfd, section->target_index).donerel)
|
||||
{
|
||||
EDATA (abfd, section->target_index).donerel = 1;
|
||||
|
@ -790,6 +800,9 @@ versados_canonicalize_reloc (bfd *abfd,
|
|||
|
||||
src[count].sym_ptr_ptr = e->section->symbol_ptr_ptr;
|
||||
}
|
||||
/* PR 17512: file:3757-2936-0.004. */
|
||||
else if ((unsigned) (esdid - ES_BASE) >= bfd_get_symcount (abfd))
|
||||
src[count].sym_ptr_ptr = bfd_und_section_ptr->symbol_ptr_ptr;
|
||||
else
|
||||
src[count].sym_ptr_ptr = symbols + esdid - ES_BASE;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
2014-11-26 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR binutils/17512
|
||||
* dwarf.c (display_block): Do nothing if the block starts after
|
||||
the end of the buffer.
|
||||
(read_and_display_attr_value): Add range checks.
|
||||
(struct Frame_Chunk): Make the ncols and ra fields unsigned.
|
||||
(frame_need_space): Test for an ncols of zero.
|
||||
(read_cie): Fail if the augmentation data extends off the end of
|
||||
the buffer.
|
||||
(display_debug_frames): Add checks for read_cie failing. Add
|
||||
range checks.
|
||||
|
||||
2014-11-25 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* objdump.c (objdump_print_symname): Replace
|
||||
|
|
|
@ -861,6 +861,8 @@ display_block (unsigned char *data,
|
|||
dwarf_vma maxlen;
|
||||
|
||||
printf (_(" %s byte block: "), dwarf_vmatoa ("u", length));
|
||||
if (data > end)
|
||||
return (unsigned char *) end;
|
||||
|
||||
maxlen = (dwarf_vma) (end - data);
|
||||
length = length > maxlen ? maxlen : length;
|
||||
|
@ -1654,6 +1656,12 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
case DW_FORM_exprloc:
|
||||
uvalue = read_uleb128 (data, & bytes_read, end);
|
||||
block_start = data + bytes_read;
|
||||
if (block_start >= end)
|
||||
{
|
||||
warn (_("Block ends prematurely\n"));
|
||||
uvalue = 0;
|
||||
block_start = end;
|
||||
}
|
||||
/* PR 17512: file: 008-103549-0.001:0.1. */
|
||||
if (block_start + uvalue > end)
|
||||
{
|
||||
|
@ -1669,6 +1677,12 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
case DW_FORM_block1:
|
||||
SAFE_BYTE_GET (uvalue, data, 1, end);
|
||||
block_start = data + 1;
|
||||
if (block_start >= end)
|
||||
{
|
||||
warn (_("Block ends prematurely\n"));
|
||||
uvalue = 0;
|
||||
block_start = end;
|
||||
}
|
||||
if (block_start + uvalue > end)
|
||||
{
|
||||
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
|
||||
|
@ -1683,6 +1697,12 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
case DW_FORM_block2:
|
||||
SAFE_BYTE_GET (uvalue, data, 2, end);
|
||||
block_start = data + 2;
|
||||
if (block_start >= end)
|
||||
{
|
||||
warn (_("Block ends prematurely\n"));
|
||||
uvalue = 0;
|
||||
block_start = end;
|
||||
}
|
||||
if (block_start + uvalue > end)
|
||||
{
|
||||
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
|
||||
|
@ -1697,6 +1717,13 @@ read_and_display_attr_value (unsigned long attribute,
|
|||
case DW_FORM_block4:
|
||||
SAFE_BYTE_GET (uvalue, data, 4, end);
|
||||
block_start = data + 4;
|
||||
/* PR 17512: file: 3371-3907-0.004. */
|
||||
if (block_start >= end)
|
||||
{
|
||||
warn (_("Block ends prematurely\n"));
|
||||
uvalue = 0;
|
||||
block_start = end;
|
||||
}
|
||||
if (block_start + uvalue > end)
|
||||
{
|
||||
warn (_("Corrupt attribute block length: %lx\n"), (long) uvalue);
|
||||
|
@ -5080,7 +5107,7 @@ typedef struct Frame_Chunk
|
|||
{
|
||||
struct Frame_Chunk *next;
|
||||
unsigned char *chunk_start;
|
||||
int ncols;
|
||||
unsigned int ncols;
|
||||
/* DW_CFA_{undefined,same_value,offset,register,unreferenced} */
|
||||
short int *col_type;
|
||||
int *col_offset;
|
||||
|
@ -5091,7 +5118,7 @@ typedef struct Frame_Chunk
|
|||
dwarf_vma pc_range;
|
||||
int cfa_reg;
|
||||
int cfa_offset;
|
||||
int ra;
|
||||
unsigned int ra;
|
||||
unsigned char fde_encoding;
|
||||
unsigned char cfa_exp;
|
||||
unsigned char ptr_size;
|
||||
|
@ -5106,13 +5133,13 @@ static unsigned int dwarf_regnames_count;
|
|||
in the frame info. */
|
||||
#define DW_CFA_unreferenced (-1)
|
||||
|
||||
/* Return 0 if not more space is needed, 1 if more space is needed,
|
||||
/* Return 0 if no more space is needed, 1 if more space is needed,
|
||||
-1 for invalid reg. */
|
||||
|
||||
static int
|
||||
frame_need_space (Frame_Chunk *fc, unsigned int reg)
|
||||
{
|
||||
int prev = fc->ncols;
|
||||
unsigned int prev = fc->ncols;
|
||||
|
||||
if (reg < (unsigned int) fc->ncols)
|
||||
return 0;
|
||||
|
@ -5122,6 +5149,11 @@ frame_need_space (Frame_Chunk *fc, unsigned int reg)
|
|||
return -1;
|
||||
|
||||
fc->ncols = reg + 1;
|
||||
/* PR 17512: file: 10450-2643-0.004.
|
||||
If reg == -1 then this can happen... */
|
||||
if (fc->ncols == 0)
|
||||
return -1;
|
||||
|
||||
fc->col_type = (short int *) xcrealloc (fc->col_type, fc->ncols,
|
||||
sizeof (short int));
|
||||
fc->col_offset = (int *) xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
|
||||
|
@ -5280,9 +5312,9 @@ regname (unsigned int regno, int row)
|
|||
}
|
||||
|
||||
static void
|
||||
frame_display_row (Frame_Chunk *fc, int *need_col_headers, int *max_regs)
|
||||
frame_display_row (Frame_Chunk *fc, int *need_col_headers, unsigned int *max_regs)
|
||||
{
|
||||
int r;
|
||||
unsigned int r;
|
||||
char tmp[100];
|
||||
|
||||
if (*max_regs < fc->ncols)
|
||||
|
@ -5422,6 +5454,12 @@ read_cie (unsigned char *start, unsigned char *end,
|
|||
augmentation_data_len = LEB ();
|
||||
augmentation_data = start;
|
||||
start += augmentation_data_len;
|
||||
/* PR 17512: file: 11042-2589-0.004. */
|
||||
if (start > end)
|
||||
{
|
||||
warn (_("Augmentation data too long: 0x%lx"), augmentation_data_len);
|
||||
return end;
|
||||
}
|
||||
}
|
||||
|
||||
if (augmentation_data_len)
|
||||
|
@ -5430,7 +5468,7 @@ read_cie (unsigned char *start, unsigned char *end,
|
|||
p = (unsigned char *) fc->augmentation + 1;
|
||||
q = augmentation_data;
|
||||
|
||||
while (1)
|
||||
while (p < end && q < augmentation_data + augmentation_data_len)
|
||||
{
|
||||
if (*p == 'L')
|
||||
q++;
|
||||
|
@ -5469,7 +5507,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
Frame_Chunk *rs;
|
||||
int is_eh = strcmp (section->name, ".eh_frame") == 0;
|
||||
unsigned int length_return;
|
||||
int max_regs = 0;
|
||||
unsigned int max_regs = 0;
|
||||
const char *bad_reg = _("bad register: ");
|
||||
int saved_eh_addr_size = eh_addr_size;
|
||||
|
||||
|
@ -5534,18 +5572,19 @@ display_debug_frames (struct dwarf_section *section,
|
|||
|| (offset_size == 8 && cie_id == DW64_CIE_ID)))
|
||||
{
|
||||
int version;
|
||||
int mreg;
|
||||
unsigned int mreg;
|
||||
|
||||
start = read_cie (start, end, &cie, &version,
|
||||
&augmentation_data_len, &augmentation_data);
|
||||
/* PR 17512: file: 027-135133-0.005. */
|
||||
if (cie == NULL)
|
||||
break;
|
||||
|
||||
fc = cie;
|
||||
fc->next = chunks;
|
||||
chunks = fc;
|
||||
fc->chunk_start = saved_start;
|
||||
mreg = max_regs - 1;
|
||||
mreg = max_regs > 0 ? max_regs - 1 : 0;
|
||||
if (mreg < fc->ra)
|
||||
mreg = fc->ra;
|
||||
frame_need_space (fc, mreg);
|
||||
|
@ -5578,8 +5617,11 @@ display_debug_frames (struct dwarf_section *section,
|
|||
if (augmentation_data_len)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
printf (" Augmentation data: ");
|
||||
for (i = 0; i < augmentation_data_len; ++i)
|
||||
/* FIXME: If do_wide is FALSE, then we should
|
||||
add carriage returns at 80 columns... */
|
||||
printf (" %02x", augmentation_data[i]);
|
||||
putchar ('\n');
|
||||
}
|
||||
|
@ -5635,14 +5677,20 @@ display_debug_frames (struct dwarf_section *section,
|
|||
|| (off_size == 8 && c_id == DW64_CIE_ID)))
|
||||
{
|
||||
int version;
|
||||
int mreg;
|
||||
unsigned int mreg;
|
||||
|
||||
read_cie (cie_scan, end, &cie, &version,
|
||||
&augmentation_data_len, &augmentation_data);
|
||||
/* PR 17512: file: 3450-2098-0.004. */
|
||||
if (cie == NULL)
|
||||
{
|
||||
warn (_("Failed to read CIE information\n"));
|
||||
break;
|
||||
}
|
||||
cie->next = forward_refs;
|
||||
forward_refs = cie;
|
||||
cie->chunk_start = look_for;
|
||||
mreg = max_regs - 1;
|
||||
mreg = max_regs > 0 ? max_regs - 1 : 0;
|
||||
if (mreg < cie->ra)
|
||||
mreg = cie->ra;
|
||||
frame_need_space (cie, mreg);
|
||||
|
@ -5665,7 +5713,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
fc->ncols = 0;
|
||||
fc->col_type = (short int *) xmalloc (sizeof (short int));
|
||||
fc->col_offset = (int *) xmalloc (sizeof (int));
|
||||
frame_need_space (fc, max_regs - 1);
|
||||
frame_need_space (fc, max_regs > 0 ? max_regs - 1 : 0);
|
||||
cie = fc;
|
||||
fc->augmentation = "";
|
||||
fc->fde_encoding = 0;
|
||||
|
@ -5688,7 +5736,7 @@ display_debug_frames (struct dwarf_section *section,
|
|||
fc->cfa_reg = cie->cfa_reg;
|
||||
fc->cfa_offset = cie->cfa_offset;
|
||||
fc->ra = cie->ra;
|
||||
frame_need_space (fc, max_regs - 1);
|
||||
frame_need_space (fc, max_regs > 0 ? max_regs - 1: 0);
|
||||
fc->fde_encoding = cie->fde_encoding;
|
||||
}
|
||||
|
||||
|
@ -6167,10 +6215,9 @@ display_debug_frames (struct dwarf_section *section,
|
|||
|
||||
case DW_CFA_def_cfa_expression:
|
||||
ul = LEB ();
|
||||
if (start >= block_end)
|
||||
if (start >= block_end || start + ul > block_end)
|
||||
{
|
||||
printf (" DW_CFA_def_cfa_expression: <corrupt>\n");
|
||||
warn (_("Corrupt length field in DW_CFA_def_cfa_expression\n"));
|
||||
printf (_(" DW_CFA_def_cfa_expression: <corrupt len %lu>\n"), ul);
|
||||
break;
|
||||
}
|
||||
if (! do_debug_frames_interp)
|
||||
|
@ -6190,10 +6237,9 @@ display_debug_frames (struct dwarf_section *section,
|
|||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
/* PR 17512: file: 069-133014-0.006. */
|
||||
if (start >= block_end)
|
||||
if (start >= block_end || start + ul > block_end)
|
||||
{
|
||||
printf (" DW_CFA_expression: <corrupt>\n");
|
||||
warn (_("Corrupt length field in DW_CFA_expression\n"));
|
||||
printf (_(" DW_CFA_expression: <corrupt len %lu>\n"), ul);
|
||||
break;
|
||||
}
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
@ -6214,10 +6260,9 @@ display_debug_frames (struct dwarf_section *section,
|
|||
ul = LEB ();
|
||||
if (reg >= (unsigned int) fc->ncols)
|
||||
reg_prefix = bad_reg;
|
||||
if (start >= block_end)
|
||||
if (start >= block_end || start + ul > block_end)
|
||||
{
|
||||
printf (" DW_CFA_val_expression: <corrupt>\n");
|
||||
warn (_("Corrupt length field in DW_CFA_val_expression\n"));
|
||||
printf (" DW_CFA_val_expression: <corrupt len %lu>\n", ul);
|
||||
break;
|
||||
}
|
||||
if (! do_debug_frames_interp || *reg_prefix != '\0')
|
||||
|
|
Loading…
Reference in New Issue