PR #24199 opened by unfunnyatearug URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24199 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24199.patch
## impact these changes fix an uninitialized-memory disclosure in the fsb and genh thp extradata handling. the issue is similar in nature to the recent webp fix in commit `cfaaf00`, where truncated input could result in uninitialized memory being exposed. the primary issue is that the demuxers assumed that the requested extradata was fully read without verifying the actual amount returned by the io operation. ## verification the changes were ai-assisted (Claude Opus 5 and 4.8) and reviewed and verified by unfunnyatearug. a proof of concept is included: * `poc.fsb` * `leak_demo.c` the poc demonstrates the truncated extradata condition and the resulting memory disclosure behavior. >From 604863fed0666f778b6a688713a3eccffb7c63a5 Mon Sep 17 00:00:00 2001 From: unfunnyatearug <[email protected]> Date: Tue, 18 Aug 2026 14:46:35 +0300 Subject: [PATCH 1/2] avformat/fsb: reject truncated thp coefficient extradata the fsb demuxer used `avio_read(..., 32)` for each channel but ignored the return value. `ff_alloc_extradata()` only clears the padding area. if the input file is truncated, the remaining extradata can therefore contain uninitialized memory. `nb_channels` is a 16-bit value and was only limited by the `int_max / 32` calculation. this allows a truncated file to cause a leak of up to ~2 MB of uninitialized memory. the affected extradata is used by the `adpcm_thp` decoder and can also be copied to the output during remuxing. the fix replaces the unchecked reads with `ffio_read_size()`, which reports an error when the requested amount of data cannot be read. both the thp v3 and v4 paths are fixed. Signed-off-by: unfunnyatearug <[email protected]> --- libavformat/fsb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libavformat/fsb.c b/libavformat/fsb.c index 0febeffd56..1164f48b94 100644 --- a/libavformat/fsb.c +++ b/libavformat/fsb.c @@ -23,6 +23,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio.h" +#include "avio_internal.h" #include "demux.h" #include "internal.h" @@ -93,7 +94,9 @@ static int fsb_read_header(AVFormatContext *s) return ret; avio_seek(pb, 0x68, SEEK_SET); for (c = 0; c < par->ch_layout.nb_channels; c++) { - avio_read(pb, par->extradata + 32 * c, 32); + ret = ffio_read_size(pb, par->extradata + 32 * c, 32); + if (ret < 0) + return ret; avio_skip(pb, 14); } } else { @@ -146,7 +149,9 @@ static int fsb_read_header(AVFormatContext *s) return ret; avio_seek(pb, 0x80, SEEK_SET); for (c = 0; c < par->ch_layout.nb_channels; c++) { - avio_read(pb, par->extradata + 32 * c, 32); + ret = ffio_read_size(pb, par->extradata + 32 * c, 32); + if (ret < 0) + return ret; avio_skip(pb, 14); } par->block_align = 8 * par->ch_layout.nb_channels; -- 2.52.0 >From af9676a31357554348aa37163ae35f5f618b7713 Mon Sep 17 00:00:00 2001 From: unfunnyatearug <[email protected]> Date: Tue, 18 Aug 2026 14:46:35 +0300 Subject: [PATCH 2/2] avformat/genh: check thp extradata read and allocation the genh demuxer had the same short-read issue at one location. the read is now performed with `ffio_read_size()` so truncated input is rejected instead of leaving uninitialized data in the extradata. `ff_alloc_extradata()` also had its return value unchecked. if allocation failed, the code could dereference a null pointer. the return value is now checked. the affected path is capped at two channels, so the potential information leak is relatively small, but it is the same underlying bug class. Signed-off-by: unfunnyatearug <[email protected]> --- libavformat/genh.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libavformat/genh.c b/libavformat/genh.c index deecca4a4c..32cad7382b 100644 --- a/libavformat/genh.c +++ b/libavformat/genh.c @@ -22,6 +22,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "avio_internal.h" #include "demux.h" #include "internal.h" @@ -132,14 +133,18 @@ static int genh_read_header(AVFormatContext *s) return AVERROR_PATCHWELCOME; } - ff_alloc_extradata(st->codecpar, 32 * st->codecpar->ch_layout.nb_channels); + ret = ff_alloc_extradata(st->codecpar, 32 * st->codecpar->ch_layout.nb_channels); + if (ret < 0) + return ret; for (ch = 0; ch < st->codecpar->ch_layout.nb_channels; ch++) { if (coef_type & 1) { avpriv_request_sample(s, "coef_type & 1"); return AVERROR_PATCHWELCOME; } else { avio_seek(s->pb, coef[ch], SEEK_SET); - avio_read(s->pb, st->codecpar->extradata + 32 * ch, 32); + ret = ffio_read_size(s->pb, st->codecpar->extradata + 32 * ch, 32); + if (ret < 0) + return ret; } } -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
