This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix segfault with 'set print object on' + 'whatis <struct>' & co


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5c319bb260fa9637048cfae5fceba807e7849b39

commit 5c319bb260fa9637048cfae5fceba807e7849b39
Author: Pedro Alves <palves@redhat.com>
Date:   Mon Jan 22 17:33:13 2018 +0000

    Fix segfault with 'set print object on' + 'whatis <struct>' & co
    
    Compiling GDB with a recent GCC exposes a problem:
    
      ../../gdb/typeprint.c: In function 'void whatis_exp(const char*, int)':
      ../../gdb/typeprint.c:515:12: warning: 'val' may be used uninitialized in this function [-Wmaybe-uninitialized]
        real_type = value_rtti_type (val, &full, &top, &using_enc);
        ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    The warning is correct.  There are indeed code paths that use
    uninitialized 'val', leading to crashes.  Inside the
    value_rtti_indirect_type/value_rtti_type calls here in whatis_exp:
    
      if (opts.objectprint)
        {
          if (((TYPE_CODE (type) == TYPE_CODE_PTR) || TYPE_IS_REFERENCE (type))
    	  && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT))
            real_type = value_rtti_indirect_type (val, &full, &top, &using_enc);
          else if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
    	real_type = value_rtti_type (val, &full, &top, &using_enc);
        }
    
    We reach those calls above with "set print object on", and then with
    any of:
    
      (gdb) whatis struct some_structure_type
      (gdb) whatis struct some_structure_type *
      (gdb) whatis struct some_structure_type &
    
    because "whatis" with a type argument enters this branch:
    
          /* The behavior of "whatis" depends on whether the user
    	 expression names a type directly, or a language expression
    	 (including variable names).  If the former, then "whatis"
    	 strips one level of typedefs, only.  If an expression,
    	 "whatis" prints the type of the expression without stripping
    	 any typedef level.  "ptype" always strips all levels of
    	 typedefs.  */
          if (show == -1 && expr->elts[0].opcode == OP_TYPE)
    	{
    
    which does not initialize VAL.  Trying the above triggers crashes like
    this:
    
      (gdb) set print object on
      (gdb) whatis some_structure_type
    
      Thread 1 "gdb" received signal SIGSEGV, Segmentation fault.
      0x00000000005dda90 in check_typedef (type=0x6120736573756170) at src/gdb/gdbtypes.c:2388
      2388      int instance_flags = TYPE_INSTANCE_FLAGS (type);
      ...
    
    This is a regression caused by a recent-ish refactoring of the code on
    'whatis_exp', introduced by:
    
      commit c973d0aa4a2c737ab527ae44a617f1c357e07364
      Date:   Mon Aug 21 11:34:32 2017 +0100
    
          Fix type casts losing typedefs and reimplement "whatis" typedef stripping
    
    Fix this by setting VAL to NULL in the "whatis TYPE" case, and
    skipping fetching the dynamic type if there's no value to fetch it
    from.
    
    New tests included.
    
    gdb/ChangeLog:
    2018-01-22  Pedro Alves  <palves@redhat.com>
    	    Sergio Durigan Junior  <sergiodj@redhat.com>
    
    	* typeprint.c (whatis_exp): Initialize "val" in the "whatis type"
    	case.
    
    gdb/testsuite/ChangeLog:
    2018-01-22  Pedro Alves  <palves@redhat.com>
    	    Sergio Durigan Junior  <sergiodj@redhat.com>
    
    	* gdb.base/whatis.exp: Add tests for 'set print object on' +
    	'whatis <struct>' 'whatis <struct> *' and 'whatis <struct> &'.

Diff:
---
 gdb/ChangeLog                     |  6 ++++++
 gdb/testsuite/ChangeLog           |  6 ++++++
 gdb/testsuite/gdb.base/whatis.exp | 25 +++++++++++++++++++++----
 gdb/typeprint.c                   |  6 +++++-
 4 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 77914bc..b1e9f9f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2018-01-22  Pedro Alves  <palves@redhat.com>
+	    Sergio Durigan Junior  <sergiodj@redhat.com>
+
+	* typeprint.c (whatis_exp): Initialize "val" in the "whatis type"
+	case.
+
 2018-01-22  Maciej W. Rozycki  <macro@mips.com>
 
 	* MAINTAINERS: Update my company e-mail address.
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index f9fe3ab..0f02f4a 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2018-01-22  Pedro Alves  <palves@redhat.com>
+	    Sergio Durigan Junior  <sergiodj@redhat.com>
+
+	* gdb.base/whatis.exp: Add tests for 'set print object on' +
+	'whatis <struct>' 'whatis <struct> *' and 'whatis <struct> &'.
+
 2018-01-22  Joel Brobecker  <brobecker@adacore.com>
 
 	* gdb.base/break-include.c, gdb.base/break-include.inc,
diff --git a/gdb/testsuite/gdb.base/whatis.exp b/gdb/testsuite/gdb.base/whatis.exp
index dd6aeb0..509183e 100644
--- a/gdb/testsuite/gdb.base/whatis.exp
+++ b/gdb/testsuite/gdb.base/whatis.exp
@@ -282,14 +282,31 @@ gdb_test "whatis v_double_pointer" \
 
 
 # test whatis command with structure types
+
+# First with a type argument, with both "set print object" set to "on"
+# and "off", ending with "off" for the following tests.
+foreach_with_prefix print_object {"on" "off"} {
+    gdb_test_no_output "set print object $print_object"
+
+    gdb_test "whatis struct t_struct" \
+	"type = struct t_struct" \
+	"whatis named structure using type name"
+
+    gdb_test "whatis struct t_struct *" \
+	"type = struct t_struct \\*" \
+	"whatis named structure using type name and pointer"
+
+    gdb_test "whatis struct t_struct &" \
+	"type = struct t_struct &" \
+	"whatis named structure using type name and reference"
+}
+
+# Now with an expression argument.
+
 gdb_test "whatis v_struct1" \
     "type = struct t_struct" \
     "whatis named structure"
 
-gdb_test "whatis struct t_struct" \
-    "type = struct t_struct" \
-    "whatis named structure using type name"
-
 gdb_test "whatis v_struct2" \
     "type = struct \{\.\.\.\}" \
     "whatis unnamed structure"
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index 9a12507..c098a3f 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -489,6 +489,10 @@ whatis_exp (const char *exp, int show)
 	  check_typedef (type);
 	  if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
 	    type = TYPE_TARGET_TYPE (type);
+
+	  /* If the expression is actually a type, then there's no
+	     value to fetch the dynamic type from.  */
+	  val = NULL;
 	}
       else
 	{
@@ -506,7 +510,7 @@ whatis_exp (const char *exp, int show)
     }
 
   get_user_print_options (&opts);
-  if (opts.objectprint)
+  if (val != NULL && opts.objectprint)
     {
       if (((TYPE_CODE (type) == TYPE_CODE_PTR) || TYPE_IS_REFERENCE (type))
 	  && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT))


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]