PR #25690 opened by michaelni URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25690 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25690.patch
>From 70c31321badb5d400bd2092764d694271b32466e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 29 Oct 2026 02:57:00 +0100 Subject: [PATCH 1/6] avcodec/sgienc: compute the row offset in signed arithmetic Fixes: out of array read Fixes: bDSjy2ewIh1A Fixes: AISLE-2026-0150-00823 Out of array read Replicated through UnModified FFmpeg with ASAN Found-by: Joshua Rogers (AISLE) --- libavcodec/sgienc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c index a6ec4439700..e093bd1b4fc 100644 --- a/libavcodec/sgienc.c +++ b/libavcodec/sgienc.c @@ -100,8 +100,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, PutByteContext pbc; uint8_t *encode_buf; int x, y, z, length, tablesize, ret, i; - unsigned int width, height, depth, dimension; - unsigned int bytes_per_channel, pixmax, put_be; + int width, height, depth, dimension; + int bytes_per_channel, pixmax, put_be; width = avctx->width; height = avctx->height; -- 2.54.0 >From 8d71667b5bdfdde67225746ee68dabc26d528e80 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 29 Oct 2026 03:03:39 +0100 Subject: [PATCH 2/6] avcodec/gif: remap into a buffer with the context width as stride Fixes: out of array write Fixes: 8onJqhybXBbq Fixes: AISLE-2026-0150-00715 Out of array write Replicated through UnModified FFmpeg with ASAN Found-by: Joshua Rogers (AISLE) --- libavcodec/gif.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libavcodec/gif.c b/libavcodec/gif.c index 132ce07e6cd..49dd64a2c51 100644 --- a/libavcodec/gif.c +++ b/libavcodec/gif.c @@ -300,6 +300,7 @@ static int gif_image_write_image(AVCodecContext *avctx, int x_start = 0, y_start = 0, trans = s->transparent_index; int bcid = -1, honor_transparency = (s->flags & GF_TRANSDIFF) && s->last_frame && !palette; const uint8_t *ptr; + int ptr_linesize = linesize; uint32_t shrunk_palette[AVPALETTE_COUNT]; uint8_t map[AVPALETTE_COUNT] = { 0 }; size_t shrunk_palette_count = 0; @@ -402,14 +403,15 @@ static int gif_image_write_image(AVCodecContext *avctx, if (shrunk_palette_count) { if (!s->shrunk_buf) { - s->shrunk_buf = av_malloc(avctx->height * linesize); + s->shrunk_buf = av_malloc(avctx->height * avctx->width); if (!s->shrunk_buf) { av_log(avctx, AV_LOG_ERROR, "Could not allocated remapped frame buffer.\n"); return AVERROR(ENOMEM); } } - remap_frame_to_palette(buf, linesize, s->shrunk_buf, linesize, avctx->width, avctx->height, map); - ptr = s->shrunk_buf + y_start*linesize + x_start; + remap_frame_to_palette(buf, linesize, s->shrunk_buf, avctx->width, avctx->width, avctx->height, map); + ptr = s->shrunk_buf + y_start*avctx->width + x_start; + ptr_linesize = avctx->width; } else { ptr = buf + y_start*linesize + x_start; } @@ -423,13 +425,13 @@ static int gif_image_write_image(AVCodecContext *avctx, if (ref[x] == ptr[x]) s->tmpl[x] = trans; len += ff_lzw_encode(s->lzw, s->tmpl, width); - ptr += linesize; + ptr += ptr_linesize; ref += ref_linesize; } } else { for (y = 0; y < height; y++) { len += ff_lzw_encode(s->lzw, ptr, width); - ptr += linesize; + ptr += ptr_linesize; } } len += ff_lzw_encode_flush(s->lzw); -- 2.54.0 >From 3d6c2df6bf79a60d690c68f00645846bfa060711 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 29 Oct 2026 03:09:46 +0100 Subject: [PATCH 3/6] avcodec/pcxenc: do not read the scanline padding from the frame Encode the pixels of the plane and a zero padding byte instead. Fixes: out of array read Fixes: oHpVCeufOIJY Fixes: AISLE-2026-0150-00405 Out of array read Replicated through API with ASAN Found-by: Joshua Rogers (AISLE) --- libavcodec/pcxenc.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/libavcodec/pcxenc.c b/libavcodec/pcxenc.c index f450d7bca18..ecbcca667a8 100644 --- a/libavcodec/pcxenc.c +++ b/libavcodec/pcxenc.c @@ -39,7 +39,8 @@ static const uint32_t monoblack_pal[16] = { 0x000000, 0xFFFFFF }; * @param dst output buffer * @param dst_size size of output buffer * @param src input buffer - * @param src_plane_size size of one plane of input buffer in bytes + * @param src_plane_size size of one plane of input buffer in bytes, an odd + * size is padded with a zero byte * @param nplanes number of planes in input buffer * @return number of bytes written to dst or -1 on error * @bug will not work for nplanes != 1 && bpp != 8 @@ -49,20 +50,24 @@ static int pcx_rle_encode( uint8_t *dst, int dst_size, { int p; const uint8_t *dst_start = dst; + int pad = src_plane_size & 1; // check worst-case upper bound on dst_size - if (dst_size < 2LL * src_plane_size * nplanes || src_plane_size <= 0) + if (dst_size < 2LL * (src_plane_size + pad) * nplanes || src_plane_size <= 0) return AVERROR(EINVAL); for (p = 0; p < nplanes; p++) { int count = 1; const uint8_t *src_plane = src + p; const uint8_t *src_plane_end = src_plane + src_plane_size * nplanes; + const uint8_t *pad_end = src_plane_end + pad * nplanes; uint8_t prev = *src_plane; src_plane += nplanes; for (; ; src_plane += nplanes) { - if (src_plane < src_plane_end && *src_plane == prev && count < 0x3F) { + uint8_t cur = src_plane < src_plane_end ? *src_plane : 0; + + if (src_plane < pad_end && cur == prev && count < 0x3F) { // current byte is same as prev ++count; } else { @@ -71,12 +76,12 @@ static int pcx_rle_encode( uint8_t *dst, int dst_size, *dst++ = 0xC0 | count; *dst++ = prev; - if (src_plane == src_plane_end) + if (src_plane == pad_end) break; // start new run count = 1; - prev = *src_plane; + prev = cur; } } } @@ -90,7 +95,7 @@ static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const uint8_t *buf_end; uint8_t *buf; - int bpp, nplanes, i, y, line_bytes, written, ret, max_pkt_size, sw, sh; + int bpp, nplanes, i, y, line_bytes, src_plane_size, written, ret, max_pkt_size, sw, sh; const uint32_t *pal = NULL; uint32_t palette256[256]; const uint8_t *src; @@ -130,8 +135,8 @@ static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return AVERROR(EINVAL); } - line_bytes = (avctx->width * bpp + 7) >> 3; - line_bytes = (line_bytes + 1) & ~1; + src_plane_size = (avctx->width * bpp + 7) >> 3; + line_bytes = (src_plane_size + 1) & ~1; max_pkt_size = 128 + avctx->height * 2 * line_bytes * nplanes + (pal ? 256*3 + 1 : 0); if ((ret = ff_alloc_packet(avctx, pkt, max_pkt_size)) < 0) @@ -167,7 +172,7 @@ static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, for (y = 0; y < avctx->height; y++) { if ((written = pcx_rle_encode(buf, buf_end - buf, - src, line_bytes, nplanes)) < 0) { + src, src_plane_size, nplanes)) < 0) { av_log(avctx, AV_LOG_ERROR, "buffer too small\n"); return AVERROR_BUG; } -- 2.54.0 >From 896c70c9f215aeee3382895a80ba8e270779feb0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 29 Oct 2026 03:09:49 +0100 Subject: [PATCH 4/6] avcodec/dpxenc: reject unsupported depths for RGB48 input Only 10 and 16 bit output exist for RGB48, reject everything else at init. Fixes: NULL pointer dereference Fixes: cPU32SjSff6g Fixes: AISLE-2026-0150-00374 NULL pointer dereference Replicated through UnModified FFmpeg with ASAN Found-by: Joshua Rogers (AISLE) --- libavcodec/dpxenc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/dpxenc.c b/libavcodec/dpxenc.c index 68e7fece128..68a8e2c11bb 100644 --- a/libavcodec/dpxenc.c +++ b/libavcodec/dpxenc.c @@ -68,8 +68,12 @@ static av_cold int encode_init(AVCodecContext *avctx) break; case AV_PIX_FMT_RGB48LE: case AV_PIX_FMT_RGB48BE: - if (avctx->bits_per_raw_sample) - s->bits_per_component = avctx->bits_per_raw_sample; + if (avctx->bits_per_raw_sample == 10) { + s->bits_per_component = 10; + } else if (avctx->bits_per_raw_sample && avctx->bits_per_raw_sample != 16) { + av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", avctx->bits_per_raw_sample); + return AVERROR(EINVAL); + } break; } -- 2.54.0 >From 33822ab81cf9b1f068e29367d0a8a4c364e29181 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 29 Oct 2026 03:09:54 +0100 Subject: [PATCH 5/6] avcodec/xwdenc: do not read the scanline padding from the frame Copy the pixels of the row and write zero padding instead. Fixes: out of array read Fixes: 3w9JM5wjYYJx Fixes: AISLE-2026-0150-00370 Out of array read Replicated through API with ASAN Found-by: Joshua Rogers (AISLE) --- libavcodec/xwdenc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/xwdenc.c b/libavcodec/xwdenc.c index 1d8b7d90029..378f07950cd 100644 --- a/libavcodec/xwdenc.c +++ b/libavcodec/xwdenc.c @@ -39,7 +39,7 @@ static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, uint32_t pixdepth, bpp, bpad, ncolors = 0, lsize, vclass, be = 0; uint32_t rgb[3] = { 0 }, bitorder = 0; uint32_t header_size; - int i, out_size, ret; + int i, out_size, ret, row_bytes; const uint8_t *ptr; uint8_t *buf; uint32_t pal[256]; @@ -144,6 +144,7 @@ static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return AVERROR(EINVAL); } + row_bytes = (bpp * avctx->width + 7) / 8; lsize = FFALIGN(bpp * avctx->width, bpad) / 8; header_size = XWD_HEADER_SIZE + WINDOW_NAME_SIZE; out_size = header_size + ncolors * XWD_CMAP_SIZE + avctx->height * lsize; @@ -204,7 +205,9 @@ static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ptr = p->data[0]; for (i = 0; i < avctx->height; i++) { - bytestream_put_buffer(&buf, ptr, lsize); + bytestream_put_buffer(&buf, ptr, row_bytes); + memset(buf, 0, lsize - row_bytes); + buf += lsize - row_bytes; ptr += p->linesize[0]; } -- 2.54.0 >From 96032cb7528580936a459300c90d01406c9472b5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 29 Oct 2026 03:03:47 +0100 Subject: [PATCH 6/6] avcodec/exrenc: propagate the scanline encoder errors This is not a security issue. Found-by: Joshua Rogers (AISLE) --- libavcodec/exrenc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/exrenc.c b/libavcodec/exrenc.c index 68eb683aa5a..2c697e66b65 100644 --- a/libavcodec/exrenc.c +++ b/libavcodec/exrenc.c @@ -437,15 +437,17 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, /* nothing to do */ break; case EXR_RLE: - encode_scanline_rle(s, frame); + ret = encode_scanline_rle(s, frame); break; case EXR_ZIP16: case EXR_ZIP1: - encode_scanline_zip(s, frame); + ret = encode_scanline_zip(s, frame); break; default: av_assert0(0); } + if (ret < 0) + return ret; switch (s->compression) { case EXR_RAW: -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
