public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] [gdb/exp] Fix printing of out of bounds struct members
@ 2024-01-22 13:28 Tom de Vries
  2024-01-22 16:29 ` Tom Tromey
  0 siblings, 1 reply; 5+ messages in thread
From: Tom de Vries @ 2024-01-22 13:28 UTC (permalink / raw)
  To: gdb-patches

When building gdb with -O0 -fsanitize=address, and running test-case
gdb.ada/uninitialized_vars.exp, I run into:
...
(gdb) info locals
a = 0
z = (a => 1, b => false, c => 2.0)
=================================================================
==66372==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000097f58 at pc 0xffff52c0da1c bp 0xffffc90a1d40 sp 0xffffc90a1d80
READ of size 4 at 0x602000097f58 thread T0
    #0 0xffff52c0da18 in memmove (/lib64/libasan.so.8+0x6da18)
    #1 0xbcab24 in unsigned char* std::__copy_move_backward<false, true, std::random_access_iterator_tag>::__copy_move_b<unsigned char const, unsigned char>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:748
    #2 0xbc9bf4 in unsigned char* std::__copy_move_backward_a2<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:769
    #3 0xbc898c in unsigned char* std::__copy_move_backward_a1<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:778
    #4 0xbc715c in unsigned char* std::__copy_move_backward_a<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:807
    #5 0xbc4e6c in unsigned char* std::copy_backward<unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:867
    #6 0xbc2934 in void gdb::copy<unsigned char const, unsigned char>(gdb::array_view<unsigned char const>, gdb::array_view<unsigned char>) gdb/../gdbsupport/array-view.h:223
    #7 0x20e0100 in value::contents_copy_raw(value*, long, long, long) gdb/value.c:1239
    #8 0x20e9830 in value::primitive_field(long, int, type*) gdb/value.c:3078
    #9 0x20e98f8 in value_field(value*, int) gdb/value.c:3095
    #10 0xcafd64 in print_field_values gdb/ada-valprint.c:658
    #11 0xcb0fa0 in ada_val_print_struct_union gdb/ada-valprint.c:857
    #12 0xcb1bb4 in ada_value_print_inner(value*, ui_file*, int, value_print_options const*) gdb/ada-valprint.c:1042
    #13 0xc66e04 in ada_language::value_print_inner(value*, ui_file*, int, value_print_options const*) const (/home/vries/gdb/build/gdb/gdb+0xc66e04)
    #14 0x20ca1e8 in common_val_print(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1092
    #15 0x20caabc in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1184
    #16 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
    #17 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
    #18 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
    #19 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
    #20 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
    #21 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
    #22 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
    #23 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
    #24 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
    #25 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
    #26 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
    #27 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
    #28 0x1384080 in command_handler(char const*) gdb/event-top.c:566
    #29 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
    #30 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
    #31 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
    #32 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
    #33 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
    #34 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
    #35 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
    #36 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
    #37 0x35ff9d8 in gdb_wait_for_event gdbsupport/event-loop.cc:694
    #38 0x35fd284 in gdb_do_one_event(int) gdbsupport/event-loop.cc:264
    #39 0x1768080 in start_event_loop gdb/main.c:408
    #40 0x17684c4 in captured_command_loop gdb/main.c:472
    #41 0x176cfc8 in captured_main gdb/main.c:1342
    #42 0x176d088 in gdb_main(captured_main_args*) gdb/main.c:1361
    #43 0xb73edc in main gdb/gdb.c:39
    #44 0xffff519b09d8 in __libc_start_call_main (/lib64/libc.so.6+0x309d8)
    #45 0xffff519b0aac in __libc_start_main@@GLIBC_2.34 (/lib64/libc.so.6+0x30aac)
    #46 0xb73c2c in _start (/home/vries/gdb/build/gdb/gdb+0xb73c2c)

0x602000097f58 is located 0 bytes after 8-byte region [0x602000097f50,0x602000097f58)
allocated by thread T0 here:
    #0 0xffff52c65218 in calloc (/lib64/libasan.so.8+0xc5218)
    #1 0xcbc278 in xcalloc gdb/alloc.c:97
    #2 0x35f21e8 in xzalloc(unsigned long) gdbsupport/common-utils.cc:29
    #3 0x20de270 in value::allocate_contents(bool) gdb/value.c:937
    #4 0x20edc08 in value::fetch_lazy() gdb/value.c:4033
    #5 0x20dadc0 in value::entirely_covered_by_range_vector(std::vector<range, std::allocator<range> > const&) gdb/value.c:229
    #6 0xcb2298 in value::entirely_optimized_out() gdb/value.h:560
    #7 0x20ca6fc in value_check_printable gdb/valprint.c:1133
    #8 0x20caa8c in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1182
    #9 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
    #10 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
    #11 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
    #12 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
    #13 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
    #14 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
    #15 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
    #16 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
    #17 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
    #18 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
    #19 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
    #20 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
    #21 0x1384080 in command_handler(char const*) gdb/event-top.c:566
    #22 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
    #23 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
    #24 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
    #25 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
    #26 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
    #27 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
    #28 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
    #29 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573

SUMMARY: AddressSanitizer: heap-buffer-overflow (/lib64/libasan.so.8+0x6da18) in memmove
...

The error happens when trying to print either variable y or y2:
...
   type Variable_Record (A : Boolean := True) is record
      case A is
         when True =>
            B : Integer;
         when False =>
            C : Float;
            D : Integer;
      end case;
   end record;
   Y  : Variable_Record := (A => True, B => 1);
   Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
...
when the variables are uninitialized.

The error happens only when printing the entire variable:
...
(gdb) p y.a
$2 = 216
(gdb) p y.b
There is no member named b.
(gdb) p y.c
$3 = 9.18340949e-41
(gdb) p y.d
$4 = 1
(gdb) p y
<AddressSanitizer: heap-buffer-overflow>
...

The error happens as follows:
- field a functions as discriminant, choosing either the b, or c+d variant.
- when y.a happens to be set to 216, as above, gdb interprets this as the
  variable having the c+d variant (which is why trying to print y.b fails).
- when printing y, gdb allocates a value, copies the bytes into it from the
  target, and then prints the value.
- gdb allocates the value using the type size, which is 8.  It's 8 because
  that's what the DW_AT_byte_size indicates.  Note that for valid values of a,
  it gives correct results: if a is 0 (c+d variant), size is 12, if a is 1
  (b variant), size is 8.
- gdb tries to print field d, which is at an 8 byte offset, and that results
  in a out-of-bounds access for the allocated 8-byte value.

Fix this by handling this case in value::contents_copy_raw, such that we have:
...
(gdb) p y
$1 = (a => 24, c => 9.18340949e-41, d => <optimized out>)
...

[ Given the description at the top of gdb/value.h of optimized out and
unavailable, I was not sure which one to pick for this case, so this is more
or less a random choice.

Alternatively, we could throw an error, say "out of bounds", and we'd get:
...
(gdb) print y
$1 = (a => 24, c => 9.18340949e-41,
      d => <error reading variable: out of bounds>)
... ]

The test-case source file gdb.ada/uninitialized-variable-record/parse.adb is
a reduced version of gdb.ada/uninitialized_vars/parse.adb, so it copies the
copyright years.

Note that the test-case needs gcc-12 or newer, it's unsupported for older gcc
versions. [ So, it would be nice to rewrite it into a dwarf assembly
test-case. ]

The test-case loops over all languages.  This is inherited from an earlier
attempt to fix this, which had language-specific fixes (in print_field_values,
cp_print_value_fields, pascal_object_print_value_fields and
f_language::value_print_inner).  I've left this in, but I suppose it's not
strictly necessary anymore.

Tested on x86_64-linux.

PR exp/31258
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31258
---
 .../gdb.ada/uninitialized-variable-record.exp | 135 ++++++++++++++++++
 .../uninitialized-variable-record/parse.adb   |  33 +++++
 gdb/value.c                                   |   6 +
 3 files changed, 174 insertions(+)
 create mode 100644 gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
 create mode 100644 gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb

diff --git a/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp b/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
new file mode 100644
index 00000000000..31f0ee4038a
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/uninitialized-variable-record.exp
@@ -0,0 +1,135 @@
+# Copyright 2024 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/>.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile parse
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" } {
+  return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "START" ${testdir}/parse.adb]
+runto "parse.adb:$bp_location"
+
+# Check that we have the expected value for variable y2.
+
+gdb_test "p y2" [string_to_regexp " = (a => false, c => 1.0, d => 2)"]
+
+# Get the address of y2.a.  We use it modify y2.a.
+
+set re_cast [string_to_regexp "(access boolean)"]
+gdb_test_multiple "print &y2.a" "" {
+    -re -wrap " = $re_cast (.*)" {
+	set addr_a $expect_out(1,string)
+	pass $gdb_test_name
+    }
+}
+
+# Calculate the offset of y2.d.
+
+set re_cast [string_to_regexp "(access integer)"]
+gdb_test_multiple "print &y2.d" "" {
+    -re -wrap " = $re_cast (.*)" {
+	set addr_d $expect_out(1,string)
+	pass $gdb_test_name
+    }
+}
+set offset_d [expr $addr_d - $addr_a]
+
+# Shorthand.
+
+proc set_lang { lang } {
+    gdb_test_multiple "set language $lang" "" {
+	-re -wrap "" {
+	}
+    }
+}
+
+# Try to find a interesting discriminator value, such that at the same time:
+# - the d field is part of the variable, and
+# - the type size is too small to contain d.
+
+set interesting_discriminator -1
+for { set i 0 } { $i < 256 } { incr i } {
+    with_test_prefix $i {
+
+	# Patch in the discriminator value.
+	set_lang c
+	gdb_test_multiple "set var *(unsigned char *)($addr_a)=$i" "" {
+	    -re -wrap "" {
+	    }
+	}
+
+	# Check that we have the variant with fields c and d instead of b.
+	set ok 1
+	set_lang ada
+	gdb_test_multiple "print y2.b" "" {
+	    -re -wrap " = $decimal" {
+		set ok 0
+	    }
+	    -re -wrap "" {
+	    }
+	}
+	if { !$ok } {
+	    # This is the variant with field b.
+	    continue
+	}
+
+	set size 0
+	set_lang c
+	gdb_test_multiple "print sizeof (y2)" "" {
+	    -re -wrap " = (.*)" {
+		set size $expect_out(1,string)
+	    }
+	}
+
+	if { ! $size } {
+	    continue
+	}
+
+	if { [expr $size > $offset_d] } {
+	    # Field d fits in the size.
+	    continue
+	}
+
+	set interesting_discriminator $i
+	break
+    }
+}
+
+require {expr $interesting_discriminator != -1}
+
+foreach lang [gdb_supported_languages] {
+    with_test_prefix $lang {
+	set_lang $lang
+
+	gdb_test_multiple "print y2" "" {
+	    -re -wrap ", d => $decimal.*" {
+		fail $gdb_test_name
+	    }
+	    -re -wrap ", d = $decimal.*" {
+		fail $gdb_test_name
+	    }
+	    -re -wrap "" {
+		pass $gdb_test_name
+	    }
+	}
+    }
+}
diff --git a/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb b/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
new file mode 100644
index 00000000000..f00c75ca2dc
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/uninitialized-variable-record/parse.adb
@@ -0,0 +1,33 @@
+--  Copyright 2009-2024 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/>.
+
+-- Based on gdb.ada/uninitialized_vars/parse.adb.
+
+procedure Parse is
+
+   type Variable_Record (A : Boolean := True) is record
+      case A is
+         when True =>
+            B : Integer;
+         when False =>
+            C : Float;
+            D : Integer;
+      end case;
+   end record;
+   Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
+
+begin
+   null;  -- START
+end Parse;
diff --git a/gdb/value.c b/gdb/value.c
index 4ec9babcce8..50d436e37c2 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1236,6 +1236,12 @@ value::contents_copy_raw (struct value *dst, LONGEST dst_offset,
   gdb::array_view<const gdb_byte> src_contents
     = contents_all_raw ().slice (src_offset * unit_size,
 				 copy_length * unit_size);
+  if ((src_offset + copy_length) * unit_size > enclosing_type ()-> length ())
+    {
+      dst->mark_bytes_optimized_out (dst_offset * unit_size,
+				     copy_length * unit_size);
+      return;
+    }
   gdb::copy (src_contents, dst_contents);
 
   /* Copy the meta-data, adjusted.  */

base-commit: c2625a463ffd8c0d10b85b65e80ab8b67b28e441
-- 
2.35.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] [gdb/exp] Fix printing of out of bounds struct members
  2024-01-22 13:28 [PATCH] [gdb/exp] Fix printing of out of bounds struct members Tom de Vries
@ 2024-01-22 16:29 ` Tom Tromey
  2024-01-24 16:15   ` Tom de Vries
  0 siblings, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2024-01-22 16:29 UTC (permalink / raw)
  To: Tom de Vries; +Cc: gdb-patches

>>>>> "Tom" == Tom de Vries <tdevries@suse.de> writes:

Tom> When building gdb with -O0 -fsanitize=address, and running test-case
Tom> gdb.ada/uninitialized_vars.exp, I run into:
Tom> ...

Thanks for looking into this.

Tom> - when y.a happens to be set to 216, as above, gdb interprets this as the
Tom>   variable having the c+d variant (which is why trying to print y.b fails).

One thing I see here is that y.a is not one of the valid values.  So I
wonder if this kind of corruption should be detected at a different
spot, like throwing an exception from compute_variant_fields_inner.

Tom> [ Given the description at the top of gdb/value.h of optimized out and
Tom> unavailable, I was not sure which one to pick for this case, so this is more
Tom> or less a random choice.

Yeah, neither seems like precisely the right fit.

Tom

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] [gdb/exp] Fix printing of out of bounds struct members
  2024-01-22 16:29 ` Tom Tromey
@ 2024-01-24 16:15   ` Tom de Vries
  2024-01-24 17:33     ` Tom Tromey
  0 siblings, 1 reply; 5+ messages in thread
From: Tom de Vries @ 2024-01-24 16:15 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 1/22/24 17:29, Tom Tromey wrote:
>>>>>> "Tom" == Tom de Vries <tdevries@suse.de> writes:
> 
> Tom> When building gdb with -O0 -fsanitize=address, and running test-case
> Tom> gdb.ada/uninitialized_vars.exp, I run into:
> Tom> ...
> 
> Thanks for looking into this.
> 
> Tom> - when y.a happens to be set to 216, as above, gdb interprets this as the
> Tom>   variable having the c+d variant (which is why trying to print y.b fails).
> 
> One thing I see here is that y.a is not one of the valid values.  So I
> wonder if this kind of corruption should be detected at a different
> spot, like throwing an exception from compute_variant_fields_inner.
> 

I've looked into that, but I think it requires a cleanup related to 
TYPE_CODE_BOOL, see this PR ( 
https://sourceware.org/bugzilla/show_bug.cgi?id=31282 ).  Currently 
there's no reliable way to determine what valid bool values are.  I've 
updated the commit message to mention this way of fixing it in the v2.

> Tom> [ Given the description at the top of gdb/value.h of optimized out and
> Tom> unavailable, I was not sure which one to pick for this case, so this is more
> Tom> or less a random choice.
> 
> Yeah, neither seems like precisely the right fit.

OK, I've updated v2 to use an error then.

V2: https://sourceware.org/pipermail/gdb-patches/2024-January/206200.html

Thanks,
- Tom


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] [gdb/exp] Fix printing of out of bounds struct members
  2024-01-24 16:15   ` Tom de Vries
@ 2024-01-24 17:33     ` Tom Tromey
  2024-01-25 12:56       ` Tom de Vries
  0 siblings, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2024-01-24 17:33 UTC (permalink / raw)
  To: Tom de Vries; +Cc: Tom Tromey, gdb-patches

>>>>> "Tom" == Tom de Vries <tdevries@suse.de> writes:

>> One thing I see here is that y.a is not one of the valid values.  So
>> I
>> wonder if this kind of corruption should be detected at a different
>> spot, like throwing an exception from compute_variant_fields_inner.
>> 

Tom> I've looked into that, but I think it requires a cleanup related to
Tom> TYPE_CODE_BOOL

In this particular test, I would have expect the variants to enumerate
the valid values, due to the 'when True' / 'when False'.

However, I see the compiler decides not to do that :-(

That is, it says:

 <4><1158>: Abbrev Number: 8 (DW_TAG_variant)
    <1159>   DW_AT_discr_value : 1
    <115a>   DW_AT_sibling     : <0x1169>
 <5><115e>: Abbrev Number: 1 (DW_TAG_member)
[...]
 <4><1169>: Abbrev Number: 9 (DW_TAG_variant)
 <5><116a>: Abbrev Number: 1 (DW_TAG_member)

Tom

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] [gdb/exp] Fix printing of out of bounds struct members
  2024-01-24 17:33     ` Tom Tromey
@ 2024-01-25 12:56       ` Tom de Vries
  0 siblings, 0 replies; 5+ messages in thread
From: Tom de Vries @ 2024-01-25 12:56 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 1/24/24 18:33, Tom Tromey wrote:
>>>>>> "Tom" == Tom de Vries <tdevries@suse.de> writes:
> 
>>> One thing I see here is that y.a is not one of the valid values.  So
>>> I
>>> wonder if this kind of corruption should be detected at a different
>>> spot, like throwing an exception from compute_variant_fields_inner.
>>>
> 
> Tom> I've looked into that, but I think it requires a cleanup related to
> Tom> TYPE_CODE_BOOL
> 
> In this particular test, I would have expect the variants to enumerate
> the valid values, due to the 'when True' / 'when False'.
> 
> However, I see the compiler decides not to do that :-(
> 
> That is, it says:
> 
>   <4><1158>: Abbrev Number: 8 (DW_TAG_variant)
>      <1159>   DW_AT_discr_value : 1
>      <115a>   DW_AT_sibling     : <0x1169>
>   <5><115e>: Abbrev Number: 1 (DW_TAG_member)
> [...]
>   <4><1169>: Abbrev Number: 9 (DW_TAG_variant)
>   <5><116a>: Abbrev Number: 1 (DW_TAG_member)

Yeah, I saw this in gcc's analyze_variants_discr, I wondered if that is 
related:
...
       /* Now, try to analyze the predicate and deduce a discriminant 
for
          it.  */
       if (match_expr == boolean_true_node)
         /* Typically happens for the default variant: it matches all 
cases that
            previous variants rejected.  Don't output any matching value 
for
            this one.  */
	continue;
...

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-01-25 12:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-22 13:28 [PATCH] [gdb/exp] Fix printing of out of bounds struct members Tom de Vries
2024-01-22 16:29 ` Tom Tromey
2024-01-24 16:15   ` Tom de Vries
2024-01-24 17:33     ` Tom Tromey
2024-01-25 12:56       ` Tom de Vries

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).