diff options
author | Tom de Vries <tdevries@suse.de> | 2025-05-02 22:21:36 +0200 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2025-05-02 22:21:36 +0200 |
commit | 6ec31a457e953f4dbcdb7740d6dda676cdfb2a73 (patch) | |
tree | c02b14e35e183794948394ffe1c59896fd62351f | |
parent | fdaf750f3271e45a2ca4b381e8e8d4058abbb58a (diff) | |
download | binutils-6ec31a457e953f4dbcdb7740d6dda676cdfb2a73.zip binutils-6ec31a457e953f4dbcdb7740d6dda676cdfb2a73.tar.gz binutils-6ec31a457e953f4dbcdb7740d6dda676cdfb2a73.tar.bz2 |
[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): <string index too big>
...
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 <tom@tromey.com>
-rw-r--r-- | gdb/dwarf2/read.c | 13 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw-form-strx-out-of-bounds.exp | 35 |
2 files changed, 45 insertions, 3 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 951f9d2..6848f63 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 0000000..f2123fa --- /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 <http://www.gnu.org/licenses/>. + +# 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] |