PR #23492 opened by Bogdan Lisman (bogdanpydev)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23492
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23492.patch

For an edge block, get_block_rd() copies the full-OBMC-weight central
region directly from cur[] into the reconstruction.  It moved one
boundary to block_w/block_h but overwrote the in-plane clip (x0/x1/y0/y1
computed earlier from the plane size) instead of intersecting with it.
When a plane is narrower than block_w - e.g. a tiny field/chroma plane
produced by the mcdeint filter - the right-edge case left x0 = block_w
while x1 stayed clipped to w - sx < block_w, so x1 - x0 became negative
and was passed to memcpy() as a huge size_t, crashing with SIGSEGV.

Intersect the moved boundaries with the existing clip so the copy region
stays inside the plane and the memcpy length can never be negative.

Reproducible with the GPL mcdeint filter in slow/extra_slow mode, e.g.

    ffmpeg -f lavfi -i testsrc=s=5x32 -vf mcdeint=mode=slow -f null -

This is a separate crash from the get_dc() SIGFPE (ticket #7779) reached
through the same iterative_me() path.  Add a lavfi-based FATE regression
test.

Signed-off-by: Bogdan Lisman <[email protected]>

# 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 77d4ac5f89b16ade995c6e15207189be58839a70 Mon Sep 17 00:00:00 2001
From: Bogdan Lisman <[email protected]>
Date: Mon, 15 Jun 2026 04:07:59 +0300
Subject: [PATCH] avcodec/snowenc: fix out-of-bounds memcpy in get_block_rd()
 for narrow planes

For an edge block, get_block_rd() copies the full-OBMC-weight central
region directly from cur[] into the reconstruction.  It moved one
boundary to block_w/block_h but overwrote the in-plane clip (x0/x1/y0/y1
computed earlier from the plane size) instead of intersecting with it.
When a plane is narrower than block_w - e.g. a tiny field/chroma plane
produced by the mcdeint filter - the right-edge case left x0 = block_w
while x1 stayed clipped to w - sx < block_w, so x1 - x0 became negative
and was passed to memcpy() as a huge size_t, crashing with SIGSEGV.

Intersect the moved boundaries with the existing clip so the copy region
stays inside the plane and the memcpy length can never be negative.

Reproducible with the GPL mcdeint filter in slow/extra_slow mode, e.g.

    ffmpeg -f lavfi -i testsrc=s=5x32 -vf mcdeint=mode=slow -f null -

This is a separate crash from the get_dc() SIGFPE (ticket #7779) reached
through the same iterative_me() path.  Add a lavfi-based FATE regression
test.

Signed-off-by: Bogdan Lisman <[email protected]>
---
 libavcodec/snowenc.c                    | 9 +++++----
 tests/fate/filter-video.mak             | 3 +++
 tests/ref/fate/filter-mcdeint-slow-edge | 8 ++++++++
 3 files changed, 16 insertions(+), 4 deletions(-)
 create mode 100644 tests/ref/fate/filter-mcdeint-slow-edge

diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index 29a1f114c3..fbc2d05b92 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -819,13 +819,14 @@ static int get_block_rd(SnowEncContext *enc, int mb_x, 
int mb_y,
     if ((mb_x == 0 || mb_x == b_stride-1) &&
         (mb_y == 0 || mb_y == b_height-1)){
         if(mb_x == 0)
-            x1 = block_w;
+            x1 = FFMIN(x1, block_w);
         else
-            x0 = block_w;
+            x0 = FFMAX(x0, block_w);
         if(mb_y == 0)
-            y1 = block_h;
+            y1 = FFMIN(y1, block_h);
         else
-            y0 = block_h;
+            y0 = FFMAX(y0, block_h);
+        x0 = FFMIN(x0, x1);
         for(y=y0; y<y1; y++)
             memcpy(dst + sx+x0 + (sy+y)*ref_stride, cur + x0 + y*ref_stride, 
x1-x0);
     }
diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak
index af9c374e1c..374e50b966 100644
--- a/tests/fate/filter-video.mak
+++ b/tests/fate/filter-video.mak
@@ -51,6 +51,9 @@ fate-filter-mcdeint-medium: CMD = framecrc -flags bitexact 
-idct simple -i $(TAR
 
 FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, MCDEINT, MPEGTS, MPEG2VIDEO, 
SNOW_ENCODER) += $(FATE_MCDEINT)
 
+FATE_FILTER-$(call FILTERFRAMECRC, MCDEINT TESTSRC, SNOW_ENCODER) += 
fate-filter-mcdeint-slow-edge
+fate-filter-mcdeint-slow-edge: CMD = framecrc -auto_conversion_filters -flags 
bitexact -lavfi testsrc=s=5x32:r=25:d=1,mcdeint=mode=slow -frames:v 3
+
 FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, CODECVIEW, RM, RV40) += 
fate-filter-codecview-mvs
 fate-filter-codecview-mvs: CMD = framecrc -flags2 +export_mvs -i 
$(TARGET_SAMPLES)/real/spygames-2MB.rmvb -vf codecview=mv=pf+bf+bb -frames:v 60 
-an
 
diff --git a/tests/ref/fate/filter-mcdeint-slow-edge 
b/tests/ref/fate/filter-mcdeint-slow-edge
new file mode 100644
index 0000000000..c6411b3ada
--- /dev/null
+++ b/tests/ref/fate/filter-mcdeint-slow-edge
@@ -0,0 +1,8 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: rawvideo
+#dimensions 0: 5x32
+#sar 0: 1/1
+0,          0,          0,        1,      480, 0xe8a1f302
+0,          1,          1,        1,      480, 0x0789f31c
+0,          2,          2,        1,      480, 0x113af329
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to