PR #25854 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25854
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25854.patch


>From 3ec3fb92b82fa92673cf22a82e0d5053147375c0 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 6 Nov 2026 22:51:53 +0100
Subject: [PATCH 1/6] avfilter/vf_spp: index the QP table by macroblock for all
 chroma subsamplings

Fixes: heap-buffer-overflow
Fixes: cxHWRwP1s1BE

Found-by: SecBuddyF, Tencent KeenLab (CodeBuddy Security)

Heap out of array read Replicated through UnModified FFmpeg with ASAN
---
 libavfilter/vf_spp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavfilter/vf_spp.c b/libavfilter/vf_spp.c
index 20c9fd43401..1f369ad67fa 100644
--- a/libavfilter/vf_spp.c
+++ b/libavfilter/vf_spp.c
@@ -282,8 +282,9 @@ static void filter(SPPContext *p, uint8_t *dst, uint8_t 
*src,
             if (p->qp) {
                 qp = p->qp;
             } else{
-                const int qps = 3 + is_luma;
-                qp = qp_table[(FFMIN(x, width - 1) >> qps) + (FFMIN(y, height 
- 1) >> qps) * qp_stride];
+                const int qpsh = 4 - p->hsub * !is_luma;
+                const int qpsv = 4 - p->vsub * !is_luma;
+                qp = qp_table[(FFMIN(x, width - 1) >> qpsh) + (FFMIN(y, height 
- 1) >> qpsv) * qp_stride];
                 qp = FFMAX(1, ff_norm_qscale(qp, p->qscale_type));
             }
             for (i = 0; i < count; i++) {
-- 
2.54.0


>From 0db23a42db2f19c24e4d45642169d846eb9fe746 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 6 Nov 2026 22:51:53 +0100
Subject: [PATCH 2/6] avfilter/vf_pp7: index the QP table by macroblock for all
 chroma subsamplings

Fixes: heap-buffer-overflow
Fixes: cxHWRwP1s1BE

Found-by: SecBuddyF, Tencent KeenLab (CodeBuddy Security)

Heap out of array read Replicated through UnModified FFmpeg with ASAN
---
 libavfilter/vf_pp7.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavfilter/vf_pp7.c b/libavfilter/vf_pp7.c
index a2ad3752273..a33ff29ce1a 100644
--- a/libavfilter/vf_pp7.c
+++ b/libavfilter/vf_pp7.c
@@ -231,14 +231,15 @@ static void filter(PP7Context *p, uint8_t *dst, const 
uint8_t *src,
             dctA_c(tp + 4 * 8, p_src + index, stride);
         }
         for (x = 0; x < width; ) {
-            const int qps = 3 + is_luma;
+            const int qpsh = 4 - p->hsub * !is_luma;
+            const int qpsv = 4 - p->vsub * !is_luma;
             int qp;
             int end = FFMIN(x + 8, width);
 
             if (p->qp)
                 qp = p->qp;
             else {
-                qp = qp_store[ (FFMIN(x, width - 1) >> qps) + (FFMIN(y, height 
- 1) >> qps) * qp_stride];
+                qp = qp_store[ (FFMIN(x, width - 1) >> qpsh) + (FFMIN(y, 
height - 1) >> qpsv) * qp_stride];
                 qp = ff_norm_qscale(qp, p->qscale_type);
             }
             for (; x < end; x++) {
-- 
2.54.0


>From b583b809511a3fb49d3957d795f7dbe4a91628aa Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 6 Nov 2026 23:58:54 +0100
Subject: [PATCH 3/6] avfilter/vf_owdenoise: copy planes with the correct
 dimensions

Fixes: heap-buffer-overflow
Fixes: GGSK9ga7taB4
Fixes: RHcGTqZzYSqy

Found-by: SecBuddyF, Tencent KeenLab (CodeBuddy Security)
The report covers both errors in the chroma plane copies; the width in
samples of the luma plane was found during triage of the report.

Heap out of array read Replicated through UnModified FFmpeg with ASAN
---
 libavfilter/vf_owdenoise.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libavfilter/vf_owdenoise.c b/libavfilter/vf_owdenoise.c
index 55d6dd0f22f..4d02f8eba1d 100644
--- a/libavfilter/vf_owdenoise.c
+++ b/libavfilter/vf_owdenoise.c
@@ -151,6 +151,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     AVFrame *out;
     const int cw = AV_CEIL_RSHIFT(inlink->w, s->hsub);
     const int ch = AV_CEIL_RSHIFT(inlink->h, s->vsub);
+    const int bytes_per_sample = (s->pixel_depth + 7) / 8;
 
     if (av_frame_is_writable(in)) {
         out = in;
@@ -172,14 +173,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         if (s->luma_strength > 0) {
             filter(s, out->data[0], out->linesize[0], in->data[0], 
in->linesize[0], inlink->w, inlink->h, s->luma_strength);
         } else {
-            av_image_copy_plane(out->data[0], out->linesize[0], in ->data[0], 
in ->linesize[0], inlink->w, inlink->h);
+            av_image_copy_plane(out->data[0], out->linesize[0], in ->data[0], 
in ->linesize[0], inlink->w * bytes_per_sample, inlink->h);
         }
         if (s->chroma_strength > 0) {
             filter(s, out->data[1], out->linesize[1], in->data[1], 
in->linesize[1], cw, ch, s->chroma_strength);
             filter(s, out->data[2], out->linesize[2], in->data[2], 
in->linesize[2], cw, ch, s->chroma_strength);
         } else {
-            av_image_copy_plane(out->data[1], out->linesize[1], in ->data[1], 
in ->linesize[1], inlink->w, inlink->h);
-            av_image_copy_plane(out->data[2], out->linesize[2], in ->data[2], 
in ->linesize[2], inlink->w, inlink->h);
+            av_image_copy_plane(out->data[1], out->linesize[1], in ->data[1], 
in ->linesize[1], cw * bytes_per_sample, ch);
+            av_image_copy_plane(out->data[2], out->linesize[2], in ->data[2], 
in ->linesize[2], cw * bytes_per_sample, ch);
         }
 
         if (in->data[3])
-- 
2.54.0


>From 812d0979c337dc7ae040fe55fb182bd07c27dd42 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 6 Nov 2026 22:57:48 +0100
Subject: [PATCH 4/6] avformat/rtsp: do not pass a media without stream to
 ff_real_parse_sdp_a_line()

Fixes: heap-buffer-overflow
Fixes: sRHeb0Z1vF6q

Found-by: SecBuddyF, Tencent KeenLab (CodeBuddy Security)

Heap out of array read Replicated through UnModified FFmpeg with ASAN
---
 libavformat/rtsp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c
index 29f219c366a..9bc389c4526 100644
--- a/libavformat/rtsp.c
+++ b/libavformat/rtsp.c
@@ -743,7 +743,7 @@ static void sdp_parse_line(AVFormatContext *s, 
SDPParseState *s1,
             if (s->nb_streams > 0) {
                 rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1];
 
-                if (rt->server_type == RTSP_SERVER_REAL)
+                if (rt->server_type == RTSP_SERVER_REAL && 
rtsp_st->stream_index >= 0)
                     ff_real_parse_sdp_a_line(s, rtsp_st->stream_index, p);
 
                 if (rtsp_st->dynamic_handler &&
-- 
2.54.0


>From f2a260a35aaa9ddc54cf6131675e1b1d1cfe2314 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 6 Nov 2026 23:13:42 +0100
Subject: [PATCH 5/6] avfilter/af_adeclick: check the size of the interpolation
 matrix

Fixes: signed integer overflow: 65537 * 65537 cannot be represented in type 
'int'
Fixes: out of array write
Fixes: gqEpoZGEUAEO

Found-by: SecBuddyF, Tencent KeenLab (CodeBuddy Security)

Out of array write Replicated through UnModified FFmpeg with ASAN and UBSAN
---
 libavfilter/af_adeclick.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavfilter/af_adeclick.c b/libavfilter/af_adeclick.c
index 198e7fab633..ffd0bfbaa31 100644
--- a/libavfilter/af_adeclick.c
+++ b/libavfilter/af_adeclick.c
@@ -399,6 +399,9 @@ static int interpolation(DeclickChannel *c, const double 
*src, int ar_order,
     double *vector, *matrix;
     int i, j;
 
+    if (nb_errors > INT_MAX / sizeof(*c->matrix) / nb_errors)
+        return AVERROR(ENOMEM);
+
     av_fast_malloc(&c->matrix, &c->matrix_size, nb_errors * nb_errors * 
sizeof(*c->matrix));
     matrix = c->matrix;
     if (!matrix)
-- 
2.54.0


>From 0c201eea800da022e34cba153a63f508965bf452 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 6 Nov 2026 23:22:12 +0100
Subject: [PATCH 6/6] avfilter/vf_fillborders: do not copy more than the plane
 width in margins mode

Fixes: heap-buffer-overflow
Fixes: 1fWderspZvGT

Found-by: SecBuddyF, Tencent KeenLab (CodeBuddy Security)

Heap out of array write Replicated through UnModified FFmpeg with ASAN
---
 libavfilter/vf_fillborders.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/libavfilter/vf_fillborders.c b/libavfilter/vf_fillborders.c
index 3ba009dae47..9ad8432662e 100644
--- a/libavfilter/vf_fillborders.c
+++ b/libavfilter/vf_fillborders.c
@@ -498,6 +498,7 @@ static void margins_borders8(FillBordersContext *s, AVFrame 
*frame)
         const int bottom = s->borders[p].bottom;
         const int width = s->planewidth[p];
         const int height = s->planeheight[p];
+        const int tail_width = FFMIN(width, 8);
 
         for (int y = top; y < height - bottom; y++) {
             memset(ptr + linesize * y, ptr[linesize * y + left], left);
@@ -506,7 +507,7 @@ static void margins_borders8(FillBordersContext *s, AVFrame 
*frame)
 
         for (int y = top - 1; y >= 0; y--) {
             ptr[linesize * y] = ptr[linesize * (y + 1)];
-            memcpy(ptr + linesize * y + width - 8, ptr + linesize * (y + 1) + 
width - 8, 8);
+            memcpy(ptr + linesize * y + width - tail_width, ptr + linesize * 
(y + 1) + width - tail_width, tail_width);
 
             for (int x = 1; x < width - 8; x++) {
                 int prev = ptr[linesize * (y + 1) + x - 1];
@@ -519,7 +520,7 @@ static void margins_borders8(FillBordersContext *s, AVFrame 
*frame)
 
         for (int y = height - bottom; y < height; y++) {
             ptr[linesize * y] = ptr[linesize * (y - 1)];
-            memcpy(ptr + linesize * y + width - 8, ptr + linesize * (y - 1) + 
width - 8, 8);
+            memcpy(ptr + linesize * y + width - tail_width, ptr + linesize * 
(y - 1) + width - tail_width, tail_width);
 
             for (int x = 1; x < width - 8; x++) {
                 int prev = ptr[linesize * (y - 1) + x - 1];
@@ -543,6 +544,7 @@ static void margins_borders16(FillBordersContext *s, 
AVFrame *frame)
         const int bottom = s->borders[p].bottom;
         const int width = s->planewidth[p];
         const int height = s->planeheight[p];
+        const int tail_width = FFMIN(width, 8);
 
         for (int y = top; y < height - bottom; y++) {
             for (int x = 0; x < left; x++)
@@ -554,7 +556,7 @@ static void margins_borders16(FillBordersContext *s, 
AVFrame *frame)
 
         for (int y = top - 1; y >= 0; y--) {
             ptr[linesize * y] = ptr[linesize * (y + 1)];
-            memcpy(ptr + linesize * y + width - 8, ptr + linesize * (y + 1) + 
width - 8, 16);
+            memcpy(ptr + linesize * y + width - tail_width, ptr + linesize * 
(y + 1) + width - tail_width, tail_width * 2);
 
             for (int x = 1; x < width - 8; x++) {
                 int prev = ptr[linesize * (y + 1) + x - 1];
@@ -567,7 +569,7 @@ static void margins_borders16(FillBordersContext *s, 
AVFrame *frame)
 
         for (int y = height - bottom; y < height; y++) {
             ptr[linesize * y] = ptr[linesize * (y - 1)];
-            memcpy(ptr + linesize * y + width - 8, ptr + linesize * (y - 1) + 
width - 8, 16);
+            memcpy(ptr + linesize * y + width - tail_width, ptr + linesize * 
(y - 1) + width - tail_width, tail_width * 2);
 
             for (int x = 1; x < width - 8; x++) {
                 int prev = ptr[linesize * (y - 1) + x - 1];
-- 
2.54.0

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

Reply via email to