PR #25462 opened by anishagg17 URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25462 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25462.patch
Context: when the MOV/MP4 muxer writes a DVD subtitle stream, it builds the track's decoder specific info from the text in the stream's extradata. One field is the subtitle palette, parsed from the `palette:` line with sscanf() into a 16-entry array. Problem: `mov_create_dvd_sub_decoder_specific_info()` never checks how many entries sscanf() actually converted. `have_palette` is set unconditionally and all 16 entries of the stack array are written to the output, so a palette line with fewer than 16 values — including a line with a single value, or none — puts uninitialised stack contents into the muxed file. The extradata is attacker-controlled in a normal remux flow: the Matroska demuxer copies an S_VOBSUB track's CodecPrivate verbatim into codecpar extradata, so anyone who supplies a crafted .mkv controls this line, and anyone who remuxes it to MP4 leaks bytes from their own process's stack into the result. This is reproducible with a hand-built Matroska file whose CodecPrivate is `palette: 112233`: the unpatched muxer emits a 64-byte palette block whose entries 1–15 are leftover stack data (with a second, fully-specified subtitle track in the same file, they are that track's palette values). Solution: claim the palette only when the parse produced all 16 entries. A DVD subtitle palette has 16 entries by definition and every producer of this extradata in the tree writes all 16, so well-formed input is unaffected — output for a full palette is byte-identical before and after the change — while a short palette line now behaves like a missing one instead of exposing stack memory. The commit message contains the same description with the repro summary. Tested by remuxing crafted Matroska inputs (short palette, full palette, and both as tracks of one file) with ASan builds of the unpatched and patched tree and comparing the emitted palette blocks. From 59e90a42eac8fb2821a04745f95fbdcaabbdbfa4 Mon Sep 17 00:00:00 2001 From: Anish Aggarwal <[email protected]> Date: Sun, 25 Oct 2026 22:46:08 +0000 Subject: [PATCH] avformat/movenc: only use a DVD subtitle palette parsed in full mov_create_dvd_sub_decoder_specific_info() parses the "palette:" line of a DVD subtitle stream's extradata with sscanf() but never checks how many of the 16 entries were actually converted. have_palette is set unconditionally and all 16 entries of the stack array are written into the track's decoder specific info, so for a palette line with fewer than 16 values the uninitialised remainder of the array is written to the output file. The extradata can be attacker controlled: the Matroska demuxer copies an S_VOBSUB track's CodecPrivate verbatim into codecpar extradata, and the mov muxer calls this function for every DVD subtitle stream when writing the header. Remuxing a crafted Matroska file whose palette line holds a single value ("palette: 112233") to MP4 with the unpatched build produces a 64-byte palette block whose entries 1-15 are whatever the stack held; with a second, fully specified subtitle track in the same file, those entries come out as the other track's converted palette values, i.e. data from the remuxing process's memory ends up in the output file. A DVD subtitle palette has 16 entries by definition and every in-tree producer of this extradata always writes all 16, so only claim the palette when the parse produced all of them. Output for well-formed palettes is unchanged (verified byte-identical), and a short palette line now behaves like a missing one instead of exposing stack contents. Signed-off-by: Anish Aggarwal <[email protected]> --- libavformat/movenc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index debe1acb7e0..ab8d8d15fc4 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -8206,10 +8206,12 @@ static int mov_create_dvd_sub_decoder_specific_info(MOVTrack *track, &palette[ 8], &palette[ 9], &palette[10], &palette[11], &palette[12], &palette[13], &palette[14], &palette[15]); - for (i = 0; i < count; i++) { - palette[i] = rgb_to_yuv(palette[i]); + if (count == 16) { + for (i = 0; i < count; i++) { + palette[i] = rgb_to_yuv(palette[i]); + } + have_palette = 1; } - have_palette = 1; } else if (!strncmp("size:", cur, 5)) { sscanf(cur + 5, "%dx%d", &width, &height); have_size = 1; -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
