gdb: Guard against NULL dereference in dwarf2_init_integer_type
authorAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 6 Nov 2018 19:55:21 +0000 (19:55 +0000)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 7 Nov 2018 12:58:56 +0000 (12:58 +0000)
In this commit:

    commit eb77c9df9f6d2f7aa644a170280fe31ce080f887
    Date:   Thu Oct 18 14:04:27 2018 +0100

        gdb: Handle ICC's unexpected void return type

A potential dereference of a NULL pointer was introduced if a
DW_TAG_base_type is missing a DW_AT_name attribute.

I have taken this opportunity to fix a slight confusion that existed
in the test also added in the above commit, the test had two C
variables, declared like this:

    int var_a = 5;

    void *var_ptr = &var_a;

However, the fake DWARF in the test script declared them like this:

    void var_a = 5;

    void *var_ptr = &var_a;

This wasn't a problem as the test never uses 'var_a' directly, this
only exists so 'var_ptr' can be initialised.  However, it seemed worth
fixing.

I've also added a test for a DW_TAG_base_type with a missing
DW_AT_name, as clearly there's not test currently that covers this
(the original patch tested cleanly).  I can confirm that the new test
causes GDB to crash before this patch, and passes with this patch.

gdb/ChangeLog:

* dwarf2read.c (dwarf2_init_integer_type): Check for name being
NULL before dereferencing it.

gdb/testsuite/ChangeLog:

* gdb.dwarf2/void-type.exp: Rename types, and make var_a an 'int'.
* gdb.dwarf2/missing-type-name.exp: New file.

gdb/ChangeLog
gdb/dwarf2read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.dwarf2/missing-type-name.exp [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/void-type.exp

index 92a69c3ad34f01fda790f5dcd952fa60c9831413..f7d1de52270f0fe0af88a76d894f8cef6b15b230 100644 (file)
@@ -1,3 +1,8 @@
+2018-11-07  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * dwarf2read.c (dwarf2_init_integer_type): Check for name being
+       NULL before dereferencing it.
+
 2018-11-06  Tom de Vries  <tdevries@suse.de>
 
        * linux-tdep.c (linux_vsyscall_range_raw): Use xmalloc to allocate
index b237c81fe4f01ba37d02864a0cdc860376ea00ba..d2a8cd44f9a5513ef9f55481967beffdd99aa3a4 100644 (file)
@@ -17522,7 +17522,8 @@ dwarf2_init_integer_type (struct dwarf2_cu *cu, struct objfile *objfile,
   /* Versions of Intel's C Compiler generate an integer type called "void"
      instead of using DW_TAG_unspecified_type.  This has been seen on
      at least versions 14, 17, and 18.  */
-  if (bits == 0 && producer_is_icc (cu) && strcmp (name, "void") == 0)
+  if (bits == 0 && producer_is_icc (cu) && name != nullptr
+      && strcmp (name, "void") == 0)
     type = objfile_type (objfile)->builtin_void;
   else
     type = init_integer_type (objfile, bits, unsigned_p, name);
index b52819069d8574c27a84741f239cd76f03fed3a1..eaed8d75bbdd9110577a5cb7c317a9623fa30ecd 100644 (file)
@@ -1,3 +1,8 @@
+2018-11-07  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.dwarf2/void-type.exp: Rename types, and make var_a an 'int'.
+       * gdb.dwarf2/missing-type-name.exp: New file.
+
 2018-11-06  Tom de Vries  <tdevries@suse.de>
 
        * gdb.base/many-headers.c: New test.
diff --git a/gdb/testsuite/gdb.dwarf2/missing-type-name.exp b/gdb/testsuite/gdb.dwarf2/missing-type-name.exp
new file mode 100644 (file)
index 0000000..62d46e4
--- /dev/null
@@ -0,0 +1,123 @@
+# Copyright 2018 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/>.
+
+# This tests some non-standard DWARF that we still expect GDB to be
+# able to handle.
+#
+# The DWARF standard (v5 5.1) says this:
+#
+#     A base type is represented by a debugging information entry with
+#     the tag DW_TAG_base_type.
+#
+#     A base type entry may have a DW_AT_name attribute whose value is
+#     a null-terminated string containing the name of the base type as
+#     recognized by the programming language of the compilation unit
+#     containing the base type entry.
+#
+# So the DW_AT_name field for a DW_TAG_base_type is optional.  This
+# test provides some basic checking that GDB doesn't crash when
+# presented with this situation.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+    return 0
+}
+
+standard_testfile void-type.c void-type.S
+
+# Make some DWARF for the test.
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    global srcdir subdir srcfile
+
+    set func_result [function_range func ${srcdir}/${subdir}/${srcfile}]
+    set func_start [lindex $func_result 0]
+    set func_length [lindex $func_result 1]
+
+    set main_result [function_range main ${srcdir}/${subdir}/${srcfile}]
+    set main_start [lindex $main_result 0]
+    set main_length [lindex $main_result 1]
+
+    cu {} {
+       DW_TAG_compile_unit {
+               {DW_AT_producer "GNU C 8.1"}
+                {DW_AT_language @DW_LANG_C}
+                {DW_AT_name     void-type.c}
+                {DW_AT_comp_dir /tmp}
+        } {
+           declare_labels main_type int_type ptr_type
+
+           main_type: DW_TAG_base_type {
+               {DW_AT_byte_size 4 DW_FORM_sdata}
+               {DW_AT_encoding  @DW_ATE_signed}
+           }
+
+           int_type: DW_TAG_base_type {
+               {DW_AT_byte_size 0 DW_FORM_sdata}
+               {DW_AT_encoding  @DW_ATE_signed}
+           }
+
+           ptr_type: DW_TAG_pointer_type {
+               {DW_AT_type :$int_type}
+           }
+
+            DW_TAG_subprogram {
+                {name func}
+                {low_pc $func_start addr}
+                {high_pc "$func_start + $func_length" addr}
+                {type :$int_type}
+           }
+            DW_TAG_subprogram {
+                {name main}
+                {low_pc $main_start addr}
+                {high_pc "$main_start + $main_length" addr}
+                {type :$main_type}
+           }
+
+           DW_TAG_variable {
+               {DW_AT_name "var_a"}
+               {DW_AT_type :$main_type}
+               {DW_AT_external 1 DW_FORM_flag}
+               {DW_AT_location {DW_OP_addr [gdb_target_symbol "var_a"]} SPECIAL_expr}
+           }
+
+           DW_TAG_variable {
+               {DW_AT_name "var_ptr"}
+               {DW_AT_type :$ptr_type}
+               {DW_AT_external 1 DW_FORM_flag}
+               {DW_AT_location {DW_OP_addr [gdb_target_symbol "var_ptr"]} SPECIAL_expr}
+           }
+       }
+    }
+}
+
+if { [prepare_for_testing "failed to prepare" ${testfile} \
+         [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+# Use 'ptype' on two variables that are using DW_TAG_base_type types
+# with missing DW_AT_name attributes.
+gdb_test "ptype var_ptr" "type = <invalid type code $decimal> \\*" \
+    "ptype of a pointer to a basic type with missing name"
+
+gdb_test "ptype var_a" "type = <invalid type code $decimal>" \
+    "ptype of a variable that is a basic type with a missing name"
index 3691bff77925a3049d4d53d341947fbdad39c0e2..4367eee8c516aad576f209a001ad304ca8dd5a4b 100644 (file)
@@ -53,35 +53,35 @@ Dwarf::assemble $asm_file {
                 {DW_AT_name     void-type.c}
                 {DW_AT_comp_dir /tmp}
         } {
-           declare_labels main_type int_type ptr_type
+           declare_labels int_type void_type ptr_type
 
-           main_type: DW_TAG_base_type {
+           int_type: DW_TAG_base_type {
                {DW_AT_byte_size 4 DW_FORM_sdata}
                {DW_AT_encoding  @DW_ATE_signed}
                {DW_AT_name      int}
            }
 
-           int_type: DW_TAG_base_type {
+           void_type: DW_TAG_base_type {
                {DW_AT_byte_size 0 DW_FORM_sdata}
                {DW_AT_encoding  @DW_ATE_signed}
                {DW_AT_name      void}
            }
 
            ptr_type: DW_TAG_pointer_type {
-               {DW_AT_type :$int_type}
+               {DW_AT_type :$void_type}
            }
 
             DW_TAG_subprogram {
                 {name func}
                 {low_pc $func_start addr}
                 {high_pc "$func_start + $func_length" addr}
-                {type :$int_type}
+                {type :$void_type}
            }
             DW_TAG_subprogram {
                 {name main}
                 {low_pc $main_start addr}
                 {high_pc "$main_start + $main_length" addr}
-                {type :$main_type}
+                {type :$int_type}
            }
 
            DW_TAG_variable {