SEGV in whisper_free_state via uninitialized whisper_batch pointer
## Summary
A SEGV (null/wild pointer dereference) occurs in `whisper_free_state()` at `src/whisper.cpp:3824` when error cleanup frees an uninitialized `whisper_batch` structure. When `whisper_init_state()` fails during KV cache initialization, `whisper_batch` fields contain uninitialized memory, and the subsequent `whisper_batch_free()` call attempts to free wild pointers.
CWE-824 (Access of Uninitialized Pointer), CVSS 6.5 (Medium).
## Tested version
- Commit: `fc67457` (current `master` HEAD, 2026-04-20)
- Build: cmake with `-fsanitize=address,undefined -fno-omit-frame-pointer -g`
- Platform: Ubuntu 22.04 x86_64, GCC 11
## Root cause
In `whisper_init_state()`, `whisper_batch` is allocated as part of `whisper_state` but not zero-initialized before error paths that call cleanup:
```cpp
// whisper.cpp:3392 (error path in whisper_init_state)
whisper_free_state(state); // state->batch contains uninitialized memory
// whisper.cpp:3824 (in whisper_free_state)
whisper_batch_free(state->batch); // frees wild pointers
// whisper.cpp:499 (in whisper_batch_free)
free(batch.token); // wild pointer → SEGV
```
When `kv_cache_init()` fails (e.g., due to corrupted model parameters), the error cleanup path calls `whisper_free_state()`, which tries to free `state->batch.token` — a pointer that was never initialized.
## ASAN output
```
==3137759==ERROR: AddressSanitizer: SEGV on unknown address
The signal is caused by a READ memory access.
Hint: this fault was caused by a dereference of a high value address.
#0 in __asan::Allocator::Deallocate
#1 in __interceptor_free
#2 in whisper_batch_free(whisper_batch) whisper.cpp:499
#3 in whisper_free_state whisper.cpp:3824
#4 in whisper_init_state whisper.cpp:3392
#5 in whisper_init_from_file_with_params whisper.cpp:3741
```
## Suggested fix
Zero-initialize `whisper_batch` before any error path can trigger cleanup:
```cpp
// In whisper_init_state(), after allocating state:
state->batch = {}; // or memset(&state->batch, 0, sizeof(state->batch));
```
Or add a null check in `whisper_batch_free()`:
```cpp
void whisper_batch_free(struct whisper_batch batch) {
if (batch.token) free(batch.token);
if (batch.embd) free(batch.embd);
// ...
}
```
## Impact
- **Denial of Service**: Crafted model file crashes any application using whisper.cpp model loading
- **Potential UAF**: If the uninitialized pointer happens to point to a valid-but-freed heap region, this becomes a use-after-free with potential code execution impact
## Disclosure
These vulnerabilities were found via generative fuzzing with a custom harness. The report was polished with AI assistance.
PoC file will be provided via gist link in comment below.
1 条评论