This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA] Fix gdb/15827 (crash w/corrupt DWARF)
- From: Keith Seitz <keiths at redhat dot com>
- To: "gdb-patches at sourceware dot org ml" <gdb-patches at sourceware dot org>
- Date: Fri, 21 Mar 2014 09:48:13 -0700
- Subject: [RFA] Fix gdb/15827 (crash w/corrupt DWARF)
- Authentication-results: sourceware.org; auth=none
Hi,
I think most of us know that the dwarf2read.c pretty much assumes that
the DWARF input is okay. The reporter of this bug used a binary fuzzer
to corrupt the DWARF info:
<1><569>: Abbrev Number: 16 (DW_TAG_enumeration_type)
<56a> DW_AT_byte_size : 4
<56b> DW_AT_decl_file : 17
<56c> DW_AT_decl_line : 73
<56d> DW_AT_sibling : <0xb12>
<2><571>: Abbrev Number: 17 (DW_TAG_enumerator)
<572> DW_AT_name : (indirect string, offset: 0xf14):
_SC_ARG_MAX
<576> DW_AT_const_value : 0
[snip]
<2><a8c>: Abbrev Number: 17 (DW_TAG_enumerator)
<a8d> DW_AT_name : (indirect string, offset: 0x9b7):
_SC_LEVEL3_CACHE_ASSOC
<a91> DW_AT_const_value : 2243
<2><a93>: Abbrev Number: 12 (DW_TAG_array_type)
<a94> DW_AT_type : <0x114>
<a98> DW_AT_sibling : <0x761101c4>
<3><a9c>: Abbrev Number: 10 (DW_TAG_member)
<a9d> DW_AT_name : (indirect string, offset: 0x1c50000):
<offset is
too big>
<aa1> DW_AT_decl_file : 17
<aa2> DW_AT_decl_line : 2539
<aa4> DW_AT_type : <0x1c60000>
<aa8> DW_AT_data_member_location: 17
As you can see, the sibling for DIE 0xa93 points of to la-la land. This
causes skip_one_die to crash, since it never validates whether the
offset of the sibling is contained within the current readers's input
buffer. This function does check, however, whether the offset is negative.
This patch essentially adds the counterpoint check and a beginning at
some tests for catch-all "corrupt" DWARF.
Keith
ChangeLog
2014-03-20 Keith Seitz <keiths@redhat.com>
PR gdb/15827
* dwarf2read.c (skip_one_die): Check that all relative-offset
sibling DIEs fall within range of the current reader's buffer.
(read_partial_die): Likewise.
testsuite/ChangeLog
2014-03-20 Keith Seitz <keiths@redhat.com>
PR gdb/15827
* gdb.dwarf2/corrupt.c: New file.
* gdb.dwarf2/corrupt.exp: New file.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 705dc2d..c30b1b3 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7103,6 +7103,8 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
if (sibling_ptr < info_ptr)
complaint (&symfile_complaints,
_("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ dwarf2_section_buffer_overflow_complaint (reader->die_section);
else
return sibling_ptr;
}
@@ -15416,6 +15418,8 @@ read_partial_die (const struct die_reader_specs *reader,
if (sibling_ptr < info_ptr)
complaint (&symfile_complaints,
_("DW_AT_sibling points backwards"));
+ else if (sibling_ptr > reader->buffer_end)
+ dwarf2_section_buffer_overflow_complaint (reader->die_section);
else
part_die->sibling = sibling_ptr;
}
diff --git a/gdb/testsuite/gdb.dwarf2/corrupt.c b/gdb/testsuite/gdb.dwarf2/corrupt.c
new file mode 100644
index 0000000..4120f3d
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/corrupt.c
@@ -0,0 +1,24 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* Dummy main function. */
+
+int
+main()
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/corrupt.exp b/gdb/testsuite/gdb.dwarf2/corrupt.exp
new file mode 100644
index 0000000..ba5e551
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/corrupt.exp
@@ -0,0 +1,78 @@
+# Copyright 2014 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test corrupt DWARF input
+# PR gdb/15827
+
+load_lib dwarf.exp
+
+if {![dwarf2_support]} {
+ return 0
+}
+
+standard_testfile corrupt.c corrupt.S
+
+# Make the DWARF used for the test.
+#
+# Here we put DW_AT_sibling DIEs into the output which
+# point off into la-la land. The whole purpose is to simulate
+# corrupt DWARF information and make sure that GDB can handle it
+# without crashing.
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ cu {} {
+ compile_unit {} {
+ declare_labels int_label
+
+ int_label: base_type {
+ {byte_size 4}
+ {name "int"}
+ }
+
+ enumeration_type {
+ {name "ENUM"}
+ {byte_size 4}
+ } {
+ enumerator {
+ {name "A"}
+ {const_value 0}
+ }
+ enumerator {
+ {name "B"}
+ {const_value 1}
+ {sibling 12345678 DW_FORM_ref4}
+ } {
+ base_type {
+ {byte_size 1}
+ {name "char"}
+ }
+ }
+ array_type {
+ {type :$int_label}
+ {sibling 12345678 DW_FORM_ref4}
+ }
+ }
+ }
+ }
+}
+
+if {[prepare_for_testing $testfile.exp $testfile \
+ [list $srcfile $asm_file] {nodebug}]} {
+ return -1
+}
+
+# If we get here and gdb hasn't crashed, the tests pass.
+pass "corrupt DWARF"