[PR] avfilter/afir: bound the crossfades by the samples of the input frame (PR #24100)

michaelni via ffmpeg-devel <[email protected]>
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178649380250.59.17442946400255284192@29965ddac10e>
PR #24100 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24100
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24100.patch

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: 1835f884b7ae475d2079d044003966981823502e
Found-by: Eunsoo Kim, Microsoft FORGE Labs

# Summary of changes

Briefly describe what this PR does and why.

<!--
If this PR requires new FATE test samples, attach them to the PR and
list their target paths below (relative to the fate-suite root).

Attached filenames must match the sample's filename:

```fate-samples
# e.g. vorbis/new-sample.ogg
```
-->



>From a1a7f6b543373f036156fe896e8c78ecc99e7863 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Wed, 12 Aug 2026 01:57:57 +0200
Subject: [PATCH] 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: 1835f884b7ae475d2079d044003966981823502e
Found-by: Eunsoo Kim, Microsoft FORGE Labs
---
 libavfilter/afir_template.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/libavfilter/afir_template.c b/libavfilter/afir_template.c
index c45b29902e..10dc677c20 100644
--- a/libavfilter/afir_template.c
+++ b/libavfilter/afir_template.c
@@ -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);
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.