https://sourceware.org/bugzilla/show_bug.cgi?id=34660
Bug ID: 34660
Summary: Heap-buffer-overflow read in PE import-thunk printing
(`bfd/peXXigen.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 17019
--> https://sourceware.org/bugzilla/attachment.cgi?id=17019&action=edit
The `artifacts.zip` package includes the PoC generation script, the sanitizer
report, the bug report, and the candidate patch
## Vulnerability description
`pe_print_idata` converts untrusted PE virtual addresses into offsets in an
import-data buffer. The first-thunk offset is stored in a signed `int`; a large
address truncates or becomes negative. Subtracting that value from `datasize`
yields an enormous remaining length, and later thunk reads reach before or
beyond the allocation.
```c
int ft_idx;
ft_idx = first_thunk - adj;
ft_data = data + ft_idx;
ft_datasize = datasize - ft_idx;
```
The supplied sparse PE file drives `objdump -p` into an out-of-bounds 32-bit
thunk read.
## 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 an AddressSanitizer build; the input declares a roughly
4 GB import-data range.
## 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_pe_import_ftidx.py` in a writable directory and
generate the sparse PE input:
```sh
export WORK="$PWD/poc-work"
mkdir -p "$WORK"
python3 gen_pe_import_ftidx.py "$WORK/sample.elf"
```
4. Trigger the fault:
```sh
ASAN_OPTIONS=detect_leaks=0:abort_on_error=1 \\
"$BUILD/binutils/objdump" -p "$WORK/sample.elf" >/dev/null
```
## Sanitizer report
The following is the complete, unmodified contents of `sanitizer_report.txt`.
```text
=================================================================
==557528==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x760c43fff7fe at pc 0x6201dc651073 bp 0x7ffea72dca70 sp 0x7ffea72dca60
READ of size 1 at 0x760c43fff7fe thread T0
#0 0x6201dc651072 in bfd_getl32 ../../bfd/libbfd.c:846
#1 0x6201dc877899 in pe_print_idata ../../bfd/peXXigen.c:1551
#2 0x6201dc87f864 in _bfd_pex64_print_private_bfd_data_common
../../bfd/peXXigen.c:3014
#3 0x6201dc893d85 in pe_print_private_bfd_data ../../bfd/peicode.h:358
#4 0x6201dc4f4eab in dump_bfd_private_header ../../binutils/objdump.c:5078
#5 0x6201dc4f8b26 in dump_bfd ../../binutils/objdump.c:5817
#6 0x6201dc4f9374 in display_object_bfd ../../binutils/objdump.c:5971
#7 0x6201dc4f9696 in display_any_bfd ../../binutils/objdump.c:6050
#8 0x6201dc4f9706 in display_file ../../binutils/objdump.c:6071
#9 0x6201dc4fb222 in main ../../binutils/objdump.c:6494
#10 0x760d47c2a1c9 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
#11 0x760d47c2a28a in __libc_start_main_impl ../csu/libc-start.c:360
#12 0x6201dc4de374 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)
0x760c43fff7fe is located 2 bytes before 4294967295-byte region
[0x760c43fff800,0x760d43fff7ff)
allocated by thread T0 here:
#0 0x760d480fd9c7 in malloc
../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x6201dc650243 in bfd_malloc ../../bfd/libbfd.c:291
#2 0x6201dc647930 in bfd_get_full_section_contents ../../bfd/compress.c:763
#3 0x6201dc65b240 in bfd_malloc_and_get_section ../../bfd/section.c:1644
#4 0x6201dc876b3f in pe_print_idata ../../bfd/peXXigen.c:1393
#5 0x6201dc87f864 in _bfd_pex64_print_private_bfd_data_common
../../bfd/peXXigen.c:3014
#6 0x6201dc893d85 in pe_print_private_bfd_data ../../bfd/peicode.h:358
#7 0x6201dc4f4eab in dump_bfd_private_header ../../binutils/objdump.c:5078
#8 0x6201dc4f8b26 in dump_bfd ../../binutils/objdump.c:5817
#9 0x6201dc4f9374 in display_object_bfd ../../binutils/objdump.c:5971
#10 0x6201dc4f9696 in display_any_bfd ../../binutils/objdump.c:6050
#11 0x6201dc4f9706 in display_file ../../binutils/objdump.c:6071
#12 0x6201dc4fb222 in main ../../binutils/objdump.c:6494
#13 0x760d47c2a1c9 in __libc_start_call_main
../sysdeps/nptl/libc_start_call_main.h:58
#14 0x760d47c2a28a in __libc_start_main_impl ../csu/libc-start.c:360
#15 0x6201dc4de374 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 ../../bfd/libbfd.c:846 in
bfd_getl32
Shadow bytes around the buggy address:
0x760c43fff500: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x760c43fff580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x760c43fff600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x760c43fff680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x760c43fff700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x760c43fff780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]
0x760c43fff800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x760c43fff880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x760c43fff900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x760c43fff980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x760c43fffa00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==557528==ABORTING
```
## Potential fix
Use `bfd_size_type` for derived offsets and reject underflowing or out-of-range
virtual-address-to-buffer translations before pointer arithmetic. Apply the
same check when the thunk table resides in another section.
```diff
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
@@
- int ft_idx;
+ bfd_size_type ft_idx;
@@
+ if (first_thunk < (bfd_vma) adj || first_thunk - adj > datasize)
+ continue;
ft_idx = first_thunk - adj;
ft_data = data + ft_idx;
ft_datasize = datasize - ft_idx;
```
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.