Fix printf of a convenience variable holding an inferior address
authorSergio Durigan Junior <sergiodj@redhat.com>
Sun, 1 Mar 2020 23:15:53 +0000 (18:15 -0500)
committerSergio Durigan Junior <sergiodj@redhat.com>
Tue, 3 Mar 2020 16:28:09 +0000 (11:28 -0500)
Back at:

commit 1f6f6e21fa86dc3411a6498608f32e9eb24b7851
Author: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date:   Mon Jun 10 21:41:51 2019 +0200

    Ensure GDB printf command can print convenience var strings without a target.

GDB was extended in order to allow the printing of convenience
variables that are strings without a target.  However, this introduced
a regression that hasn't been caught by our testsuite (because there
were no tests for it).

The problem happens when we try to print a convenience variable that
holds the address of a string in the inferior.  The following
two-liners can reproduce the issue:

$ echo -e 'int main(){const char a[]="test";return 0;}' | gcc -x c - -O0-g3
$ ./gdb/gdb --data-directory ./gdb/data-directory -q ./a.out -ex 'start' -ex 'set $x = (const char *) (&a[0] + 2)' -ex 'printf "%s\n", $x'

After some investigation, I found that the problem happens on
printcmd.c:printf_c_string.  In the case above, we're taking the first
branch of the 'if' condition, which assumes that there will be a value
to be printed at "value_contents (value)".  There isn't.  We actually
need to obtain the address that the variable points to, and read the
contents from memory.

It seems to me that we should avoid this branch if the TYPE_CODE of
"value_type (value)" is TYPE_CODE_PTR (i.e., a pointer to the
inferior's memory).  This is what this patch does.

I took the liberty to extend the current testcase under
gdb.base/printcmds.exp and create a test that exercises this scenario.

No regressions have been found on Buildbot.

gdb/ChangeLog:
2020-03-03  Sergio Durigan Junior  <sergiodj@redhat.com>

* printcmd.c (print_c_string): Check also for TYPE_CODE_PTR
when verifying if dealing with a convenience variable.

gdb/testsuite/ChangeLog:
2020-03-03  Sergio Durigan Junior  <sergiodj@redhat.com>

* gdb.base/printcmds.exp: Add test to verify printf of a
variable holding an address.

gdb/ChangeLog
gdb/printcmd.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/printcmds.exp

index 2400982e5040fd4772c9ee8bba86a570b58f17ca..291e83af8e76484a6c91c9d3708e63c463af059c 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-03  Sergio Durigan Junior  <sergiodj@redhat.com>
+
+       * printcmd.c (print_c_string): Check also for TYPE_CODE_PTR
+       when verifying if dealing with a convenience variable.
+
 2020-03-03  Luis Machado  <luis.machado@linaro.org>
 
        * auxv.c (default_print_auxv_entry): Add new AUXV entries.
index 797041484eb5c74cfee17738a88b2c2da9504203..78d8d3d81e1863e7698c2ecfc68a80a1760d13de 100644 (file)
@@ -2260,7 +2260,8 @@ printf_c_string (struct ui_file *stream, const char *format,
 {
   const gdb_byte *str;
 
-  if (VALUE_LVAL (value) == lval_internalvar
+  if (TYPE_CODE (value_type (value)) != TYPE_CODE_PTR
+      && VALUE_LVAL (value) == lval_internalvar
       && c_is_string_type_p (value_type (value)))
     {
       size_t len = TYPE_LENGTH (value_type (value));
index 0563fec5326da5b9808b9505d9cc82a6538c0b7c..28726b8fcb308b8520e8ab88968864668c1c1803 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-03  Sergio Durigan Junior  <sergiodj@redhat.com>
+
+       * gdb.base/printcmds.exp: Add test to verify printf of a
+       variable holding an address.
+
 2020-03-03  Tom de Vries  <tdevries@suse.de>
 
        * gdb.mi/gdb2549.exp: Fix "register values t" check-read1 timeout.
index bd2afc8696f0ee142634b5ce473ea9081e1957f2..c87a1517f0b747d60519e9746e633b40839a32bb 100644 (file)
@@ -1039,6 +1039,14 @@ gdb_test_no_output "set may-call-functions off"
 test_printf_convenience_var "with target, may-call-functions off"
 gdb_test_no_output "set may-call-functions on"
 
+# Test printf of a variable that holds the address to a substring in
+# the inferior.  This test will not work without a target.
+gdb_test_no_output "set var \$test_substr = \(char \*\) \(&teststring\[0\] + 4\)" \
+    "set \$test_substr var"
+gdb_test "printf \"test_substr val = %s\\n\", \$test_substr" \
+    "test_substr val = string contents" \
+    "print \$test_substr"
+
 test_integer_literals_accepted
 test_integer_literals_rejected
 test_float_accepted