Skip to content

Commit a9ff7ee

Browse files
committed
math: auditory: guard mod_psy_get_mel_filterbank() against zero divisors
The mel-bin loop in mod_psy_get_mel_filterbank() divides by delta_cl and delta_rc on every FFT bin, and by (right_hz - left_hz) when slaney normalization is enabled. With unusual configurations these denominators can become zero or negative — for example when start_freq >= end_freq, when the requested mel_bins is large enough that integer division truncates the mel step to zero, or at extreme inputs where psy_mel_to_hz saturates and right_hz no longer exceeds left_hz. Reject such configurations explicitly. After computing mel_step, return -EINVAL if it is not positive, which also covers both delta values since they equal mel_step. In the slaney_normalize branch, also verify right_hz > left_hz before computing the scale factor. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent 462cfb5 commit a9ff7ee

1 file changed

Lines changed: 29 additions & 0 deletions

File tree

src/math/auditory/auditory.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@
1212
#include <sof/math/fft.h>
1313
#include <sof/math/log.h>
1414
#include <sof/math/numbers.h>
15+
#include <sof/trace/trace.h>
1516
#include <ipc/topology.h>
1617
#include <errno.h>
1718
#include <stdint.h>
1819

20+
LOG_MODULE_REGISTER(math_auditory, CONFIG_SOF_LOG_LEVEL);
21+
1922
#define ONE_Q16 Q_CONVERT_FLOAT(1, 16)
2023
#define ONE_Q20 Q_CONVERT_FLOAT(1, 20)
2124
#define ONE_Q30 Q_CONVERT_FLOAT(1, 30)
@@ -148,7 +151,28 @@ int mod_psy_get_mel_filterbank(struct processing_module *mod, struct psy_mel_fil
148151

149152
mel_start = psy_hz_to_mel(fb->start_freq);
150153
mel_end = psy_hz_to_mel(fb->end_freq);
154+
/* fb->mel_bins is used both as the loop bound and as part of the
155+
* (mel_bins + 1) divisor below. Reject non-positive values up front to
156+
* avoid a divide by zero (mel_bins == -1) and to keep mel_step
157+
* meaningful.
158+
*/
159+
if (fb->mel_bins <= 0) {
160+
comp_cl_err(mod->dev, "Invalid mel_bins %d", fb->mel_bins);
161+
return -EINVAL;
162+
}
163+
151164
mel_step = (mel_end - mel_start) / (fb->mel_bins + 1);
165+
/* delta_cl / delta_rc below are both equal to mel_step; guard against
166+
* a non-positive step (start_freq >= end_freq, or so many bins that
167+
* the integer division truncates to zero) before using them as
168+
* divisors.
169+
*/
170+
if (mel_step <= 0) {
171+
comp_cl_err(mod->dev, "Invalid mel_step %d (start_freq=%d end_freq=%d mel_bins=%d)",
172+
mel_step, fb->start_freq, fb->end_freq, fb->mel_bins);
173+
return -EINVAL;
174+
}
175+
152176
for (i = 0; i < fb->mel_bins; i++) {
153177
left_mel = mel_start + i * mel_step;
154178
center_mel = mel_start + (i + 1) * mel_step;
@@ -160,6 +184,11 @@ int mod_psy_get_mel_filterbank(struct processing_module *mod, struct psy_mel_fil
160184
if (fb->slaney_normalize) {
161185
left_hz = psy_mel_to_hz(left_mel);
162186
right_hz = psy_mel_to_hz(right_mel);
187+
if (right_hz <= left_hz) {
188+
comp_cl_err(mod->dev, "Invalid Hz range left=%d right=%d at mel bin %d",
189+
left_hz, right_hz, i);
190+
return -EINVAL;
191+
}
163192
scale = Q_SHIFT_RND(TWO_Q29 / (right_hz - left_hz), 29, 16); /* Q16.16*/
164193
if (i == 0) {
165194
scale_inv = Q_SHIFT_LEFT(ONE_Q30 / scale, 14, 16);

0 commit comments

Comments
 (0)