PR #22587 opened by Zhao Zhili (quink) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22587 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22587.patch
When zx == -width (or zy == -height), the expression zx % width + width * (zx < 0) yields width instead of a value in [0, width), causing OOB read. Fix by only adding width when -width < zx < 0. For slideright and slidedown where z is always non-negative, simply drop the dead correction. Also guard squeezeh/squeezev against division by zero when progress == 0. Fixes: #22273 Co-authored-by: scriptituk <[email protected]> Signed-off-by: Zhao Zhili <[email protected]> >From edc7148ed696fbc58cad0f2e6ca7b86873fd7039 Mon Sep 17 00:00:00 2001 From: Zhao Zhili <[email protected]> Date: Mon, 23 Mar 2026 16:29:07 +0800 Subject: [PATCH] avfilter/vf_xfade: fix out-of-bounds index in slide/cover/reveal transitions When zx == -width (or zy == -height), the expression zx % width + width * (zx < 0) yields width instead of a value in [0, width), causing OOB read. Fix by only adding width when -width < zx < 0. For slideright and slidedown where z is always non-negative, simply drop the dead correction. Also guard squeezeh/squeezev against division by zero when progress == 0. Fixes: #22273 Co-authored-by: scriptituk <[email protected]> Signed-off-by: Zhao Zhili <[email protected]> --- libavfilter/vf_xfade.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index 4517e4e6b3..2e2521197f 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -469,7 +469,7 @@ static void slideleft##name##_transition(AVFilterContext *ctx, for (int y = 0; y < height; y++) { \ for (int x = 0; x < width; x++) { \ const int zx = z + x; \ - const int zz = zx % width + width * (zx < 0); \ + const int zz = zx % width + width * (zx < 0 && zx > -width); \ dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \ } \ \ @@ -502,7 +502,7 @@ static void slideright##name##_transition(AVFilterContext *ctx, for (int y = 0; y < height; y++) { \ for (int x = 0; x < width; x++) { \ const int zx = z + x; \ - const int zz = zx % width + width * (zx < 0); \ + const int zz = zx % width; \ dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \ } \ \ @@ -532,7 +532,7 @@ static void slideup##name##_transition(AVFilterContext *ctx, \ for (int y = slice_start; y < slice_end; y++) { \ const int zy = z + y; \ - const int zz = zy % height + height * (zy < 0); \ + const int zz = zy % height + height * (zy < 0 && zy > -height); \ const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ \ @@ -564,7 +564,7 @@ static void slidedown##name##_transition(AVFilterContext *ctx, \ for (int y = slice_start; y < slice_end; y++) { \ const int zy = z + y; \ - const int zz = zy % height + height * (zy < 0); \ + const int zz = zy % height; \ const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ \ @@ -1633,7 +1633,7 @@ static void squeezeh##name##_transition(AVFilterContext *ctx, for (int y = 0; y < height; y++) { \ const float z = .5f + ((slice_start + y) / h - .5f) / progress; \ \ - if (z < 0.f || z > 1.f) { \ + if (progress <= 0.f || z < 0.f || z > 1.f) { \ for (int x = 0; x < width; x++) \ dst[x] = xf1[x]; \ } else { \ @@ -1673,7 +1673,7 @@ static void squeezev##name##_transition(AVFilterContext *ctx, for (int x = 0; x < width; x++) { \ const float z = .5f + (x / w - .5f) / progress; \ \ - if (z < 0.f || z > 1.f) { \ + if (progress <= 0.f || z < 0.f || z > 1.f) { \ dst[x] = xf1[x]; \ } else { \ const int xx = lrintf(z * (w - 1.f)); \ @@ -1884,7 +1884,7 @@ static void cover##dir##name##_transition(AVFilterContext *ctx, for (int y = 0; y < height; y++) { \ for (int x = 0; x < width; x++) { \ const int zx = z + x; \ - const int zz = zx % width + width * (zx < 0); \ + const int zz = zx % width + width * (zx < 0 && zx > -width); \ dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[x]; \ } \ \ @@ -1916,7 +1916,7 @@ static void cover##dir##name##_transition(AVFilterContext *ctx, \ for (int y = slice_start; y < slice_end; y++) { \ const int zy = z + y; \ - const int zz = zy % height + height * (zy < 0); \ + const int zz = zy % height + height * (zy < 0 && zy > -height); \ const type *xf0 = (const type *)(a->data[p] + y * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ \ @@ -1952,7 +1952,7 @@ static void reveal##dir##name##_transition(AVFilterContext *ctx, for (int y = 0; y < height; y++) { \ for (int x = 0; x < width; x++) { \ const int zx = z + x; \ - const int zz = zx % width + width * (zx < 0); \ + const int zz = zx % width + width * (zx < 0 && zx > -width); \ dst[x] = (zx >= 0) && (zx < width) ? xf1[x] : xf0[zz]; \ } \ \ @@ -1984,7 +1984,7 @@ static void reveal##dir##name##_transition(AVFilterContext *ctx, \ for (int y = slice_start; y < slice_end; y++) { \ const int zy = z + y; \ - const int zz = zy % height + height * (zy < 0); \ + const int zz = zy % height + height * (zy < 0 && zy > -height); \ const type *xf0 = (const type *)(a->data[p] + zz * a->linesize[p]); \ const type *xf1 = (const type *)(b->data[p] + y * b->linesize[p]); \ \ -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
