avfilter/afir: bound the crossfades by the samples of the input frame

Fixes: ffmpeg -i tail.wav -i ir.wav -filter_complex "[0][1]afir=dry=1:wet=1:enable='lte(t,0.5)'" -f null -

Fixes: out of array access
Fixes: uQcNui1HxUqe
Regression since: 1835f884b7
Found-by: Eunsoo Kim, Microsoft FORGE Labs
This commit is contained in:
Michael Niedermayer authored and michaelni committed 2026-08-12 01:05:04 +00:00
1 parent cfaaf0062c
commit a681001244
1 file changed
+8 -6
+8 -6
View File
@@ -140,7 +140,7 @@ static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int ioffs
const ftype *in = (const ftype *)s->in->extended_data[ch] + ioffset;
ftype *blockout, *ptr = (ftype *)out->extended_data[ch] + offset;
const int min_part_size = s->min_part_size;
const int nb_samples = FFMIN(min_part_size, out->nb_samples - offset);
const int nb_samples = FFMIN(min_part_size, s->in->nb_samples - ioffset);
const int nb_segments = s->nb_segments[selir];
const float dry_gain = s->dry_gain;
const float wet_gain = s->wet_gain;
@@ -246,6 +246,8 @@ static void fn(fir_quantums)(AVFilterContext *ctx, AudioFIRContext *s, AVFrame *
int min_part_size, int ch, int offset,
int prev_selir, int selir)
{
const int nb_samples = FFMIN(min_part_size, s->in->nb_samples - offset);
if (ctx->is_disabled || s->prev_is_disabled) {
const ftype *in = (const ftype *)s->in->extended_data[ch] + offset;
const ftype *xfade0 = (const ftype *)s->xfade[0]->extended_data[ch];
@@ -257,15 +259,15 @@ static void fn(fir_quantums)(AVFilterContext *ctx, AudioFIRContext *s, AVFrame *
if (ctx->is_disabled && !s->prev_is_disabled) {
memset(src0, 0, min_part_size * sizeof(ftype));
fn(fir_quantum)(ctx, s->fadein[0], ch, offset, 0, selir);
for (int n = 0; n < min_part_size; n++)
for (int n = 0; n < nb_samples; n++)
dst[n] = xfade1[n] * src0[n] + xfade0[n] * in[n];
} else if (!ctx->is_disabled && s->prev_is_disabled) {
memset(src1, 0, min_part_size * sizeof(ftype));
fn(fir_quantum)(ctx, s->fadein[1], ch, offset, 0, selir);
for (int n = 0; n < min_part_size; n++)
for (int n = 0; n < nb_samples; n++)
dst[n] = xfade1[n] * in[n] + xfade0[n] * src1[n];
} else {
memcpy(dst, in, sizeof(ftype) * min_part_size);
memcpy(dst, in, sizeof(ftype) * nb_samples);
}
} else if (prev_selir != selir && s->loading[ch] != 0) {
const ftype *xfade0 = (const ftype *)s->xfade[0]->extended_data[ch];
@@ -281,11 +283,11 @@ static void fn(fir_quantums)(AVFilterContext *ctx, AudioFIRContext *s, AVFrame *
fn(fir_quantum)(ctx, s->fadein[1], ch, offset, 0, selir);
if (s->loading[ch] > s->max_offset[selir]) {
for (int n = 0; n < min_part_size; n++)
for (int n = 0; n < nb_samples; n++)
dst[n] = xfade1[n] * src0[n] + xfade0[n] * src1[n];
s->loading[ch] = 0;
} else {
memcpy(dst, src0, min_part_size * sizeof(ftype));
memcpy(dst, src0, nb_samples * sizeof(ftype));
}
} else {
fn(fir_quantum)(ctx, out, ch, offset, offset, selir);