Fix seg fault objdumping a corrupt binary with an invalid sh_link field.
authorNick Clifton <nickc@redhat.com>
Mon, 9 May 2016 16:31:07 +0000 (17:31 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 9 May 2016 16:31:07 +0000 (17:31 +0100)
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
bfd/elf.c
binutils/ChangeLog
binutils/readelf.c

index d5edec4588541e9a7bad375b5f131e75fae19a2d..29dad0121d336301a53544ea1f13f251a68dcde5 100644 (file)
@@ -1,3 +1,9 @@
+2016-05-09  Nick Clifton  <nickc@redhat.com>
+
+       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  <christophe.monat@st.com>
 
        PR ld/20030
index 4be7d73973925082a997a5994ecad9a31a53913b..1592183fae7f0990589dcf0bd2489ceb5a04cc0a 100644 (file)
--- 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)
        {
index 12e8bb2dac4a9f039682608f1a6da9af6c437937..89ebe1573ff4ee9f76ac3ef9c1d0969f2975e380 100644 (file)
@@ -1,3 +1,10 @@
+2016-05-09  Nick Clifton  <nickc@redhat.com>
+
+       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  <senthil_kumar.selvaraj@atmel.com>
 
        * testsuite/lib/binutils-common.exp (is_elf_format): Add avr-*-*.
index 3d31b38bf38d38236c15a5bfd5268ee0caa21f6d..13e7751c8edd3fcfacaac8d54bcdb6e5447b7ae6 100644 (file)
@@ -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);