https://sourceware.org/bugzilla/show_bug.cgi?id=34664

            Bug ID: 34664
           Summary: Heap-buffer-overflow read in STABS enum-value copying
                    (`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 17023
  --> https://sourceware.org/bugzilla/attachment.cgi?id=17023&action=edit
The `artifacts.zip` package includes the PoC generation script, the sanitizer
report, the bug report, and the candidate patch

## Vulnerability description

On a 32-bit build with 64-bit BFD enabled, a pointer is four bytes while
`bfd_signed_vma` is eight. `parse_stab_enum_type` allocates and copies the enum
value array using `sizeof (*names)` rather than `sizeof (*values)`. The later
enum printer treats the undersized allocation as 64-bit values and reads past
it.

```c
xvalues = debug_xalloc (dhandle, (n + 1) * sizeof (*names));
memcpy (xvalues, values, (n + 1) * sizeof (*names));
```

## Version and commit

GNU Binutils 2.47.50, commit `d715260f420066befb2d30ec8f5befcdf7ecfd84`
(2026-09-08).

## Environment

Ubuntu 24.04.4 LTS on x86_64, using an i686 AddressSanitizer build with 64-bit
BFD enabled; GCC 13.3.0 and Python 3.12.3.

## Steps to reproduce

1. Install the native build prerequisites plus 32-bit compiler and libc
development support:

   ```sh
   sudo apt-get update
   sudo apt-get install -y build-essential bison flex texinfo python3 \
       gcc-multilib g++-multilib libc6-dev-i386 \
       libgmp-dev libmpfr-dev libmpc-dev zlib1g-dev
   ```

2. Obtain the affected revision and make a 32-bit AddressSanitizer build with
64-bit BFD enabled:

   ```sh
   export SRC="$PWD/binutils-gdb"
   git clone https://sourceware.org/git/binutils-gdb.git "$SRC"
   git -C "$SRC" checkout d715260f420066befb2d30ec8f5befcdf7ecfd84
   mkdir "$SRC/build-i686-asan" && cd "$SRC/build-i686-asan"
   CC='gcc -m32' CXX='g++ -m32' \
   CFLAGS='-O1 -g -m32 -fsanitize=address -static-libasan
-fno-omit-frame-pointer' \
   LDFLAGS='-m32 -fsanitize=address -static-libasan' \
   "$SRC/configure" --target=i686-linux-gnu --enable-targets=all
--enable-64-bit-bfd \
       --disable-gdb --disable-gdbserver --disable-sim --disable-gas
--disable-ld \
       --disable-gold --disable-gprof --disable-gprofng --disable-nls
--disable-werror --without-zlib
   make -j"$(nproc)" all-binutils
   export BUILD="$SRC/build-i686-asan"
   ```

3. Place the supplied `poc-stabs.o` in a writable directory:

   ```sh
   export WORK="$PWD/poc-work"
   mkdir -p "$WORK"
   cp poc-stabs.o "$WORK/"
   ```

4. Trigger the fault:

   ```sh
   ASAN_OPTIONS=detect_leaks=0:abort_on_error=1 \
     "$BUILD/binutils/objdump" --debugging "$WORK/poc-stabs.o" >/dev/null
   ```

## Sanitizer report

The following is the complete, unmodified contents of `sanitizer_report.txt`.

```text
=================================================================
==2412617==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xe762e238
at pc 0x5c29daab bp 0xffda45a8 sp 0xffda4598
READ of size 8 at 0xe762e238 thread T0
    #0 0x5c29daaa in pr_enum_type
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/prdbg.c:632
    #1 0x5c2b0609 in debug_write_type
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/debug.c:2557
    #2 0x5c2b15f3 in debug_write_type
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/debug.c:2656
    #3 0x5c2b181e in debug_write_name
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/debug.c:2380
    #4 0x5c2b35b5 in debug_write
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/debug.c:2352
    #5 0x5c2a3727 in print_debugging_info
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/prdbg.c:296
    #6 0x5c2401b8 in dump_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:5920
    #7 0x5c24070d in display_object_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:5971
    #8 0x5c24070d in display_any_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6050
    #9 0x5c24088b in display_file
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6071
    #10 0x5c242bc6 in main
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6494
    #11 0xe9b09c74 
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task57_access177/sysroot/usr/lib32/libc.so.6+0x24c74)
(BuildId: a6ac4013957ce900e167743cd60a25daff1344bb)
    #12 0xe9b09d37 in __libc_start_main
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task57_access177/sysroot/usr/lib32/libc.so.6+0x24d37)
(BuildId: a6ac4013957ce900e167743cd60a25daff1344bb)
    #13 0x5c0fa976 in _start
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task57_access177/build32-asan/binutils/objdump+0x554976)
(BuildId: eba6e450aa82f75dd183943d97439ec4c01df4ea)

0xe762e23c is located 0 bytes after 4412-byte region [0xe762d100,0xe762e23c)
allocated by thread T0 here:
    #0 0x5c1c37cb in malloc
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task57_access177/build32-asan/binutils/objdump+0x61d7cb)
(BuildId: eba6e450aa82f75dd183943d97439ec4c01df4ea)
    #1 0x5d6bf491 in _objalloc_alloc
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/libiberty/objalloc.c:143
    #2 0x5c6b71af in bfd_alloc
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/bfd/libbfd.c:453
    #3 0x5c2cbd9e in bfd_xalloc
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/bucomm.c:152
    #4 0x5c2a61a8 in debug_xalloc
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/debug.c:679
    #5 0x5c2be4e0 in parse_stab_enum_type
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/stabs.c:2111
    #6 0x5c2be4e0 in parse_stab_type
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/stabs.c:1626
    #7 0x5c2c640c in parse_stab_string
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/stabs.c:1051
    #8 0x5c2c640c in parse_stab
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/stabs.c:688
    #9 0x5c2a4ef4 in read_section_stabs_debugging_info
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/rddbg.c:244
    #10 0x5c2a4ef4 in read_debugging_info
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/rddbg.c:59
    #11 0x5c24014a in dump_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:5917
    #12 0x5c24070d in display_object_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:5971
    #13 0x5c24070d in display_any_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6050
    #14 0x5c24088b in display_file
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6071
    #15 0x5c242bc6 in main
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6494
    #16 0xe9b09c74 
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task57_access177/sysroot/usr/lib32/libc.so.6+0x24c74)
(BuildId: a6ac4013957ce900e167743cd60a25daff1344bb)

SUMMARY: AddressSanitizer: heap-buffer-overflow
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/prdbg.c:632
in pr_enum_type
Shadow bytes around the buggy address:
  0xe762df80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0xe762e000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0xe762e080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0xe762e100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0xe762e180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0xe762e200: 00 00 00 00 00 00 00[04]fa fa fa fa fa fa fa fa
  0xe762e280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0xe762e300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0xe762e380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0xe762e400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0xe762e480: 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
==2412617==ABORTING
```

## Potential fix

Allocate and copy `xvalues` using the element type actually stored in it. The
change is architecture-independent and preserves the number of enum members.

```diff
diff --git a/binutils/stabs.c b/binutils/stabs.c
@@
-  xvalues = debug_xalloc (dhandle, (n + 1) * sizeof (*names));
-  memcpy (xvalues, values, (n + 1) * sizeof (*names));
+  xvalues = debug_xalloc (dhandle, (n + 1) * sizeof (*values));
+  memcpy (xvalues, values, (n + 1) * sizeof (*values));
```

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.

Reply via email to