PR ld/13962
authorAlan Modra <amodra@gmail.com>
Wed, 16 May 2012 03:35:29 +0000 (03:35 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 16 May 2012 03:35:29 +0000 (03:35 +0000)
  PR ld/7023
* elf.c (bfd_section_from_shdr): Fail when .dynsym sh_info is
out of range.  As a special case, fix sh_info for zero sh_size.
Do the same for .symtab.

bfd/ChangeLog
bfd/elf.c

index 05bc0de6809741092fc5c51efac770f11277edc9..34bee4f160866225df36b5b4b608b0a7c182980c 100644 (file)
@@ -1,3 +1,11 @@
+2012-05-16  Alan Modra  <amodra@gmail.com>
+
+       PR ld/13962
+       PR ld/7023
+       * elf.c (bfd_section_from_shdr): Fail when .dynsym sh_info is
+       out of range.  As a special case, fix sh_info for zero sh_size.
+       Do the same for .symtab.
+
 2012-05-15  James Murray <jsm@jsm-net.demon.co.uk>
            Stephane Carrez <stcarrez@nerim.fr>
 
index 9481c0e1d5692d430426224286440c36e2d39007..7acf1422e5d0f47d92561f424046db98a6d6f2b8 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1646,7 +1646,15 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       if (hdr->sh_entsize != bed->s->sizeof_sym)
        return FALSE;
       if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
-       return FALSE;
+       {
+         if (hdr->sh_size != 0)
+           return FALSE;
+         /* 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;
+       }
       BFD_ASSERT (elf_onesymtab (abfd) == 0);
       elf_onesymtab (abfd) = shindex;
       elf_tdata (abfd)->symtab_hdr = *hdr;
@@ -1699,6 +1707,16 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 
       if (hdr->sh_entsize != bed->s->sizeof_sym)
        return FALSE;
+      if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
+       {
+         if (hdr->sh_size != 0)
+           return FALSE;
+         /* 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;
+       }
       BFD_ASSERT (elf_dynsymtab (abfd) == 0);
       elf_dynsymtab (abfd) = shindex;
       elf_tdata (abfd)->dynsymtab_hdr = *hdr;