[v2] gdb/dwarf2read.c: Sanity check DW_AT_sibling values.

Message ID 527A0AB0.6070904@linaro.org
State Accepted
Headers show

Commit Message

Will Newton Nov. 6, 2013, 9:24 a.m.
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-01  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/dwarf2read.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

Changes in v2:
 - Wrap over long lines

Comments

Tom Tromey Nov. 6, 2013, 3:04 p.m. | #1
>>>>> "Will" == Will Newton <will.newton@linaro.org> writes:

Will> 2013-11-01  Will Newton  <will.newton@linaro.org>
Will> 	PR gdb/12866
Will> 	* dwarf2read.c (skip_one_die): Sanity check DW_AT_sibling
Will> 	values.  (read_partial_die): Likewise.

This is ok.
Thanks again.

Tom

Patch

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 3974d0b..bc8e8ca 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -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;