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]
