https://sourceware.org/bugzilla/show_bug.cgi?id=34662
Bug ID: 34662
Summary: Heap-buffer-overflow write in STABS physical-name
construction (`binutils/stabs.c`)
Product: binutils
Version: 2.47
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: binutils
Assignee: unassigned at sourceware dot org
Reporter: hdzhao214 at gmail dot com
Target Milestone: ---
Created attachment 17021
--> https://sourceware.org/bugzilla/attachment.cgi?id=17021&action=edit
The `artifacts.zip` package includes the PoC generation script, the sanitizer
report, the bug report, and the candidate patch
## Vulnerability description
`parse_stab_argtypes` computes the size of a C++ physical name with several
attacker-controlled `strlen` values held in `unsigned int`. A STABS
argument-type string longer than 4 GB wraps the total, `debug_xalloc` returns a
small buffer, and the subsequent `strcat` copies the full string past it.
```c
unsigned int len, buf_len, mangled_name_len;
mangled_name_len = ... + strlen (argtypes) + 1;
physname = debug_xalloc (dhandle, mangled_name_len);
strcat (physname, argtypes);
```
## Version and commit
GNU Binutils 2.47.50, commit `d715260f420066befb2d30ec8f5befcdf7ecfd84`
(2026-09-08).
## Environment
Ubuntu 24.04.4 LTS, x86_64, Linux 6.8.0-136-generic; GCC 13.3.0 and Python
3.12.3. AddressSanitizer was enabled. The default generator writes a roughly 4
GB STABS string.
## Steps to reproduce
1. Install build prerequisites (for example, on Ubuntu):
```sh
sudo apt-get update
sudo apt-get install -y build-essential bison flex texinfo python3 \
libgmp-dev libmpfr-dev libmpc-dev zlib1g-dev
```
2. Obtain the affected revision and make an AddressSanitizer build:
```sh
export SRC="$PWD/binutils-gdb"
git clone https://sourceware.org/git/binutils-gdb.git "$SRC"
git -C "$SRC" checkout d715260f420066befb2d30ec8f5befcdf7ecfd84
mkdir "$SRC/build-asan" && cd "$SRC/build-asan"
CC=gcc CFLAGS='-O0 -g3 -fsanitize=address -fno-omit-frame-pointer' \
LDFLAGS='-fsanitize=address' \
"$SRC/configure" --disable-gdb --disable-gdbserver --disable-sim \
--disable-gprofng --disable-gold --disable-werror --disable-nls
make -j"$(nproc)" all-binutils
export BUILD="$SRC/build-asan"
```
3. Place the supplied `gen_poc.py` in a writable directory and generate the
input:
```sh
export WORK="$PWD/poc-work"
mkdir -p "$WORK"
python3 gen_poc.py "$WORK/sample.elf"
```
4. Trigger the fault (discard malformed-input diagnostics):
```sh
ASAN_OPTIONS=detect_leaks=0:abort_on_error=1 \
"$BUILD/binutils/objdump" -g "$WORK/sample.elf" >/dev/null
2>"$WORK/asan.txt"
```
## Sanitizer report
The following is the complete, unmodified contents of `sanitizer_report.txt`.
```text
=================================================================
==1781576==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x5210000088e0 at pc 0x76faa80f6260 bp 0x7fffde943770 sp 0x7fffde942f18
WRITE of size 4294967297 at 0x5210000088e0 thread T0
#0 0x76faa80f625f in strcat
../../../../src/libsanitizer/asan/asan_interceptors.cpp:515
#1 0x5fd90ac755ac in parse_stab_argtypes ../../binutils/stabs.c:3086
#2 0x5fd90ac745e3 in parse_stab_members ../../binutils/stabs.c:2929
#3 0x5fd90ac71ac7 in parse_stab_struct_type ../../binutils/stabs.c:2151
#4 0x5fd90ac6f879 in parse_stab_type ../../binutils/stabs.c:1632
#5 0x5fd90ac6d126 in parse_stab_string ../../binutils/stabs.c:1018
#6 0x5fd90ac6bc67 in parse_stab ../../binutils/stabs.c:688
#7 0x5fd90ac5a044 in read_section_stabs_debugging_info
../../binutils/rddbg.c:244
#8 0x5fd90ac590ae in read_debugging_info ../../binutils/rddbg.c:59
#9 0x5fd90abe80e6 in dump_bfd ../../binutils/objdump.c:5917
#10 0x5fd90abe8374 in display_object_bfd ../../binutils/objdump.c:5971
#11 0x5fd90abe8696 in display_any_bfd ../../binutils/objdump.c:6050
#12 0x5fd90abe8706 in display_file ../../binutils/objdump.c:6071
#13 0x5fd90abea222 in main ../../binutils/objdump.c:6494
#14 0x76faa7c2a1c9 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
#15 0x76faa7c2a28a in __libc_start_main_impl ../csu/libc-start.c:360
#16 0x5fd90abcd374 in _start
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/build-asan/binutils/objdump+0x143374)
(BuildId: 7b3b22cfe8266150e71d8e259cd00c3996daee41)
0x5210000088e0 is located 0 bytes after 4064-byte region
[0x521000007900,0x5210000088e0)
allocated by thread T0 here:
#0 0x76faa80fd9c7 in malloc
../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x5fd90aff2942 in _objalloc_alloc ../../libiberty/objalloc.c:159
#2 0x5fd90ad3f501 in bfd_alloc ../../bfd/libbfd.c:453
#3 0x5fd90adb380e in bfd_elf64_object_p ../../bfd/elfcode.h:717
#4 0x5fd90ad3aae8 in bfd_check_format_matches ../../bfd/format.c:547
#5 0x5fd90abe835c in display_object_bfd ../../binutils/objdump.c:5969
#6 0x5fd90abe8696 in display_any_bfd ../../binutils/objdump.c:6050
#7 0x5fd90abe8706 in display_file ../../binutils/objdump.c:6071
#8 0x5fd90abea222 in main ../../binutils/objdump.c:6494
#9 0x76faa7c2a1c9 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
#10 0x76faa7c2a28a in __libc_start_main_impl ../csu/libc-start.c:360
#11 0x5fd90abcd374 in _start
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/build-asan/binutils/objdump+0x143374)
(BuildId: 7b3b22cfe8266150e71d8e259cd00c3996daee41)
SUMMARY: AddressSanitizer: heap-buffer-overflow
../../../../src/libsanitizer/asan/asan_interceptors.cpp:515 in strcat
Shadow bytes around the buggy address:
0x521000008600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x521000008680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x521000008700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x521000008780: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x521000008800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x521000008880: 00 00 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa
0x521000008900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x521000008980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x521000008a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x521000008a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x521000008b00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==1781576==ABORTING
```
## Potential fix
Use `size_t` for every length, perform checked additions, and reject a total
that cannot be passed safely to the legacy demangler. Use `snprintf` for the
fixed prefix.
```diff
diff --git a/binutils/stabs.c b/binutils/stabs.c
@@
- unsigned int len, buf_len, mangled_name_len;
+ size_t len, buf_len, mangled_name_len;
@@
- mangled_name_len = ... + strlen (argtypes) + 1;
+ mangled_name_len = 1;
+ if (fieldname_len > (size_t) -1 - mangled_name_len)
+ return DEBUG_TYPE_NULL;
+ ...
+ if (mangled_name_len > UINT_MAX)
+ return DEBUG_TYPE_NULL;
```
The complete, apply-ready patch is included as `proposed-fix.patch`. It was
applied to a disposable checkout of the stated commit and the supplied proof of
concept was rerun without an AddressSanitizer finding.
--
You are receiving this mail because:
You are on the CC list for the bug.