Fix segfault when using 'set print object on' + whatis <struct>
Commit Message
This problem was hidden behind a "maybe-uninitialized" warning
generated when compiling GDB with a recent GCC. The warning is:
../../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);
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I submitted a patch fixing this by initializing "val" to NULL, but it
was the wrong fix, as Pedro pointed out on
<https://sourceware.org/ml/gdb-patches/2018-01/msg00346.html>:
(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);
...
So I set off to find the cause of the problem. It turns out that 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
was the reason of the failure. After investigating what 'set print
object on' was supposed to do to the output of 'whatis', if made sense
initialize "val = evaluate_type (expr.get ());" all the time, not only
when we're dealing with the 'ptype' command.
I've regtested this on the BuildBot, without seeing any regressions.
I've also extended 'gdb.base/whatis.exp' to check if the segfault is
not there anymore.
gdb/ChangeLog:
yyyy-mm-dd Sergio Durigan Junior <sergiodj@redhat.com>
* typeprint.c (whatis_exp): Move initialization of "val"
outside of "if".
gdb/testsuite/ChangeLog:
yyyy-mm-dd Sergio Durigan Junior <sergiodj@redhat.com>
* gdb.base/whatis.exp: Test that 'set print object on' +
'whatis <struct>' doesn't segfault.
---
gdb/testsuite/gdb.base/whatis.exp | 7 +++++++
gdb/typeprint.c | 3 ++-
2 files changed, 9 insertions(+), 1 deletion(-)
@@ -566,3 +566,10 @@ gdb_test "whatis int (*)(void, int, int)" \
gdb_test "whatis int (*)(int, void, int)" \
"'void' invalid as parameter type" \
"whatis applied to function with 'void' parameter type"
+
+# Test that 'set print object on' + whatis doesn't segfault.
+clean_restart $binfile
+gdb_test_no_output "set print object on"
+gdb_test "whatis v_struct1" \
+ "type = struct t_struct" \
+ "whatis + set print object on doesn't segfault"
@@ -471,6 +471,8 @@ whatis_exp (const char *exp, int show)
expression_up expr = parse_expression (exp);
+ val = evaluate_type (expr.get ());
+
/* 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"
@@ -495,7 +497,6 @@ whatis_exp (const char *exp, int show)
/* The user expression names a type indirectly by naming an
object or expression of that type. Find that
indirectly-named type. */
- val = evaluate_type (expr.get ());
type = value_type (val);
}
}