filter-graph: protect against large values

Limit the delay in the convolver to 10 seconds.

Limit the convolver block sizes to 64K.

Avoid overflows when using large rates, file size or number of
channels in the provided impulse response.
This commit is contained in:
Wim Taymans 2026-04-29 11:02:11 +02:00
parent 72b9577d3c
commit eaaf125d13
2 changed files with 24 additions and 11 deletions

View file

@ -124,7 +124,7 @@ static struct partition *partition_new(struct convolver *conv, int block,
struct spa_fga_dsp *dsp = conv->dsp; struct spa_fga_dsp *dsp = conv->dsp;
int i, j; int i, j;
if (block == 0) if (block <= 0)
return NULL; return NULL;
part = calloc(1, sizeof(*part)); part = calloc(1, sizeof(*part));
@ -283,7 +283,8 @@ struct convolver *convolver_new_many(struct spa_fga_dsp *dsp, int head_block, in
if (head_block == 0 || tail_block == 0) if (head_block == 0 || tail_block == 0)
return NULL; return NULL;
head_block = SPA_MAX(1, head_block); head_block = SPA_CLAMP(head_block, 1, (1<<16));
tail_block = SPA_CLAMP(tail_block, 1, (1<<16));
if (head_block > tail_block) if (head_block > tail_block)
SPA_SWAP(head_block, tail_block); SPA_SWAP(head_block, tail_block);

View file

@ -826,7 +826,7 @@ static void impulse_clear(struct impulse *ir)
static int finfo_read_samples(struct plugin *pl, struct finfo *info, struct impulse *ir) static int finfo_read_samples(struct plugin *pl, struct finfo *info, struct impulse *ir)
{ {
float *samples, v; float *samples, v;
int i, n, h, delay = (int)(ir->delay * info->rate); int i, n, h, delay = (int)(ir->delay * info->rate), alloc_size;
if (ir->length <= 0) if (ir->length <= 0)
ir->length = info->def_frames; ir->length = info->def_frames;
@ -835,11 +835,13 @@ static int finfo_read_samples(struct plugin *pl, struct finfo *info, struct impu
ir->length -= SPA_MIN(ir->offset, ir->length); ir->length -= SPA_MIN(ir->offset, ir->length);
n = delay + ir->length; if (spa_overflow_add(delay, ir->length, &n) || n == 0)
if (n == 0)
return -EINVAL; return -EINVAL;
samples = calloc(n * info->channels, sizeof(float)); if (spa_overflow_mul(n, info->channels, &alloc_size))
return -ENOMEM;
samples = calloc(alloc_size, sizeof(float));
if (samples == NULL) if (samples == NULL)
return -errno; return -errno;
@ -948,10 +950,15 @@ static float *resample_buffer(struct plugin *pl, float *samples, int *n_samples,
#ifdef HAVE_SPA_PLUGINS #ifdef HAVE_SPA_PLUGINS
uint32_t in_len, out_len, total_out = 0; uint32_t in_len, out_len, total_out = 0;
int out_n_samples; int out_n_samples;
float *out_samples, *out_buf, *in_buf; float *out_samples = NULL, *out_buf, *in_buf;
struct resample r; struct resample r;
int res; int res;
if (*n_samples <= 0 || in_rate == 0 || out_rate == 0) {
errno = EINVAL;
return NULL;
}
spa_zero(r); spa_zero(r);
r.channels = 1; r.channels = 1;
r.i_rate = in_rate; r.i_rate = in_rate;
@ -961,10 +968,15 @@ static float *resample_buffer(struct plugin *pl, float *samples, int *n_samples,
if ((res = resample_native_init(&r)) < 0) { if ((res = resample_native_init(&r)) < 0) {
spa_log_error(pl->log, "resampling failed: %s", spa_strerror(res)); spa_log_error(pl->log, "resampling failed: %s", spa_strerror(res));
errno = -res; errno = -res;
return NULL; goto error;
} }
out_n_samples = SPA_ROUND_UP(*n_samples * out_rate, in_rate) / in_rate; if (spa_overflow_mul(*n_samples, out_rate, &out_n_samples) ||
spa_overflow_add(out_n_samples, in_rate-1, &out_n_samples)) {
errno = ENOMEM;
goto error;
}
out_n_samples /= in_rate;
out_samples = calloc(out_n_samples, sizeof(float)); out_samples = calloc(out_n_samples, sizeof(float));
if (out_samples == NULL) if (out_samples == NULL)
goto error; goto error;
@ -1099,8 +1111,8 @@ static int convolver_read_impulse(struct plugin *pl, struct spa_json *obj,
goto error; goto error;
} }
if (ir->delay < 0.0f) /* 10 seconds delay max */
ir->delay = 0.0f; ir->delay = SPA_CLAMPF(ir->delay, 0.0f, 10.0f);
if (ir->offset < 0) if (ir->offset < 0)
ir->offset = 0; ir->offset = 0;