From b9502d3fd7848cd4d843be8bdc28633a3d24438d Mon Sep 17 00:00:00 2001 From: Will Newton Date: Fri, 1 Nov 2013 14:14:50 -0700 Subject: [PATCH] gdb/dwarf2read.c: Sanity check DW_AT_sibling values. 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 PR gdb/12866 * dwarf2read.c (skip_one_die): Sanity check DW_AT_sibling values. (read_partial_die): Likewise. --- gdb/ChangeLog | 6 ++++++ gdb/dwarf2read.c | 22 ++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e721f029d99..45f92e8210e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2013-11-06 Will Newton + + PR gdb/12866 + * dwarf2read.c (skip_one_die): Sanity check DW_AT_sibling + values. (read_partial_die): Likewise. + 2013-11-06 Muhammad Bilal PR cli/16122 diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 3974d0b2f8a..bc8e8ca6966 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; -- 2.30.2