GNU Bison obprintf.c Assertion Failure

Xudong Cao <[email protected]> Fri, 25 Jul 2025 14:24:19 +0800
Newsgroups gmane.comp.parsers.bison.bugs
Message-ID <CAKEs_LKcM7Sum1cC4fjFKVJjW7UDZFcoBzuOyaEZA=SuZ41Yng@mail.gmail.com>
## Description

GNU Bison contains a critical assertion failure in the
`__obstack_vprintf_internal` function within `obprintf.c:158`. When
processing specially crafted grammar files containing malformed `$variable`
references, the program triggers an assertion failure that causes immediate
program termination with SIGABRT.

## Technical Analysis

### Stack Trace
```
#0 __pthread_kill_implementation (no_tid=3D0, signo=3D6,
threadid=3D140737351530368) at ./nptl/pthread_kill.c:44
#1 __pthread_kill_internal (signo=3D6, threadid=3D140737351530368) at
./nptl/pthread_kill.c:78
#2 __GI___pthread_kill (threadid=3D140737351530368, signo=3Dsigno@entry=3D6=
) at
./nptl/pthread_kill.c:89
#3 0x00007ffff7dc8476 in __GI_raise (sig=3Dsig@entry=3D6) at
../sysdeps/posix/raise.c:26
#4 0x00007ffff7dae7f3 in __GI_abort () at ./stdlib/abort.c:79
#5 0x00007ffff7dae71b in __assert_fail_base (fmt=3D0x7ffff7f63130 "%s%s%s:%=
u:
%s%sAssertion `%s' failed.\n%n", assertion=3D0x7ffff7f63c08 "size =3D=3D
(new_f.ofile.file.file._IO_write_end -
new_f.ofile.file.file._IO_write_base)", file=3D0x7ffff7f5f416 "obprintf.c",
line=3D158, function=3D<optimized out>) at ./assert/assert.c:94
#6 0x00007ffff7dbfe96 in __GI___assert_fail
(assertion=3Dassertion@entry=3D0x7ffff7f63c08
"size =3D=3D (new_f.ofile.file.file._IO_write_end -
new_f.ofile.file.file._IO_write_base)", file=3Dfile@entry=3D0x7ffff7f5f416
"obprintf.c", line=3Dline@entry=3D158, function=3Dfunction@entry=3D0x7ffff7=
f67740
<__PRETTY_FUNCTION__.1> "__obstack_vprintf_internal") at
./assert/assert.c:103
#7 0x00007ffff7e0e81a in __obstack_vprintf_internal (obstack=3D0x5555558656=
c0
<obstack_for_string>, format=3D0x55555555fab8 "]b4_lhs_value(orig %d, ",
args=3Dargs@entry=3D0x7fffffff8200, mode_flags=3D2) at ./libio/obprintf.c:1=
58
#8 0x00007ffff7ebc353 in __obstack_printf_chk (obstack=3D<optimized out>,
flag=3D<optimized out>, format=3D<optimized out>) at ./debug/obprintf_chk.c=
:34
#9 0x00005555555f8c8b in handle_action_dollar (rule=3D0x555555887510,
text=3D<optimized out>, dollar_loc=3D<optimized out>) at src/scan-code.l:66=
1
#10 code_lex (self=3D0x5555558875a8, sc_context=3D<optimized out>) at
src/scan-code.l:171
#11 translate_action (self=3D0x5555558875a8, sc_context=3D<optimized out>) =
at
src/scan-code.l:768
#12 0x00005555555f8c8b in code_props_translate_code (self=3D0x5555558875a8)
#13 0x00005555555f0ffc in check_and_convert_grammar () at src/reader.c:1002
#14 reader (gram=3D<optimized out>) at src/reader.c:772
#15 0x00005555555a4f52 in main (argc=3D<optimized out>, argv=3D0x7fffffffdc=
e8)
at src/main.c:118
```

### Root Cause Analysis

The vulnerability exists in Bison's obstack (object stack) buffer
management system. During grammar processing, the `handle_action_dollar`
function calls `obstack_printf` to format output strings. The assertion
failure occurs when the obstack's internal state becomes inconsistent:

**Failed Assertion**: `size =3D=3D (new_f.ofile.file.file._IO_write_end -
new_f.ofile.file.file._IO_write_base)`

This indicates that the difference between `_IO_write_end` and
`_IO_write_base` pointers does not match the expected buffer size,
suggesting corruption in the obstack's internal pointer management.

### Call Chain Analysis
1. `main()` =E2=86=92 `reader()` =E2=86=92 `check_and_convert_grammar()`
2. `code_props_translate_code()` =E2=86=92 `translate_action()`
3. `code_lex()` =E2=86=92 `handle_action_dollar()` (src/scan-code.l:661)
4. `__obstack_printf_chk()` =E2=86=92 `__obstack_vprintf_internal()`
5. **Assertion failure** at obprintf.c:158

## Proof of Concept

The vulnerability can be triggered using the provided POC file:

**File**: `POC_bison_obprintf_assertion_failure`[
https://drive.google.com/file/d/1iId0E6HVYNwqLsS5nARQexj5TQqzcnej/view?usp=
=3Ddrive_link
]

**Reproduction Steps**:
1. Execute: `bison POC_bison_obprintf_assertion_failure`
2. Observe the assertion failure and program crash
3. Verify SIGABRT signal is generated

**Expected Output**:
```
bison: obprintf.c:158: __obstack_vprintf_internal: Assertion `size =3D=3D
(new_f.ofile.file.file._IO_write_end -
new_f.ofile.file.file._IO_write_base)' failed.
Aborted (core dumped)
```

## Vulnerability Confirmation

This vulnerability has been confirmed through:
- GDB stack trace analysis showing consistent crash location
- Multiple POC files triggering identical assertion failures
- Reproducible crash across different input variations

The assertion failure demonstrates a fundamental buffer management issue in
Bison's core processing logic, making this a legitimate security
vulnerability affecting program reliability.

### Credit
Xudong Cao (UCAS)
Yuqing Zhang (UCAS, Zhongguancun Laboratory)