From a075929b91ddec8fcae7e3a68be24195fe8dc86c Mon Sep 17 00:00:00 2001 From: Sebastian Alba Date: Mon, 27 Apr 2026 19:38:16 -0600 Subject: [PATCH] whisper: validate mel filter dimensions to prevent integer overflow 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 --- src/whisper.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/whisper.cpp b/src/whisper.cpp index 2f356da0f06..33cd8b49da7 100644 --- a/src/whisper.cpp +++ b/src/whisper.cpp @@ -1580,7 +1580,23 @@ static bool whisper_model_load(struct whisper_model_loader * loader, whisper_con read_safe(loader, filters.n_mel); read_safe(loader, filters.n_fft); - filters.data.resize(filters.n_mel * filters.n_fft); + // Validate dimensions to prevent integer overflow in the resize() multiplication + // below and to ensure consistency with hparams.n_mels. + if (filters.n_mel <= 0 || filters.n_mel > 1024 || + filters.n_fft <= 0 || filters.n_fft > WHISPER_N_FFT) { + WHISPER_LOG_ERROR("%s: invalid mel filter dimensions (n_mel=%d, n_fft=%d)\n", + __func__, filters.n_mel, filters.n_fft); + return false; + } + + if (filters.n_mel != hparams.n_mels) { + WHISPER_LOG_ERROR("%s: mel filter n_mel=%d does not match hparams n_mels=%d\n", + __func__, filters.n_mel, hparams.n_mels); + return false; + } + + const size_t total_size = (size_t)filters.n_mel * (size_t)filters.n_fft; + filters.data.resize(total_size); loader->read(loader->context, filters.data.data(), filters.data.size() * sizeof(float)); BYTESWAP_FILTERS(filters); }