From 6ec31a457e953f4dbcdb7740d6dda676cdfb2a73 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Fri, 2 May 2025 22:21:36 +0200 Subject: [PATCH] [gdb/symtab] Throw DWARF error on out-of-bounds DW_FORM_strx With the test-case contained in the patch, and gdb build with -fsanitize=address we get: ... ==23678==ERROR: AddressSanitizer: heap-buffer-overflow ...^M READ of size 1 at 0x6020000c30dc thread T3^[[1m^[[0m^M ptype global_var^M #0 0x2c6a40b in bfd_getl32 bfd/libbfd.c:846^M #1 0x168f96c in read_str_index gdb/dwarf2/read.c:15349^M ... The executable contains an out-of-bounds DW_FORM_strx attribute: ... $ readelf -wi $exec <2eb> DW_AT_name :readelf: Warning: string index of 1 converts to \ an offset of 0xc which is too big for section .debug_str (indexed string: 0x1): ... and read_str_index doesn't check for this: ... info_ptr = (str_offsets_section->buffer + str_offsets_base + str_index * offset_size); if (offset_size == 4) str_offset = bfd_get_32 (abfd, info_ptr); ... and consequently reads out-of-bounds. Fix this in read_str_index by checking for the out-of-bounds condition and throwing a DWARF error: ... (gdb) ptype global_var DWARF Error: Offset from DW_FORM_GNU_str_index or DW_FORM_strx pointing \ outside of .debug_str_offsets section in CU at offset 0x2d7 \ [in module dw-form-strx-out-of-bounds] No symbol "global_var" in current context. (gdb) ... Tested on x86_64-linux. Approved-By: Tom Tromey --- gdb/dwarf2/read.c | 13 +++++-- .../gdb.dwarf2/dw-form-strx-out-of-bounds.exp | 35 +++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw-form-strx-out-of-bounds.exp diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 951f9d26e4b..6848f63aa2e 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -15333,9 +15333,16 @@ read_str_index (struct dwarf2_cu *cu, " in CU at offset %s [in module %s]"), form_name, str_section->get_name (), sect_offset_str (cu->header.sect_off), objf_name); - info_ptr = (str_offsets_section->buffer - + str_offsets_base - + str_index * offset_size); + + ULONGEST str_offsets_offset = str_offsets_base + str_index * offset_size; + if (str_offsets_offset >= str_offsets_section->size) + error (_(DWARF_ERROR_PREFIX + "Offset from %s pointing outside of %s section in CU at offset %s" + " [in module %s]"), + form_name, str_offsets_section->get_name (), + sect_offset_str (cu->header.sect_off), objf_name); + info_ptr = str_offsets_section->buffer + str_offsets_offset; + if (offset_size == 4) str_offset = bfd_get_32 (abfd, info_ptr); else diff --git a/gdb/testsuite/gdb.dwarf2/dw-form-strx-out-of-bounds.exp b/gdb/testsuite/gdb.dwarf2/dw-form-strx-out-of-bounds.exp new file mode 100644 index 00000000000..f2123fa7e07 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw-form-strx-out-of-bounds.exp @@ -0,0 +1,35 @@ +# Copyright 2025 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 . + +# Check that an out-of-bounds DW_FORM_strx attribute triggers a DWARF error. + +# Out of bounds index. +set int_str_idx 1 + +source $srcdir/$subdir/dw-form-strx.exp.tcl + +set re_dwarf_error \ + [string_list_to_regexp \ + "DWARF Error: Offset from DW_FORM_GNU_str_index or DW_FORM_strx" \ + " pointing outside of .debug_str_offsets section in CU at offset"\ + " "]$hex +set re_in_module \ + {in module [^\r\n]+} +set re_in_module [string_to_regexp {[}]$re_in_module[string_to_regexp {]}] +set re_no_symbol [string_to_regexp {No symbol "global_var" in current context.}] +gdb_test "ptype global_var" \ + [multi_line \ + "$re_dwarf_error $re_in_module"\ + $re_no_symbol] -- 2.39.5