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]

Reply via email to