diff options
author | Nick Clifton <nickc@redhat.com> | 2015-03-24 16:32:44 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2015-03-24 16:32:44 +0000 |
commit | 7a57494b3cf09162ed556f4d1da2bd77d2acc4e4 (patch) | |
tree | 5865985c47d4279fd8baa389ff6d04247d999e96 | |
parent | 4f9583e9c45482e111d30f94df650a3f2cf36b99 (diff) | |
download | binutils-7a57494b3cf09162ed556f4d1da2bd77d2acc4e4.zip binutils-7a57494b3cf09162ed556f4d1da2bd77d2acc4e4.tar.gz binutils-7a57494b3cf09162ed556f4d1da2bd77d2acc4e4.tar.bz2 |
Import fixes from mainline that address illegal memory accesses when working with COFF/PE based files.
Apply from master:
2015-02-26 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* coffcode.h (coff_compute_section_file_positions): Report
negative page sizes.
2015-02-10 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* coffcode.h (styp_to_sec_flags): Use an unsigned long type to
hold the flag bits.
2015-02-06 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* peXXigen.c (rsrc_print_resource_entries): Add range check for
addresses that wrap around the address space.
(rsrc_parse_entry): Likewise.
2015-02-03 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* ecoff.c: Use bfd_alloc2 to allocate space for structure arrays.
(_bfd_ecoff_slurp_symbol_table): Check for a negative symbol
index or an out of range fdr index.
* peXXigen.c (pe_print_edata): Check for numeric overflow in edt
fields.
2015-01-22 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* coffcode.h (handle_COMDAT): When searching for the section
symbol, make sure that there is space left in the symbol table.
2015-01-21 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* coffcode.h (coff_set_arch_mach_hook): Check return value from
bfd_malloc.
(coff_slurp_line_table): Return FALSE if the line number
information was corrupt.
(coff_slurp_symbol_table): Return FALSE if the symbol information
was corrupt.
* peXXigen.c (_bfd_XXi_swap_aouthdr_in): Set bfd_error if the
read fails.
(slurp_symtab): Check the return from bfd_malloc.
(_bfd_XX_bfd_copy_private_bfd_data_common): Fail if the copy
encountered an error.
(_bfd_XXi_final_link_postscript): Fail if a section could not be
copied.
* peicode.h (pe_bfd_object_p): Fail if the header could not be
swapped in.
2015-01-08 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* coffcode.h (coff_slurp_symbol_table): Return false if we failed
to load the line table.
2015-01-06 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* coff-i860.c (CALC_ADDEND): Always set an addend value.
2014-11-27 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* ecoff.c (_bfd_ecoff_slurp_symbol_table): Warn about and correct
a discrepancy between the isymMax and ifdMax values in the
symbolic header.
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.
2014-11-21 Nick Clifton <nickc@redhat.com>
PR binutils/17512
* coffgen.c (coff_get_normalized_symtab): Check for an excessive
number of auxillary entries.
2014-11-21 Alexander Cherepanov <cherepan@mccme.ru>
PR binutils/17512
* coffgen.c (_bfd_coff_read_string_table): Test allocation of
string table before clearing the first few bytes.
-rw-r--r-- | bfd/ChangeLog | 123 | ||||
-rw-r--r-- | bfd/coff-h8300.c | 2 | ||||
-rw-r--r-- | bfd/coff-h8500.c | 2 | ||||
-rw-r--r-- | bfd/coff-i860.c | 5 | ||||
-rw-r--r-- | bfd/coff-m68k.c | 1 | ||||
-rw-r--r-- | bfd/coff-mcore.c | 16 | ||||
-rw-r--r-- | bfd/coff-tic30.c | 2 | ||||
-rw-r--r-- | bfd/coff-w65.c | 9 | ||||
-rw-r--r-- | bfd/coff-we32k.c | 9 | ||||
-rw-r--r-- | bfd/coff-x86_64.c | 13 | ||||
-rw-r--r-- | bfd/coff-z80.c | 2 | ||||
-rw-r--r-- | bfd/coff-z8k.c | 2 | ||||
-rw-r--r-- | bfd/coffcode.h | 65 | ||||
-rw-r--r-- | bfd/coffgen.c | 41 | ||||
-rw-r--r-- | bfd/cofflink.c | 2 | ||||
-rw-r--r-- | bfd/ecoff.c | 49 | ||||
-rw-r--r-- | bfd/opncls.c | 14 | ||||
-rw-r--r-- | bfd/pe-mips.c | 7 | ||||
-rw-r--r-- | bfd/peXXigen.c | 85 | ||||
-rw-r--r-- | bfd/pei-x86_64.c | 158 | ||||
-rw-r--r-- | bfd/peicode.h | 3 | ||||
-rw-r--r-- | bfd/xcofflink.c | 2 |
22 files changed, 509 insertions, 103 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b1dcab2..906c975 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,126 @@ +2015-03-24 Nick Clifton <nickc@redhat.com> + + Apply from master: + 2015-02-26 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * coffcode.h (coff_compute_section_file_positions): Report + negative page sizes. + + 2015-02-10 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * coffcode.h (styp_to_sec_flags): Use an unsigned long type to + hold the flag bits. + + 2015-02-06 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * peXXigen.c (rsrc_print_resource_entries): Add range check for + addresses that wrap around the address space. + (rsrc_parse_entry): Likewise. + + 2015-02-03 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * ecoff.c: Use bfd_alloc2 to allocate space for structure arrays. + (_bfd_ecoff_slurp_symbol_table): Check for a negative symbol + index or an out of range fdr index. + * peXXigen.c (pe_print_edata): Check for numeric overflow in edt + fields. + + 2015-01-22 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * coffcode.h (handle_COMDAT): When searching for the section + symbol, make sure that there is space left in the symbol table. + + 2015-01-21 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * coffcode.h (coff_set_arch_mach_hook): Check return value from + bfd_malloc. + (coff_slurp_line_table): Return FALSE if the line number + information was corrupt. + (coff_slurp_symbol_table): Return FALSE if the symbol information + was corrupt. + * peXXigen.c (_bfd_XXi_swap_aouthdr_in): Set bfd_error if the + read fails. + (slurp_symtab): Check the return from bfd_malloc. + (_bfd_XX_bfd_copy_private_bfd_data_common): Fail if the copy + encountered an error. + (_bfd_XXi_final_link_postscript): Fail if a section could not be + copied. + * peicode.h (pe_bfd_object_p): Fail if the header could not be + swapped in. + + 2015-01-08 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * coffcode.h (coff_slurp_symbol_table): Return false if we failed + to load the line table. + + 2015-01-06 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * coff-i860.c (CALC_ADDEND): Always set an addend value. + + 2014-11-27 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * ecoff.c (_bfd_ecoff_slurp_symbol_table): Warn about and correct + a discrepancy between the isymMax and ifdMax values in the + symbolic header. + + 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. + + 2014-11-21 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * coffgen.c (coff_get_normalized_symtab): Check for an excessive + number of auxillary entries. + + 2014-11-21 Alexander Cherepanov <cherepan@mccme.ru> + + PR binutils/17512 + * coffgen.c (_bfd_coff_read_string_table): Test allocation of + string table before clearing the first few bytes. + +2014-11-18 Nick Clifton <nickc@redhat.com> + + PR binutils/17512 + * peXXigen.c (pe_print_pdata): Fail if the section's virtual size + is larger than its real size. + (rsrc_print_section): Fix off-by-one error checking for overflow. + * pei-x86_64.c (pex64_bfd_print_pdata): Handle empty unwind + sections. + 2015-03-18 Alan Modra <amodra@gmail.com> Apply from master diff --git a/bfd/coff-h8300.c b/bfd/coff-h8300.c index 5ec48c9..10123d3 100644 --- a/bfd/coff-h8300.c +++ b/bfd/coff-h8300.c @@ -337,7 +337,7 @@ rtype2howto (arelent *internal, struct internal_reloc *dst) internal->howto = howto_table + 19; break; default: - abort (); + internal->howto = NULL; break; } } diff --git a/bfd/coff-h8500.c b/bfd/coff-h8500.c index 574f956..b6a996e 100644 --- a/bfd/coff-h8500.c +++ b/bfd/coff-h8500.c @@ -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; diff --git a/bfd/coff-i860.c b/bfd/coff-i860.c index 341183f..338ec75 100644 --- a/bfd/coff-i860.c +++ b/bfd/coff-i860.c @@ -467,7 +467,10 @@ static reloc_howto_type howto_table[] = FIXME: This macro refers to symbols and asect; these are from the calling function, not the macro arguments. */ -#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) +/* PR 17512: file: 0a38fb7c + Set an addend value, even if it is not going to be used. A tool + like coffdump might be used to print out the contents of the reloc. */ +#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) (cache_ptr)->addend = 0 /* We use the special COFF backend linker. */ #define coff_relocate_section _bfd_coff_generic_relocate_section diff --git a/bfd/coff-m68k.c b/bfd/coff-m68k.c index f7089a6..5ebf52c 100644 --- a/bfd/coff-m68k.c +++ b/bfd/coff-m68k.c @@ -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; } } diff --git a/bfd/coff-mcore.c b/bfd/coff-mcore.c index 7dad44f..9f30cfc 100644 --- a/bfd/coff-mcore.c +++ b/bfd/coff-mcore.c @@ -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; diff --git a/bfd/coff-tic30.c b/bfd/coff-tic30.c index 740c82c..ab95308 100644 --- a/bfd/coff-tic30.c +++ b/bfd/coff-tic30.c @@ -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; } } diff --git a/bfd/coff-w65.c b/bfd/coff-w65.c index f208730..d575f58 100644 --- a/bfd/coff-w65.c +++ b/bfd/coff-w65.c @@ -42,6 +42,8 @@ static reloc_howto_type howto_table[] = 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. */ #define SELECT_RELOC(x,howto) \ @@ -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) diff --git a/bfd/coff-we32k.c b/bfd/coff-we32k.c index d5481b8..b754815 100644 --- a/bfd/coff-we32k.c +++ b/bfd/coff-we32k.c @@ -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 diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c index 2a21bb8..742adc2 100644 --- a/bfd/coff-x86_64.c +++ b/bfd/coff-x86_64.c @@ -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; } } diff --git a/bfd/coff-z80.c b/bfd/coff-z80.c index 7b62cdf..fd68b12 100644 --- a/bfd/coff-z80.c +++ b/bfd/coff-z80.c @@ -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; diff --git a/bfd/coff-z8k.c b/bfd/coff-z8k.c index c85713f..7f67ee8 100644 --- a/bfd/coff-z8k.c +++ b/bfd/coff-z8k.c @@ -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; diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 9990b16..2b1c3d0 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -1009,6 +1009,13 @@ handle_COMDAT (bfd * abfd, seen_state = 1; + /* PR 17512: file: e2cfe54f. */ + if (esym + bfd_coff_symesz (abfd) >= esymend) + { + _bfd_error_handler (_("%B: warning: No symbol for section '%s' found"), + abfd, symname); + break; + } /* This is the section symbol. */ bfd_coff_swap_aux_in (abfd, (esym + bfd_coff_symesz (abfd)), isym.n_type, isym.n_sclass, @@ -1162,7 +1169,7 @@ styp_to_sec_flags (bfd *abfd, flagword *flags_ptr) { struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr; - long styp_flags = internal_s->s_flags; + unsigned long styp_flags = internal_s->s_flags; flagword sec_flags; bfd_boolean result = TRUE; bfd_boolean is_dbg = FALSE; @@ -1185,7 +1192,7 @@ styp_to_sec_flags (bfd *abfd, /* Process each flag bit in styp_flags in turn. */ while (styp_flags) { - long flag = styp_flags & - styp_flags; + unsigned long flag = styp_flags & - styp_flags; char * unhandled = NULL; styp_flags &= ~ flag; @@ -2073,7 +2080,11 @@ coff_mkobject_hook (bfd * abfd, #endif if ((internal_f->f_flags & F_GO32STUB) != 0) - coff->go32stub = (char *) bfd_alloc (abfd, (bfd_size_type) GO32_STUBSIZE); + { + coff->go32stub = (char *) bfd_alloc (abfd, (bfd_size_type) GO32_STUBSIZE); + if (coff->go32stub == NULL) + return NULL; + } if (coff->go32stub != NULL) memcpy (coff->go32stub, internal_f->go32stub, GO32_STUBSIZE); @@ -2278,6 +2289,8 @@ coff_set_arch_mach_hook (bfd *abfd, void * filehdr) bfd_size_type amt = bfd_coff_symesz (abfd); buf = bfd_malloc (amt); + if (buf == NULL) + return FALSE; if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0 || bfd_bread (buf, amt, abfd) != amt) { @@ -2666,10 +2679,16 @@ coff_write_relocs (bfd * abfd, int first_undef) amt = s->reloc_count; amt *= sizeof (arelent *); p = bfd_malloc (amt); - if (p == NULL && s->reloc_count > 0) - return FALSE; - memcpy (p, s->orelocation, (size_t) amt); - qsort (p, s->reloc_count, sizeof (arelent *), compare_arelent_ptr); + if (p == NULL) + { + if (s->reloc_count > 0) + return FALSE; + } + else + { + memcpy (p, s->orelocation, (size_t) amt); + qsort (p, s->reloc_count, sizeof (arelent *), compare_arelent_ptr); + } } #endif @@ -3151,6 +3170,15 @@ coff_compute_section_file_positions (bfd * abfd) This repairs 'ld -r' for arm-wince-pe target. */ if (page_size == 0) page_size = 1; + + /* PR 17512: file: 0ac816d3. */ + if (page_size < 0) + { + bfd_set_error (bfd_error_file_too_big); + (*_bfd_error_handler) + (_("%B: page size is too large (0x%x)"), abfd, page_size); + return FALSE; + } } else page_size = PE_DEF_FILE_ALIGNMENT; @@ -4526,6 +4554,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect) unsigned int nbr_func; LINENO *src; bfd_boolean have_func; + bfd_boolean ret = TRUE; BFD_ASSERT (asect->lineno == NULL); @@ -4575,6 +4604,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect) (_("%B: warning: illegal symbol index 0x%lx in line number entry %d"), abfd, (long) symndx, counter); cache_ptr->line_number = -1; + ret = FALSE; continue; } @@ -4587,6 +4617,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect) (_("%B: warning: illegal symbol index 0x%lx in line number entry %d"), abfd, (long) symndx, counter); cache_ptr->line_number = -1; + ret = FALSE; continue; } sym = (coff_symbol_type *) (ent->u.syment._n._n_n._n_zeroes); @@ -4599,6 +4630,7 @@ coff_slurp_line_table (bfd *abfd, asection *asect) (_("%B: warning: illegal symbol in line number entry %d"), abfd, counter); cache_ptr->line_number = -1; + ret = FALSE; continue; } @@ -4678,11 +4710,15 @@ coff_slurp_line_table (bfd *abfd, asection *asect) memcpy (lineno_cache, n_lineno_cache, amt); } + else + ret = FALSE; bfd_release (abfd, func_table); } + else + ret = FALSE; } - return TRUE; + return ret; } /* Slurp in the symbol table, converting it to generic form. Note @@ -4697,6 +4733,7 @@ coff_slurp_symbol_table (bfd * abfd) unsigned int *table_ptr; bfd_size_type amt; unsigned int number_of_symbols = 0; + bfd_boolean ret = TRUE; if (obj_symbols (abfd)) return TRUE; @@ -5012,13 +5049,14 @@ coff_slurp_symbol_table (bfd * abfd) #if defined(TIC80COFF) || defined(TICOFF) case C_UEXT: /* Tentative external definition. */ #endif - case C_EXTLAB: /* External load time label. */ - case C_HIDDEN: /* Ext symbol in dmert public lib. */ default: (*_bfd_error_handler) (_("%B: Unrecognized storage class %d for %s symbol `%s'"), abfd, src->u.syment.n_sclass, dst->symbol.section->name, dst->symbol.name); + ret = FALSE; + case C_EXTLAB: /* External load time label. */ + case C_HIDDEN: /* Ext symbol in dmert public lib. */ dst->symbol.flags = BSF_DEBUGGING; dst->symbol.value = (src->u.syment.n_value); break; @@ -5046,12 +5084,13 @@ coff_slurp_symbol_table (bfd * abfd) p = abfd->sections; while (p) { - coff_slurp_line_table (abfd, p); + if (! coff_slurp_line_table (abfd, p)) + return FALSE; p = p->next; } } - return TRUE; + return ret; } /* Classify a COFF symbol. A couple of targets have globally visible @@ -5310,7 +5349,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) diff --git a/bfd/coffgen.c b/bfd/coffgen.c index a22f67a..d071d8a 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -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); } @@ -463,7 +468,10 @@ _bfd_coff_internal_syment_name (bfd *abfd, if (strings == NULL) return NULL; } - if (sym->_n._n_n._n_offset >= obj_coff_strings_len (abfd)) + /* PR 17910: Only check for string overflow if the length has been set. + Some DLLs, eg those produced by Visual Studio, may not set the length field. */ + if (obj_coff_strings_len (abfd) > 0 + && sym->_n._n_n._n_offset >= obj_coff_strings_len (abfd)) return NULL; return strings + sym->_n._n_n._n_offset; } @@ -760,8 +768,9 @@ coff_renumber_symbols (bfd *bfd_ptr, int *first_undef) for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) { - coff_symbol_type *coff_symbol_ptr = coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); + coff_symbol_type *coff_symbol_ptr; + coff_symbol_ptr = coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); symbol_ptr_ptr[symbol_index]->udata.i = symbol_index; if (coff_symbol_ptr && coff_symbol_ptr->native) { @@ -805,9 +814,9 @@ coff_mangle_symbols (bfd *bfd_ptr) for (symbol_index = 0; symbol_index < symbol_count; symbol_index++) { - coff_symbol_type *coff_symbol_ptr = - coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); + coff_symbol_type *coff_symbol_ptr; + coff_symbol_ptr = coff_symbol_from (bfd_ptr, symbol_ptr_ptr[symbol_index]); if (coff_symbol_ptr && coff_symbol_ptr->native) { int i; @@ -1711,15 +1720,15 @@ _bfd_coff_read_string_table (bfd *abfd) } strings = (char *) bfd_malloc (strsize + 1); + if (strings == NULL) + return NULL; + /* PR 17521 file: 079-54929-0.004. A corrupt file could contain an index that points into the first STRING_SIZE_SIZE bytes of the string table, so make sure that they are zero. */ memset (strings, 0, STRING_SIZE_SIZE); - if (strings == NULL) - return NULL; - if (bfd_bread (strings + STRING_SIZE_SIZE, strsize - STRING_SIZE_SIZE, abfd) != strsize - STRING_SIZE_SIZE) { @@ -1808,6 +1817,16 @@ coff_get_normalized_symtab (bfd *abfd) symbol_ptr = internal_ptr; internal_ptr->is_sym = TRUE; + /* PR 17512: file: 1353-1166-0.004. */ + if (symbol_ptr->u.syment.n_sclass == C_FILE + && symbol_ptr->u.syment.n_numaux > 0 + && raw_src + symesz + symbol_ptr->u.syment.n_numaux + * symesz > raw_end) + { + bfd_release (abfd, internal); + return NULL; + } + for (i = 0; i < symbol_ptr->u.syment.n_numaux; i++) @@ -1815,7 +1834,10 @@ coff_get_normalized_symtab (bfd *abfd) internal_ptr++; /* PR 17512: Prevent buffer overrun. */ if (internal_ptr >= internal_end) - return NULL; + { + bfd_release (abfd, internal); + return NULL; + } raw_src += symesz; bfd_coff_swap_aux_in (abfd, (void *) raw_src, @@ -1823,6 +1845,7 @@ coff_get_normalized_symtab (bfd *abfd) symbol_ptr->u.syment.n_sclass, (int) i, symbol_ptr->u.syment.n_numaux, &(internal_ptr->u.auxent)); + internal_ptr->is_sym = FALSE; coff_pointerize_aux (abfd, internal, symbol_ptr, i, internal_ptr); diff --git a/bfd/cofflink.c b/bfd/cofflink.c index 2782795..ef9e362 100644 --- a/bfd/cofflink.c +++ b/bfd/cofflink.c @@ -2789,7 +2789,7 @@ _bfd_coff_reloc_link_order (bfd *output_bfd, size = bfd_get_reloc_size (howto); buf = (bfd_byte *) bfd_zmalloc (size); - if (buf == NULL) + if (buf == NULL && size != 0) return FALSE; rstat = _bfd_relocate_contents (howto, output_bfd, diff --git a/bfd/ecoff.c b/bfd/ecoff.c index 01f51e6..f65249b 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -504,7 +504,6 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd, struct fdr *fdr_ptr; bfd_size_type raw_end; bfd_size_type cb_end; - bfd_size_type amt; file_ptr pos; BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info); @@ -607,14 +606,16 @@ _bfd_ecoff_slurp_symbolic_info (bfd *abfd, We need to look at the fdr to deal with a lot of information in the symbols, so we swap them here. */ - amt = internal_symhdr->ifdMax; - amt *= sizeof (struct fdr); - debug->fdr = (FDR *) bfd_alloc (abfd, amt); + debug->fdr = (FDR *) bfd_alloc2 (abfd, internal_symhdr->ifdMax, + sizeof (struct fdr)); if (debug->fdr == NULL) return FALSE; 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); @@ -856,7 +857,6 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd) = backend->debug_swap.swap_ext_in; void (* const swap_sym_in) (bfd *, void *, SYMR *) = backend->debug_swap.swap_sym_in; - bfd_size_type internal_size; ecoff_symbol_type *internal; ecoff_symbol_type *internal_ptr; char *eraw_src; @@ -875,9 +875,8 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd) if (bfd_get_symcount (abfd) == 0) return TRUE; - internal_size = bfd_get_symcount (abfd); - internal_size *= sizeof (ecoff_symbol_type); - internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size); + internal = (ecoff_symbol_type *) bfd_alloc2 (abfd, bfd_get_symcount (abfd), + sizeof (ecoff_symbol_type)); if (internal == NULL) return FALSE; @@ -891,16 +890,30 @@ _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 + || internal_esym.asym.iss < 0) + 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, &internal_ptr->symbol, 1, internal_esym.weakext)) return FALSE; + /* The alpha uses a negative ifd field for section symbols. */ if (internal_esym.ifd >= 0) - internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr - + internal_esym.ifd); + { + /* PR 17512: file: 3372-1983-0.004. */ + if (internal_esym.ifd >= ecoff_data (abfd)->debug_info.symbolic_header.ifdMax) + internal_ptr->fdr = NULL; + else + internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr + + internal_esym.ifd); + } else internal_ptr->fdr = NULL; internal_ptr->local = FALSE; @@ -938,6 +951,20 @@ _bfd_ecoff_slurp_symbol_table (bfd *abfd) } } + /* PR 17512: file: 3372-3080-0.004. + A discrepancy between ecoff_data (abfd)->debug_info.symbolic_header.isymMax + and ecoff_data (abfd)->debug_info.symbolic_header.ifdMax can mean that + we have fewer symbols than we were expecting. Allow for this by updating + the symbol count and warning the user. */ + if (internal_ptr - internal < (ptrdiff_t) bfd_get_symcount (abfd)) + { + bfd_get_symcount (abfd) = internal_ptr - internal; + (*_bfd_error_handler) + (_("%B: warning: isymMax (%ld) is greater than ifdMax (%d)\n"), + abfd, ecoff_data (abfd)->debug_info.symbolic_header.isymMax, + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax); + } + ecoff_data (abfd)->canonical_symbols = internal; return TRUE; @@ -3976,7 +4003,7 @@ ecoff_reloc_link_order (bfd *output_bfd, size = bfd_get_reloc_size (rel.howto); buf = (bfd_byte *) bfd_zmalloc (size); - if (buf == NULL) + if (buf == NULL && size != 0) return FALSE; rstat = _bfd_relocate_contents (rel.howto, output_bfd, (bfd_vma) addend, buf); diff --git a/bfd/opncls.c b/bfd/opncls.c index 75af627..404b944 100644 --- a/bfd/opncls.c +++ b/bfd/opncls.c @@ -940,15 +940,19 @@ bfd_alloc (bfd *abfd, bfd_size_type size) unsigned long ul_size = (unsigned long) size; if (size != ul_size - /* A small negative size can result in objalloc_alloc allocating just - 1 byte of memory, but the caller will be expecting more. So catch - this case here. */ - || (size != 0 && (((ul_size + OBJALLOC_ALIGN - 1) &~ (OBJALLOC_ALIGN - 1)) == 0))) + /* Note - although objalloc_alloc takes an unsigned long as its + argument, internally the size is treated as a signed long. This can + lead to problems where, for example, a request to allocate -1 bytes + can result in just 1 byte being allocated, rather than + ((unsigned long) -1) bytes. Also memory checkers will often + complain about attempts to allocate a negative amount of memory. + So to stop these problems we fail if the size is negative. */ + || ((signed long) ul_size) < 0) { bfd_set_error (bfd_error_no_memory); return NULL; } - + ret = objalloc_alloc ((struct objalloc *) abfd->memory, ul_size); if (ret == NULL) bfd_set_error (bfd_error_no_memory); diff --git a/bfd/pe-mips.c b/bfd/pe-mips.c index 57ec51f..d7edc2b 100644 --- a/bfd/pe-mips.c +++ b/bfd/pe-mips.c @@ -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 diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c index 13e39e4..c09779a 100644 --- a/bfd/peXXigen.c +++ b/bfd/peXXigen.c @@ -526,6 +526,8 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd, (*_bfd_error_handler) (_("%B: aout header specifies an invalid number of data-directory entries: %d"), abfd, a->NumberOfRvaAndSizes); + bfd_set_error (bfd_error_bad_value); + /* Paranoia: If the number is corrupt, then assume that the actual entries themselves might be corrupt as well. */ a->NumberOfRvaAndSizes = 0; @@ -1149,7 +1151,7 @@ _bfd_XXi_slurp_codeview_record (bfd * abfd, file_ptr where, unsigned long length /* Ensure null termination of filename. */ buffer[256] = '\0'; - cvinfo->CVSignature = H_GET_32(abfd, buffer); + cvinfo->CVSignature = H_GET_32 (abfd, buffer); cvinfo->Age = 0; if ((cvinfo->CVSignature == CVINFO_PDB70_CVSIGNATURE) @@ -1755,6 +1757,8 @@ pe_print_edata (bfd * abfd, void * vfile) /* PR 17512: Handle corrupt PE binaries. */ if (edt.eat_addr + (edt.num_functions * 4) - adj >= datasize + /* PR 17512: file: 092b1829 */ + || (edt.num_functions * 4) < edt.num_functions /* PR 17512 file: 140-165018-0.004. */ || data + edt.eat_addr - adj < data) fprintf (file, _("\tInvalid Export Address Table rva (0x%lx) or entry count (0x%lx)\n"), @@ -1799,6 +1803,8 @@ pe_print_edata (bfd * abfd, void * vfile) /* PR 17512: Handle corrupt PE binaries. */ if (edt.npt_addr + (edt.num_names * 4) - adj >= datasize + /* PR 17512: file: bb68816e. */ + || edt.num_names * 4 < edt.num_names || (data + edt.npt_addr - adj) < data) fprintf (file, _("\tInvalid Name Pointer Table rva (0x%lx) or entry count (0x%lx)\n"), (long) edt.npt_addr, @@ -1890,6 +1896,14 @@ pe_print_pdata (bfd * abfd, void * vfile) if (datasize == 0) return TRUE; + /* PR 17512: file: 002-193900-0.004. */ + if (datasize < stop) + { + fprintf (file, _("Virtual size of .pdata section (%ld) larger than real size (%ld)\n"), + (long) stop, (long) datasize); + return FALSE; + } + if (! bfd_malloc_and_get_section (abfd, section, &data)) { if (data != NULL) @@ -1999,7 +2013,11 @@ slurp_symtab (bfd *abfd, sym_cache *psc) if (storage < 0) return NULL; if (storage) - sy = (asymbol **) bfd_malloc (storage); + { + sy = (asymbol **) bfd_malloc (storage); + if (sy == NULL) + return NULL; + } psc->symcount = bfd_canonicalize_symtab (abfd, sy); if (psc->symcount < 0) @@ -2198,7 +2216,7 @@ pe_print_reloc (bfd * abfd, void * vfile) { int j; bfd_vma virtual_address; - long number, size; + unsigned long number, size; bfd_byte *chunk_end; /* The .reloc section is a sequence of blocks, with a header consisting @@ -2213,7 +2231,7 @@ pe_print_reloc (bfd * abfd, void * vfile) fprintf (file, _("\nVirtual Address: %08lx Chunk size %ld (0x%lx) Number of fixups %ld\n"), - (unsigned long) virtual_address, size, (unsigned long) size, number); + (unsigned long) virtual_address, size, size, number); chunk_end = p + size; if (chunk_end > end) @@ -2284,6 +2302,7 @@ rsrc_print_resource_entries (FILE * file, bfd_vma rva_bias) { unsigned long entry, addr, size; + bfd_byte * leaf; if (data + 8 >= regions->section_end) return regions->section_end + 1; @@ -2364,18 +2383,21 @@ rsrc_print_resource_entries (FILE * file, regions, rva_bias); } - if (regions->section_start + entry + 16 >= regions->section_end) + leaf = regions->section_start + entry; + + if (leaf + 16 >= regions->section_end + /* PR 17512: file: 055dff7e. */ + || leaf < regions->section_start) return regions->section_end + 1; fprintf (file, _("%03x %*.s Leaf: Addr: %#08lx, Size: %#08lx, Codepage: %d\n"), - (int) (entry), - indent, " ", - addr = (long) bfd_get_32 (abfd, regions->section_start + entry), - size = (long) bfd_get_32 (abfd, regions->section_start + entry + 4), - (int) bfd_get_32 (abfd, regions->section_start + entry + 8)); + (int) (entry), indent, " ", + addr = (long) bfd_get_32 (abfd, leaf), + size = (long) bfd_get_32 (abfd, leaf + 4), + (int) bfd_get_32 (abfd, leaf + 8)); /* Check that the reserved entry is 0. */ - if (bfd_get_32 (abfd, regions->section_start + entry + 12) != 0 + if (bfd_get_32 (abfd, leaf + 12) != 0 /* And that the data address/size is valid too. */ || (regions->section_start + (addr - rva_bias) + size > regions->section_end)) return regions->section_end + 1; @@ -2526,7 +2548,7 @@ rsrc_print_section (bfd * abfd, void * vfile) /* If the extra data is all zeros then do not complain. This is just padding so that the section meets the page size requirements. */ - while (data ++ < regions.section_end) + while (++ data < regions.section_end) if (*data != 0) break; if (data < regions.section_end) @@ -2652,7 +2674,10 @@ pe_print_debugdata (bfd * abfd, void * vfile) if (idd.Type == PE_IMAGE_DEBUG_TYPE_CODEVIEW) { char signature[CV_INFO_SIGNATURE_LENGTH * 2 + 1]; - char buffer[256 + 1]; + /* PR 17512: file: 065-29434-0.001:0.1 + We need to use a 32-bit aligned buffer + to safely read in a codeview record. */ + char buffer[256 + 1] ATTRIBUTE_ALIGNED_ALIGNOF (CODEVIEW_INFO); CODEVIEW_INFO *cvinfo = (CODEVIEW_INFO *) buffer; /* The debug entry doesn't have to have to be in a section, @@ -2922,6 +2947,16 @@ _bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd) struct external_IMAGE_DEBUG_DIRECTORY *dd = (struct external_IMAGE_DEBUG_DIRECTORY *)(data + (addr - section->vma)); + /* PR 17512: file: 0f15796a. */ + if (ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size + (addr - section->vma) + > bfd_get_section_size (section)) + { + _bfd_error_handler (_("%B: Data Directory size (%lx) exceeds space left in section (%lx)"), + obfd, ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size, + bfd_get_section_size (section) - (addr - section->vma)); + return FALSE; + } + for (i = 0; i < ope->pe_opthdr.DataDirectory[PE_DEBUG_DATA].Size / sizeof (struct external_IMAGE_DEBUG_DIRECTORY); i++) { @@ -2945,8 +2980,16 @@ _bfd_XX_bfd_copy_private_bfd_data_common (bfd * ibfd, bfd * obfd) } if (!bfd_set_section_contents (obfd, section, data, 0, section->size)) - _bfd_error_handler (_("Failed to update file offsets in debug directory")); + { + _bfd_error_handler (_("Failed to update file offsets in debug directory")); + return FALSE; + } } + else if (section) + { + _bfd_error_handler (_("%B: Failed to read debug data section"), obfd); + return FALSE; + } } return TRUE; @@ -3228,9 +3271,14 @@ rsrc_parse_entry (bfd * abfd, if (entry->value.leaf == NULL) return dataend; - addr = bfd_get_32 (abfd, datastart + val); - size = entry->value.leaf->size = bfd_get_32 (abfd, datastart + val + 4); - entry->value.leaf->codepage = bfd_get_32 (abfd, datastart + val + 8); + data = datastart + val; + if (data < datastart || data >= dataend) + return dataend; + + addr = bfd_get_32 (abfd, data); + size = entry->value.leaf->size = bfd_get_32 (abfd, data + 4); + entry->value.leaf->codepage = bfd_get_32 (abfd, data + 8); + /* FIXME: We assume that the reserved field (data + 12) is OK. */ entry->value.leaf->data = bfd_malloc (size); if (entry->value.leaf->data == NULL) @@ -3560,6 +3608,7 @@ rsrc_cmp (bfd_boolean is_name, rsrc_entry * a, rsrc_entry * b) #elif defined HAVE_WCHAR_H { unsigned int i; + res = 0; for (i = min (alen, blen); i--; astring += 2, bstring += 2) { @@ -4457,6 +4506,8 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo) } free (tmp_data); } + else + result = FALSE; } } #endif diff --git a/bfd/pei-x86_64.c b/bfd/pei-x86_64.c index 48554d3..e53a353 100644 --- a/bfd/pei-x86_64.c +++ b/bfd/pei-x86_64.c @@ -276,8 +276,9 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd, fprintf (file, ", unknown(%u))", info); break; default: - /* Already caught by the previous scan. */ - abort (); + /* PR 17512: file: 2245-7442-0.004. */ + fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1])); + break; } if (unexpected) fprintf (file, " [Unexpected!]"); @@ -317,17 +318,31 @@ pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma vaddr; bfd_vma end_addr; bfd_vma addr = rf->rva_UnwindData; + bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size; struct pex64_unwind_info ui; vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase; addr -= vaddr; + /* PR 17512: file: 2245-7442-0.004. */ + if (addr >= sec_size) + { + fprintf (file, _("warning: xdata section corrupt\n")); + return; + } + if (endx) - end_addr = endx[0] - vaddr; + { + end_addr = endx[0] - vaddr; + /* PR 17512: file: 2245-7442-0.004. */ + if (end_addr > sec_size) + { + fprintf (file, _("warning: xdata section corrupt")); + end_addr = sec_size; + } + } else - end_addr = (xdata_section->rawsize != 0 ? - xdata_section->rawsize : xdata_section->size); - + end_addr = sec_size; pex64_get_unwind_info (abfd, &ui, &xdata[addr]); @@ -380,7 +395,11 @@ pex64_dump_xdata (FILE *file, bfd *abfd, ui.FrameRegister == 0 ? "none" : pex_regs[(unsigned int) ui.FrameRegister]); - pex64_xdata_print_uwd_codes (file, abfd, &ui, rf); + /* PR 17512: file: 2245-7442-0.004. */ + if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size) + fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes); + else + pex64_xdata_print_uwd_codes (file, abfd, &ui, rf); switch (ui.Flags) { @@ -439,23 +458,24 @@ sort_xdata_arr (const void *l, const void *r) /* Display unwind tables for x86-64. */ static bfd_boolean -pex64_bfd_print_pdata (bfd *abfd, void *vfile) +pex64_bfd_print_pdata_section (bfd *abfd, void *vfile, asection *pdata_section) { FILE *file = (FILE *) vfile; bfd_byte *pdata = NULL; bfd_byte *xdata = NULL; - asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata"); - asection *xdata_section; + asection *xdata_section = NULL; bfd_vma xdata_base; bfd_size_type i; + bfd_size_type datasize; bfd_size_type stop; - bfd_vma prev_beginaddress = 0; - bfd_vma prev_unwinddata_rva = 0; + bfd_vma prev_beginaddress = (bfd_vma) -1; + bfd_vma prev_unwinddata_rva = (bfd_vma) -1; bfd_vma imagebase; int onaline = PDATA_ROW_SIZE; int seen_error = 0; bfd_vma *xdata_arr = NULL; int xdata_arr_cnt; + bfd_boolean virt_size_is_zero = FALSE; /* Sanity checks. */ if (pdata_section == NULL @@ -466,12 +486,38 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) stop = pei_section_data (abfd, pdata_section)->virt_size; if ((stop % onaline) != 0) fprintf (file, - _("warning: .pdata section size (%ld) is not a multiple of %d\n"), - (long) stop, onaline); + _("Warning: %s section size (%ld) is not a multiple of %d\n"), + pdata_section->name, (long) stop, onaline); + + datasize = pdata_section->size; + if (datasize == 0) + { + if (stop) + fprintf (file, _("Warning: %s section size is zero\n"), + pdata_section->name); + return TRUE; + } + + /* virt_size might be zero for objects. */ + if (stop == 0 && strcmp (abfd->xvec->name, "pe-x86-64") == 0) + { + stop = (datasize / onaline) * onaline; + virt_size_is_zero = TRUE; + } + else if (datasize < stop) + { + fprintf (file, + _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"), + pdata_section->name, (unsigned long) datasize, + (unsigned long) stop); + /* Be sure not to read passed datasize. */ + stop = datasize / onaline; + } /* Display functions table. */ fprintf (file, - _("\nThe Function Table (interpreted .pdata section contents)\n")); + _("\nThe Function Table (interpreted %s section contents)\n"), + pdata_section->name); fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n")); @@ -482,7 +528,10 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1)); xdata_arr_cnt = 0; - imagebase = pe_data (abfd)->pe_opthdr.ImageBase; + if (strcmp (abfd->xvec->name, "pei-x86-64") == 0) + imagebase = pe_data (abfd)->pe_opthdr.ImageBase; + else + imagebase = 0; for (i = 0; i < stop; i += onaline) { @@ -490,6 +539,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) if (i + PDATA_ROW_SIZE > stop) break; + pex64_get_runtime_function (abfd, &rf, &pdata[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 @@ -528,8 +578,9 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) seen_error = 1; fprintf (file, " has negative unwind address\n"); } - if (rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) - xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData; + else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) + || virt_size_is_zero) + xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData; } if (seen_error) @@ -545,20 +596,42 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) /* Find the section containing the unwind data (.xdata). */ xdata_base = xdata_arr[0]; - xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata"); - - if (!xdata_section) - xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data"); + /* For sections with long names, first look for the same + section name, replacing .pdata by .xdata prefix. */ + if (strcmp (pdata_section->name, ".pdata") != 0) + { + size_t len = strlen (pdata_section->name); + char *xdata_name = alloca (len + 1); + + xdata_name = memcpy (xdata_name, pdata_section->name, len + 1); + /* Transform .pdata prefix into .xdata prefix. */ + if (len > 1) + xdata_name [1] = 'x'; + xdata_section = pex64_get_section_by_rva (abfd, xdata_base, + xdata_name); + } + /* Second, try the .xdata section itself. */ if (!xdata_section) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".xdata"); - if (!xdata_section) + /* Otherwise, if xdata_base is non zero, search also inside + other standard sections. */ + if (!xdata_section && xdata_base) + xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata"); + if (!xdata_section && xdata_base) + xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data"); + if (!xdata_section && xdata_base) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata"); - if (!xdata_section) + if (!xdata_section && xdata_base) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text"); + /* Transfer xdata section into xdata array. */ if (!xdata_section || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata)) goto done; + /* Avoid "also used "... ouput for single unwind info + in object file. */ + prev_unwinddata_rva = (bfd_vma) -1; + /* Do dump of pdata related xdata. */ for (i = 0; i < stop; i += onaline) { @@ -566,6 +639,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) if (i + PDATA_ROW_SIZE > stop) break; + pex64_get_runtime_function (abfd, &rf, &pdata[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 @@ -573,7 +647,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) /* We are probably into the padding of the section now. */ break; if (i == 0) - fprintf (file, "\nDump of .xdata\n"); + fprintf (file, _("\nDump of %s\n"), xdata_section->name); fputc (' ', file); fprintf_vma (file, rf.rva_UnwindData + imagebase); @@ -596,7 +670,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) fprintf_vma (file, rf.rva_EndAddress + imagebase); fputc ('\n', file); - if (rf.rva_UnwindData != 0) + if (rf.rva_UnwindData != 0 || virt_size_is_zero) { if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) { @@ -635,6 +709,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) identical pointers in the array; advance past all of them. */ while (p[0] <= rf.rva_UnwindData) ++p; + if (p[0] == ~((bfd_vma) 0)) p = NULL; @@ -651,6 +726,37 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) return TRUE; } +/* Static counter of number of found pdata sections. */ +static bfd_boolean pdata_count; + +/* Functionn prototype. */ +bfd_boolean pex64_bfd_print_pdata (bfd *, void *); + +/* Helper function for bfd_map_over_section. */ +static void +pex64_print_all_pdata_sections (bfd *abfd, asection *pdata, void *obj) +{ + if (CONST_STRNEQ (pdata->name, ".pdata")) + { + if (pex64_bfd_print_pdata_section (abfd, obj, pdata)) + pdata_count++; + } +} + +bfd_boolean +pex64_bfd_print_pdata (bfd *abfd, void *vfile) +{ + asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata"); + + if (pdata_section) + return pex64_bfd_print_pdata_section (abfd, vfile, pdata_section); + + pdata_count = 0; + bfd_map_over_sections (abfd, pex64_print_all_pdata_sections, vfile); + return (pdata_count > 0); +} + #define bfd_pe_print_pdata pex64_bfd_print_pdata +#define bfd_coff_std_swap_table bfd_coff_pei_swap_table #include "coff-x86_64.c" diff --git a/bfd/peicode.h b/bfd/peicode.h index 8365353..ab39cd6 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -1343,7 +1343,10 @@ pe_bfd_object_p (bfd * abfd) != (bfd_size_type) opt_hdr_size) return NULL; + bfd_set_error (bfd_error_no_error); bfd_coff_swap_aouthdr_in (abfd, opthdr, & internal_a); + if (bfd_get_error () != bfd_error_no_error) + return NULL; } return coff_real_object_p (abfd, internal_f.f_nscns, &internal_f, diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c index 9522974..7f321ee 100644 --- a/bfd/xcofflink.c +++ b/bfd/xcofflink.c @@ -5738,7 +5738,7 @@ xcoff_reloc_link_order (bfd *output_bfd, size = bfd_get_reloc_size (howto); buf = bfd_zmalloc (size); - if (buf == NULL) + if (buf == NULL && size != 0) return FALSE; rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf); |