[PATCH] gdb: Check DW_OP_deref_type size against type

Jielun Wu <[email protected]>
Newsgroups gmane.comp.gdb.patches
Message-ID <[email protected]>
DWARF v5 requires the explicit size operand of DW_OP_deref_type to
match the size of the referenced base type.  The evaluator currently
passes both sizes to dwarf_expr_context::deref without validating the
encoding, and the generic dereference helper accepts the mismatch by
zero-extending the bytes read from memory.

Reject a mismatch after resolving the base type.  Add a DWARF assembler
test covering both DW_OP_deref_type and DW_OP_GNU_deref_type.

Tested on x86_64-linux.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34277
Signed-off-by: Jielun Wu <[email protected]>
---
 gdb/dwarf2/expr.c                             |  3 +
 .../gdb.dwarf2/dw2-deref-type-size.exp        | 78 +++++++++++++++++++
 2 files changed, 81 insertions(+)
 create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.exp

diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index 3a6b8f58199..ff23fb3e891 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -2027,6 +2027,9 @@ dwarf_expr_context::execute_stack_op (gdb::array_view<const gdb_byte> expr)
 		op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
 		cu_offset type_die_cu_off = (cu_offset) uoffset;
 		type = get_base_type (type_die_cu_off);
+		if (type->length () != addr_size)
+		  error (_("DW_OP_deref_type has different sizes for type and "
+			   "data"));
 	      }
 	    else
 	      type = address_type;
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.exp b/gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.exp
new file mode 100644
index 00000000000..52eae9e9eae
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-deref-type-size.exp
@@ -0,0 +1,78 @@
+# Copyright 2026 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/>.
+
+# Test that DW_OP_deref_type rejects an explicit dereference size that
+# differs from the size of the referenced base type.
+
+load_lib dwarf.exp
+
+require dwarf2_support
+
+standard_testfile main.c -dw.S
+
+set asm_file [standard_output_file $srcfile2]
+
+Dwarf::assemble $asm_file {
+    cu {version 5} {
+	compile_unit {} {
+	    declare_labels uint64_label
+
+	    uint64_label: base_type {
+		DW_AT_name "uint64_t"
+		DW_AT_encoding @DW_ATE_unsigned
+		DW_AT_byte_size 8 DW_FORM_sdata
+	    }
+
+	    foreach {var op} {
+		bad_deref_type DW_OP_deref_type
+		bad_gnu_deref_type DW_OP_GNU_deref_type
+	    } {
+		DW_TAG_variable {
+		    DW_AT_name $var
+		    DW_AT_type :$uint64_label
+		    DW_AT_external 1 DW_FORM_flag
+		    DW_AT_location {
+			variable _constants
+			variable _cu_label
+
+			DW_OP_addr main_label
+			_op .byte $_constants($op) $op
+			_op .byte 4 "dereference size"
+			_op .uleb128 "$uint64_label - $_cu_label" \
+			    "base type DIE offset"
+			DW_OP_stack_value
+		    } SPECIAL_expr
+		}
+	    }
+	}
+    }
+}
+
+if {[prepare_for_testing "failed to prepare" ${testfile} \
+	 [list $srcfile $asm_file] nodebug]} {
+    return
+}
+
+if {![runto_main]} {
+    return
+}
+
+foreach_with_prefix var {
+    bad_deref_type
+    bad_gnu_deref_type
+} {
+    gdb_test "print $var" \
+	"DW_OP_deref_type has different sizes for type and data"
+}
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.