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]
