From 315350be6598235df12a0190a5a4c21447eead36 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 9 May 2016 17:31:07 +0100 Subject: Fix seg fault objdumping a corrupt binary with an invalid sh_link field. PR binutils/20063 * elf.c (bfd_elf_get_elf_syms): Check for out of range sh_link field before accessing sections array. * readelf.c (get_32bit_section_headers): Warn if an out of range sh_link or sh_info field is encountered. (get_64bit_section_headers): Likewise. --- bfd/ChangeLog | 6 ++++++ bfd/elf.c | 16 +++++++++++----- binutils/ChangeLog | 7 +++++++ binutils/readelf.c | 8 ++++++++ 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index d5edec4..29dad01 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2016-05-09 Nick Clifton + + PR binutils/20063 + * elf.c (bfd_elf_get_elf_syms): Check for out of range sh_link + field before accessing sections array. + 2016-05-09 Christophe Monat PR ld/20030 diff --git a/bfd/elf.c b/bfd/elf.c index 4be7d73..1592183 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -407,11 +407,17 @@ bfd_elf_get_elf_syms (bfd *ibfd, /* Find an index section that is linked to this symtab section. */ for (entry = elf_symtab_shndx_list (ibfd); entry != NULL; entry = entry->next) - if (sections[entry->hdr.sh_link] == symtab_hdr) - { - shndx_hdr = & entry->hdr; - break; - }; + { + /* PR 20063. */ + if (entry->hdr.sh_link >= elf_numsections (ibfd)) + continue; + + if (sections[entry->hdr.sh_link] == symtab_hdr) + { + shndx_hdr = & entry->hdr; + break; + }; + } if (shndx_hdr == NULL) { diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 12e8bb2..89ebe15 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2016-05-09 Nick Clifton + + PR binutils/20063 + * readelf.c (get_32bit_section_headers): Warn if an out of range + sh_link or sh_info field is encountered. + (get_64bit_section_headers): Likewise. + 2016-05-04 Senthil Kumar Selvaraj * testsuite/lib/binutils-common.exp (is_elf_format): Add avr-*-*. diff --git a/binutils/readelf.c b/binutils/readelf.c index 3d31b38..13e7751 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -5059,6 +5059,10 @@ get_32bit_section_headers (FILE * file, bfd_boolean probe) internal->sh_info = BYTE_GET (shdrs[i].sh_info); internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize); + if (!probe && internal->sh_link > num) + warn (_("Section %u has an out of range sh_link value of %u\n"), i, internal->sh_link); + if (!probe && internal->sh_flags & SHF_INFO_LINK && internal->sh_info > num) + warn (_("Section %u has an out of range sh_info value of %u\n"), i, internal->sh_info); } free (shdrs); @@ -5117,6 +5121,10 @@ get_64bit_section_headers (FILE * file, bfd_boolean probe) internal->sh_info = BYTE_GET (shdrs[i].sh_info); internal->sh_offset = BYTE_GET (shdrs[i].sh_offset); internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); + if (!probe && internal->sh_link > num) + warn (_("Section %u has an out of range sh_link value of %u\n"), i, internal->sh_link); + if (!probe && internal->sh_flags & SHF_INFO_LINK && internal->sh_info > num) + warn (_("Section %u has an out of range sh_info value of %u\n"), i, internal->sh_info); } free (shdrs); -- cgit v1.1