PR #25682 opened by michaelni URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25682 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25682.patch
>From 4b82959626f1b55c5f127fc8196971599099d0ef Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 19 Oct 2026 23:46:27 +0200 Subject: [PATCH 1/6] avcodec/v4l2_buffers: reject copies starting past the end of the V4L2 plane Fixes: IBRDgbKBAWrE Fixes: AISLE-2026-0150-00324 Fixes: out of array write Out of array write Replicated through UnModified FFmpeg with ASAN using a stub V4L2 mem2mem device Found-by: Joshua Rogers (AISLE) --- libavcodec/v4l2_buffers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index f96c26771b7..05650da66c6 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -304,6 +304,8 @@ static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, i return AVERROR(EINVAL); length = out->plane_info[plane].length; + if (offset > length) + return AVERROR(EINVAL); bytesused = FFMIN(size+offset, length); memcpy((uint8_t*)out->plane_info[plane].mm_addr+offset, data, FFMIN(size, length-offset)); -- 2.54.0 >From f53819a1d1c902af301558c9818b2bcc81071ff4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 19 Oct 2026 23:47:14 +0200 Subject: [PATCH 2/6] avcodec/v4l2_buffers: reject negative sizes when copying into a V4L2 plane Fixes: 6HcYrs8zKQn8 Fixes: AISLE-2026-0150-00907 Fixes: out of array read Out of array read Replicated through UnModified FFmpeg with ASAN using a stub V4L2 mem2mem device and the vflip filter Found-by: Joshua Rogers (AISLE) The report suggested rejecting negative linesizes on this path. --- libavcodec/v4l2_buffers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index 05650da66c6..a9de67e3f28 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -304,7 +304,7 @@ static int v4l2_bufref_to_buf(V4L2Buffer *out, int plane, const uint8_t* data, i return AVERROR(EINVAL); length = out->plane_info[plane].length; - if (offset > length) + if (size < 0 || offset > length) return AVERROR(EINVAL); bytesused = FFMIN(size+offset, length); -- 2.54.0 >From 1f194aae35adb8a05874a6b2cbf4ac6da0f678e5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 19 Oct 2026 23:47:24 +0200 Subject: [PATCH 3/6] avcodec/v4l2_buffers: count a buffer once in the context reference count Fixes: 2VchxeAyBc35 Fixes: AISLE-2026-0150-00089 Fixes: hang Hang Replicated through UnModified FFmpeg (ffprobe) with gdb using a stub V4L2 mem2mem decoder with a two plane capture format Found-by: Joshua Rogers (AISLE) The report suggested incrementing the count only on the first reference to a buffer. --- libavcodec/v4l2_buffers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index a9de67e3f28..5a97e9dd837 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -268,10 +268,10 @@ static int v4l2_buf_increase_ref(V4L2Buffer *in) in->context_ref = av_refstruct_ref(s->self_ref); in->context_refcount = 1; + atomic_fetch_add_explicit(&s->refcount, 1, memory_order_relaxed); } in->status = V4L2BUF_RET_USER; - atomic_fetch_add_explicit(&s->refcount, 1, memory_order_relaxed); return 0; } -- 2.54.0 >From 992d5dcf09f7b02968659b8639e5f669228459a9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Mon, 2 Nov 2026 14:41:56 +0100 Subject: [PATCH 4/6] avcodec/encode: reject video frames larger than the encoder too Fixes: HXFS7VRNHzgr Fixes: JN4xU8n5QSCA Fixes: TDILTq5sYK4u Fixes: AISLE-2026-0150-00805 Fixes: AISLE-2026-0150-00343 Fixes: AISLE-2026-0150-00596 Fixes: AISLE-2026-0150-00810 Fixes: out of array read Out of array read Replicated through UnModified FFmpeg with ASAN, using -noautoscale Found-by: Joshua Rogers (AISLE) The report described the VideoToolbox and QSV encoders and suggested rejecting frames whose dimensions or format differ from the context. The software encoders were found during triage of the report. --- libavcodec/encode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 82ea3aedbb4..c84cd878267 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -524,7 +524,7 @@ static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) if (!(desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL) && (src->format != avctx->pix_fmt || - src->width < avctx->width || src->height < avctx->height)) { + src->width != avctx->width || src->height != avctx->height)) { av_log(avctx, AV_LOG_ERROR, "Frame size or pixel format does not match the encoder\n"); return AVERROR(EINVAL); } -- 2.54.0 >From e0235a49227e319d1946db8d105e4ea0761bf311 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Sat, 24 Oct 2026 06:18:36 +0200 Subject: [PATCH 5/6] avcodec/flashsvenc: use the previous frame's own linesize Fixes: HXFS7VRNHzgr Fixes: out of array read Out of array read Replicated through UnModified FFmpeg with ASAN, using -noautoscale Found during triage/review of the security report AISLE-2026-R0043 --- libavcodec/flashsvenc.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libavcodec/flashsvenc.c b/libavcodec/flashsvenc.c index bd4c8651e20..b7328cd84fc 100644 --- a/libavcodec/flashsvenc.c +++ b/libavcodec/flashsvenc.c @@ -61,8 +61,7 @@ typedef struct FlashSVContext { AVCodecContext *avctx; - const uint8_t *previous_frame; - AVBufferRef *prev_frame_buf; + AVFrame *prev_frame; int image_width, image_height; unsigned packet_size; int64_t last_key_frame; @@ -71,14 +70,15 @@ typedef struct FlashSVContext { } FlashSVContext; static int copy_region_enc(const uint8_t *sptr, uint8_t *dptr, int dx, int dy, - int h, int w, int stride, const uint8_t *pfptr) + int h, int w, int stride, const uint8_t *pfptr, + int pstride) { int i, j; int diff = 0; for (i = dx + h; i > dx; i--) { const uint8_t *nsptr = sptr + i * stride + dy * 3; - const uint8_t *npfptr = pfptr + i * stride + dy * 3; + const uint8_t *npfptr = pfptr + i * pstride + dy * 3; for (j = 0; j < w * 3; j++) { diff |= npfptr[j] ^ nsptr[j]; dptr[j] = nsptr[j]; @@ -94,7 +94,7 @@ static av_cold int flashsv_encode_end(AVCodecContext *avctx) { FlashSVContext *s = avctx->priv_data; - av_buffer_unref(&s->prev_frame_buf); + av_frame_free(&s->prev_frame); return 0; } @@ -112,6 +112,10 @@ static av_cold int flashsv_encode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } + s->prev_frame = av_frame_alloc(); + if (!s->prev_frame) + return AVERROR(ENOMEM); + s->last_key_frame = 0; s->image_width = avctx->width; @@ -132,7 +136,7 @@ static av_cold int flashsv_encode_init(AVCodecContext *avctx) static int encode_bitstream(FlashSVContext *s, const AVFrame *p, uint8_t *buf, int buf_size, int block_width, int block_height, - const uint8_t *previous_frame, int *I_frame) + const AVFrame *prev, int *I_frame) { PutBitContext pb; @@ -172,7 +176,8 @@ static int encode_bitstream(FlashSVContext *s, const AVFrame *p, uint8_t *buf, res = copy_region_enc(p->data[0], s->tmpblock, s->image_height - (y_pos + cur_blk_height + 1), x_pos, cur_blk_height, cur_blk_width, - p->linesize[0], previous_frame); + p->linesize[0], prev->data[0], + prev->linesize[0]); if (res || *I_frame) { unsigned long zsize = 3 * block_width * block_height + 12; @@ -208,14 +213,14 @@ static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { FlashSVContext * const s = avctx->priv_data; - const uint8_t *prev_frame = s->previous_frame; + const AVFrame *prev_frame = s->prev_frame; int res; int I_frame = 0; int opt_w = 4, opt_h = 4; /* First frame needs to be a keyframe */ - if (!s->previous_frame) { - prev_frame = pict->data[0]; + if (!s->prev_frame->data[0]) { + prev_frame = pict; I_frame = 1; } @@ -244,12 +249,7 @@ static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt, *got_packet = 1; //save the current frame - res = av_buffer_replace(&s->prev_frame_buf, pict->buf[0]); - if (res < 0) - return res; - s->previous_frame = pict->data[0]; - - return 0; + return av_frame_replace(s->prev_frame, pict); } const FFCodec ff_flashsv_encoder = { -- 2.54.0 >From 1dde2b13e8b4c99bc195ce082cd30f4cb5fbe141 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Sat, 24 Oct 2026 06:18:36 +0200 Subject: [PATCH 6/6] avcodec/null: declare support for parameter changes in the vnull encoder The encoder discards every frame, so the size and format of a frame do not matter to it. --- libavcodec/null.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/null.c b/libavcodec/null.c index e443ddf4f98..4191e5866e0 100644 --- a/libavcodec/null.c +++ b/libavcodec/null.c @@ -70,6 +70,7 @@ const FFCodec ff_vnull_encoder = { CODEC_LONG_NAME("null video"), .p.type = AVMEDIA_TYPE_VIDEO, .p.id = AV_CODEC_ID_VNULL, + .p.capabilities = AV_CODEC_CAP_PARAM_CHANGE, FF_CODEC_ENCODE_CB(null_encode), }; #endif -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
