PR #25849 opened by romainhedouin
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25849
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25849.patch

An object with more than 65528 bytes of pixel data got truncated 16 bit 
lengths, but the encoder still returned success.

Return AVERROR(EINVAL) instead. ffmpeg then stops with "Subtitle encoding 
failed".

Although probably rare in the real world, it can technically happen for example 
with subtitles of 1150x220 pixels (3 lines of captions at 1080p with an 
outline) encoded with 8 bits per pixel as PGS input is, which needs about 66 KB 
; or two lines on a 4K canvas (about 2300x270 pixels), which needs over 100 KB.

Testing: independent spec parser for the exact limit, differential against 
master, ASan/UBSan, leaks, DVB FATE tests.

Found during a code review sweep of ffmpeg using an LLM.

<!--
If this PR requires new FATE test samples, attach them to the PR and
list their target paths below (relative to the fate-suite root).

Attached filenames must match the sample's filename:

```fate-samples
# e.g. vorbis/new-sample.ogg
```
-->



>From 1e7cdd5fe8eee114fa5b70f14530f057fbe1ac08 Mon Sep 17 00:00:00 2001
From: romainhedouin <[email protected]>
Date: Sat, 7 Nov 2026 19:13:59 +0100
Subject: [PATCH] avcodec/dvbsubenc: reject object data that does not fit in
 one segment

segment_length and the top and bottom field lengths of an object data
segment are 16 bit fields. When the pixel data of an object needed more
than 65528 bytes they were written truncated, but the encoder still
returned success, and the decoder then skipped the object or showed it
cut. A three line caption of about 1150x220 pixels coded with 8 bits per
pixel, which is what the encoder uses for PGS input, needs about 66 KB.

Return AVERROR(EINVAL) instead, like the other limits here. ffmpeg then
stops with "Subtitle encoding failed".

Found during a code review sweep of ffmpeg using an LLM.

Signed-off-by: romainhedouin <[email protected]>
---
 libavcodec/dvbsubenc.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libavcodec/dvbsubenc.c b/libavcodec/dvbsubenc.c
index a7507723568..698e291ddac 100644
--- a/libavcodec/dvbsubenc.c
+++ b/libavcodec/dvbsubenc.c
@@ -544,6 +544,13 @@ static int dvbsub_encode(AVCodecContext *avctx, uint8_t 
*outbuf, int buf_size,
                 bytestream_put_be16(&pbottom_field_len, q - bottom_ptr);
             }
 
+            /* segment_length is 16 bits, and so are the two field lengths */
+            if (q - pseg_len - 2 > 0xFFFF) {
+                av_log(avctx, AV_LOG_ERROR,
+                       "Object %d needs a segment of %td bytes, the maximum is 
65535\n",
+                       object_id, q - pseg_len - 2);
+                return AVERROR(EINVAL);
+            }
             bytestream_put_be16(&pseg_len, q - pseg_len - 2);
         }
     }
-- 
2.54.0

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

Reply via email to