gdb/dwarf2read.c: Sanity check DW_AT_sibling values.
authorWill Newton <will.newton@linaro.org>
Fri, 1 Nov 2013 21:14:50 +0000 (14:14 -0700)
committerWill Newton <will.newton@linaro.org>
Wed, 6 Nov 2013 15:15:12 +0000 (15:15 +0000)
When reading objects with corrupt debug information it is possible that
the sibling chain can form a loop, which leads to an infinite loop and
memory exhaustion.

Avoid this situation by disregarding and DW_AT_sibling values that point
to a lower address than the current entry.

gdb/ChangeLog:

2013-11-06  Will Newton  <will.newton@linaro.org>

PR gdb/12866
* dwarf2read.c (skip_one_die): Sanity check DW_AT_sibling
values.  (read_partial_die): Likewise.

gdb/ChangeLog
gdb/dwarf2read.c

index e721f02..45f92e8 100644 (file)
@@ -1,3 +1,9 @@
+2013-11-06  Will Newton  <will.newton@linaro.org>
+
+       PR gdb/12866
+       * dwarf2read.c (skip_one_die): Sanity check DW_AT_sibling
+       values.  (read_partial_die): Likewise.
+
 2013-11-06  Muhammad Bilal  <mbilal@codesourcery.com>
 
        PR cli/16122
index 3974d0b..bc8e8ca 100644 (file)
@@ -7016,7 +7016,16 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
            complaint (&symfile_complaints,
                       _("ignoring absolute DW_AT_sibling"));
          else
-           return buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
+           {
+             unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
+             const gdb_byte *sibling_ptr = buffer + off;
+
+             if (sibling_ptr < info_ptr)
+               complaint (&symfile_complaints,
+                          _("DW_AT_sibling points backwards"));
+             else
+               return sibling_ptr;
+           }
        }
 
       /* If it isn't DW_AT_sibling, skip this attribute.  */
@@ -15134,7 +15143,16 @@ read_partial_die (const struct die_reader_specs *reader,
            complaint (&symfile_complaints,
                       _("ignoring absolute DW_AT_sibling"));
          else
-           part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
+           {
+             unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
+             const gdb_byte *sibling_ptr = buffer + off;
+
+             if (sibling_ptr < info_ptr)
+               complaint (&symfile_complaints,
+                          _("DW_AT_sibling points backwards"));
+             else
+               part_die->sibling = sibling_ptr;
+           }
          break;
         case DW_AT_byte_size:
           part_die->has_byte_size = 1;