https://sourceware.org/bugzilla/show_bug.cgi?id=34661
Bug ID: 34661
Summary: Heap-buffer-overflow write in DWARF line-table file
entries (`binutils/dwarf.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 17020
--> https://sourceware.org/bugzilla/attachment.cgi?id=17020&action=edit
The `artifacts.zip` package includes the PoC generation script, the sanitizer
report, the bug report, and the candidate patch
## Vulnerability description
For pre-DWARF-5 line tables, `display_debug_lines_decoded` counts file-name
entries in a 32-bit `unsigned int`, allocates an array from the wrapped count,
then traverses the same table a second time. With `2^32 + 1` entries, `n_files`
becomes one, but the second pass stores the second and later `File_Entry`
values past the one-entry allocation.
```c
while (data < end && *data != 0)
{ ... n_files++; }
file_table = xmalloc (n_files * sizeof (File_Entry));
...
file_table[i].name = (char *) ptr_file_name_table;
```
## 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. The target was built with AddressSanitizer. Generating the default
input requires about 20 GB of disk and running it needs substantial RAM.
## 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
default `2^32 + 1`-entry line table:
```sh
export WORK="$PWD/poc-work"
mkdir -p "$WORK"
python3 gen_poc.py "$WORK/sample.elf"
```
4. Trigger the fault:
```sh
ASAN_OPTIONS=detect_leaks=0:abort_on_error=1 \
"$BUILD/binutils/objdump" --dwarf=decodedline "$WORK/sample.elf"
>/dev/null
```
## Sanitizer report
The following is the complete, unmodified contents of `sanitizer_report.txt`.
```text
=================================================================
==1381546==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x503000000298 at pc 0x5b4682ea6c39 bp 0x7ffc8112df60 sp 0x7ffc8112df50
WRITE of size 8 at 0x503000000298 thread T0
#0 0x5b4682ea6c38 in display_debug_lines_decoded
../../binutils/dwarf.c:6726
#1 0x5b4682eaa0cb in display_debug_lines ../../binutils/dwarf.c:7225
#2 0x5b4682e731f5 in dump_dwarf_section ../../binutils/objdump.c:4516
#3 0x5b4682fdb924 in bfd_map_over_sections ../../bfd/section.c:1369
#4 0x5b4682e7371a in dump_dwarf_info ../../binutils/objdump.c:4593
#5 0x5b4682e737a2 in dump_dwarf ../../binutils/objdump.c:4601
#6 0x5b4682e79fb4 in dump_bfd ../../binutils/objdump.c:5893
#7 0x5b4682e7a374 in display_object_bfd ../../binutils/objdump.c:5971
#8 0x5b4682e7a696 in display_any_bfd ../../binutils/objdump.c:6050
#9 0x5b4682e7a706 in display_file ../../binutils/objdump.c:6071
#10 0x5b4682e7c222 in main ../../binutils/objdump.c:6494
#11 0x78361342a1c9 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
#12 0x78361342a28a in __libc_start_main_impl ../csu/libc-start.c:360
#13 0x5b4682e5f374 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)
0x503000000298 is located 0 bytes after 24-byte region
[0x503000000280,0x503000000298)
allocated by thread T0 here:
#0 0x7836138fd9c7 in malloc
../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x5b468328f864 in xmalloc ../../libiberty/xmalloc.c:149
#2 0x5b4682ea6bdf in display_debug_lines_decoded
../../binutils/dwarf.c:6721
#3 0x5b4682eaa0cb in display_debug_lines ../../binutils/dwarf.c:7225
#4 0x5b4682e731f5 in dump_dwarf_section ../../binutils/objdump.c:4516
#5 0x5b4682fdb924 in bfd_map_over_sections ../../bfd/section.c:1369
#6 0x5b4682e7371a in dump_dwarf_info ../../binutils/objdump.c:4593
#7 0x5b4682e737a2 in dump_dwarf ../../binutils/objdump.c:4601
#8 0x5b4682e79fb4 in dump_bfd ../../binutils/objdump.c:5893
#9 0x5b4682e7a374 in display_object_bfd ../../binutils/objdump.c:5971
#10 0x5b4682e7a696 in display_any_bfd ../../binutils/objdump.c:6050
#11 0x5b4682e7a706 in display_file ../../binutils/objdump.c:6071
#12 0x5b4682e7c222 in main ../../binutils/objdump.c:6494
#13 0x78361342a1c9 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
#14 0x78361342a28a in __libc_start_main_impl ../csu/libc-start.c:360
#15 0x5b4682e5f374 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 ../../binutils/dwarf.c:6726 in
display_debug_lines_decoded
Shadow bytes around the buggy address:
0x503000000000: fa fa 00 00 00 fa fa fa 00 00 00 06 fa fa fd fd
0x503000000080: fd fd fa fa fd fd fd fd fa fa 00 00 00 03 fa fa
0x503000000100: 00 00 00 00 fa fa fd fd fd fd fa fa fd fd fd fd
0x503000000180: fa fa 00 00 00 00 fa fa 00 00 00 fa fa fa fd fd
0x503000000200: fd fa fa fa fd fd fd fa fa fa 00 00 00 fa fa fa
=>0x503000000280: 00 00 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa
0x503000000300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x503000000380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x503000000400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x503000000480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x503000000500: 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
==1381546==ABORTING
```
## Potential fix
Stop parsing when the entry counter would overflow or cannot be represented in
the corresponding allocation. The decoder emits a warning and does not enter
the vulnerable second pass.
```diff
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
@@
+ if (n_files == UINT_MAX
+ || n_files >= (size_t) -1 / sizeof (*file_table))
+ {
+ warn (_("too many files in line table\n"));
+ free (directory_table);
+ return 0;
+ }
n_files++;
```
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.