aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2025-07-29 07:48:21 -0600
committerTom Tromey <tromey@adacore.com>2025-08-11 07:39:10 -0600
commitddd2795c52228cbbdf11aa95e11b68647b10df88 (patch)
tree830a5899a4f514f4de280f65b56b41faecd968b0
parent3c64cee8151d925ac3c438026074a2a1491e275f (diff)
downloadbinutils-ddd2795c52228cbbdf11aa95e11b68647b10df88.zip
binutils-ddd2795c52228cbbdf11aa95e11b68647b10df88.tar.gz
binutils-ddd2795c52228cbbdf11aa95e11b68647b10df88.tar.bz2
Do not allow DAP clients to dereference "void *"
While investigating a different bug, I noticed that the DAP code would report a "void *"-typed register as having children -- however, requesting the children of this register would fail. The issue here is that a plain "void *" can't be dereferenced. This patch changes the default visualizer to treat a "void *" as a scalar. This adds a new test; but also arranges to examine all the returned registers -- this was the first thing I attempted and it seemed reasonable to have a test that double-checks that all the registers really can be dereferenced as appropriate. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33228
-rw-r--r--gdb/python/lib/gdb/printing.py14
-rw-r--r--gdb/testsuite/gdb.dap/scopes.c2
-rw-r--r--gdb/testsuite/gdb.dap/scopes.exp30
3 files changed, 36 insertions, 10 deletions
diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py
index cba27d2..cda033f 100644
--- a/gdb/python/lib/gdb/printing.py
+++ b/gdb/python/lib/gdb/printing.py
@@ -415,11 +415,17 @@ def make_visualizer(value):
result = NoOpArrayPrinter(ty, value)
elif ty.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION):
result = NoOpStructPrinter(ty, value)
- elif ty.code in (
- gdb.TYPE_CODE_PTR,
- gdb.TYPE_CODE_REF,
- gdb.TYPE_CODE_RVALUE_REF,
+ elif (
+ ty.code
+ in (
+ gdb.TYPE_CODE_PTR,
+ gdb.TYPE_CODE_REF,
+ gdb.TYPE_CODE_RVALUE_REF,
+ )
+ and ty.target().code != gdb.TYPE_CODE_VOID
):
+ # Note we avoid "void *" here because those pointers can't
+ # be dereferenced without a cast.
result = NoOpPointerReferencePrinter(value)
else:
result = NoOpScalarPrinter(value)
diff --git a/gdb/testsuite/gdb.dap/scopes.c b/gdb/testsuite/gdb.dap/scopes.c
index d8929f1..2a1d76c 100644
--- a/gdb/testsuite/gdb.dap/scopes.c
+++ b/gdb/testsuite/gdb.dap/scopes.c
@@ -27,6 +27,8 @@ int main ()
static int scalar = 23;
+ void *ptr = (void *) &scalar;
+
{
const char *inner = "inner block";
diff --git a/gdb/testsuite/gdb.dap/scopes.exp b/gdb/testsuite/gdb.dap/scopes.exp
index 59d344b..b2066e5 100644
--- a/gdb/testsuite/gdb.dap/scopes.exp
+++ b/gdb/testsuite/gdb.dap/scopes.exp
@@ -70,7 +70,8 @@ lassign $scopes scope reg_scope
gdb_assert {[dict get $scope name] == "Locals"} "scope is locals"
gdb_assert {[dict get $scope presentationHint] == "locals"} \
"locals presentation hint"
-gdb_assert {[dict get $scope namedVariables] == 3} "three vars in scope"
+set count [dict get $scope namedVariables]
+gdb_assert {$count == 4} "four vars in scope"
gdb_assert {[dict get $reg_scope name] == "Registers"} \
"second scope is registers"
@@ -89,8 +90,8 @@ set refs1 [lindex [dap_check_request_and_response "fetch variables 0,1" \
set refs2 [lindex [dap_check_request_and_response "fetch variables 2" \
"variables" \
[format {o variablesReference [i %d] \
- start [i 2] count [i 1]} \
- $num]] \
+ start [i 2] count [i %d]} \
+ $num [expr {$count - 2}]]] \
0]
set vars [concat [dict get $refs1 body variables] \
@@ -115,6 +116,10 @@ foreach var $vars {
"scalar" {
gdb_assert {[dict get $var value] == 23} "check value of scalar"
}
+ "ptr" {
+ gdb_assert {[dict get $var memoryReference] != ""} \
+ "check memoryReference of ptr"
+ }
default {
fail "unknown variable $name"
}
@@ -129,10 +134,23 @@ set deivals [dict get $refs body variables]
gdb_assert {[llength $deivals] == 2} "dei has two members"
set num [dict get $reg_scope variablesReference]
-# The request succeeding is sufficient.
-set val [dap_check_request_and_response "fetch first register" \
+lassign [dap_check_request_and_response "fetch all registers" \
"variables" \
- [format {o variablesReference [i %d] count [i 1]} $num]]
+ [format {o variablesReference [i %d] count [i %d]} $num\
+ [dict get $reg_scope namedVariables]]] \
+ val events
+
+# If any register has children, try to fetch those as well. This is a
+# regression test for part of PR dap/33228.
+foreach var [dict get $val body variables] {
+ set regvar [dict get $var variablesReference]
+ if {$regvar > 0} {
+ dap_check_request_and_response "fetch register children for $regvar" \
+ "variables" \
+ [format {o variablesReference [i %d] count [i %d]} \
+ $regvar [dict get $var namedVariables]]
+ }
+}
set num [dict get $scope variablesReference]
set refs [lindex [dap_check_request_and_response "set variable scalar" \