]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Fix seg-fault in readelf when scanniing a corrupt binary.
authorNick Clifton <nickc@redhat.com>
Thu, 3 Sep 2015 15:15:49 +0000 (16:15 +0100)
committerNick Clifton <nickc@redhat.com>
Thu, 3 Sep 2015 15:15:49 +0000 (16:15 +0100)
PR binutils/18879
* readelf.c (get_unwind_section_word): Check for negative offsets
and very small sections.
(dump_arm_unwind): Warn if the table offset is too large.

binutils/ChangeLog
binutils/readelf.c

index c2406dab9ebd24bc3e1f20f9a9372e5d064e5518..ae9c9955c2a332ef06b7e1e8e841c8a1ce25f53a 100644 (file)
@@ -1,3 +1,10 @@
+2015-09-03  Nick Clifton  <nickc@redhat.com>
+
+       PR binutils/18879
+       * readelf.c (get_unwind_section_word): Check for negative offsets
+       and very small sections.
+       (dump_arm_unwind): Warn if the table offset is too large.
+
 2015-08-28  H.J. Lu  <hongjiu.lu@intel.com>
 
        * Makefile.am (TOOL_PROGS): Add readelf.
index 6298f1e29d8a298010078a7d1b23a9a0a5fa1519..12fb415eee77db6ff8ec012047bc378336ea41d6 100644 (file)
@@ -7518,7 +7518,10 @@ get_unwind_section_word (struct arm_unw_aux_info *  aux,
     return FALSE;
 
   /* If the offset is invalid then fail.  */
-  if (word_offset > sec->sh_size - 4)
+  if (word_offset > (sec->sh_size - 4)
+      /* PR 18879 */
+      || (sec->sh_size < 5 && word_offset >= sec->sh_size)
+      || ((bfd_signed_vma) word_offset) < 0)
     return FALSE;
 
   /* Get the word at the required offset.  */
@@ -8301,6 +8304,15 @@ dump_arm_unwind (struct arm_unw_aux_info *aux, Elf_Internal_Shdr *exidx_sec)
            {
              table_sec = section_headers + entry_addr.section;
              table_offset = entry_addr.offset;
+             /* PR 18879 */
+             if (table_offset > table_sec->sh_size
+                 || ((bfd_signed_vma) table_offset) < 0)
+               {
+                 warn (_("Unwind entry contains corrupt offset (0x%lx) into section %s\n"),
+                       (unsigned long) table_offset,
+                       printable_section_name (table_sec));
+                 continue;
+               }
            }
          else
            {