PR #23511 opened by Bogdan Lisman (bogdanpydev)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23511
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23511.patch
get_dc() folds the OBMC window weight of an off-plane neighbour block
back onto the boundary pixel via obmc[index +/- block_w] and
obmc[index +/- block_h*obmc_stride]. These reads assume the plane is at
least one block wide and tall. When a plane is narrower or shorter than
a block - e.g. a tiny field/chroma plane produced by the mcdeint filter,
or simply a small frame encoded with -motion_est iter - the folded index
leaves the ff_obmc_tab[] array and is read out of bounds (AddressSanitizer
global-buffer-overflow).
This is the overflow that the existing fate-filter-mcdeint-slow-edge test
triggers under AddressSanitizer.
Only fold in the neighbour weight when its index stays inside the window;
outside the window that weight is zero, so every in-bounds case is
unchanged and all existing output stays bit-exact.
Reproducible without the mcdeint/GPL path, e.g.
ffmpeg -f lavfi -i testsrc=s=30x20 -c:v snow -motion_est iter -f null -
Add a self-contained lavfi 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 1d536edb922e00a755501b7174204c1ff904a784 Mon Sep 17 00:00:00 2001
From: Bogdan Lisman <[email protected]>
Date: Wed, 17 Jun 2026 03:00:06 +0300
Subject: [PATCH] avcodec/snowenc: fix out-of-bounds read of ff_obmc_tab in
get_dc()
get_dc() folds the OBMC window weight of an off-plane neighbour block
back onto the boundary pixel via obmc[index +/- block_w] and
obmc[index +/- block_h*obmc_stride]. These reads assume the plane is at
least one block wide and tall. When a plane is narrower or shorter than
a block - e.g. a tiny field/chroma plane produced by the mcdeint filter,
or simply a small frame encoded with -motion_est iter - the folded index
leaves the ff_obmc_tab[] array and is read out of bounds (AddressSanitizer
global-buffer-overflow).
This is the overflow that the existing fate-filter-mcdeint-slow-edge test
triggers under AddressSanitizer.
Only fold in the neighbour weight when its index stays inside the window;
outside the window that weight is zero, so every in-bounds case is
unchanged and all existing output stays bit-exact.
Reproducible without the mcdeint/GPL path, e.g.
ffmpeg -f lavfi -i testsrc=s=30x20 -c:v snow -motion_est iter -f null -
Add a self-contained lavfi FATE regression test.
Signed-off-by: Bogdan Lisman <[email protected]>
---
libavcodec/snowenc.c | 12 ++++++++----
tests/fate/video.mak | 5 +++++
tests/ref/fate/snow-enc-edge | 7 +++++++
3 files changed, 20 insertions(+), 4 deletions(-)
create mode 100644 tests/ref/fate/snow-enc-edge
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index fbc2d05b92..9ba6a4d08f 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -708,10 +708,14 @@ static int get_dc(SnowEncContext *enc, int mb_x, int
mb_y, int plane_index)
int index= x2-(block_w*mb_x - block_w/2) + (y2-(block_h*mb_y -
block_h/2))*obmc_stride;
int obmc_v= obmc[index];
int d;
- if(y<0) obmc_v += obmc[index + block_h*obmc_stride];
- if(x<0) obmc_v += obmc[index + block_w];
- if(y+block_h>h) obmc_v += obmc[index - block_h*obmc_stride];
- if(x+block_w>w) obmc_v += obmc[index - block_w];
+ if(y<0 && index + block_h*obmc_stride <
obmc_stride*obmc_stride)
+ obmc_v += obmc[index + block_h*obmc_stride];
+ if(x<0 && index + block_w < obmc_stride*obmc_stride)
+ obmc_v += obmc[index + block_w];
+ if(y+block_h>h && index >= block_h*obmc_stride)
+ obmc_v += obmc[index - block_h*obmc_stride];
+ if(x+block_w>w && index >= block_w)
+ obmc_v += obmc[index - block_w];
//FIXME precalculate this or simplify it somehow else
d = -dst[index] + (1<<(FRAC_BITS-1));
diff --git a/tests/fate/video.mak b/tests/fate/video.mak
index 10d1b20cd5..de41ffab13 100644
--- a/tests/fate/video.mak
+++ b/tests/fate/video.mak
@@ -168,6 +168,11 @@ FATE_DXVENC_FMT = dxt1
FATE_VIDEO-$(call FILTERFRAMECRC, TESTSRC2, DXV_ENCODER) +=
$(FATE_DXVENC_FMT:%=fate-dxv3enc-%)
fate-dxvenc: $(FATE_DXVENC_FMT:%=fate-dxv3enc-%)
+# Encode a plane narrower/shorter than an OBMC block with iterative motion
+# estimation; exercises the get_dc() plane-edge handling (snowenc.c).
+FATE_VIDEO-$(call FILTERFRAMECRC, TESTSRC, SNOW_ENCODER) += fate-snow-enc-edge
+fate-snow-enc-edge: CMD = framecrc -auto_conversion_filters -flags bitexact
-lavfi testsrc=s=30x20:r=25:d=1 -frames:v 2 -c:v snow -motion_est iter
+
FATE_VIDEO-$(call FRAMECRC, SEGAFILM, CINEPAK) += fate-film-cvid
fate-film-cvid: CMD = framecrc -i $(TARGET_SAMPLES)/film/logo-capcom.cpk -an
diff --git a/tests/ref/fate/snow-enc-edge b/tests/ref/fate/snow-enc-edge
new file mode 100644
index 0000000000..a996d4dc72
--- /dev/null
+++ b/tests/ref/fate/snow-enc-edge
@@ -0,0 +1,7 @@
+#tb 0: 1/25
+#media_type 0: video
+#codec_id 0: snow
+#dimensions 0: 30x20
+#sar 0: 1/1
+0, 0, 0, 1, 888, 0x52b4b640, S=1, Quality stats,
8, 0x05ec00be
+0, 1, 1, 1, 36, 0x48321166, F=0x0, S=1, Quality
stats, 8, 0x076800ee
--
2.52.0
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]