Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
cross-ia64-binutils.237
binutils-fuzz-fix.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File binutils-fuzz-fix.diff of Package cross-ia64-binutils.237
Fix for several CVEs found when feeding fuzzed binary files into various binutils programs like strings, objdump or readelf. This fixes: bnc #902676, #902677, #903655, #905735, #905736. This is also: CVE-2014-8485, CVE-2014-8484, CVE-2014-8501, CVE-2014-8502, CVE-2014-8503, CVE-2014-8504, CVE-2014-8738, CVE-2014-8737 . And is also upstream bugs, PR17510, PR17512, PR17521, PR17531, PR17533, PR17552, PR17597, PR17605. This is essentially generated by backporting the following GIT commits, ignoring any changes in binutils/dwarf.c binutils/dwarf.h, binutils/readelf.c: 493a33860c71cac998f1a56d6d87d6faa801fbaa 17510 7e1e19887abd24aeb15066b141cdff5541e0ec8e 17512 # not applicable to 2.23 (has hardcoded 16 already) bf67003b4567600ed3022a439207ac8f26454f91 17512 708d7d0d11f0f2d776171979aa3479e8e12a38a0 17510 5a4b0ccc20ba30caef53b01bee2c0aaa5b855339 17512 e5b470e24ce448a56230137a37d3b17299593041 17512 7e760b06b212f01b3819d5b37e8f5b613e0db34c 17512 0102ea8cec5fc509bba6c91df61b7ce23a799d32 17512 f54498b45795194df671207c6ef3d6cd6d0c0ebb 17512 690725fa0d98ae52c991f4b3ea58b6b47b4fbc80 17512 99b4a5a08507a96f6d014553c9ac4c5e257f37a2 ??? but range test for msp430, not applicable to 2.23 5a3f568b70bdfb91aacdfb66657b56d8c6d242f1 17512 049b0c3a2467c785f9068915d81fdba4985470bf 17531 bb0d867169d7e9743d229804106a8fbcab7f3b3f 17533 e0a31db1b16fe0a010aa46185e4a31a08e7fd97f 17531 79f2a78e76fae1885163027f843e1bafde984b4c 17512 20ad5e2842911039a60b6bdf9880cee895179e43 17512 74e1a04b9787c02ba0fa9b93e3dae691bb44ed96 17531 a6f921c87700c2349cf6fa35fbc8ec9d3e3fb88e 17512 834107255bbefceb445fa733ebc1ea5d9f41ec7f fix some previous stuff dd9b91de2149ee81d47f708e7b0bbf57da10ad42 17552, 17533 (ar pathnames) 405724050266e30fcc8cbcee416cde41862e8e8f revert problematic size checks 071436c6e94be13904438b6eb70ee79c73354a61 17531 36e9d67b868c85232ab630514260f0d9c9c6b27b 17521 5e186ece2feebb46e63ff6bb2d2490aad0d5a724 17552 (remove temp files) 4082ef846466438ea2cd5b3606f304f6fded152b 17531 fcfa62408aec326a54765a6fd8895349fb41eb7c 17512 0ac2337434968896a6393fdd8c0624bd2945bbea 17512 201159ecec7e17600df4153e5d4e7a145f0c7cfe 17512 6bb3e67958b0ee59f1b69619761e6d5ad1f7544b 17512 541a3cbda9de8ae8888906cfe14887c394a3f772 17531 8b73c35699b4b1da558be29ac3c90aee0e0e1e49 17531 f41e4712a7b7ac60f181e7dfc984ca35c222f0d7 17512 3102e897eeda28961a32826095befef5c4a74097 17531 a5c71af8d3c7c535f27614947f72883233658706 17512 f8521a03584f2451e52cbc90bff5c1050a588c0f 17512 57494d81b631343380888b8a6ca55bf8a6110436 17512 041830e03cca866f12be18198898139e558ad31e 17512 470c009be81f3ac0205d4efb1d16fc4216093b69 17597 0eff716535f3e8f501d6b438f7f796b70a0b9f98 17531 6937bb54a9c3ddc7ba330bc18af76f8dbe856ac3 17512 0593bd3ace3cb64775f4d9e8039da919c26803cd 17605 (invalid time data in archive) 5d921cbd81554867007e903b634acc6bc8281f9f 17531 0a9d414aa114b7b7e609cbcbc285f79031bbe608 17512 bd25671c6f202c4a5108883caa2adb24ff6f361f 17510 (though not explicitely mentioned) The changes to dwarf.c and readelf.c come in via verbatim copying the current master versions of them (from the binutils-new-readelf.tar.gz tarball, together with updated testsuite expect files) into the source tree, with necessary related changes in ELF headers from binutils-readelf-header.diff. It follows the list of all commit messages of these commits (still showing the readelf.c/dwarf.c parts), and after that the combined diff as backported. commit 493a33860c71cac998f1a56d6d87d6faa801fbaa Author: Nick Clifton <nickc@redhat.com> Date: Mon Oct 27 12:43:16 2014 +0000 This patch closes a potential security hole in applications that use the bfd library to parse binaries containing maliciously corrupt section group headers. PR binutils/17510 * elf.c (setup_group): Improve handling of corrupt group sections. commit 7e1e19887abd24aeb15066b141cdff5541e0ec8e Author: Nick Clifton <nickc@redhat.com> Date: Mon Oct 27 14:45:06 2014 +0000 Fix a seg-fault in strings and other binutuils when parsing a corrupt PE executable with an invalid value in the NumberOfRvaAndSizes field of the AOUT header. PR binutils/17512 * peXXigen.c (_bfd_XXi_swap_aouthdr_in): Handle corrupt binaries with an invalid value for NumberOfRvaAndSizes. commit bf67003b4567600ed3022a439207ac8f26454f91 Author: Nick Clifton <nickc@redhat.com> Date: Mon Oct 27 18:05:37 2014 +0000 This fixes more seg-faults in tools like "strings" and "objdump" when presented with corrupt binaries. PR binutils/17512 * elf.c (bfd_section_from_shdr): Detect and warn about ELF binaries with a group of sections linked by the string table indicies. * peXXigen.c (pe_print_edata): Detect out of range rvas and entry counts for the Export Address table, Name Pointer table and Ordinal table. commit 708d7d0d11f0f2d776171979aa3479e8e12a38a0 Author: Nick Clifton <nickc@redhat.com> Date: Tue Oct 28 10:48:14 2014 +0000 This patch fixes a flaw in the SREC parser which could cause a stack overflow and potential secuiryt breach. PR binutils/17510 * srec.c (srec_bad_byte): Increase size of buf to allow for negative values. (srec_scan): Use an unsigned char buffer to hold header bytes. commit 5a4b0ccc20ba30caef53b01bee2c0aaa5b855339 Author: Nick Clifton <nickc@redhat.com> Date: Tue Oct 28 15:42:56 2014 +0000 More fixes for corrupt binaries crashing the binutils. PR binutils/17512 * elf.c (bfd_section_from_shdr): Allocate and free the recursion detection table on a per-bfd basis. * peXXigen.c (pe_print_edata): Handle binaries with a truncated export table. commit e5b470e24ce448a56230137a37d3b17299593041 Author: Nick Clifton <nickc@redhat.com> Date: Wed Oct 29 20:58:13 2014 +0000 Fixes another memory corruption bug introduced by patches for PR 17512. * elf.c (bfd_section_from_shdr): Fix heap use after free memory leak. commit 7e760b06b212f01b3819d5b37e8f5b613e0db34c Author: Nick Clifton <nickc@redhat.com> Date: Thu Oct 30 15:52:10 2014 +0000 Closes another memory corruption, this time due to heap overrun. PR binutils/17512 * coffgen.c (coff_get_normalized_symtab): Prevent buffer overrun. commit 0102ea8cec5fc509bba6c91df61b7ce23a799d32 Author: Nick Clifton <nickc@redhat.com> Date: Thu Oct 30 17:16:17 2014 +0000 Fixes a seg-fault in the ihex parser when it encounters a malformed ihex file. PR binutils/17512 * ihex.c (ihex_scan): Fix typo in invocation of ihex_bad_byte. part of commit f54498b45795194df671207c6ef3d6cd6d0c0ebb Author: Nick Clifton <nickc@redhat.com> Date: Fri Oct 31 16:36:31 2014 +0000 Avoid allocating over-large buffers when parsing corrupt binaries. PR binutils/17512 * coffgen.c (_bfd_coff_get_external_symbols): Do not try to load a symbol table bigger than the file. * elf.c (bfd_elf_get_str_section): Do not try to load a string table bigger than the file. commit 690725fa0d98ae52c991f4b3ea58b6b47b4fbc80 Author: Nick Clifton <nickc@redhat.com> Date: Fri Oct 31 18:00:55 2014 +0000 Fix an (almost) infinite loop in the tekhex parser. PR binutils/17512 * tekhex.c (first_phase): Check that the section range is sane. commit 99b4a5a08507a96f6d014553c9ac4c5e257f37a2 Author: Nick Clifton <nickc@redhat.com> Date: Mon Nov 3 11:15:53 2014 +0000 Fixes a snafu checking the size of 20-bit immedaite values. * config/tc-msp430.c (msp430_srcoperand): Fix range test for 20-bit values. commit 5a3f568b70bdfb91aacdfb66657b56d8c6d242f1 Author: Nick Clifton <nickc@redhat.com> Date: Mon Nov 3 17:44:00 2014 +0000 More fixes for buffer overruns instigated by corrupt binaries. PR binutils/17512 * objdump.c (slurp_symtab): Fail gracefully if the table could not be read. (dump_relocs_in_section): Likewise. * aoutx.h (slurp_symbol_table): Check that computed table size is not bigger than the file from which is it being read. (slurp_reloc_table): Likewise. * coffcode.h (coff_slurp_line_table): Remove unneeded local 'warned'. Do not try to print the details of a symbol with an * coffgen.c (make_a_sectiobn_from_file): Check computed string (bfd_coff_internal_syment_name): Check read in string offset against length of string table. (build_debug_section): Return a pointer to the section used. (_bfd_coff_read_string_table): Store the length of the string table in the coff_tdata structure. (bfd_coff_free_symbols): Set the length of the string table to zero when it is freed. (coff_get_normalized_symtab): Check offsets against string table or data table lengths as appropriate. * cofflink.c (_bfd_coff_link_input_bfd): Check offset against length of string table. * compress.c (bfd_get_full_section_contents): Check computed size against the size of the file. * libcoff-in.h (obj_coff_strings_len): Define. (struct coff_tdata): Add strings_len field. * libcoff.h: Regenerate. * peXXigen.c (pe_print_debugdata): Do not attempt to print the data if the debug section is too small. * xcofflink.c (xcoff_link_input_bfd): Check offset against length of string table. commit 049b0c3a2467c785f9068915d81fdba4985470bf Author: Nick Clifton <nickc@redhat.com> Date: Tue Nov 4 11:58:16 2014 +0000 Fixes for crashes running readelf. PR binutils/17531 * readelf.c (get_data): If the reason parameter is null, do not print any error messages. (get_32bit_section_headers): Verify section header entry size before reading in the section headers. (get_64bit_section_headers): Likewise. (process_section_headers): Pass FALSE to get_section_headers. (get_file_header): Pass TRUE to get_section_headers. (process_dynamic_section): Change an assert to an error message. (process_symbol_table): Handle corrupt histograms. commit bb0d867169d7e9743d229804106a8fbcab7f3b3f Author: Nick Clifton <nickc@redhat.com> Date: Tue Nov 4 13:15:37 2014 +0000 Fix a seg-fault triggered by reading a mal-formed archive. PR binutils/17533 * archive.c (_bfd_slurp_extended_name_table): Handle archives with corrupt extended name tables. commit e0a31db1b16fe0a010aa46185e4a31a08e7fd97f Author: Nick Clifton <nickc@redhat.com> Date: Tue Nov 4 15:29:03 2014 +0000 More fixes for memory corruption when readelf processes corrupt files. PR binutils/17531 (get_32bit_program_headers): Verify program header entry size before reading in the program headers. (get_64bit_program_headers): Likewise. (get_unwind_section_word): Do nothing if no section was provided. Fail if the offset is outside of the section. (print_dynamic_symbol): Catch out of range symbol indicies. (process_mips_specific): Likewise. (process_attributes): Make sure that there is enough space left in the section before attempting to read the length of the next attribute. commit 79f2a78e76fae1885163027f843e1bafde984b4c Author: Nick Clifton <nickc@redhat.com> Date: Tue Nov 4 16:00:10 2014 +0000 Fix problem with linker created sections being mistakenly flagged as corrupt by the new error checking code in bfd_get_full_section_contents. PR binutils/17512 * compress.c (bfd_get_full_section_contents): Improve test for linker created objects. part of commit 20ad5e2842911039a60b6bdf9880cee895179e43 Author: Nick Clifton <nickc@redhat.com> Date: Wed Nov 5 10:13:16 2014 +0000 More fixes for processing corrupt files. PR binutils/17512 * peXXigen.c (pe_print_idata): Add range checks. (pe_print_edata): Likewise. (rsrc_print_resource_entries): Likewise. Avoid printing control characters. Terminate priniting if corruption is detected. (rsrc_print_resource_directory): Terminate printing if an unknown directory type is encountered. (pe_print_debugdata): Fix off-by-one error. (rsrc_count_entries): Add range checking. (rsrc_parse_entry): Likewise. commit bd25671c6f202c4a5108883caa2adb24ff6f361f Author: Alan Modra <amodra@gmail.com> Date: Fri Aug 29 10:36:29 2014 +0930 Report an error for S-records with less than the miniumum size * srec.c (srec_scan): Revert last change. Report an error for S-records with less than the miniumum byte count. Index: binutils-2.24/bfd/elf.c =================================================================== --- binutils-2.24.orig/bfd/elf.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/elf.c 2014-12-01 16:31:37.000000000 +0100 @@ -608,9 +608,10 @@ setup_group (bfd *abfd, Elf_Internal_Shd if (shdr->contents == NULL) { _bfd_error_handler - (_("%B: Corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size); + (_("%B: corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size); bfd_set_error (bfd_error_bad_value); - return FALSE; + -- num_group; + continue; } memset (shdr->contents, 0, amt); @@ -618,8 +619,17 @@ setup_group (bfd *abfd, Elf_Internal_Shd if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0 || (bfd_bread (shdr->contents, shdr->sh_size, abfd) != shdr->sh_size)) - return FALSE; - + { + _bfd_error_handler + (_("%B: invalid size field in group section header: 0x%lx"), abfd, shdr->sh_size); + bfd_set_error (bfd_error_bad_value); + -- num_group; + /* PR 17510: If the group contents are even partially + corrupt, do not allow any of the contents to be used. */ + memset (shdr->contents, 0, amt); + continue; + } + /* Translate raw contents, a flag word followed by an array of elf section indices all in target byte order, to the flag word followed by an array of elf section @@ -651,6 +661,21 @@ setup_group (bfd *abfd, Elf_Internal_Shd } } } + + /* PR 17510: Corrupt binaries might contain invalid groups. */ + if (num_group != (unsigned) elf_tdata (abfd)->num_group) + { + elf_tdata (abfd)->num_group = num_group; + + /* If all groups are invalid then fail. */ + if (num_group == 0) + { + elf_tdata (abfd)->group_sect_ptr = NULL; + elf_tdata (abfd)->num_group = num_group = -1; + (*_bfd_error_handler) (_("%B: no valid group sections found"), abfd); + bfd_set_error (bfd_error_bad_value); + } + } } } @@ -716,6 +741,7 @@ setup_group (bfd *abfd, Elf_Internal_Shd { (*_bfd_error_handler) (_("%B: no group info for section %A"), abfd, newsect); + return FALSE; } return TRUE; } @@ -1548,38 +1574,74 @@ bfd_section_from_shdr (bfd *abfd, unsign Elf_Internal_Ehdr *ehdr; const struct elf_backend_data *bed; const char *name; + bfd_boolean ret = TRUE; + static bfd_boolean * sections_being_created = NULL; + static bfd * sections_being_created_abfd = NULL; + static unsigned int nesting = 0; if (shindex >= elf_numsections (abfd)) return FALSE; + if (++ nesting > 3) + { + /* PR17512: A corrupt ELF binary might contain a recursive group of + sections, each the string indicies pointing to the next in the + loop. Detect this here, by refusing to load a section that we are + already in the process of loading. We only trigger this test if + we have nested at least three sections deep as normal ELF binaries + can expect to recurse at least once. + + FIXME: It would be better if this array was attached to the bfd, + rather than being held in a static pointer. */ + + if (sections_being_created_abfd != abfd) + 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)); + sections_being_created_abfd = abfd; + } + if (sections_being_created [shindex]) + { + (*_bfd_error_handler) + (_("%B: warning: loop in section dependencies detected"), abfd); + return FALSE; + } + sections_being_created [shindex] = TRUE; + } + hdr = elf_elfsections (abfd)[shindex]; ehdr = elf_elfheader (abfd); name = bfd_elf_string_from_elf_section (abfd, ehdr->e_shstrndx, hdr->sh_name); if (name == NULL) - return FALSE; + goto fail; bed = get_elf_backend_data (abfd); switch (hdr->sh_type) { case SHT_NULL: /* Inactive section. Throw it away. */ - return TRUE; + goto success; - case SHT_PROGBITS: /* Normal section with contents. */ - case SHT_NOBITS: /* .bss section. */ - case SHT_HASH: /* .hash section. */ - case SHT_NOTE: /* .note section. */ + case SHT_PROGBITS: /* Normal section with contents. */ + case SHT_NOBITS: /* .bss section. */ + case SHT_HASH: /* .hash section. */ + case SHT_NOTE: /* .note section. */ case SHT_INIT_ARRAY: /* .init_array section. */ case SHT_FINI_ARRAY: /* .fini_array section. */ case SHT_PREINIT_ARRAY: /* .preinit_array section. */ case SHT_GNU_LIBLIST: /* .gnu.liblist section. */ case SHT_GNU_HASH: /* .gnu.hash section. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_DYNAMIC: /* Dynamic linking information. */ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + goto fail; + if (hdr->sh_link > elf_numsections (abfd)) { /* PR 10478: Accept Solaris binaries with a sh_link @@ -1593,11 +1655,11 @@ bfd_section_from_shdr (bfd *abfd, unsign break; /* Otherwise fall through. */ default: - return FALSE; + goto fail; } } else if (elf_elfsections (abfd)[hdr->sh_link] == NULL) - return FALSE; + goto fail; else if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB) { Elf_Internal_Shdr *dynsymhdr; @@ -1626,24 +1688,26 @@ bfd_section_from_shdr (bfd *abfd, unsign } } } - break; + goto success; - case SHT_SYMTAB: /* A symbol table */ + case SHT_SYMTAB: /* A symbol table. */ if (elf_onesymtab (abfd) == shindex) - return TRUE; + goto success; if (hdr->sh_entsize != bed->s->sizeof_sym) - return FALSE; + goto fail; + if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size) { if (hdr->sh_size != 0) - return FALSE; + goto fail; /* Some assemblers erroneously set sh_info to one with a zero sh_size. ld sees this as a global symbol count of (unsigned) -1. Fix it here. */ hdr->sh_info = 0; - return TRUE; + goto success; } + BFD_ASSERT (elf_onesymtab (abfd) == 0); elf_onesymtab (abfd) = shindex; elf_tdata (abfd)->symtab_hdr = *hdr; @@ -1660,7 +1724,7 @@ bfd_section_from_shdr (bfd *abfd, unsign && (abfd->flags & DYNAMIC) != 0 && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + goto fail; /* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we can't read symbols without that section loaded as well. It @@ -1686,26 +1750,29 @@ bfd_section_from_shdr (bfd *abfd, unsign break; } if (i != shindex) - return bfd_section_from_shdr (abfd, i); + ret = bfd_section_from_shdr (abfd, i); } - return TRUE; + goto success; - case SHT_DYNSYM: /* A dynamic symbol table */ + case SHT_DYNSYM: /* A dynamic symbol table. */ if (elf_dynsymtab (abfd) == shindex) - return TRUE; + goto success; if (hdr->sh_entsize != bed->s->sizeof_sym) - return FALSE; + goto fail; + if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size) { if (hdr->sh_size != 0) - return FALSE; + goto fail; + /* Some linkers erroneously set sh_info to one with a zero sh_size. ld sees this as a global symbol count of (unsigned) -1. Fix it here. */ hdr->sh_info = 0; - return TRUE; + goto success; } + BFD_ASSERT (elf_dynsymtab (abfd) == 0); elf_dynsymtab (abfd) = shindex; elf_tdata (abfd)->dynsymtab_hdr = *hdr; @@ -1714,34 +1781,38 @@ bfd_section_from_shdr (bfd *abfd, unsign /* Besides being a symbol table, we also treat this as a regular section, so that objcopy can handle it. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; - case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections */ + case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections. */ if (elf_symtab_shndx (abfd) == shindex) - return TRUE; + goto success; BFD_ASSERT (elf_symtab_shndx (abfd) == 0); elf_symtab_shndx (abfd) = shindex; elf_tdata (abfd)->symtab_shndx_hdr = *hdr; elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr; - return TRUE; + goto success; - case SHT_STRTAB: /* A string table */ + case SHT_STRTAB: /* A string table. */ if (hdr->bfd_section != NULL) - return TRUE; + goto success; + if (ehdr->e_shstrndx == shindex) { elf_tdata (abfd)->shstrtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr; - return TRUE; + goto success; } + if (elf_elfsections (abfd)[elf_onesymtab (abfd)]->sh_link == shindex) { symtab_strtab: elf_tdata (abfd)->strtab_hdr = *hdr; elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr; - return TRUE; + goto success; } + if (elf_elfsections (abfd)[elf_dynsymtab (abfd)]->sh_link == shindex) { dynsymtab_strtab: @@ -1750,8 +1821,9 @@ bfd_section_from_shdr (bfd *abfd, unsign elf_elfsections (abfd)[shindex] = hdr; /* We also treat this as a regular section, so that objcopy can handle it. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, - shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, + shindex); + goto success; } /* If the string table isn't one of the above, then treat it as a @@ -1769,9 +1841,9 @@ bfd_section_from_shdr (bfd *abfd, unsign { /* Prevent endless recursion on broken objects. */ if (i == shindex) - return FALSE; + goto fail; if (! bfd_section_from_shdr (abfd, i)) - return FALSE; + goto fail; if (elf_onesymtab (abfd) == i) goto symtab_strtab; if (elf_dynsymtab (abfd) == i) @@ -1779,7 +1851,8 @@ bfd_section_from_shdr (bfd *abfd, unsign } } } - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_REL: case SHT_RELA: @@ -1794,7 +1867,7 @@ bfd_section_from_shdr (bfd *abfd, unsign if (hdr->sh_entsize != (bfd_size_type) (hdr->sh_type == SHT_REL ? bed->s->sizeof_rel : bed->s->sizeof_rela)) - return FALSE; + goto fail; /* Check for a bogus link to avoid crashing. */ if (hdr->sh_link >= num_sec) @@ -1802,8 +1875,9 @@ bfd_section_from_shdr (bfd *abfd, unsign ((*_bfd_error_handler) (_("%B: invalid link %lu for reloc section %s (index %u)"), abfd, hdr->sh_link, name, shindex)); - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, - shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, + shindex); + goto success; } /* For some incomprehensible reason Oracle distributes @@ -1844,7 +1918,7 @@ bfd_section_from_shdr (bfd *abfd, unsign if ((elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB || elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_DYNSYM) && ! bfd_section_from_shdr (abfd, hdr->sh_link)) - return FALSE; + goto fail; /* If this reloc section does not use the main symbol table we don't treat it as a reloc section. BFD can't adequately @@ -1859,14 +1933,18 @@ bfd_section_from_shdr (bfd *abfd, unsign || hdr->sh_info >= num_sec || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA) - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, - shindex); + { + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, + shindex); + goto success; + } if (! bfd_section_from_shdr (abfd, hdr->sh_info)) - return FALSE; + goto fail; + target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info); if (target_sect == NULL) - return FALSE; + goto fail; esdt = elf_section_data (target_sect); if (hdr->sh_type == SHT_RELA) @@ -1878,7 +1956,7 @@ bfd_section_from_shdr (bfd *abfd, unsign amt = sizeof (*hdr2); hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt); if (hdr2 == NULL) - return FALSE; + goto fail; *hdr2 = *hdr; *p_hdr = hdr2; elf_elfsections (abfd)[shindex] = hdr2; @@ -1894,34 +1972,37 @@ bfd_section_from_shdr (bfd *abfd, unsign target_sect->use_rela_p = 1; } abfd->flags |= HAS_RELOC; - return TRUE; + goto success; } case SHT_GNU_verdef: elf_dynverdef (abfd) = shindex; elf_tdata (abfd)->dynverdef_hdr = *hdr; - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_GNU_versym: if (hdr->sh_entsize != sizeof (Elf_External_Versym)) - return FALSE; + goto fail; elf_dynversym (abfd) = shindex; elf_tdata (abfd)->dynversym_hdr = *hdr; - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_GNU_verneed: elf_dynverref (abfd) = shindex; elf_tdata (abfd)->dynverref_hdr = *hdr; - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; case SHT_SHLIB: - return TRUE; + goto success; case SHT_GROUP: if (! IS_VALID_GROUP_SECTION_HEADER (hdr, GRP_ENTRY_SIZE)) - return FALSE; + goto fail; if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + goto fail; if (hdr->contents != NULL) { Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents; @@ -1947,7 +2028,7 @@ bfd_section_from_shdr (bfd *abfd, unsign } } } - break; + goto success; default: /* Possibly an attributes section. */ @@ -1955,14 +2036,14 @@ bfd_section_from_shdr (bfd *abfd, unsign || hdr->sh_type == bed->obj_attrs_section_type) { if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + goto fail; _bfd_elf_parse_attributes (abfd, hdr); - return TRUE; + goto success; } /* Check for any processor-specific section types. */ if (bed->elf_backend_section_from_shdr (abfd, hdr, name, shindex)) - return TRUE; + goto success; if (hdr->sh_type >= SHT_LOUSER && hdr->sh_type <= SHT_HIUSER) { @@ -1974,9 +2055,12 @@ bfd_section_from_shdr (bfd *abfd, unsign "specific section `%s' [0x%8x]"), abfd, name, hdr->sh_type); else - /* Allow sections reserved for applications. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, - shindex); + { + /* Allow sections reserved for applications. */ + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, + shindex); + goto success; + } } else if (hdr->sh_type >= SHT_LOPROC && hdr->sh_type <= SHT_HIPROC) @@ -1997,8 +2081,11 @@ bfd_section_from_shdr (bfd *abfd, unsign "`%s' [0x%8x]"), abfd, name, hdr->sh_type); else - /* Otherwise it should be processed. */ - return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + { + /* Otherwise it should be processed. */ + ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); + goto success; + } } else /* FIXME: We should handle this section. */ @@ -2006,10 +2093,20 @@ bfd_section_from_shdr (bfd *abfd, unsign (_("%B: don't know how to handle section `%s' [0x%8x]"), abfd, name, hdr->sh_type); - return FALSE; + goto fail; } - return TRUE; + fail: + ret = FALSE; + success: + if (sections_being_created && sections_being_created_abfd == abfd) + sections_being_created [shindex] = FALSE; + if (-- nesting == 0) + { + sections_being_created = NULL; + sections_being_created_abfd = abfd; + } + return ret; } /* Return the local symbol specified by ABFD, R_SYMNDX. */ @@ -7121,8 +7218,12 @@ _bfd_elf_slurp_version_tables (bfd *abfd hdr = &elf_tdata (abfd)->dynverref_hdr; - elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) + if (hdr->sh_info) + elf_tdata (abfd)->verref = (Elf_Internal_Verneed *) bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed)); + else + elf_tdata (abfd)->verref = NULL; + if (elf_tdata (abfd)->verref == NULL) goto error_return; @@ -7282,8 +7383,12 @@ error_return_verref: else freeidx = ++maxidx; } - elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) + if (maxidx) + elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef)); + else + elf_tdata (abfd)->verdef = NULL; + if (elf_tdata (abfd)->verdef == NULL) goto error_return; @@ -7424,16 +7529,12 @@ asymbol * _bfd_elf_make_empty_symbol (bfd *abfd) { elf_symbol_type *newsym; - bfd_size_type amt = sizeof (elf_symbol_type); - newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt); + newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym); if (!newsym) return NULL; - else - { - newsym->symbol.the_bfd = abfd; - return &newsym->symbol; - } + newsym->symbol.the_bfd = abfd; + return &newsym->symbol; } void Index: binutils-2.24/bfd/peXXigen.c =================================================================== --- binutils-2.24.orig/bfd/peXXigen.c 2013-11-26 12:37:33.000000000 +0100 +++ binutils-2.24/bfd/peXXigen.c 2014-12-01 16:31:37.000000000 +0100 @@ -141,8 +141,13 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * name = _bfd_coff_internal_syment_name (abfd, in, namebuf); if (name == NULL) - /* FIXME: Return error. */ - abort (); + { + _bfd_error_handler (_("%B: unable to find name for empty section"), + abfd); + bfd_set_error (bfd_error_invalid_target); + return; + } + sec = bfd_get_section_by_name (abfd, name); if (sec != NULL) in->n_scnum = sec->target_index; @@ -162,15 +167,22 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * { name = (const char *) bfd_alloc (abfd, strlen (namebuf) + 1); if (name == NULL) - /* FIXME: Return error. */ - abort (); + { + _bfd_error_handler (_("%B: out of memory creating name for empty section"), + abfd); + return; + } strcpy ((char *) name, namebuf); } + flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD; sec = bfd_make_section_anyway_with_flags (abfd, name, flags); if (sec == NULL) - /* FIXME: Return error. */ - abort (); + { + _bfd_error_handler (_("%B: unable to create fake empty section"), + abfd); + return; + } sec->vma = 0; sec->lma = 0; @@ -239,6 +251,9 @@ _bfd_XXi_swap_aux_in (bfd * abfd, AUXENT *ext = (AUXENT *) ext1; union internal_auxent *in = (union internal_auxent *) in1; + /* PR 17521: Make sure that all fields in the aux structure + are initialised. */ + memset (in, 0, sizeof * in); switch (in_class) { case C_FILE: @@ -414,6 +429,7 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd, aouthdr_int->entry = GET_AOUTHDR_ENTRY (abfd, aouthdr_ext->entry); aouthdr_int->text_start = GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start); + #if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) /* PE32+ does not have data_start member! */ aouthdr_int->data_start = @@ -474,6 +490,13 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd, else a->DataDirectory[idx].VirtualAddress = 0; } + + while (idx < IMAGE_NUMBEROF_DIRECTORY_ENTRIES) + { + a->DataDirectory[idx].Size = 0; + a->DataDirectory[idx].VirtualAddress = 0; + idx ++; + } } if (aouthdr_int->entry) @@ -717,7 +740,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, v { int idx; - for (idx = 0; idx < 16; idx++) + for (idx = 0; idx < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; idx++) { H_PUT_32 (abfd, extra->DataDirectory[idx].VirtualAddress, aouthdr_out->DataDirectory[idx][0]); @@ -1214,7 +1237,9 @@ pe_print_idata (bfd * abfd, void * vfile break; dll = (char *) data + dll_name - adj; - fprintf (file, _("\n\tDLL Name: %s\n"), dll); + /* PR 17512 file: 078-12277-0.004. */ + bfd_size_type maxlen = (char *)(data + datasize) - dll - 1; + fprintf (file, _("\n\tDLL Name: %.*s\n"), (int) maxlen, dll); if (hint_addr != 0) { @@ -1279,23 +1304,30 @@ pe_print_idata (bfd * abfd, void * vfile #ifdef COFF_WITH_pex64 for (j = 0; idx + j + 8 <= datasize; j += 8) { + bfd_size_type amt; unsigned long member = bfd_get_32 (abfd, data + idx + j); unsigned long member_high = bfd_get_32 (abfd, data + idx + j + 4); if (!member && !member_high) break; + amt = member - adj; + if (member_high & 0x80000000) fprintf (file, "\t%lx%08lx\t %4lx%08lx <none>", member_high,member, member_high & 0x7fffffff, member); + /* PR binutils/17512: Handle corrupt PE data. */ + else if (amt + 2 >= datasize) + fprintf (file, _("\t<corrupt: 0x%04lx>"), member); else { int ordinal; char *member_name; - ordinal = bfd_get_16 (abfd, data + member - adj); - member_name = (char *) data + member - adj + 2; - fprintf (file, "\t%04lx\t %4d %s",member, ordinal, member_name); + ordinal = bfd_get_16 (abfd, data + amt); + member_name = (char *) data + amt + 2; + fprintf (file, "\t%04lx\t %4d %.*s",member, ordinal, + (int) (datasize - (amt + 2)), member_name); } /* If the time stamp is not zero, the import address @@ -1311,24 +1343,30 @@ pe_print_idata (bfd * abfd, void * vfile #else for (j = 0; idx + j + 4 <= datasize; j += 4) { + bfd_size_type amt; unsigned long member = bfd_get_32 (abfd, data + idx + j); /* Print single IMAGE_IMPORT_BY_NAME vector. */ if (member == 0) break; + amt = member - adj; if (member & 0x80000000) fprintf (file, "\t%04lx\t %4lu <none>", member, member & 0x7fffffff); + /* PR binutils/17512: Handle corrupt PE data. */ + else if (amt + 2 >= datasize) + fprintf (file, _("\t<corrupt: 0x%04lx>"), member); else { int ordinal; char *member_name; - ordinal = bfd_get_16 (abfd, data + member - adj); - member_name = (char *) data + member - adj + 2; - fprintf (file, "\t%04lx\t %4d %s", - member, ordinal, member_name); + ordinal = bfd_get_16 (abfd, data + amt); + member_name = (char *) data + amt + 2; + fprintf (file, "\t%04lx\t %4d %.*s", + member, ordinal, + (int) (datasize - (amt + 2)), member_name); } /* If the time stamp is not zero, the import address @@ -1364,7 +1402,7 @@ pe_print_edata (bfd * abfd, void * vfile bfd_size_type datasize = 0; bfd_size_type dataoff; bfd_size_type i; - bfd_signed_vma adj; + bfd_vma adj; struct EDT_type { long export_flags; /* Reserved - should be zero. */ @@ -1426,6 +1464,15 @@ pe_print_edata (bfd * abfd, void * vfile } } + /* PR 17512: Handle corrupt PE binaries. */ + if (datasize < 36) + { + fprintf (file, + _("\nThere is an export table in %s, but it is too small (%d)\n"), + section->name, (int) datasize); + return TRUE; + } + fprintf (file, _("\nThere is an export table in %s at 0x%lx\n"), section->name, (unsigned long) addr); @@ -1469,8 +1516,13 @@ pe_print_edata (bfd * abfd, void * vfile fprintf (file, _("Name \t\t\t\t")); bfd_fprintf_vma (abfd, file, edt.name); - fprintf (file, - " %s\n", data + edt.name - adj); + + if ((edt.name >= adj) && (edt.name < adj + datasize)) + fprintf (file, " %.*s\n", + (int) (datasize - (edt.name - adj)), + data + edt.name - adj); + else + fprintf (file, "(outside .edata section)\n"); fprintf (file, _("Ordinal Base \t\t\t%ld\n"), edt.base); @@ -1516,7 +1568,14 @@ pe_print_edata (bfd * abfd, void * vfile _("\nExport Address Table -- Ordinal Base %ld\n"), edt.base); - for (i = 0; i < edt.num_functions; ++i) + /* PR 17512: Handle corrupt PE binaries. */ + if (edt.eat_addr + (edt.num_functions * 4) - adj >= datasize + /* 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"), + (long) edt.eat_addr, + (long) edt.num_functions); + else for (i = 0; i < edt.num_functions; ++i) { bfd_vma eat_member = bfd_get_32 (abfd, data + edt.eat_addr + (i * 4) - adj); @@ -1528,11 +1587,12 @@ pe_print_edata (bfd * abfd, void * vfile /* This rva is to a name (forwarding function) in our section. */ /* Should locate a function descriptor. */ fprintf (file, - "\t[%4ld] +base[%4ld] %04lx %s -- %s\n", + "\t[%4ld] +base[%4ld] %04lx %s -- %.*s\n", (long) i, (long) (i + edt.base), (unsigned long) eat_member, _("Forwarder RVA"), + (int)(datasize - (eat_member - adj)), data + eat_member - adj); } else @@ -1552,7 +1612,19 @@ pe_print_edata (bfd * abfd, void * vfile fprintf (file, _("\n[Ordinal/Name Pointer] Table\n")); - for (i = 0; i < edt.num_names; ++i) + /* PR 17512: Handle corrupt PE binaries. */ + if (edt.npt_addr + (edt.num_names * 4) - adj >= datasize + || (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, + (long) edt.num_names); + /* PR 17512: file: 140-147171-0.004. */ + else if (edt.ot_addr + (edt.num_names * 2) - adj >= datasize + || data + edt.ot_addr - adj < data) + fprintf (file, _("\tInvalid Ordinal Table rva (0x%lx) or entry count (0x%lx)\n"), + (long) edt.ot_addr, + (long) edt.num_names); + else for (i = 0; i < edt.num_names; ++i) { bfd_vma name_ptr = bfd_get_32 (abfd, data + @@ -1565,8 +1637,8 @@ pe_print_edata (bfd * abfd, void * vfile data + edt.ot_addr + (i*2) - adj); - fprintf (file, - "\t[%4ld] %s\n", (long) ord, name); + fprintf (file, "\t[%4ld] %.*s\n", (long) ord, + (int)((char *)(data + datasize) - name), name); } free (data); @@ -1807,6 +1879,14 @@ _bfd_XX_print_ce_compressed_pdata (bfd * 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) Index: binutils-2.24/bfd/srec.c =================================================================== --- binutils-2.24.orig/bfd/srec.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/srec.c 2015-01-16 18:06:05.000000000 +0100 @@ -248,7 +248,7 @@ srec_bad_byte (bfd *abfd, } else { - char buf[10]; + char buf[40]; if (! ISPRINT (c)) sprintf (buf, "\\%03o", (unsigned int) c); @@ -454,8 +454,8 @@ srec_scan (bfd *abfd) case 'S': { file_ptr pos; - char hdr[3]; - unsigned int bytes; + unsigned char hdr[3]; + unsigned int bytes, min_bytes; bfd_vma address; bfd_byte *data; unsigned char check_sum; @@ -478,6 +478,19 @@ srec_scan (bfd *abfd) } check_sum = bytes = HEX (hdr + 1); + min_bytes = 3; + if (hdr[0] == '2' || hdr[0] == '8') + min_bytes = 4; + else if (hdr[0] == '3' || hdr[0] == '7') + min_bytes = 5; + if (bytes < min_bytes) + { + (*_bfd_error_handler) (_("%B:%d: byte count %d too small\n"), + abfd, lineno, bytes); + bfd_set_error (bfd_error_bad_value); + goto error_return; + } + if (bytes * 2 > bufsize) { if (buf != NULL) Index: binutils-2.24/bfd/coffgen.c =================================================================== --- binutils-2.24.orig/bfd/coffgen.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/coffgen.c 2014-12-01 16:31:37.000000000 +0100 @@ -86,9 +86,8 @@ make_a_section_from_file (bfd *abfd, strings = _bfd_coff_read_string_table (abfd); if (strings == NULL) return FALSE; - /* FIXME: For extra safety, we should make sure that - strindex does not run us past the end, but right now we - don't know the length of the string table. */ + if ((bfd_size_type)(strindex + 2) >= obj_coff_strings_len (abfd)) + return FALSE; strings += strindex; name = (char *) bfd_alloc (abfd, (bfd_size_type) strlen (strings) + 1 + 1); @@ -466,6 +465,8 @@ _bfd_coff_internal_syment_name (bfd *abf if (strings == NULL) return NULL; } + if (sym->_n._n_n._n_offset >= obj_coff_strings_len (abfd)) + return NULL; return strings + sym->_n._n_n._n_offset; } } @@ -762,12 +763,14 @@ coff_renumber_symbols (bfd *bfd_ptr, int 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]); + symbol_ptr_ptr[symbol_index]->udata.i = symbol_index; if (coff_symbol_ptr && coff_symbol_ptr->native) { combined_entry_type *s = coff_symbol_ptr->native; int i; + BFD_ASSERT (s->is_sym); if (s->u.syment.n_sclass == C_FILE) { if (last_file != NULL) @@ -812,6 +815,7 @@ coff_mangle_symbols (bfd *bfd_ptr) int i; combined_entry_type *s = coff_symbol_ptr->native; + BFD_ASSERT (s->is_sym); if (s->fix_value) { /* FIXME: We should use a union here. */ @@ -835,6 +839,8 @@ coff_mangle_symbols (bfd *bfd_ptr) for (i = 0; i < s->u.syment.n_numaux; i++) { combined_entry_type *a = s + i + 1; + + BFD_ASSERT (! a->is_sym); if (a->fix_tag) { a->u.auxent.x_sym.x_tagndx.l = @@ -878,6 +884,7 @@ coff_fix_symbol_name (bfd *abfd, } name_length = strlen (name); + BFD_ASSERT (native->is_sym); if (native->u.syment.n_sclass == C_FILE && native->u.syment.n_numaux > 0) { @@ -893,6 +900,7 @@ coff_fix_symbol_name (bfd *abfd, else strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN); + BFD_ASSERT (! (native + 1)->is_sym); auxent = &(native + 1)->u.auxent; filnmlen = bfd_coff_filnmlen (abfd); @@ -995,6 +1003,8 @@ coff_write_symbol (bfd *abfd, void * buf; bfd_size_type symesz; + BFD_ASSERT (native->is_sym); + if (native->u.syment.n_sclass == C_FILE) symbol->flags |= BSF_DEBUGGING; @@ -1035,6 +1045,7 @@ coff_write_symbol (bfd *abfd, return FALSE; for (j = 0; j < native->u.syment.n_numaux; j++) { + BFD_ASSERT (! (native + j + 1)->is_sym); bfd_coff_swap_aux_out (abfd, &((native + j + 1)->u.auxent), type, n_sclass, (int) j, @@ -1080,10 +1091,12 @@ coff_write_alien_symbol (bfd *abfd, { symbol->name = ""; if (isym != NULL) - memset (isym, 0, sizeof(*isym)); + memset (isym, 0, sizeof (*isym)); return TRUE; } native = dummy; + native->is_sym = TRUE; + native[1].is_sym = FALSE; native->u.syment.n_type = T_NULL; native->u.syment.n_flags = 0; native->u.syment.n_numaux = 0; @@ -1110,7 +1123,7 @@ coff_write_alien_symbol (bfd *abfd, name to keep it from being put in the string table. */ symbol->name = ""; if (isym != NULL) - memset (isym, 0, sizeof(*isym)); + memset (isym, 0, sizeof (*isym)); return TRUE; } else @@ -1169,6 +1182,7 @@ coff_write_native_symbol (bfd *abfd, return TRUE; } + BFD_ASSERT (native->is_sym); /* If this symbol has an associated line number, we must store the symbol index in the line number field. We also tag the auxent to point to the right place in the lineno table. */ @@ -1278,8 +1292,9 @@ coff_write_symbols (bfd *abfd) symbol which has no associated section and we do not have to worry about this, all we need to know is that it is local. */ current_error_handler = bfd_set_error_handler (null_error_handler); + BFD_ASSERT (c_symbol->native->is_sym); sym_class = bfd_coff_classify_symbol (abfd, - &c_symbol->native->u.syment); + &c_symbol->native->u.syment); (void) bfd_set_error_handler (current_error_handler); n_sclass = &c_symbol->native->u.syment.n_sclass; @@ -1370,6 +1385,9 @@ coff_write_symbols (bfd *abfd) file name, nor does it go in the .debug section. */ maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN; + else if (! c_symbol->native->is_sym) + maxlen = bfd_coff_force_symnames_in_strings (abfd) ? 0 : SYMNMLEN; + else if (bfd_coff_symname_in_debug (abfd, &c_symbol->native->u.syment)) /* This symbol name is in the XCOFF .debug section. @@ -1460,6 +1478,7 @@ coff_write_linenumbers (bfd *abfd) { /* Found a linenumber entry, output. */ struct internal_lineno out; + memset ((void *) & out, 0, sizeof (out)); out.l_lnno = 0; out.l_addr.l_symndx = l->u.offset; @@ -1507,6 +1526,7 @@ coff_pointerize_aux (bfd *abfd, unsigned int type = symbol->u.syment.n_type; unsigned int n_sclass = symbol->u.syment.n_sclass; + BFD_ASSERT (symbol->is_sym); if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook) { if ((*coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook) @@ -1520,6 +1540,7 @@ coff_pointerize_aux (bfd *abfd, if (n_sclass == C_FILE) return; + BFD_ASSERT (! auxent->is_sym); /* Otherwise patch up. */ #define N_TMASK coff_data (abfd)->local_n_tmask #define N_BTSHFT coff_data (abfd)->local_n_btshft @@ -1547,7 +1568,7 @@ coff_pointerize_aux (bfd *abfd, we didn't want to go to the trouble until someone needed it. */ static char * -build_debug_section (bfd *abfd) +build_debug_section (bfd *abfd, asection ** sect_return) { char *debug_section; file_ptr position; @@ -1575,6 +1596,8 @@ build_debug_section (bfd *abfd) || bfd_bread (debug_section, sec_size, abfd) != sec_size || bfd_seek (abfd, position, SEEK_SET) != 0) return NULL; + + * sect_return = sect; return debug_section; } @@ -1637,7 +1660,9 @@ _bfd_coff_get_external_symbols (bfd *abf /* Read in the external strings. The strings are not loaded until they are needed. This is because we have no simple way of - detecting a missing string table in an archive. */ + detecting a missing string table in an archive. If the strings + are loaded then the STRINGS and STRINGS_LEN fields in the + coff_tdata structure will be set. */ const char * _bfd_coff_read_string_table (bfd *abfd) @@ -1687,7 +1712,13 @@ _bfd_coff_read_string_table (bfd *abfd) return NULL; } - strings = (char *) bfd_malloc (strsize); + strings = (char *) bfd_malloc (strsize + 1); + /* 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; @@ -1699,7 +1730,9 @@ _bfd_coff_read_string_table (bfd *abfd) } obj_coff_strings (abfd) = strings; - + obj_coff_strings_len (abfd) = strsize; + /* Terminate the string table, just in case. */ + strings[strsize] = 0; return strings; } @@ -1719,6 +1752,7 @@ _bfd_coff_free_symbols (bfd *abfd) { free (obj_coff_strings (abfd)); obj_coff_strings (abfd) = NULL; + obj_coff_strings_len (abfd) = 0; } return TRUE; } @@ -1739,21 +1773,22 @@ coff_get_normalized_symtab (bfd *abfd) char *raw_src; char *raw_end; const char *string_table = NULL; - char *debug_section = NULL; + asection * debug_sec = NULL; + char *debug_sec_data = NULL; bfd_size_type size; if (obj_raw_syments (abfd) != NULL) return obj_raw_syments (abfd); + if (! _bfd_coff_get_external_symbols (abfd)) + return NULL; + size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type); internal = (combined_entry_type *) bfd_zalloc (abfd, size); if (internal == NULL && size != 0) return NULL; internal_end = internal + obj_raw_syment_count (abfd); - - if (! _bfd_coff_get_external_symbols (abfd)) - return NULL; - + raw_src = (char *) obj_coff_external_syms (abfd); /* Mark the end of the symbols. */ @@ -1768,23 +1803,44 @@ coff_get_normalized_symtab (bfd *abfd) raw_src < raw_end; raw_src += symesz, internal_ptr++) { - unsigned int i; + bfd_coff_swap_sym_in (abfd, (void *) raw_src, (void *) & internal_ptr->u.syment); 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 + * sizeof (union internal_auxent) >= raw_end) + { + bfd_release (abfd, internal); + return NULL; + } for (i = 0; i < symbol_ptr->u.syment.n_numaux; i++) { internal_ptr++; + /* PR 17512: Prevent buffer overrun. */ + if (internal_ptr >= internal_end) + { + bfd_release (abfd, internal); + return NULL; + } + raw_src += symesz; + bfd_coff_swap_aux_in (abfd, (void *) raw_src, symbol_ptr->u.syment.n_type, 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); } @@ -1798,12 +1854,18 @@ coff_get_normalized_symtab (bfd *abfd) for (internal_ptr = internal; internal_ptr < internal_end; internal_ptr++) { + BFD_ASSERT (internal_ptr->is_sym); + if (internal_ptr->u.syment.n_sclass == C_FILE && internal_ptr->u.syment.n_numaux > 0) { + combined_entry_type * aux = internal_ptr + 1; + /* Make a file symbol point to the name in the auxent, since the text ".file" is redundant. */ - if ((internal_ptr + 1)->u.auxent.x_file.x_n.x_zeroes == 0) + BFD_ASSERT (! aux->is_sym); + + if (aux->u.auxent.x_file.x_n.x_zeroes == 0) { /* The filename is a long one, point into the string table. */ if (string_table == NULL) @@ -1813,10 +1875,12 @@ coff_get_normalized_symtab (bfd *abfd) return NULL; } - internal_ptr->u.syment._n._n_n._n_offset = - ((bfd_hostptr_t) - (string_table - + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset)); + if ((bfd_size_type)(aux->u.auxent.x_file.x_n.x_offset) + >= obj_coff_strings_len (abfd)) + internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>"); + else + internal_ptr->u.syment._n._n_n._n_offset = + (bfd_hostptr_t) (string_table + (aux->u.auxent.x_file.x_n.x_offset)); } else { @@ -1826,15 +1890,15 @@ coff_get_normalized_symtab (bfd *abfd) if (internal_ptr->u.syment.n_numaux > 1 && coff_data (abfd)->pe) internal_ptr->u.syment._n._n_n._n_offset = - ((bfd_hostptr_t) - copy_name (abfd, - (internal_ptr + 1)->u.auxent.x_file.x_fname, - internal_ptr->u.syment.n_numaux * symesz)); + (bfd_hostptr_t) + copy_name (abfd, + aux->u.auxent.x_file.x_fname, + internal_ptr->u.syment.n_numaux * symesz); else internal_ptr->u.syment._n._n_n._n_offset = ((bfd_hostptr_t) copy_name (abfd, - (internal_ptr + 1)->u.auxent.x_file.x_fname, + aux->u.auxent.x_file.x_fname, (size_t) bfd_coff_filnmlen (abfd))); } } @@ -1871,18 +1935,33 @@ coff_get_normalized_symtab (bfd *abfd) if (string_table == NULL) return NULL; } - internal_ptr->u.syment._n._n_n._n_offset = - ((bfd_hostptr_t) - (string_table - + internal_ptr->u.syment._n._n_n._n_offset)); + if (internal_ptr->u.syment._n._n_n._n_offset >= obj_coff_strings_len (abfd) + || string_table + internal_ptr->u.syment._n._n_n._n_offset < string_table) + internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>"); + else + internal_ptr->u.syment._n._n_n._n_offset = + ((bfd_hostptr_t) + (string_table + + internal_ptr->u.syment._n._n_n._n_offset)); } else { /* Long name in debug section. Very similar. */ - if (debug_section == NULL) - debug_section = build_debug_section (abfd); - internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) - (debug_section + internal_ptr->u.syment._n._n_n._n_offset); + if (debug_sec_data == NULL) + debug_sec_data = build_debug_section (abfd, & debug_sec); + if (debug_sec_data != NULL) + { + BFD_ASSERT (debug_sec != NULL); + /* PR binutils/17512: Catch out of range offsets into the debug data. */ + if (internal_ptr->u.syment._n._n_n._n_offset > debug_sec->size + || debug_sec_data + internal_ptr->u.syment._n._n_n._n_offset < debug_sec_data) + internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) _("<corrupt>"); + else + internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) + (debug_sec_data + internal_ptr->u.syment._n._n_n._n_offset); + } + else + internal_ptr->u.syment._n._n_n._n_offset = (bfd_hostptr_t) ""; } } internal_ptr += internal_ptr->u.syment.n_numaux; @@ -1915,7 +1994,7 @@ coff_make_empty_symbol (bfd *abfd) if (new_symbol == NULL) return NULL; new_symbol->symbol.section = 0; - new_symbol->native = 0; + new_symbol->native = NULL; new_symbol->lineno = NULL; new_symbol->done_lineno = FALSE; new_symbol->symbol.the_bfd = abfd; @@ -1941,6 +2020,7 @@ coff_bfd_make_debug_symbol (bfd *abfd, new_symbol->native = (combined_entry_type *) bfd_zalloc (abfd, amt); if (!new_symbol->native) return NULL; + new_symbol->native->is_sym = TRUE; new_symbol->symbol.section = bfd_abs_section_ptr; new_symbol->symbol.flags = BSF_DEBUGGING; new_symbol->lineno = NULL; @@ -1956,7 +2036,8 @@ coff_get_symbol_info (bfd *abfd, asymbol bfd_symbol_info (symbol, ret); if (coffsymbol (symbol)->native != NULL - && coffsymbol (symbol)->native->fix_value) + && coffsymbol (symbol)->native->fix_value + && coffsymbol (symbol)->native->is_sym) ret->value = coffsymbol (symbol)->native->u.syment.n_value - (bfd_hostptr_t) obj_raw_syments (abfd); } @@ -1971,7 +2052,8 @@ bfd_coff_get_syment (bfd *abfd, coff_symbol_type *csym; csym = coff_symbol_from (abfd, symbol); - if (csym == NULL || csym->native == NULL) + if (csym == NULL || csym->native == NULL + || ! csym->native->is_sym) { bfd_set_error (bfd_error_invalid_operation); return FALSE; @@ -2003,6 +2085,7 @@ bfd_coff_get_auxent (bfd *abfd, if (csym == NULL || csym->native == NULL + || ! csym->native->is_sym || indx >= csym->native->u.syment.n_numaux) { bfd_set_error (bfd_error_invalid_operation); @@ -2011,6 +2094,7 @@ bfd_coff_get_auxent (bfd *abfd, ent = csym->native + indx + 1; + BFD_ASSERT (! ent->is_sym); *pauxent = ent->u.auxent; if (ent->fix_tag) @@ -2064,6 +2148,15 @@ coff_print_symbol (bfd *abfd, fprintf (file, "[%3ld]", (long) (combined - root)); + /* PR 17512: file: 079-33786-0.001:0.1. */ + if (combined < obj_raw_syments (abfd) + || combined >= obj_raw_syments (abfd) + obj_raw_syment_count (abfd)) + { + fprintf (file, _("<corrupt info> %s"), symbol->name); + break; + } + + BFD_ASSERT (combined->is_sym); if (! combined->fix_value) val = (bfd_vma) combined->u.syment.n_value; else @@ -2083,6 +2176,7 @@ coff_print_symbol (bfd *abfd, combined_entry_type *auxp = combined + aux + 1; long tagndx; + BFD_ASSERT (! auxp->is_sym); if (auxp->fix_tag) tagndx = auxp->u.auxent.x_sym.x_tagndx.p - root; else @@ -2157,8 +2251,11 @@ coff_print_symbol (bfd *abfd, l++; while (l->line_number) { - fprintf (file, "\n%4d : ", l->line_number); - bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma); + if (l->line_number > 0) + { + fprintf (file, "\n%4d : ", l->line_number); + bfd_fprintf_vma (abfd, file, l->u.offset + symbol->section->vma); + } l++; } } @@ -2250,6 +2347,7 @@ coff_find_nearest_line_with_names (bfd * pend = p + cof->raw_syment_count; while (p < pend) { + BFD_ASSERT (p->is_sym); if (p->u.syment.n_sclass == C_FILE) break; p += 1 + p->u.syment.n_numaux; @@ -2273,6 +2371,7 @@ coff_find_nearest_line_with_names (bfd * p2 < pend; p2 += 1 + p2->u.syment.n_numaux) { + BFD_ASSERT (p2->is_sym); if (p2->u.syment.n_scnum > 0 && (section == coff_section_from_bfd_index (abfd, @@ -2284,6 +2383,8 @@ coff_find_nearest_line_with_names (bfd * break; } } + if (p2 >= pend) + break; file_addr = (bfd_vma) p2->u.syment.n_value; /* PR 11512: Include the section address of the function name symbol. */ @@ -2348,6 +2449,8 @@ coff_find_nearest_line_with_names (bfd * if (coff->native) { combined_entry_type *s = coff->native; + + BFD_ASSERT (s->is_sym); s = s + 1 + s->u.syment.n_numaux; /* In XCOFF a debugging symbol can follow the @@ -2360,6 +2463,7 @@ coff_find_nearest_line_with_names (bfd * { /* The linenumber is stored in the auxent. */ union internal_auxent *a = &((s + 1)->u.auxent); + line_base = a->x_sym.x_misc.x_lnsz.x_lnno; *line_ptr = line_base; } @@ -2497,6 +2601,7 @@ bfd_coff_set_symbol_class (bfd * if (native == NULL) return FALSE; + native->is_sym = TRUE; native->u.syment.n_type = T_NULL; native->u.syment.n_sclass = symbol_class; Index: binutils-2.24/bfd/ihex.c =================================================================== --- binutils-2.24.orig/bfd/ihex.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/ihex.c 2014-12-01 16:31:37.000000000 +0100 @@ -322,7 +322,7 @@ ihex_scan (bfd *abfd) { if (! ISHEX (buf[i])) { - ihex_bad_byte (abfd, lineno, hdr[i], error); + ihex_bad_byte (abfd, lineno, buf[i], error); goto error_return; } } Index: binutils-2.24/bfd/coffcode.h =================================================================== --- binutils-2.24.orig/bfd/coffcode.h 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/coffcode.h 2014-12-01 16:31:37.000000000 +0100 @@ -307,7 +307,7 @@ CODE_FRAGMENT .typedef struct coff_ptr_struct .{ . {* Remembers the offset from the first symbol in the file for -. this symbol. Generated by coff_renumber_symbols. *} +. this symbol. Generated by coff_renumber_symbols. *} . unsigned int offset; . . {* Should the value of this symbol be renumbered. Used for @@ -315,15 +315,15 @@ CODE_FRAGMENT . unsigned int fix_value : 1; . . {* Should the tag field of this symbol be renumbered. -. Created by coff_pointerize_aux. *} +. Created by coff_pointerize_aux. *} . unsigned int fix_tag : 1; . . {* Should the endidx field of this symbol be renumbered. -. Created by coff_pointerize_aux. *} +. Created by coff_pointerize_aux. *} . unsigned int fix_end : 1; . . {* Should the x_csect.x_scnlen field be renumbered. -. Created by coff_pointerize_aux. *} +. Created by coff_pointerize_aux. *} . unsigned int fix_scnlen : 1; . . {* Fix up an XCOFF C_BINCL/C_EINCL symbol. The value is the @@ -331,12 +331,15 @@ CODE_FRAGMENT . unsigned int fix_line : 1; . . {* The container for the symbol structure as read and translated -. from the file. *} +. from the file. *} . union . { . union internal_auxent auxent; . struct internal_syment syment; . } u; +. +. {* Selector for the union above. *} +. bfd_boolean is_sym; .} combined_entry_type; . . @@ -928,12 +931,7 @@ handle_COMDAT (bfd * abfd, bfd_coff_swap_sym_in (abfd, esym, & isym); - if (sizeof (internal_s->s_name) > SYMNMLEN) - { - /* This case implies that the matching - symbol name will be in the string table. */ - abort (); - } + BFD_ASSERT (sizeof (internal_s->s_name) <= SYMNMLEN); if (isym.n_scnum == section->target_index) { @@ -964,8 +962,12 @@ handle_COMDAT (bfd * abfd, /* All 3 branches use this. */ symname = _bfd_coff_internal_syment_name (abfd, &isym, buf); + /* PR 17512 file: 078-11867-0.004 */ if (symname == NULL) - abort (); + { + _bfd_error_handler (_("%B: unable to load COMDAT section name"), abfd); + break; + } switch (seen_state) { @@ -1793,6 +1795,7 @@ coff_new_section_hook (bfd * abfd, asect in case this symbol winds up getting written out. The value 0 for n_numaux is already correct. */ + native->is_sym = TRUE; native->u.syment.n_type = T_NULL; native->u.syment.n_sclass = sclass; @@ -2500,11 +2503,13 @@ coff_pointerize_aux_hook (bfd *abfd ATTR unsigned int indaux, combined_entry_type *aux) { + BFD_ASSERT (symbol->is_sym); int n_sclass = symbol->u.syment.n_sclass; if (CSECT_SYM_P (n_sclass) && indaux + 1 == symbol->u.syment.n_numaux) { + BFD_ASSERT (! aux->is_sym); if (SMTYP_SMTYP (aux->u.auxent.x_csect.x_smtyp) == XTY_LD) { aux->u.auxent.x_csect.x_scnlen.p = @@ -2537,6 +2542,7 @@ coff_pointerize_aux_hook (bfd *abfd ATTR /* Return TRUE if we don't want to pointerize this aux entry, which is the case for the lastfirst aux entry for a C_LEAFPROC symbol. */ return (indaux == 1 + && symbol->is_sym && (symbol->u.syment.n_sclass == C_LEAFPROC || symbol->u.syment.n_sclass == C_LEAFSTAT || symbol->u.syment.n_sclass == C_LEAFEXT)); @@ -2559,6 +2565,8 @@ coff_print_aux (bfd *abfd ATTRIBUTE_UNUS combined_entry_type *aux ATTRIBUTE_UNUSED, unsigned int indaux ATTRIBUTE_UNUSED) { + BFD_ASSERT (symbol->is_sym); + BFD_ASSERT (! aux->is_sym); #ifdef RS6000COFF_C if (CSECT_SYM_P (symbol->u.syment.n_sclass) && indaux + 1 == symbol->u.syment.n_numaux) @@ -3179,6 +3187,7 @@ coff_compute_section_file_positions (bfd cf = coff_symbol_from (abfd, *symp); if (cf != NULL && cf->native != NULL + && cf->native->is_sym && SYMNAME_IN_DEBUG (&cf->native->u.syment)) { size_t len; @@ -3876,6 +3885,7 @@ coff_write_object_contents (bfd * abfd) csym = coff_symbol_from (abfd, *psym); if (csym == NULL || csym->native == NULL + || ! csym->native->is_sym || csym->native->u.syment.n_numaux < 1 || csym->native->u.syment.n_sclass != C_STAT || csym->native->u.syment.n_type != T_NULL) @@ -3898,6 +3908,7 @@ coff_write_object_contents (bfd * abfd) x_associated field is not currently supported. */ aux = csym->native + 1; + BFD_ASSERT (! aux->is_sym); switch (current->flags & SEC_LINK_DUPLICATES) { case SEC_LINK_DUPLICATES_DISCARD: @@ -4043,8 +4054,6 @@ coff_write_object_contents (bfd * abfd) internal_f.f_flags |= F_DYNLOAD; #endif - memset (&internal_a, 0, sizeof internal_a); - /* Set up architecture-dependent stuff. */ { unsigned int magic = 0; @@ -4460,11 +4469,11 @@ buy_and_read (bfd *abfd, file_ptr where, void * area = bfd_alloc (abfd, size); if (!area) - return (NULL); + return NULL; if (bfd_seek (abfd, where, SEEK_SET) != 0 || bfd_bread (area, size, abfd) != size) - return (NULL); - return (area); + return NULL; + return area; } /* @@ -4498,6 +4507,8 @@ coff_sort_func_alent (const void * arg1, const coff_symbol_type *s1 = (const coff_symbol_type *) (al1->u.sym); const coff_symbol_type *s2 = (const coff_symbol_type *) (al2->u.sym); + if (s1 == NULL || s2 == NULL) + return 0; if (s1->symbol.value < s2->symbol.value) return -1; else if (s1->symbol.value > s2->symbol.value) @@ -4515,9 +4526,10 @@ coff_slurp_line_table (bfd *abfd, asecti unsigned int counter; alent *cache_ptr; bfd_vma prev_offset = 0; - int ordered = 1; + bfd_boolean ordered = TRUE; unsigned int nbr_func; LINENO *src; + bfd_boolean have_func; BFD_ASSERT (asect->lineno == NULL); @@ -4540,57 +4552,85 @@ coff_slurp_line_table (bfd *abfd, asecti asect->lineno = lineno_cache; src = native_lineno; nbr_func = 0; + have_func = FALSE; - for (counter = 0; counter < asect->lineno_count; counter++) + for (counter = 0; counter < asect->lineno_count; counter++, src++) { struct internal_lineno dst; bfd_coff_swap_lineno_in (abfd, src, &dst); cache_ptr->line_number = dst.l_lnno; + /* Appease memory checkers that get all excited about + uninitialised memory when copying alents if u.offset is + larger than u.sym. (64-bit BFD on 32-bit host.) */ + memset (&cache_ptr->u, 0, sizeof (cache_ptr->u)); if (cache_ptr->line_number == 0) { - bfd_boolean warned; - bfd_signed_vma symndx; + combined_entry_type * ent; + bfd_vma symndx; coff_symbol_type *sym; - nbr_func++; - warned = FALSE; + have_func = FALSE; symndx = dst.l_addr.l_symndx; - if (symndx < 0 - || (bfd_vma) symndx >= obj_raw_syment_count (abfd)) + if (symndx >= obj_raw_syment_count (abfd)) { (*_bfd_error_handler) - (_("%B: warning: illegal symbol index %ld in line numbers"), - abfd, (long) symndx); - symndx = 0; - warned = TRUE; + (_("%B: warning: illegal symbol index 0x%lx in line number entry %d"), + abfd, (long) symndx, counter); + cache_ptr->line_number = -1; + continue; } + ent = obj_raw_syments (abfd) + symndx; /* FIXME: We should not be casting between ints and pointers like this. */ - sym = ((coff_symbol_type *) - ((symndx + obj_raw_syments (abfd)) - ->u.syment._n._n_n._n_zeroes)); + if (! ent->is_sym) + { + (*_bfd_error_handler) + (_("%B: warning: illegal symbol index 0x%lx in line number entry %d"), + abfd, (long) symndx, counter); + cache_ptr->line_number = -1; + continue; + } + sym = (coff_symbol_type *) (ent->u.syment._n._n_n._n_zeroes); + + /* PR 17512 file: 078-10659-0.004 */ + if (sym < obj_symbols (abfd) + || sym >= obj_symbols (abfd) + bfd_get_symcount (abfd)) + { + (*_bfd_error_handler) + (_("%B: warning: illegal symbol in line number entry %d"), + abfd, counter); + cache_ptr->line_number = -1; + continue; + } + + have_func = TRUE; + nbr_func++; cache_ptr->u.sym = (asymbol *) sym; - if (sym->lineno != NULL && ! warned) + if (sym->lineno != NULL) (*_bfd_error_handler) (_("%B: warning: duplicate line number information for `%s'"), abfd, bfd_asymbol_name (&sym->symbol)); sym->lineno = cache_ptr; if (sym->symbol.value < prev_offset) - ordered = 0; + ordered = FALSE; prev_offset = sym->symbol.value; } + else if (!have_func) + /* Drop line information that has no associated function. + PR 17521: file: 078-10659-0.004. */ + continue; else - cache_ptr->u.offset = dst.l_addr.l_paddr - - bfd_section_vma (abfd, asect); - + cache_ptr->u.offset = (dst.l_addr.l_paddr + - bfd_section_vma (abfd, asect)); cache_ptr++; - src++; } - cache_ptr->line_number = 0; + + asect->lineno_count = cache_ptr - lineno_cache; + memset (cache_ptr, 0, sizeof (*cache_ptr)); bfd_release (abfd, native_lineno); /* On some systems (eg AIX5.3) the lineno table may not be sorted. */ @@ -4607,15 +4647,17 @@ coff_slurp_line_table (bfd *abfd, asecti alent **p = func_table; unsigned int i; - for (i = 0; i < counter; i++) + for (i = 0; i < asect->lineno_count; i++) if (lineno_cache[i].line_number == 0) *p++ = &lineno_cache[i]; + BFD_ASSERT ((unsigned int) (p - func_table) == nbr_func); + /* Sort by functions. */ qsort (func_table, nbr_func, sizeof (alent *), coff_sort_func_alent); /* Create the new sorted table. */ - amt = ((bfd_size_type) asect->lineno_count + 1) * sizeof (alent); + amt = (bfd_size_type) asect->lineno_count * sizeof (alent); n_lineno_cache = (alent *) bfd_alloc (abfd, amt); if (n_lineno_cache != NULL) { @@ -4626,18 +4668,18 @@ coff_slurp_line_table (bfd *abfd, asecti coff_symbol_type *sym; alent *old_ptr = func_table[i]; - /* Copy the function entry and update it. */ - *n_cache_ptr = *old_ptr; - sym = (coff_symbol_type *)n_cache_ptr->u.sym; - sym->lineno = n_cache_ptr; - n_cache_ptr++; - old_ptr++; - - /* Copy the line number entries. */ - while (old_ptr->line_number != 0) + /* Update the function entry. */ + sym = (coff_symbol_type *) old_ptr->u.sym; + /* PR binutils/17512: Point the lineno to where + this entry will be after the memcpy below. */ + sym->lineno = lineno_cache + (n_cache_ptr - n_lineno_cache); + /* Copy the function and line number entries. */ + do *n_cache_ptr++ = *old_ptr++; + while (old_ptr->line_number != 0); } - n_cache_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); } bfd_release (abfd, func_table); @@ -4676,7 +4718,7 @@ coff_slurp_symbol_table (bfd * abfd) amt = obj_raw_syment_count (abfd); amt *= sizeof (unsigned int); - table_ptr = (unsigned int *) bfd_alloc (abfd, amt); + table_ptr = (unsigned int *) bfd_zalloc (abfd, amt); if (table_ptr == NULL) return FALSE; @@ -4690,14 +4732,17 @@ coff_slurp_symbol_table (bfd * abfd) { combined_entry_type *src = native_symbols + this_index; table_ptr[this_index] = number_of_symbols; - dst->symbol.the_bfd = abfd; + dst->symbol.the_bfd = abfd; + BFD_ASSERT (src->is_sym); dst->symbol.name = (char *) (src->u.syment._n._n_n._n_offset); /* We use the native name field to point to the cached field. */ src->u.syment._n._n_n._n_zeroes = (bfd_hostptr_t) dst; dst->symbol.section = coff_section_from_bfd_index (abfd, src->u.syment.n_scnum); dst->symbol.flags = 0; + /* PR 17512: file: 079-7098-0.001:0.1. */ + dst->symbol.value = 0; dst->done_lineno = FALSE; switch (src->u.syment.n_sclass) @@ -4984,9 +5029,9 @@ coff_slurp_symbol_table (bfd * abfd) } dst->native = src; - dst->symbol.udata.i = 0; dst->lineno = NULL; + this_index += (src->u.syment.n_numaux) + 1; dst++; number_of_symbols++; @@ -5069,13 +5114,13 @@ coff_classify_symbol (bfd *abfd, if (syment->n_value == 0) { asection *sec; - char buf[SYMNMLEN + 1]; - - sec = coff_section_from_bfd_index (abfd, syment->n_scnum); - if (sec != NULL - && (strcmp (bfd_get_section_name (abfd, sec), - _bfd_coff_internal_syment_name (abfd, syment, buf)) - == 0)) + char * name; + char buf[SYMNMLEN + 1]; + + name = _bfd_coff_internal_syment_name (abfd, syment, buf) + sec = coff_section_from_bfd_index (abfd, syment->n_scnum); + if (sec != NULL && name != NULL + && (strcmp (bfd_get_section_name (abfd, sec), name) == 0)) return COFF_SYMBOL_PE_SECTION; } #endif @@ -5146,6 +5191,7 @@ SUBSUBSECTION else if (ptr) \ coffsym = coff_symbol_from (abfd, ptr); \ if (coffsym != NULL \ + && coffsym->native->is_sym \ && coffsym->native->u.syment.n_scnum == 0) \ cache_ptr->addend = 0; \ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \ Index: binutils-2.24/bfd/cofflink.c =================================================================== --- binutils-2.24.orig/bfd/cofflink.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/cofflink.c 2014-12-01 16:31:37.000000000 +0100 @@ -2088,7 +2088,10 @@ _bfd_coff_link_input_bfd (struct coff_fi if (strings == NULL) return FALSE; } - filename = strings + auxp->x_file.x_n.x_offset; + if ((bfd_size_type) auxp->x_file.x_n.x_offset >= obj_coff_strings_len (input_bfd)) + filename = _("<corrupt>"); + else + filename = strings + auxp->x_file.x_n.x_offset; indx = _bfd_stringtab_add (flaginfo->strtab, filename, hash, copy); if (indx == (bfd_size_type) -1) Index: binutils-2.24/bfd/libcoff-in.h =================================================================== --- binutils-2.24.orig/bfd/libcoff-in.h 2013-11-26 12:37:33.000000000 +0100 +++ binutils-2.24/bfd/libcoff-in.h 2014-12-01 16:31:37.000000000 +0100 @@ -35,6 +35,7 @@ #define obj_coff_external_syms(bfd) (coff_data (bfd)->external_syms) #define obj_coff_keep_syms(bfd) (coff_data (bfd)->keep_syms) #define obj_coff_strings(bfd) (coff_data (bfd)->strings) +#define obj_coff_strings_len(bfd) (coff_data (bfd)->strings_len) #define obj_coff_keep_strings(bfd) (coff_data (bfd)->keep_strings) #define obj_coff_sym_hashes(bfd) (coff_data (bfd)->sym_hashes) #define obj_coff_strings_written(bfd) (coff_data (bfd)->strings_written) @@ -75,6 +76,8 @@ typedef struct coff_tdata /* The string table. May be NULL. Read by _bfd_coff_read_string_table. */ char *strings; + /* The length of the strings table. For error checking. */ + bfd_size_type strings_len; /* If this is TRUE, the strings may not be freed. */ bfd_boolean keep_strings; /* If this is TRUE, the strings have been written out already. */ Index: binutils-2.24/bfd/libcoff.h =================================================================== --- binutils-2.24.orig/bfd/libcoff.h 2013-11-26 12:37:33.000000000 +0100 +++ binutils-2.24/bfd/libcoff.h 2014-12-01 16:31:37.000000000 +0100 @@ -39,6 +39,7 @@ #define obj_coff_external_syms(bfd) (coff_data (bfd)->external_syms) #define obj_coff_keep_syms(bfd) (coff_data (bfd)->keep_syms) #define obj_coff_strings(bfd) (coff_data (bfd)->strings) +#define obj_coff_strings_len(bfd) (coff_data (bfd)->strings_len) #define obj_coff_keep_strings(bfd) (coff_data (bfd)->keep_strings) #define obj_coff_sym_hashes(bfd) (coff_data (bfd)->sym_hashes) #define obj_coff_strings_written(bfd) (coff_data (bfd)->strings_written) @@ -79,6 +80,8 @@ typedef struct coff_tdata /* The string table. May be NULL. Read by _bfd_coff_read_string_table. */ char *strings; + /* The length of the strings table. For error checking. */ + bfd_size_type strings_len; /* If this is TRUE, the strings may not be freed. */ bfd_boolean keep_strings; /* If this is TRUE, the strings have been written out already. */ @@ -622,7 +625,7 @@ extern bfd_boolean ppc_process_before_al typedef struct coff_ptr_struct { /* Remembers the offset from the first symbol in the file for - this symbol. Generated by coff_renumber_symbols. */ + this symbol. Generated by coff_renumber_symbols. */ unsigned int offset; /* Should the value of this symbol be renumbered. Used for @@ -630,15 +633,15 @@ typedef struct coff_ptr_struct unsigned int fix_value : 1; /* Should the tag field of this symbol be renumbered. - Created by coff_pointerize_aux. */ + Created by coff_pointerize_aux. */ unsigned int fix_tag : 1; /* Should the endidx field of this symbol be renumbered. - Created by coff_pointerize_aux. */ + Created by coff_pointerize_aux. */ unsigned int fix_end : 1; /* Should the x_csect.x_scnlen field be renumbered. - Created by coff_pointerize_aux. */ + Created by coff_pointerize_aux. */ unsigned int fix_scnlen : 1; /* Fix up an XCOFF C_BINCL/C_EINCL symbol. The value is the @@ -646,12 +649,15 @@ typedef struct coff_ptr_struct unsigned int fix_line : 1; /* The container for the symbol structure as read and translated - from the file. */ + from the file. */ union { union internal_auxent auxent; struct internal_syment syment; } u; + + /* Selector for the union above. */ + bfd_boolean is_sym; } combined_entry_type; Index: binutils-2.24/bfd/xcofflink.c =================================================================== --- binutils-2.24.orig/bfd/xcofflink.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/xcofflink.c 2014-12-01 16:31:37.000000000 +0100 @@ -4484,7 +4484,10 @@ xcoff_link_input_bfd (struct xcoff_final if (strings == NULL) return FALSE; } - filename = strings + aux.x_file.x_n.x_offset; + if ((bfd_size_type) aux.x_file.x_n.x_offset >= obj_coff_strings_len (input_bfd)) + filename = _("<corrupt>"); + else + filename = strings + aux.x_file.x_n.x_offset; indx = _bfd_stringtab_add (flinfo->strtab, filename, hash, copy); if (indx == (bfd_size_type) -1) Index: binutils-2.24/binutils/objdump.c =================================================================== --- binutils-2.24.orig/binutils/objdump.c 2013-11-08 11:13:48.000000000 +0100 +++ binutils-2.24/binutils/objdump.c 2014-12-01 16:31:37.000000000 +0100 @@ -563,7 +563,10 @@ slurp_symtab (bfd *abfd) storage = bfd_get_symtab_upper_bound (abfd); if (storage < 0) - bfd_fatal (bfd_get_filename (abfd)); + { + non_fatal (_("failed to read symbol table from: %s"), bfd_get_filename (abfd)); + bfd_fatal (_("error message was")); + } if (storage) sy = (asymbol **) xmalloc (storage); @@ -2386,7 +2389,12 @@ dump_dwarf (bfd *abfd) else if (bfd_little_endian (abfd)) byte_get = byte_get_little_endian; else - abort (); + /* PR 17512: file: objdump-s-endless-loop.tekhex. */ + { + warn (_("File %s does not contain any dwarf debug information\n"), + bfd_get_filename (abfd)); + return; + } switch (bfd_get_arch (abfd)) { @@ -2490,7 +2498,7 @@ print_section_stabs (bfd *abfd, We start the index at -1 because there is a dummy symbol on the front of stabs-in-{coff,elf} sections that supplies sizes. */ - for (i = -1; stabp < stabs_end; stabp += STABSIZE, i++) + for (i = -1; stabp <= stabs_end - STABSIZE; stabp += STABSIZE, i++) { const char *name; unsigned long strx; @@ -2528,10 +2536,13 @@ print_section_stabs (bfd *abfd, } else { + bfd_size_type amt = strx + file_string_table_offset; + /* Using the (possibly updated) string table offset, print the string (if any) associated with this symbol. */ - if ((strx + file_string_table_offset) < stabstr_size) - printf (" %s", &strtab[strx + file_string_table_offset]); + if (amt < stabstr_size) + /* PR 17512: file: 079-79389-0.001:0.1. */ + printf (" %.*s", (int)(stabstr_size - amt), strtab + amt); else printf (" *"); } @@ -3106,7 +3117,11 @@ dump_relocs_in_section (bfd *abfd, relcount = bfd_canonicalize_reloc (abfd, section, relpp, syms); if (relcount < 0) - bfd_fatal (bfd_get_filename (abfd)); + { + printf ("\n"); + non_fatal (_("failed to read relocs in: %s"), bfd_get_filename (abfd)); + bfd_fatal (_("error message was")); + } else if (relcount == 0) printf (" (none)\n\n"); else Index: binutils-2.24/bfd/archive.c =================================================================== --- binutils-2.24.orig/bfd/archive.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/archive.c 2014-12-01 16:31:37.000000000 +0100 @@ -1299,6 +1299,8 @@ _bfd_slurp_extended_name_table (bfd *abf { byebye: free (namedata); + bfd_ardata (abfd)->extended_names = NULL; + bfd_ardata (abfd)->extended_names_size = 0; return FALSE; } @@ -1315,11 +1317,12 @@ _bfd_slurp_extended_name_table (bfd *abf text, the entries in the list are newline-padded, not null padded. In SVR4-style archives, the names also have a trailing '/'. DOS/NT created archive often have \ in them - We'll fix all problems here.. */ + We'll fix all problems here. */ { char *ext_names = bfd_ardata (abfd)->extended_names; char *temp = ext_names; char *limit = temp + namedata->parsed_size; + for (; temp < limit; ++temp) { if (*temp == ARFMAG[1]) Index: binutils-2.24/binutils/ar.c =================================================================== --- binutils-2.24.orig/binutils/ar.c 2014-12-01 16:31:37.000000000 +0100 +++ binutils-2.24/binutils/ar.c 2014-12-01 16:31:37.000000000 +0100 @@ -1033,6 +1033,15 @@ extract_file (bfd *abfd) bfd_size_type size; struct stat buf; + /* PR binutils/17533: Do not allow directory traversal + outside of the current directory tree. */ + if (! is_valid_archive_path (bfd_get_filename (abfd))) + { + non_fatal (_("illegal pathname found in archive member: %s"), + bfd_get_filename (abfd)); + return; + } + if (bfd_stat_arch_elt (abfd, &buf) != 0) /* xgettext:c-format */ fatal (_("internal stat error on %s"), bfd_get_filename (abfd)); Index: binutils-2.24/binutils/bucomm.c =================================================================== --- binutils-2.24.orig/binutils/bucomm.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/binutils/bucomm.c 2014-12-01 16:31:37.000000000 +0100 @@ -429,8 +429,12 @@ print_arelt_descr (FILE *file, bfd *abfd const char *ctime_result = (const char *) ctime (&when); bfd_size_type size; - /* POSIX format: skip weekday and seconds from ctime output. */ - sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20); + /* PR binutils/17605: Check for corrupt time values. */ + if (ctime_result == NULL) + sprintf (timebuf, _("<time data corrupt>")); + else + /* POSIX format: skip weekday and seconds from ctime output. */ + sprintf (timebuf, "%.12s %.4s", ctime_result + 4, ctime_result + 20); mode_string (buf.st_mode, modebuf); modebuf[10] = '\0'; @@ -624,3 +628,29 @@ bfd_get_archive_filename (const bfd *abf bfd_get_filename (abfd)); return buf; } + +/* Returns TRUE iff PATHNAME, a filename of an archive member, + is valid for writing. For security reasons absolute paths + and paths containing /../ are not allowed. See PR 17533. */ + +bfd_boolean +is_valid_archive_path (char const * pathname) +{ + const char * n = pathname; + + if (IS_ABSOLUTE_PATH (n)) + return FALSE; + + while (*n) + { + if (*n == '.' && *++n == '.' && ( ! *++n || IS_DIR_SEPARATOR (*n))) + return FALSE; + + while (*n && ! IS_DIR_SEPARATOR (*n)) + n++; + while (IS_DIR_SEPARATOR (*n)) + n++; + } + + return TRUE; +} Index: binutils-2.24/binutils/bucomm.h =================================================================== --- binutils-2.24.orig/binutils/bucomm.h 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/binutils/bucomm.h 2014-12-01 16:31:37.000000000 +0100 @@ -23,6 +23,8 @@ #ifndef _BUCOMM_H #define _BUCOMM_H +/* In bucomm.c. */ + /* Return the filename in a static buffer. */ const char *bfd_get_archive_filename (const bfd *); @@ -58,20 +60,22 @@ bfd_vma parse_vma (const char *, const c off_t get_file_size (const char *); +bfd_boolean is_valid_archive_path (char const *); + extern char *program_name; -/* filemode.c */ +/* In filemode.c. */ void mode_string (unsigned long, char *); -/* version.c */ +/* In version.c. */ extern void print_version (const char *); -/* rename.c */ +/* In rename.c. */ extern void set_times (const char *, const struct stat *); extern int smart_rename (const char *, const char *, int); -/* libiberty. */ +/* In libiberty. */ void *xmalloc (size_t); void *xrealloc (void *, size_t); Index: binutils-2.24/binutils/doc/binutils.texi =================================================================== --- binutils-2.24.orig/binutils/doc/binutils.texi 2013-11-08 11:13:48.000000000 +0100 +++ binutils-2.24/binutils/doc/binutils.texi 2014-12-01 16:31:37.000000000 +0100 @@ -234,7 +234,8 @@ a normal archive. Instead the elements individually to the second archive. The paths to the elements of the archive are stored relative to the -archive itself. +archive itself. For security reasons absolute paths and paths with a +@code{/../} component are not allowed. @cindex compatibility, @command{ar} @cindex @command{ar} compatibility Index: binutils-2.24/binutils/objcopy.c =================================================================== --- binutils-2.24.orig/binutils/objcopy.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/binutils/objcopy.c 2014-12-01 16:31:37.000000000 +0100 @@ -2206,6 +2206,16 @@ copy_archive (bfd *ibfd, bfd *obfd, cons bfd_boolean del = TRUE; bfd_boolean ok_object; + /* PR binutils/17533: Do not allow directory traversal + outside of the current directory tree by archive members. */ + if (! is_valid_archive_path (bfd_get_filename (this_element))) + { + non_fatal (_("illegal pathname found in archive member: %s"), + bfd_get_filename (this_element)); + status = 1; + goto cleanup_and_exit; + } + /* Create an output file for this member. */ output_name = concat (dir, "/", bfd_get_filename (this_element), (char *) 0); @@ -2215,8 +2225,12 @@ copy_archive (bfd *ibfd, bfd *obfd, cons { output_name = make_tempdir (output_name); if (output_name == NULL) - fatal (_("cannot create tempdir for archive copying (error: %s)"), - strerror (errno)); + { + non_fatal (_("cannot create tempdir for archive copying (error: %s)"), + strerror (errno)); + status = 1; + goto cleanup_and_exit; + } l = (struct name_list *) xmalloc (sizeof (struct name_list)); l->name = output_name; @@ -2258,7 +2272,7 @@ copy_archive (bfd *ibfd, bfd *obfd, cons { bfd_nonfatal_message (output_name, NULL, NULL, NULL); status = 1; - return; + goto cleanup_and_exit; } if (ok_object) @@ -2319,7 +2333,6 @@ copy_archive (bfd *ibfd, bfd *obfd, cons { status = 1; bfd_nonfatal_message (filename, NULL, NULL, NULL); - return; } filename = bfd_get_filename (ibfd); @@ -2327,9 +2340,9 @@ copy_archive (bfd *ibfd, bfd *obfd, cons { status = 1; bfd_nonfatal_message (filename, NULL, NULL, NULL); - return; } + cleanup_and_exit: /* Delete all the files that we opened. */ for (l = list; l != NULL; l = l->next) { Index: binutils-2.24/bfd/coff-i386.c =================================================================== --- binutils-2.24.orig/bfd/coff-i386.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/coff-i386.c 2014-12-01 16:31:37.000000000 +0100 @@ -342,16 +342,18 @@ static reloc_howto_type howto_table[] = PCRELOFFSET) /* pcrel_offset */ }; +#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) I386BADMAG(x) #define I386 1 /* Customize coffcode.h */ -#define RTYPE2HOWTO(cache_ptr, dst) \ - ((cache_ptr)->howto = \ - ((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0]) \ - ? howto_table + (dst)->r_type \ +#define RTYPE2HOWTO(cache_ptr, dst) \ + ((cache_ptr)->howto = \ + ((dst)->r_type < NUM_HOWTOS \ + ? howto_table + (dst)->r_type \ : NULL)) /* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared @@ -388,7 +390,8 @@ static reloc_howto_type howto_table[] = cache_ptr->addend = - (ptr->section->vma + ptr->value); \ else \ cache_ptr->addend = 0; \ - if (ptr && howto_table[reloc.r_type].pc_relative) \ + if (ptr && reloc.r_type < NUM_HOWTOS \ + && howto_table[reloc.r_type].pc_relative) \ cache_ptr->addend += asect->vma; \ } @@ -440,7 +443,7 @@ coff_i386_rtype_to_howto (bfd *abfd ATTR { reloc_howto_type *howto; - if (rel->r_type >= sizeof (howto_table) / sizeof (howto_table[0])) + if (rel->r_type >= NUM_HOWTOS) { bfd_set_error (bfd_error_bad_value); return NULL; @@ -576,7 +579,7 @@ coff_i386_reloc_name_lookup (bfd *abfd A { unsigned int i; - for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++) + for (i = 0; i < NUM_HOWTOS; i++) if (howto_table[i].name != NULL && strcasecmp (howto_table[i].name, r_name) == 0) return &howto_table[i]; Index: binutils-2.24/bfd/coff-x86_64.c =================================================================== --- binutils-2.24.orig/bfd/coff-x86_64.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/coff-x86_64.c 2014-12-01 16:31:37.000000000 +0100 @@ -449,6 +449,8 @@ static reloc_howto_type howto_table[] = PCRELOFFSET) /* pcrel_offset */ }; +#define NUM_HOWTOS ARRAY_SIZE (howto_table) + /* Turn a howto into a reloc nunmber */ #define SELECT_RELOC(x,howto) { x.r_type = howto->type; } @@ -457,7 +459,7 @@ static reloc_howto_type howto_table[] = #define RTYPE2HOWTO(cache_ptr, dst) \ ((cache_ptr)->howto = \ - ((dst)->r_type < ARRAY_SIZE (howto_table)) \ + ((dst)->r_type < NUM_HOWTOS) \ ? howto_table + (dst)->r_type \ : NULL) @@ -497,7 +499,8 @@ static reloc_howto_type howto_table[] = cache_ptr->addend = - (ptr->section->vma + ptr->value); \ else \ cache_ptr->addend = 0; \ - if (ptr && howto_table[reloc.r_type].pc_relative) \ + if (ptr && reloc.r_type < NUM_HOWTOS \ + && howto_table[reloc.r_type].pc_relative) \ cache_ptr->addend += asect->vma; \ } @@ -547,7 +550,7 @@ coff_amd64_rtype_to_howto (bfd *abfd ATT { reloc_howto_type *howto; - if (rel->r_type >= ARRAY_SIZE (howto_table)) + if (rel->r_type >= NUM_HOWTOS) { bfd_set_error (bfd_error_bad_value); return NULL; @@ -690,7 +693,7 @@ coff_amd64_reloc_name_lookup (bfd *abfd { unsigned int i; - for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++) + for (i = 0; i < NUM_HOWTOS; i++) if (howto_table[i].name != NULL && strcasecmp (howto_table[i].name, r_name) == 0) return &howto_table[i]; Index: binutils-2.24/bfd/opncls.c =================================================================== --- binutils-2.24.orig/bfd/opncls.c 2013-11-08 11:13:48.000000000 +0100 +++ binutils-2.24/bfd/opncls.c 2014-12-01 16:31:37.000000000 +0100 @@ -919,14 +919,19 @@ void * bfd_alloc (bfd *abfd, bfd_size_type size) { void *ret; + unsigned long ul_size = (unsigned long) size; - if (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))) { bfd_set_error (bfd_error_no_memory); return NULL; } - - ret = objalloc_alloc ((struct objalloc *) abfd->memory, (unsigned long) size); + + ret = objalloc_alloc ((struct objalloc *) abfd->memory, ul_size); if (ret == NULL) bfd_set_error (bfd_error_no_memory); return ret; @@ -947,8 +952,6 @@ DESCRIPTION void * bfd_alloc2 (bfd *abfd, bfd_size_type nmemb, bfd_size_type size) { - void *ret; - if ((nmemb | size) >= HALF_BFD_SIZE_TYPE && size != 0 && nmemb > ~(bfd_size_type) 0 / size) @@ -957,18 +960,7 @@ bfd_alloc2 (bfd *abfd, bfd_size_type nme return NULL; } - size *= nmemb; - - if (size != (unsigned long) size) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } - - ret = objalloc_alloc ((struct objalloc *) abfd->memory, (unsigned long) size); - if (ret == NULL) - bfd_set_error (bfd_error_no_memory); - return ret; + return bfd_alloc (abfd, size * nmemb); } /* @@ -1160,7 +1152,7 @@ bfd_get_debug_link_info (bfd *abfd, unsi asection *sect; unsigned long crc32; bfd_byte *contents; - int crc_offset; + unsigned int crc_offset; char *name; BFD_ASSERT (abfd); @@ -1178,10 +1170,13 @@ bfd_get_debug_link_info (bfd *abfd, unsi return NULL; } - /* Crc value is stored after the filename, aligned up to 4 bytes. */ + /* CRC value is stored after the filename, aligned up to 4 bytes. */ name = (char *) contents; - crc_offset = strlen (name) + 1; + /* PR 17597: avoid reading off the end of the buffer. */ + crc_offset = strnlen (name, bfd_get_section_size (sect)) + 1; crc_offset = (crc_offset + 3) & ~3; + if (crc_offset >= bfd_get_section_size (sect)) + return NULL; crc32 = bfd_get_32 (abfd, contents + crc_offset); Index: binutils-2.24/bfd/pe-mips.c =================================================================== --- binutils-2.24.orig/bfd/pe-mips.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/pe-mips.c 2014-12-01 16:31:37.000000000 +0100 @@ -341,6 +341,8 @@ static reloc_howto_type howto_table[] = FALSE), /* Pcrel_offset. */ }; +#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; } @@ -381,7 +383,8 @@ static reloc_howto_type howto_table[] = cache_ptr->addend = - (ptr->section->vma + ptr->value); \ else \ cache_ptr->addend = 0; \ - if (ptr && howto_table[reloc.r_type].pc_relative) \ + if (ptr && reloc.r_type < NUM_HOWTOS \ + && howto_table[reloc.r_type].pc_relative) \ cache_ptr->addend += asect->vma; \ } @@ -511,9 +514,7 @@ coff_mips_reloc_name_lookup (bfd *abfd A { unsigned int i; - for (i = 0; - i < sizeof (howto_table) / sizeof (howto_table[0]); - i++) + for (i = 0; i < NUM_HOWTOS; i++) if (howto_table[i].name != NULL && strcasecmp (howto_table[i].name, r_name) == 0) return &howto_table[i]; Index: binutils-2.24/bfd/peicode.h =================================================================== --- binutils-2.24.orig/bfd/peicode.h 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/peicode.h 2014-12-01 16:31:37.000000000 +0100 @@ -271,6 +271,7 @@ pe_mkobject (bfd * abfd) /* in_reloc_p is architecture dependent. */ pe->in_reloc_p = in_reloc_p; + memset (& pe->pe_opthdr, 0, sizeof pe->pe_opthdr); return TRUE; } @@ -567,6 +568,7 @@ pe_ILF_make_a_symbol (pe_ILF_vars * var ent->u.syment.n_sclass = sclass; ent->u.syment.n_scnum = section->target_index; ent->u.syment._n._n_n._n_offset = (bfd_hostptr_t) sym; + ent->is_sym = TRUE; sym->symbol.the_bfd = vars->abfd; sym->symbol.name = vars->string_ptr; Index: binutils-2.24/binutils/rdcoff.c =================================================================== --- binutils-2.24.orig/binutils/rdcoff.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/binutils/rdcoff.c 2014-12-01 16:31:37.000000000 +0100 @@ -84,7 +84,7 @@ struct coff_types debug_type basic[T_MAX + 1]; }; -static debug_type *coff_get_slot (struct coff_types *, int); +static debug_type *coff_get_slot (struct coff_types *, long); static debug_type parse_coff_type (bfd *, struct coff_symbols *, struct coff_types *, long, int, union internal_auxent *, bfd_boolean, void *); @@ -105,12 +105,17 @@ static bfd_boolean external_coff_symbol_ /* Return the slot for a type. */ static debug_type * -coff_get_slot (struct coff_types *types, int indx) +coff_get_slot (struct coff_types *types, long indx) { struct coff_slots **pps; pps = &types->slots; + /* PR 17512: file: 078-18333-0.001:0.1. + FIXME: The value of 1000 is a guess. Maybe a better heuristic is needed. */ + if (indx / COFF_SLOTS > 1000) + fatal (_("Excessively large slot index: %lx"), indx); + while (indx >= COFF_SLOTS) { if (*pps == NULL) Index: binutils-2.24/binutils/rddbg.c =================================================================== --- binutils-2.24.orig/binutils/rddbg.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/binutils/rddbg.c 2014-12-01 16:31:37.000000000 +0100 @@ -140,7 +140,7 @@ read_section_stabs_debugging_info (bfd * } strsize = bfd_section_size (abfd, strsec); - strings = (bfd_byte *) xmalloc (strsize); + strings = (bfd_byte *) xmalloc (strsize + 1); if (! bfd_get_section_contents (abfd, strsec, strings, 0, strsize)) { fprintf (stderr, "%s: %s: %s\n", @@ -148,7 +148,8 @@ read_section_stabs_debugging_info (bfd * bfd_errmsg (bfd_get_error ())); return FALSE; } - + /* Zero terminate the strings table, just in case. */ + strings [strsize] = 0; if (shandle == NULL) { shandle = start_stab (dhandle, abfd, TRUE, syms, symcount); @@ -160,7 +161,8 @@ read_section_stabs_debugging_info (bfd * stroff = 0; next_stroff = 0; - for (stab = stabs; stab < stabs + stabsize; stab += 12) + /* PR 17512: file: 078-60391-0.001:0.1. */ + for (stab = stabs; stab <= (stabs + stabsize) - 12; stab += 12) { unsigned int strx; int type; @@ -185,33 +187,43 @@ read_section_stabs_debugging_info (bfd * } else { + size_t len; char *f, *s; - f = NULL; - - if (stroff + strx > strsize) + if (stroff + strx >= strsize) { - fprintf (stderr, "%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n", + fprintf (stderr, _("%s: %s: stab entry %ld is corrupt, strx = 0x%x, type = %d\n"), bfd_get_filename (abfd), names[i].secname, (long) (stab - stabs) / 12, strx, type); continue; } s = (char *) strings + stroff + strx; + f = NULL; - while (s[strlen (s) - 1] == '\\' + /* PR 17512: file: 002-87578-0.001:0.1. + It is possible to craft a file where, without the 'strlen (s) > 0', + an attempt to read the byte before 'strings' would occur. */ + while ((len = strlen (s)) > 0 + && s[len - 1] == '\\' && stab + 12 < stabs + stabsize) { char *p; stab += 12; - p = s + strlen (s) - 1; + p = s + len - 1; *p = '\0'; - s = concat (s, - ((char *) strings - + stroff - + bfd_get_32 (abfd, stab)), - (const char *) NULL); + strx = stroff + bfd_get_32 (abfd, stab); + if (strx >= strsize) + { + fprintf (stderr, _("%s: %s: stab entry %ld is corrupt\n"), + bfd_get_filename (abfd), names[i].secname, + (long) (stab - stabs) / 12); + break; + } + else + s = concat (s, (char *) strings + strx, + (const char *) NULL); /* We have to restore the backslash, because, if the linker is hashing stabs strings, we may Index: binutils-2.24/binutils/stabs.c =================================================================== --- binutils-2.24.orig/binutils/stabs.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/binutils/stabs.c 2014-12-01 16:31:37.000000000 +0100 @@ -837,8 +837,6 @@ parse_stab_string (void *dhandle, struct case 'G': { - char leading; - long c; asymbol **ps; /* A global symbol. The value must be extracted from the @@ -847,19 +845,27 @@ parse_stab_string (void *dhandle, struct (debug_type **) NULL); if (dtype == DEBUG_TYPE_NULL) return FALSE; - leading = bfd_get_symbol_leading_char (info->abfd); - for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps) + if (name != NULL) { - const char *n; + char leading; + long c; - n = bfd_asymbol_name (*ps); - if (leading != '\0' && *n == leading) - ++n; - if (*n == *name && strcmp (n, name) == 0) - break; + leading = bfd_get_symbol_leading_char (info->abfd); + for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps) + { + const char *n; + + n = bfd_asymbol_name (*ps); + if (leading != '\0' && *n == leading) + ++n; + if (*n == *name && strcmp (n, name) == 0) + break; + } + + if (c > 0) + value = bfd_asymbol_value (*ps); } - if (c > 0) - value = bfd_asymbol_value (*ps); + if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL, value)) return FALSE; Index: binutils-2.24/gas/config/obj-coff.c =================================================================== --- binutils-2.24.orig/gas/config/obj-coff.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/gas/config/obj-coff.c 2014-12-01 16:31:37.000000000 +0100 @@ -390,6 +390,7 @@ coff_obj_symbol_new_hook (symbolS *symbo memset (s, 0, sz); coffsymbol (symbol_get_bfdsym (symbolP))->native = (combined_entry_type *) s; + coffsymbol (symbol_get_bfdsym (symbolP))->native->is_sym = TRUE; S_SET_DATA_TYPE (symbolP, T_NULL); S_SET_STORAGE_CLASS (symbolP, 0); Index: binutils-2.24/bfd/ieee.c =================================================================== --- binutils-2.24.orig/bfd/ieee.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/ieee.c 2014-12-01 16:31:37.000000000 +0100 @@ -171,9 +171,16 @@ ieee_write_id (bfd *abfd, const char *id standard requires. */ #define this_byte(ieee) *((ieee)->input_p) -#define next_byte(ieee) ((ieee)->input_p++) #define this_byte_and_next(ieee) (*((ieee)->input_p++)) +static bfd_boolean +next_byte (common_header_type * ieee) +{ + ieee->input_p++; + + return ieee->input_p < ieee->last_byte; +} + static unsigned short read_2bytes (common_header_type *ieee) { @@ -349,15 +356,15 @@ parse_int (common_header_type *ieee, bfd if (value >= 0 && value <= 127) { *value_ptr = value; - next_byte (ieee); - return TRUE; + return next_byte (ieee); } else if (value >= 0x80 && value <= 0x88) { unsigned int count = value & 0xf; result = 0; - next_byte (ieee); + if (! next_byte (ieee)) + return FALSE; while (count) { result = (result << 8) | this_byte_and_next (ieee); @@ -497,7 +504,7 @@ static reloc_howto_type rel8_howto = static ieee_symbol_index_type NOSYMBOL = {0, 0}; -static void +static bfd_boolean parse_expression (ieee_data_type *ieee, bfd_vma *value, ieee_symbol_index_type *symbol, @@ -530,68 +537,83 @@ parse_expression (ieee_data_type *ieee, { int section_n; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; *pcrel = TRUE; section_n = must_parse_int (&(ieee->h)); (void) section_n; PUSH (NOSYMBOL, bfd_abs_section_ptr, 0); break; } + case ieee_variable_L_enum: /* L variable address of section N. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0); break; + case ieee_variable_R_enum: /* R variable, logical address of section module. */ /* FIXME, this should be different to L. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0); break; + case ieee_variable_S_enum: /* S variable, size in MAUS of section module. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; PUSH (NOSYMBOL, 0, ieee->section_table[must_parse_int (&(ieee->h))]->size); break; + case ieee_variable_I_enum: /* Push the address of variable n. */ { ieee_symbol_index_type sy; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; sy.index = (int) must_parse_int (&(ieee->h)); sy.letter = 'I'; PUSH (sy, bfd_abs_section_ptr, 0); } break; + case ieee_variable_X_enum: /* Push the address of external variable n. */ { ieee_symbol_index_type sy; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; + sy.index = (int) (must_parse_int (&(ieee->h))); sy.letter = 'X'; PUSH (sy, bfd_und_section_ptr, 0); } break; + case ieee_function_minus_enum: { bfd_vma value1, value2; asection *section1, *section_dummy; ieee_symbol_index_type sy; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; POP (sy, section1, value1); POP (sy, section_dummy, value2); PUSH (sy, section1 ? section1 : section_dummy, value2 - value1); } break; + case ieee_function_plus_enum: { bfd_vma value1, value2; @@ -600,7 +622,8 @@ parse_expression (ieee_data_type *ieee, ieee_symbol_index_type sy1; ieee_symbol_index_type sy2; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; POP (sy1, section1, value1); POP (sy2, section2, value2); @@ -609,6 +632,7 @@ parse_expression (ieee_data_type *ieee, value1 + value2); } break; + default: { bfd_vma va; @@ -645,17 +669,9 @@ parse_expression (ieee_data_type *ieee, POP (*symbol, dummy, *value); if (section) *section = dummy; -} - -#define ieee_seek(ieee, offset) \ - do \ - { \ - ieee->h.input_p = ieee->h.first_byte + offset; \ - ieee->h.last_byte = (ieee->h.first_byte \ - + ieee_part_after (ieee, offset)); \ - } \ - while (0) + return TRUE; +} #define ieee_pos(ieee) \ (ieee->h.input_p - ieee->h.first_byte) @@ -677,6 +693,22 @@ ieee_part_after (ieee_data_type *ieee, f return after; } +static bfd_boolean +ieee_seek (ieee_data_type * ieee, file_ptr offset) +{ + /* PR 17512: file: 017-1157-0.004. */ + if (offset < 0 || (bfd_size_type) offset >= ieee->h.total_amt) + { + ieee->h.input_p = ieee->h.first_byte + ieee->h.total_amt; + ieee->h.last_byte = ieee->h.input_p; + return FALSE; + } + + ieee->h.input_p = ieee->h.first_byte + offset; + ieee->h.last_byte = (ieee->h.first_byte + ieee_part_after (ieee, offset)); + return TRUE; +} + static unsigned int last_index; static char last_type; /* Is the index for an X or a D. */ @@ -731,14 +763,16 @@ ieee_slurp_external_symbols (bfd *abfd) last_index = 0xffffff; ieee->symbol_table_full = TRUE; - ieee_seek (ieee, offset); + if (! ieee_seek (ieee, offset)) + return FALSE; while (loop) { switch (this_byte (&(ieee->h))) { case ieee_nn_record: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; symbol = get_symbol (abfd, ieee, symbol, &symbol_count, & prev_symbols_ptr, @@ -751,8 +785,10 @@ ieee_slurp_external_symbols (bfd *abfd) symbol->symbol.udata.p = NULL; symbol->symbol.flags = BSF_NO_FLAGS; break; + case ieee_external_symbol_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; symbol = get_symbol (abfd, ieee, symbol, &symbol_count, &prev_symbols_ptr, @@ -843,6 +879,7 @@ ieee_slurp_external_symbols (bfd *abfd) } } break; + case ieee_value_record_enum >> 8: { unsigned int symbol_name_index; @@ -850,17 +887,20 @@ ieee_slurp_external_symbols (bfd *abfd) bfd_boolean pcrel_ignore; unsigned int extra; - next_byte (&(ieee->h)); - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; + if (! next_byte (&(ieee->h))) + return FALSE; symbol_name_index = must_parse_int (&(ieee->h)); (void) symbol_name_index; - parse_expression (ieee, - &symbol->symbol.value, - &symbol_ignore, - &pcrel_ignore, - &extra, - &symbol->symbol.section); + if (! parse_expression (ieee, + &symbol->symbol.value, + &symbol_ignore, + &pcrel_ignore, + &extra, + &symbol->symbol.section)) + return FALSE; /* Fully linked IEEE-695 files tend to give every symbol an absolute value. Try to convert that back into a @@ -893,7 +933,9 @@ ieee_slurp_external_symbols (bfd *abfd) bfd_vma size; bfd_vma value; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; + /* Throw away the external reference index. */ (void) must_parse_int (&(ieee->h)); /* Fetch the default size if not resolved. */ @@ -908,7 +950,8 @@ ieee_slurp_external_symbols (bfd *abfd) break; case ieee_external_reference_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; symbol = get_symbol (abfd, ieee, symbol, &symbol_count, &prev_reference_ptr, @@ -1093,7 +1136,7 @@ get_section_entry (bfd *abfd, ieee_data_ return ieee->section_table[sindex]; } -static void +static bfd_boolean ieee_slurp_sections (bfd *abfd) { ieee_data_type *ieee = IEEE_DATA (abfd); @@ -1104,7 +1147,9 @@ ieee_slurp_sections (bfd *abfd) { bfd_byte section_type[3]; - ieee_seek (ieee, offset); + if (! ieee_seek (ieee, offset)) + return FALSE; + while (TRUE) { switch (this_byte (&(ieee->h))) @@ -1114,7 +1159,8 @@ ieee_slurp_sections (bfd *abfd) asection *section; unsigned int section_index; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section_index = must_parse_int (&(ieee->h)); section = get_section_entry (abfd, ieee, section_index); @@ -1133,22 +1179,26 @@ ieee_slurp_sections (bfd *abfd) { /* AS Absolute section attributes. */ case 0xD3: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section_type[2] = this_byte (&(ieee->h)); switch (section_type[2]) { case 0xD0: /* Normal code. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_CODE; break; case 0xC4: /* Normal data. */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_DATA; break; case 0xD2: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; /* Normal rom data. */ section->flags |= SEC_ROM | SEC_DATA; break; @@ -1165,15 +1215,18 @@ ieee_slurp_sections (bfd *abfd) switch (section_type[1]) { case 0xD0: /* Normal code (CP). */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_CODE; break; case 0xC4: /* Normal data (CD). */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_DATA; break; case 0xD2: /* Normal rom data (CR). */ - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section->flags |= SEC_ROM | SEC_DATA; break; default: @@ -1202,7 +1255,8 @@ ieee_slurp_sections (bfd *abfd) bfd_vma value; asection *section; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section_index = must_parse_int (&ieee->h); section = get_section_entry (abfd, ieee, section_index); if (section_index > ieee->section_count) @@ -1252,15 +1306,17 @@ ieee_slurp_sections (bfd *abfd) (void) must_parse_int (&(ieee->h)); break; default: - return; + return TRUE; } } break; default: - return; + return TRUE; } } } + + return TRUE; } /* Make a section for the debugging information, if any. We don't try @@ -1313,7 +1369,8 @@ ieee_archive_p (bfd *abfd) /* Ignore the return value here. It doesn't matter if we don't read the entire buffer. We might have a very small ieee file. */ - bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd); + if (bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd) <= 0) + goto got_wrong_format_error; ieee->h.first_byte = buffer; ieee->h.input_p = buffer; @@ -1323,7 +1380,8 @@ ieee_archive_p (bfd *abfd) if (this_byte (&(ieee->h)) != Module_Beginning) goto got_wrong_format_error; - next_byte (&(ieee->h)); + (void) next_byte (&(ieee->h)); + library = read_id (&(ieee->h)); if (strcmp (library, "LIBRARY") != 0) goto got_wrong_format_error; @@ -1334,7 +1392,7 @@ ieee_archive_p (bfd *abfd) ieee->element_count = 0; ieee->element_index = 0; - next_byte (&(ieee->h)); /* Drop the ad part. */ + (void) next_byte (&(ieee->h)); /* Drop the ad part. */ must_parse_int (&(ieee->h)); /* And the two dummy numbers. */ must_parse_int (&(ieee->h)); @@ -1407,8 +1465,9 @@ ieee_archive_p (bfd *abfd) ieee->h.first_byte = buffer; ieee->h.input_p = buffer; - next_byte (&(ieee->h)); /* Drop F8. */ - next_byte (&(ieee->h)); /* Drop 14. */ + (void) next_byte (&(ieee->h)); /* Drop F8. */ + if (! next_byte (&(ieee->h))) /* Drop 14. */ + goto error_return; must_parse_int (&(ieee->h)); /* Drop size of block. */ if (must_parse_int (&(ieee->h)) != 0) @@ -1467,7 +1526,8 @@ do_one (ieee_data_type *ieee, unsigned int number_of_maus; unsigned int i; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; number_of_maus = must_parse_int (&(ieee->h)); for (i = 0; i < number_of_maus; i++) @@ -1482,7 +1542,8 @@ do_one (ieee_data_type *ieee, { bfd_boolean loop = TRUE; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; while (loop) { switch (this_byte (&(ieee->h))) @@ -1505,13 +1566,16 @@ do_one (ieee_data_type *ieee, *(current_map->reloc_tail_ptr) = r; current_map->reloc_tail_ptr = &r->next; r->next = (ieee_reloc_type *) NULL; - next_byte (&(ieee->h)); -/* abort();*/ + if (! next_byte (&(ieee->h))) + return FALSE; + r->relent.sym_ptr_ptr = 0; - parse_expression (ieee, - &r->relent.addend, - &r->symbol, - &pcrel, &extra, §ion); + if (! parse_expression (ieee, + &r->relent.addend, + &r->symbol, + &pcrel, &extra, §ion)) + return FALSE; + r->relent.address = current_map->pc; s->flags |= SEC_RELOC; s->owner->flags |= HAS_RELOC; @@ -1521,7 +1585,8 @@ do_one (ieee_data_type *ieee, if (this_byte (&(ieee->h)) == (int) ieee_comma) { - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; /* Fetch number of bytes to pad. */ extra = must_parse_int (&(ieee->h)); }; @@ -1529,13 +1594,16 @@ do_one (ieee_data_type *ieee, switch (this_byte (&(ieee->h))) { case ieee_function_signed_close_b_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; break; case ieee_function_unsigned_close_b_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; break; case ieee_function_either_close_b_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; break; default: break; @@ -1634,7 +1702,8 @@ do_one (ieee_data_type *ieee, for (i = 0; i < this_size; i++) { location_ptr[current_map->pc++] = this_byte (&(ieee->h)); - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; } } else @@ -1667,7 +1736,9 @@ ieee_slurp_section_data (bfd *abfd) if (ieee->read_data) return TRUE; ieee->read_data = TRUE; - ieee_seek (ieee, ieee->w.r.data_part); + + if (! ieee_seek (ieee, ieee->w.r.data_part)) + return FALSE; /* Allocate enough space for all the section contents. */ for (s = abfd->sections; s != (asection *) NULL; s = s->next) @@ -1693,7 +1764,8 @@ ieee_slurp_section_data (bfd *abfd) return TRUE; case ieee_set_current_section_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; section_number = must_parse_int (&(ieee->h)); s = ieee->section_table[section_number]; s->flags |= SEC_LOAD | SEC_HAS_CONTENTS; @@ -1706,7 +1778,8 @@ ieee_slurp_section_data (bfd *abfd) break; case ieee_e2_first_byte_enum: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; switch (this_byte (&(ieee->h))) { case ieee_set_current_pc_enum & 0xff: @@ -1716,21 +1789,28 @@ ieee_slurp_section_data (bfd *abfd) unsigned int extra; bfd_boolean pcrel; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; must_parse_int (&(ieee->h)); /* Throw away section #. */ - parse_expression (ieee, &value, - &symbol, - &pcrel, &extra, - 0); + if (! parse_expression (ieee, &value, + &symbol, + &pcrel, &extra, + 0)) + return FALSE; + current_map->pc = value; BFD_ASSERT ((unsigned) (value - s->vma) <= s->size); } break; case ieee_value_starting_address_enum & 0xff: - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; if (this_byte (&(ieee->h)) == ieee_function_either_open_b_enum) - next_byte (&(ieee->h)); + { + if (! next_byte (&(ieee->h))) + return FALSE; + } abfd->start_address = must_parse_int (&(ieee->h)); /* We've got to the end of the data now - */ return TRUE; @@ -1748,7 +1828,8 @@ ieee_slurp_section_data (bfd *abfd) unsigned int iterations; unsigned char *start; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; iterations = must_parse_int (&(ieee->h)); start = ieee->h.input_p; if (start[0] == (int) ieee_load_constant_bytes_enum @@ -1759,9 +1840,10 @@ ieee_slurp_section_data (bfd *abfd) location_ptr[current_map->pc++] = start[2]; iterations--; } - next_byte (&(ieee->h)); - next_byte (&(ieee->h)); - next_byte (&(ieee->h)); + (void) next_byte (&(ieee->h)); + (void) next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + return FALSE; } else { @@ -1802,9 +1884,11 @@ ieee_object_p (bfd *abfd) goto fail; /* Read the first few bytes in to see if it makes sense. Ignore bfd_bread return value; The file might be very small. */ - bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd); + if (bfd_bread ((void *) buffer, (bfd_size_type) sizeof (buffer), abfd) <= 0) + goto got_wrong_format; ieee->h.input_p = buffer; + ieee->h.total_amt = sizeof (buffer); if (this_byte_and_next (&(ieee->h)) != Module_Beginning) goto got_wrong_format; @@ -1900,7 +1984,8 @@ ieee_object_p (bfd *abfd) if (this_byte (&(ieee->h)) != (int) ieee_address_descriptor_enum) goto fail; - next_byte (&(ieee->h)); + if (! next_byte (&(ieee->h))) + goto fail; if (! parse_int (&(ieee->h), &ieee->ad.number_of_bits_mau)) goto fail; @@ -1911,7 +1996,10 @@ ieee_object_p (bfd *abfd) /* If there is a byte order info, take it. */ if (this_byte (&(ieee->h)) == (int) ieee_variable_L_enum || this_byte (&(ieee->h)) == (int) ieee_variable_M_enum) - next_byte (&(ieee->h)); + { + if (! next_byte (&(ieee->h))) + goto fail; + } for (part = 0; part < N_W_VARIABLES; part++) { @@ -1942,12 +2030,17 @@ ieee_object_p (bfd *abfd) goto fail; if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) goto fail; + /* FIXME: Check return value. I'm not sure whether it needs to read the entire buffer or not. */ - bfd_bread ((void *) (IEEE_DATA (abfd)->h.first_byte), - (bfd_size_type) ieee->w.r.me_record + 1, abfd); + amt = bfd_bread ((void *) (IEEE_DATA (abfd)->h.first_byte), + (bfd_size_type) ieee->w.r.me_record + 1, abfd); + if (amt <= 0) + goto fail; - ieee_slurp_sections (abfd); + IEEE_DATA (abfd)->h.total_amt = amt; + if (ieee_slurp_sections (abfd)) + goto fail; if (! ieee_slurp_debug (abfd)) goto fail; Index: binutils-2.24/bfd/pei-x86_64.c =================================================================== --- binutils-2.24.orig/bfd/pei-x86_64.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/pei-x86_64.c 2014-12-01 16:31:37.000000000 +0100 @@ -311,6 +311,7 @@ pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma vsize; bfd_byte *data = NULL; bfd_vma end_addr; + bfd_size_type sec_size; if (!section) section = pex64_get_section_by_rva (abfd, addr, ".data"); @@ -329,13 +330,29 @@ pex64_dump_xdata (FILE *file, bfd *abfd, if (!section) return; + sec_size = section->rawsize > 0 ? section->rawsize : section->size; vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase; addr -= vsize; + /* 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] - vsize; + { + end_addr = endx[0] - vsize; + /* 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 = (section->rawsize != 0 ? section->rawsize : section->size); + end_addr = sec_size; if (bfd_malloc_and_get_section (abfd, section, &data)) { @@ -383,7 +400,11 @@ pex64_dump_xdata (FILE *file, bfd *abfd, ui.FrameRegister == 0 ? "none" : pex_regs[(unsigned int) ui.FrameRegister]); - pex64_xdata_print_uwd_codes (file, &ui, pc_addr); + /* PR 17512: file: 2245-7442-0.004. */ + if (ui.CountOfCodes * 2 + ui.rawUnwindCodes + addr >= data + section->size) + fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes); + else + pex64_xdata_print_uwd_codes (file, &ui, pc_addr); /* Now we need end of this xdata block. */ addr += ui.SizeOfBlock; @@ -439,6 +460,12 @@ pex64_bfd_print_pdata (bfd *abfd, void * return TRUE; stop = pei_section_data (abfd, section)->virt_size; + /* PR 17512: file: 005-181405-0.004. */ + if (stop == 0 || section->size == 0) + { + fprintf (file, _("No unwind data in .pdata section\n")); + return TRUE; + } if ((stop % onaline) != 0) fprintf (file, _("warning: .pdata section size (%ld) is not a multiple of %d\n"), @@ -469,6 +496,7 @@ pex64_bfd_print_pdata (bfd *abfd, void * if (i + PDATA_ROW_SIZE > stop) break; + pex64_get_runtime_function (abfd, &rf, &data[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 @@ -573,6 +601,7 @@ pex64_bfd_print_pdata (bfd *abfd, void * 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; Index: binutils-2.24/bfd/libieee.h =================================================================== --- binutils-2.24.orig/bfd/libieee.h 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/libieee.h 2014-12-01 16:31:37.000000000 +0100 @@ -67,6 +67,7 @@ typedef struct { unsigned char *input_p; unsigned char *first_byte; unsigned char *last_byte; + bfd_size_type total_amt; bfd *abfd; } common_header_type ; Index: binutils-2.24/bfd/mach-o.c =================================================================== --- binutils-2.24.orig/bfd/mach-o.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/mach-o.c 2014-12-01 16:31:37.000000000 +0100 @@ -1082,9 +1082,12 @@ bfd_mach_o_canonicalize_one_reloc (bfd * } else { + /* PR 17512: file: 006-2964-0.004. */ + if (num >= mdata->nsects) + return -1; + /* A section number. */ BFD_ASSERT (num != 0); - BFD_ASSERT (num <= mdata->nsects); sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr; /* For a symbol defined in section S, the addend (stored in the @@ -3073,10 +3076,8 @@ bfd_mach_o_read_symtab_symbols (bfd *abf unsigned long i; if (sym == NULL || sym->symbols) - { - /* Return now if there are no symbols or if already loaded. */ - return TRUE; - } + /* Return now if there are no symbols or if already loaded. */ + return TRUE; sym->symbols = bfd_alloc (abfd, sym->nsyms * sizeof (bfd_mach_o_asymbol)); @@ -3087,12 +3088,18 @@ bfd_mach_o_read_symtab_symbols (bfd *abf } if (!bfd_mach_o_read_symtab_strtab (abfd)) - return FALSE; + { + sym->symbols = NULL; + return FALSE; + } for (i = 0; i < sym->nsyms; i++) { if (!bfd_mach_o_read_symtab_symbol (abfd, sym, &sym->symbols[i], i)) - return FALSE; + { + sym->symbols = NULL; + return FALSE; + } } return TRUE; Index: binutils-2.24/bfd/versados.c =================================================================== --- binutils-2.24.orig/bfd/versados.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/versados.c 2014-12-01 16:31:37.000000000 +0100 @@ -431,7 +431,8 @@ process_otr (bfd *abfd, struct ext_otr * else { need_contents = 1; - if (dst_idx < esdid->section->size) + + if (esdid->section && dst_idx < esdid->section->size) if (pass == 2) { /* Absolute code, comes in 16 bit lumps. */ @@ -446,8 +447,15 @@ process_otr (bfd *abfd, struct ext_otr * if (!contents && need_contents) { - bfd_size_type size = esdid->section->size; - esdid->contents = bfd_alloc (abfd, size); + if (esdid->section) + { + bfd_size_type size; + + size = esdid->section->size; + esdid->contents = bfd_alloc (abfd, size); + } + else + esdid->contents = NULL; } } @@ -586,6 +594,13 @@ versados_object_p (bfd *abfd) return NULL; } + /* PR 17512: file: 726-2128-0.004. */ + if (len < 13) + { + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + if (bfd_bread (&ext.type, (bfd_size_type) len, abfd) != len) { if (bfd_get_error () != bfd_error_system_call) Index: binutils-2.24/bfd/vms-alpha.c =================================================================== --- binutils-2.24.orig/bfd/vms-alpha.c 2013-11-04 16:33:37.000000000 +0100 +++ binutils-2.24/bfd/vms-alpha.c 2014-12-01 16:31:37.000000000 +0100 @@ -364,9 +364,9 @@ struct vms_section_data_struct ((struct vms_section_data_struct *)sec->used_by_bfd) /* To be called from the debugger. */ -struct vms_private_data_struct *bfd_vms_get_data (bfd *abfd); +struct vms_private_data_struct *bfd_vms_get_data (bfd *); -static int vms_get_remaining_object_record (bfd *abfd, int read_so_far); +static int vms_get_remaining_object_record (bfd *, unsigned int); static bfd_boolean _bfd_vms_slurp_object_records (bfd * abfd); static void alpha_vms_add_fixup_lp (struct bfd_link_info *, bfd *, bfd *); static void alpha_vms_add_fixup_ca (struct bfd_link_info *, bfd *, bfd *); @@ -374,8 +374,8 @@ static void alpha_vms_add_fixup_qr (stru bfd_vma); static void alpha_vms_add_fixup_lr (struct bfd_link_info *, unsigned int, bfd_vma); -static void alpha_vms_add_lw_reloc (struct bfd_link_info *info); -static void alpha_vms_add_qw_reloc (struct bfd_link_info *info); +static void alpha_vms_add_lw_reloc (struct bfd_link_info *); +static void alpha_vms_add_qw_reloc (struct bfd_link_info *); struct vector_type { @@ -788,7 +788,7 @@ _bfd_vms_get_object_record (bfd *abfd) Return the size of the record or 0 on failure. */ static int -vms_get_remaining_object_record (bfd *abfd, int read_so_far) +vms_get_remaining_object_record (bfd *abfd, unsigned int read_so_far) { unsigned int to_read; @@ -824,7 +824,10 @@ vms_get_remaining_object_record (bfd *ab return 0; PRIV (recrd.buf_size) = to_read; } - + /* PR 17512: file: 025-1974-0.004. */ + else if (to_read <= read_so_far) + return 0; + /* Read the remaining record. */ to_read -= read_so_far;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor