PR #25832 opened by romainhedouin URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25832 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25832.patch
A CLUT entry is 4 bytes in the short form and 6 bytes in the full form, but the loop only parsed an entry when at least 5 bytes were left. So a short entry at the end of the segment was ignored. A truncated 5-byte full entry was parsed using one byte read past the segment. The loop now parses an entry when 4 bytes are left, and stops at a full entry that doesn't fit. Fuzzed streams under ASan/UBSan show the old code reading past the segment, and the new code doesn't. Streams with only full-range entries, like the real sample and our encoder's output, decode the same, and the dvbsub FATE tests are unchanged. Note: the existing "Invalid clut depth" message is now also logged when only 4 stray bytes are left at the end of a segment (before, it needed at least 5). 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 2dea9926d71b0a9b7068de9c891f7f2e163fdcea Mon Sep 17 00:00:00 2001 From: romainhedouin <[email protected]> Date: Sat, 7 Nov 2026 13:05:19 +0100 Subject: [PATCH] avcodec/dvbsubdec: do not drop a reduced-range last CLUT entry A CLUT entry is 4 bytes in reduced-range form and 6 bytes in full-range form (EN 300 743, table 16), but the CLUT segment loop only parsed an entry when at least 5 bytes were left. A reduced-range entry at the end of the segment was therefore ignored and that palette index kept its previous value (the default colour unless an earlier CLUT version set it), and a full-range entry with only 5 bytes left was parsed using one byte read past the end of the segment (the sync byte of the next segment, or the packet padding). Parse an entry when the 4 bytes of a reduced-range entry are left, and stop at a full-range entry that does not fit, so that a truncated trailing entry is ignored. Four stray bytes at the end of a segment are now parsed as an entry too, and reported by the existing "Invalid clut depth" message if their depth flags are 0. Well-formed streams that only use full-range entries, such as the ones written by the FFmpeg encoder, are not affected. Found during a code review sweep of ffmpeg using an LLM. Signed-off-by: romainhedouin <[email protected]> --- libavcodec/dvbsubdec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index 2426da896d1..fc994af099b 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -1101,7 +1101,7 @@ static int dvbsub_parse_clut_segment(AVCodecContext *avctx, clut->version = version; - while (buf + 4 < buf_end) { + while (buf + 3 < buf_end) { entry_id = *buf++; depth = (*buf) & 0xe0; @@ -1113,6 +1113,8 @@ static int dvbsub_parse_clut_segment(AVCodecContext *avctx, full_range = (*buf++) & 1; if (full_range) { + if (buf_end - buf < 4) + break; y = *buf++; cr = *buf++; cb = *buf++; -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
