Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PR] avfilter/vf_convolution: various heap over/underflow fixes (PR #21368)
@ 2026-01-03 20:56 Timo Rothenpieler via ffmpeg-devel
  0 siblings, 0 replies; only message in thread
From: Timo Rothenpieler via ffmpeg-devel @ 2026-01-03 20:56 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Timo Rothenpieler

PR #21368 opened by Timo Rothenpieler (BtbN)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21368
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21368.patch

Without all this extra clamping, the filter would happily over- and underflow the input and output image buffers.

Fixes #YWH-PGM40646-36


>From 8e2079c53e35a99a81382f2428862153f3a4d928 Mon Sep 17 00:00:00 2001
From: Timo Rothenpieler <timo@rothenpieler.org>
Date: Sat, 3 Jan 2026 21:23:02 +0100
Subject: [PATCH 1/3] avfilter/vf_convolution: clamp column and row offsets to
 actual width/height of buffer

Otherwise the buffer might be dramatically under or over-read.
---
 libavfilter/vf_convolution.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c
index ce42df2cde..2c4f706449 100644
--- a/libavfilter/vf_convolution.c
+++ b/libavfilter/vf_convolution.c
@@ -554,7 +554,7 @@ static void setup_row(int radius, const uint8_t *c[], const uint8_t *src, int st
     for (i = 0; i < radius * 2 + 1; i++) {
         int xoff = FFABS(x + i - radius);
 
-        xoff = xoff >= w ? 2 * w - 1 - xoff : xoff;
+        xoff = FFMIN(FFMAX(xoff >= w ? 2 * w - 1 - xoff : xoff, 0), w - 1);
 
         c[i] = src + xoff * bpc + y * stride;
     }
@@ -568,7 +568,7 @@ static void setup_column(int radius, const uint8_t *c[], const uint8_t *src, int
     for (i = 0; i < radius * 2 + 1; i++) {
         int xoff = FFABS(x + i - radius);
 
-        xoff = xoff >= h ? 2 * h - 1 - xoff : xoff;
+        xoff = FFMIN(FFMAX(xoff >= h ? 2 * h - 1 - xoff : xoff, 0), h - 1);
 
         c[i] = src + y * bpc + xoff * stride;
     }
-- 
2.49.1


>From a16db608a5246c82f660db4f2b80776887ecbc43 Mon Sep 17 00:00:00 2001
From: Timo Rothenpieler <timo@rothenpieler.org>
Date: Sat, 3 Jan 2026 21:45:41 +0100
Subject: [PATCH 2/3] avfilter/vf_convolution: don't over-read input stride in
 filter_column

---
 libavfilter/vf_convolution.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c
index 2c4f706449..81f66dcdac 100644
--- a/libavfilter/vf_convolution.c
+++ b/libavfilter/vf_convolution.c
@@ -502,11 +502,12 @@ static void filter_column(uint8_t *dst, int height,
         memset(sum, 0, sizeof(sum));
 
         for (int i = 0; i < 2 * radius + 1; i++) {
-            for (int off16 = 0; off16 < 16; off16++)
+            for (int off16 = 0; off16 < 16 && off16 < stride; off16++) {
                 sum[off16] += c[i][0 + y * stride + off16] * matrix[i];
+            }
         }
 
-        for (int off16 = 0; off16 < 16; off16++) {
+        for (int off16 = 0; off16 < 16 && off16 < stride && off16 < dstride; off16++) {
             sum[off16] = (int)(sum[off16] * rdiv + bias + 0.5f);
             dst[off16] = av_clip_uint8(sum[off16]);
         }
-- 
2.49.1


>From 9f5c6a8f6de328af4d577d9156d7acdb0b10f0ae Mon Sep 17 00:00:00 2001
From: Timo Rothenpieler <timo@rothenpieler.org>
Date: Sat, 3 Jan 2026 21:53:23 +0100
Subject: [PATCH 3/3] avfilter/vf_convolution: clamp x and y offsets to actual
 width/height of the image

Without this, if the input/output are sufficiently small enough, this
will over-write and read the buffers by however much the radius or
slice-size is.

Fixes #YWH-PGM40646-36
---
 libavfilter/vf_convolution.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c
index 81f66dcdac..2902d6117e 100644
--- a/libavfilter/vf_convolution.c
+++ b/libavfilter/vf_convolution.c
@@ -615,12 +615,16 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
             continue;
         }
         for (y = slice_start; y < slice_end; y += step) {
-            const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : radius * bpc;
-            const int yoff = mode == MATRIX_COLUMN ? radius * dstride : 0;
+            int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : radius * bpc;
+            int yoff = mode == MATRIX_COLUMN ? radius * dstride : 0;
+            xoff = FFMIN(FFMAX(xoff, 0), width);
+            yoff = FFMIN(FFMAX(yoff, 0), height);
 
             for (x = 0; x < radius; x++) {
-                const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
-                const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
+                int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
+                int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
+                xoff = FFMIN(FFMAX(xoff, 0), width);
+                yoff = FFMIN(FFMAX(yoff, 0), height);
 
                 s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
                 s->filter[plane](dst + yoff + xoff, 1, rdiv,
@@ -632,8 +636,10 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
                              rdiv, bias, matrix, c, s->max, radius,
                              dstride, stride, slice_end - step);
             for (x = sizew - radius; x < sizew; x++) {
-                const int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
-                const int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
+                int xoff = mode == MATRIX_COLUMN ? (y - slice_start) * bpc : x * bpc;
+                int yoff = mode == MATRIX_COLUMN ? x * dstride : 0;
+                xoff = FFMIN(FFMAX(xoff, 0), width);
+                yoff = FFMIN(FFMAX(yoff, 0), height);
 
                 s->setup[plane](radius, c, src, stride, x, width, y, height, bpc);
                 s->filter[plane](dst + yoff + xoff, 1, rdiv,
-- 
2.49.1

_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-01-03 20:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-03 20:56 [FFmpeg-devel] [PR] avfilter/vf_convolution: various heap over/underflow fixes (PR #21368) Timo Rothenpieler via ffmpeg-devel

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git