[PR] avcodec/pgssubdec: do not read beyond the segment length / avcodec/pgssubdec: always give an output rect a palette (PR #23903)

michaelni via ffmpeg-devel <[email protected]> Sat, 25 Jul 2026 01:34:46 -0000
Newsgroups gmane.comp.video.ffmpeg.devel
Message-ID <178494328697.59.11905023398668538405@29965ddac10e>
PR #23903 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23903
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23903.patch

avcodec/pgssubdec: do not read beyond the segment length ...
Fixes: poc_short_pres_header.sup
Fixes: poc_crop_overread.sup
Fixes: poc_palette_overread.sup
Fixes: NULL pointer dereference
Fixes: poc_null_deref.sup
Fixes: Fobbab5Vtlr3
Found-by: VRI with 图龙锋


From 59e528d0e2b7455eb6ab2f39e94bafb762756e8e Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Fri, 24 Jul 2026 23:09:03 +0200
Subject: [PATCH 1/2] avcodec/pgssubdec: do not read beyond the segment length
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fixes: poc_short_pres_header.sup
Fixes: poc_crop_overread.sup
Fixes: poc_palette_overread.sup
Fixes: Fobbab5Vtlr3
Found-by: VRI with 图龙锋
---
 libavcodec/pgssubdec.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c
index 20583c9afa..ed0f7766e3 100644
--- a/libavcodec/pgssubdec.c
+++ b/libavcodec/pgssubdec.c
@@ -351,7 +351,7 @@ static int parse_palette_segment(AVCodecContext *avctx,
     /* Skip palette version */
     buf += 1;
 
-    while (buf < buf_end) {
+    while (buf_end - buf >= 5) {
         color_id  = bytestream_get_byte(&buf);
         y         = bytestream_get_byte(&buf);
         cr        = bytestream_get_byte(&buf);
@@ -394,6 +394,11 @@ static int parse_presentation_segment(AVCodecContext *avctx,
     int i, state, ret;
     const uint8_t *buf_end = buf + buf_size;
 
+    if (buf_size < 11) {
+        av_log(avctx, AV_LOG_ERROR, "Insufficient space for presentation segment\n");
+        return AVERROR_INVALIDDATA;
+    }
+
     // Video descriptor
     int w = bytestream_get_be16(&buf);
     int h = bytestream_get_be16(&buf);
@@ -461,6 +466,11 @@ static int parse_presentation_segment(AVCodecContext *avctx,
 
         // If cropping
         if (object->composition_flag & 0x80) {
+            if (buf_end - buf < 8) {
+                av_log(avctx, AV_LOG_ERROR, "Insufficient space for cropping\n");
+                ctx->presentation.object_count = i;
+                return AVERROR_INVALIDDATA;
+            }
             object->crop_x = bytestream_get_be16(&buf);
             object->crop_y = bytestream_get_be16(&buf);
             object->crop_w = bytestream_get_be16(&buf);
-- 
2.52.0


From 294fbbee63fc3b2fb6bd1037fd9524604c456f78 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Wed, 22 Jul 2026 06:03:39 +0200
Subject: [PATCH 2/2] avcodec/pgssubdec: always give an output rect a palette
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fixes: NULL pointer dereference
Fixes: poc_null_deref.sup
Fixes: Fobbab5Vtlr3
Found-by: VRI with 图龙锋
---
 libavcodec/pgssubdec.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c
index ed0f7766e3..8c95e24eb7 100644
--- a/libavcodec/pgssubdec.c
+++ b/libavcodec/pgssubdec.c
@@ -547,6 +547,16 @@ static int display_end_segment(AVCodecContext *avctx, AVSubtitle *sub,
         sub->rects[sub->num_rects++] = rect;
         rect->type = SUBTITLE_BITMAP;
 
+        /* Allocate the palette now so that the error paths below, which
+         * leave the rect empty, still hand consumers a complete bitmap
+         * rect rather than one with a NULL palette. */
+        rect->nb_colors = 256;
+        rect->data[1]   = av_mallocz(AVPALETTE_SIZE);
+        if (!rect->data[1])
+            return AVERROR(ENOMEM);
+        if (!ctx->forced_subs_only || ctx->presentation.objects[i].composition_flag & 0x40)
+            memcpy(rect->data[1], palette->clut, rect->nb_colors * sizeof(uint32_t));
+
         /* Process bitmap */
         object = find_object(ctx->presentation.objects[i].id, &ctx->objects);
         if (!object) {
@@ -587,14 +597,6 @@ static int display_end_segment(AVCodecContext *avctx, AVSubtitle *sub,
                 continue;
             }
         }
-        /* Allocate memory for colors */
-        rect->nb_colors = 256;
-        rect->data[1]   = av_mallocz(AVPALETTE_SIZE);
-        if (!rect->data[1])
-            return AVERROR(ENOMEM);
-
-        if (!ctx->forced_subs_only || ctx->presentation.objects[i].composition_flag & 0x40)
-            memcpy(rect->data[1], palette->clut, rect->nb_colors * sizeof(uint32_t));
     }
     return 1;
 }
-- 
2.52.0

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