whisper: validate mel filter dimensions to prevent integer overflow#3780
Open
Sebasteuo wants to merge 1 commit intoggml-org:masterfrom
Open
whisper: validate mel filter dimensions to prevent integer overflow#3780Sebasteuo wants to merge 1 commit intoggml-org:masterfrom
Sebasteuo wants to merge 1 commit intoggml-org:masterfrom
Conversation
The mel filter loading code in whisper_model_load() multiplies filters.n_mel * filters.n_fft (both int32_t) without bounds checking or overflow protection before passing the result to filters.data.resize(). When the model file declares dimensions whose product exceeds INT32_MAX (e.g. n_mel=65537, n_fft=65536), the multiplication overflows int32_t to a small value, causing an undersized heap allocation. Subsequent reads in log_mel_spectrogram_worker_thread() then access filter data out of bounds (heap-buffer-overflow READ). This commit: - Adds explicit bounds validation for n_mel and n_fft against reasonable upper limits (1024 and WHISPER_N_FFT respectively) - Adds consistency check between filters.n_mel and hparams.n_mels, promoting an existing downstream assert to upstream validation - Uses size_t for the allocation size computation to avoid the int32_t overflow even within the validated bounds The pre-existing assert at line ~3114 (n_fft == 1 + (frame_size / 2)) is a no-op in release builds (-DNDEBUG), so it does not protect against this in production deployments. Signed-off-by: Sebastian Alba <Sebasjosue84@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds bounds validation to the mel filter loading code in
whisper_model_load()to prevent an integer overflow that leads to an undersized heap allocation and out-of-bounds read.The bug
In
src/whisper.cpp, the original code was:Both
filters.n_melandfilters.n_fftareint32_tread directly from the model file with no validation. When the model declares dimensions whose product exceedsINT32_MAX(e.g.n_mel=65537,n_fft=65536), the multiplication overflowsint32_tto a small value, the buffer is allocated undersized, and subsequent reads inlog_mel_spectrogram_worker_thread()(line ~3136) access data out of the allocated region.The pre-existing assert at line ~3114 (
n_fft == 1 + (frame_size / 2)) is a no-op in release builds compiled with-DNDEBUG, so it does not protect production deployments.Reproduction (high level)
A crafted ggml model file with attacker-controlled
n_melandn_fftheaders triggers the overflow during model loading. Confirmed with AddressSanitizer on aarch64 and x86_64 (Ubuntu 24.04) againstwhisper-clibuilt with:cmake .. -DCMAKE_CXX_FLAGS="-fsanitize=address -g -O1"
-DCMAKE_C_FLAGS="-fsanitize=address -g -O1"
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address"
-DBUILD_SHARED_LIBS=OFF
ASAN reports
heap-buffer-overflow READ of size 4inlog_mel_spectrogram_worker_thread(src/whisper.cpp:3136), located 0 bytes after the undersized region allocated atfilters.data.resize(...).The fix
This PR makes three changes inside the existing mel filters loading block:
Bounds check on the raw dimensions before any multiplication:
n_melin[1, 1024]andn_fftin[1, WHISPER_N_FFT]. These ranges comfortably accommodate all current and reasonable future Whisper variants while making the integer-overflow path unreachable.Consistency check between
filters.n_melandhparams.n_mels. This invariant was already implicitly relied upon by the assert atsrc/whisper.cpp:2386(mel_inp.n_mel == wctx.model.hparams.n_mels); promoting it to upstream validation makes the failure mode explicit and works in release builds.size_tcast for the allocation size so that even within the validated bounds, the multiplication is performed in 64-bit precision, defending against any future changes to the bounds.On invalid input the function logs a clear error and returns
false, matching the existing error-handling pattern inwhisper_model_load().Disclosure note
This issue was reported privately to the maintainer email on 2026-03-30 and re-pinged on 2026-04-17. I am opening this PR to facilitate the fix in case the private channel is no longer being monitored. The patch itself is minimal and self-contained; no exploit details, PoC, or crafted model file are included in this PR. I am happy to coordinate further on CVE assignment / advisory wording / disclosure timing as the maintainers prefer.
Testing
whisper_model_load()and only adds validation around an already-existingresizecall; no behavioral change for valid model files.whisper_model_load()(see e.g. existing checks atsrc/whisper.cpp:1500andsrc/whisper.cpp:1557).Happy to add a regression test if helpful, in this PR or as a follow-up.