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


>From 412a25cf62abc749200872609ea1b1f76d7f462b Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 14 Sep 2026 03:32:13 +0200
Subject: [PATCH 1/3] avcodec/proresenc_kostya: fill macroblock rows past the
 end of the bottom field

Fixes: ftWCoBQxUw0P
Fixes: out of array read
Found-by: Zheng Yu @ Depthfirst
---
 libavcodec/proresenc_kostya.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c
index ccb41c0d23..847a47bd2c 100644
--- a/libavcodec/proresenc_kostya.c
+++ b/libavcodec/proresenc_kostya.c
@@ -323,7 +323,7 @@ static int encode_slice(AVCodecContext *avctx, const 
AVFrame *pic,
     int i, xp, yp;
     int total_size = 0;
     const uint16_t *src;
-    int num_cblocks, pwidth, line_add;
+    int num_cblocks, pwidth, line_add, picture_height;
     ptrdiff_t linesize;
     int is_chroma;
     uint16_t *qmat;
@@ -334,6 +334,10 @@ static int encode_slice(AVCodecContext *avctx, const 
AVFrame *pic,
     else
         line_add = ctx->cur_picture_idx ^ !(pic->flags & 
AV_FRAME_FLAG_TOP_FIELD_FIRST);
 
+    if ((y << 4) * ctx->pictures_per_frame + line_add >= avctx->height)
+        line_add = 0;
+    picture_height = (avctx->height - line_add + ctx->pictures_per_frame - 1) 
/ ctx->pictures_per_frame;
+
     if (ctx->force_quant) {
         qmat = ctx->quants[0];
         qmat_chroma = ctx->quants_chroma[0];
@@ -369,7 +373,7 @@ static int encode_slice(AVCodecContext *avctx, const 
AVFrame *pic,
 
         if (i < 3) {
             get_slice_data(ctx, src, linesize, xp, yp,
-                           pwidth, avctx->height / ctx->pictures_per_frame,
+                           pwidth, picture_height,
                            ctx->blocks[0], ctx->emu_buf,
                            mbs_per_slice, num_cblocks, is_chroma);
             if (!is_chroma) {/* luma quant */
@@ -383,7 +387,7 @@ static int encode_slice(AVCodecContext *avctx, const 
AVFrame *pic,
             }
         } else {
             get_alpha_data(ctx, src, linesize, xp, yp,
-                           pwidth, avctx->height / ctx->pictures_per_frame,
+                           pwidth, picture_height,
                            ctx->blocks[0], mbs_per_slice, ctx->alpha_bits);
             encode_alpha_plane(ctx, pb, mbs_per_slice, ctx->blocks[0], quant);
         }
@@ -570,13 +574,17 @@ static int find_slice_quant(AVCodecContext *avctx,
     int overquant;
     uint16_t *qmat;
     uint16_t *qmat_chroma;
-    int linesize[4], line_add;
+    int linesize[4], line_add, picture_height;
     int alpha_bits = 0;
 
     if (ctx->pictures_per_frame == 1)
         line_add = 0;
     else
         line_add = ctx->cur_picture_idx ^ !(ctx->pic->flags & 
AV_FRAME_FLAG_TOP_FIELD_FIRST);
+
+    if ((y << 4) * ctx->pictures_per_frame + line_add >= avctx->height)
+        line_add = 0;
+    picture_height = (avctx->height - line_add + ctx->pictures_per_frame - 1) 
/ ctx->pictures_per_frame;
     mbs = x + mbs_per_slice;
 
     for (i = 0; i < ctx->num_planes; i++) {
@@ -599,12 +607,12 @@ static int find_slice_quant(AVCodecContext *avctx,
 
         if (i < 3) {
             get_slice_data(ctx, src, linesize[i], xp, yp,
-                           pwidth, avctx->height / ctx->pictures_per_frame,
+                           pwidth, picture_height,
                            td->blocks[i], td->emu_buf,
                            mbs_per_slice, num_cblocks[i], is_chroma[i]);
         } else {
             get_alpha_data(ctx, src, linesize[i], xp, yp,
-                           pwidth, avctx->height / ctx->pictures_per_frame,
+                           pwidth, picture_height,
                            td->blocks[i], mbs_per_slice, ctx->alpha_bits);
         }
     }
-- 
2.52.0


>From 05347c1fa6e0d68859be22af42f1ae012cc4f433 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 14 Sep 2026 03:32:18 +0200
Subject: [PATCH 2/3] avcodec/proresenc_anatoliy: fill the slice from the
 field's own number of lines

Fixes: yj4leb1MWWEF
Fixes: out of array read
Found-by: Zheng Yu @ Depthfirst
---
 libavcodec/proresenc_anatoliy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/proresenc_anatoliy.c b/libavcodec/proresenc_anatoliy.c
index 1d40410199..acc3c72083 100644
--- a/libavcodec/proresenc_anatoliy.c
+++ b/libavcodec/proresenc_anatoliy.c
@@ -496,7 +496,7 @@ static inline void subimage_with_fill_template(const 
uint16_t *src, unsigned x,
     } else {
         src_stride = stride; /* 2 lines stride */
         src += y * src_stride + x;
-        box_height = FFMIN(height/2 - y, dst_height);
+        box_height = FFMIN((height + is_top_field) / 2 - y, dst_height);
         if (!is_top_field)
             src += stride >> 1;
     }
-- 
2.52.0


>From aa184f459b5ff7fa50f20ae32f5f1afc013c17e6 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Mon, 14 Sep 2026 03:33:00 +0200
Subject: [PATCH 3/3] avcodec/proresenc_anatoliy: detect a partial bottom
 macroblock row from the field height

Found during triage of security report yj4leb1MWWEF
Fixes: out of array read
---
 libavcodec/proresenc_anatoliy.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libavcodec/proresenc_anatoliy.c b/libavcodec/proresenc_anatoliy.c
index acc3c72083..da2deb274f 100644
--- a/libavcodec/proresenc_anatoliy.c
+++ b/libavcodec/proresenc_anatoliy.c
@@ -673,6 +673,7 @@ static int prores_encode_picture(AVCodecContext *avctx, 
const AVFrame *pic,
     int slice_per_line = 0, rem = mb_width;
 
     if (!ctx->is_interlaced) { /* progressive encoding */
+        picture_height = avctx->height;
         mb_height = (avctx->height + 15) >> 4;
         unsafe_mb_height_limit = mb_height;
     } else {
@@ -701,7 +702,7 @@ static int prores_encode_picture(AVCodecContext *avctx, 
const AVFrame *pic,
             while (mb_width - mb_x < slice_mb_count)
                 slice_mb_count >>= 1;
 
-            unsafe_bot = (avctx->height & 0xf) && (mb_y == 
unsafe_mb_height_limit - 1);
+            unsafe_bot = (picture_height & 0xf) && (mb_y == 
unsafe_mb_height_limit - 1);
             unsafe_right = (avctx->width & 0xf) && (mb_x + slice_mb_count == 
mb_width);
 
             sl_size = encode_slice(avctx, pic, mb_x, mb_y, slice_mb_count,
@@ -884,7 +885,7 @@ static av_cold int prores_encode_init(AVCodecContext *avctx)
 
     if (avctx->profile < AV_PROFILE_PRORES_4444) { /* 422 versions */
         ctx->is_422 = 1;
-        if ((avctx->height & 0xf) || (avctx->width & 0xf)) {
+        if ((avctx->height & (ctx->is_interlaced ? 0x1f : 0xf)) || 
(avctx->width & 0xf)) {
             ctx->fill_y = av_malloc(4 * (DEFAULT_SLICE_MB_WIDTH << 8));
             if (!ctx->fill_y)
                 return AVERROR(ENOMEM);
@@ -893,7 +894,7 @@ static av_cold int prores_encode_init(AVCodecContext *avctx)
         }
     } else { /* 444 */
         ctx->is_422 = 0;
-        if ((avctx->height & 0xf) || (avctx->width & 0xf)) {
+        if ((avctx->height & (ctx->is_interlaced ? 0x1f : 0xf)) || 
(avctx->width & 0xf)) {
             ctx->fill_y = av_malloc(3 * (DEFAULT_SLICE_MB_WIDTH << 9));
             if (!ctx->fill_y)
                 return AVERROR(ENOMEM);
-- 
2.52.0

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

Reply via email to