ANT-2026-SJ7ZVBQB · ffmpeg/ffmpeg
heap-buffer-overflow medium
Severity Claude high · Security research firm medium · Maintainer -
Discovered by Claude Opus 4.6
Anthropic's analysis, sealed at approval. Disclosure to the maintainer was performed by Ada Logics.
ANT-2026-SJ7ZVBQB: Heap-buffer-overflow in mpeg.h:70
While demuxing a crafted TiVo TY file, demux_video() in libavformat/ty.c:404 calls ff_parse_pes_pts() on a PES header located at the very end of the 128 KiB chunk buffer. ff_parse_pes_pts() unconditionally dereferences 5 bytes of timestamp data, and the pointer lands 0 bytes past the end of the 131200-byte heap allocation, producing a READ of size 1 beyond the buffer. An attacker controls the record layout and sizes in the TY container that position the PES header at the buffer boundary. The result is an out-of-bounds read that can crash the process or leak adjacent heap bytes into a parsed PTS value.
Target
Project: ffmpeg
Location: mpeg.h:70
Technical Details
ASAN: "READ of size 1 at 0x747fe6227880 ... heap-buffer-overflow ... in ff_parse_pes_pts /src/ffmpeg/libavformat/mpeg.h:70:22". The faulting address is exactly 0 bytes after a 131200-byte region, meaning demux_video() did not ensure at least 5 bytes remained in the chunk before invoking ff_parse_pes_pts() on the PES timestamp, so the inline helper reads past the allocation boundary.
Crash trace (truncated — full trace in attached crash.log):
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3263152788
INFO: Loaded 1 modules (117549 inline 8-bit counters): 117549 [0x60a860eeafc8, 0x60a860f07af5),
INFO: Loaded 1 PC tables (117549 PCs): 117549 [0x60a860f07af8,0x60a8610d2dc8),
/out/ffmpeg_dem_TY_fuzzer: Running 1 inputs 1 time(s) each.
Running: /tmp/poc
EXIT_CODE:1
=== ASAN Report ===
=================================================================
==27==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x747fe6227880 at pc 0x60a860764362 bp 0x7ffce231f010 sp 0x7ffce231f008
READ of size 1 at 0x747fe6227880 thread T0
#0 0x60a860764361 in ff_parse_pes_pts /src/ffmpeg/libavformat/mpeg.h:70:22
#1 0x60a860764361 in demux_video /src/ffmpeg/libavformat/ty.c:404:34
#2 0x60a860764361 in ty_read_packet /src/ffmpeg/libavformat/ty.c:687:19
#3 0x60a860526358 in ff_read_packet /src/ffmpeg/libavformat/demux.c:659:15
#4 0x60a86052882b in read_frame_internal /src/ffmpeg/libavformat/demux.c:1400:15
#5 0x60a8605281cd in av_read_frame /src/ffmpeg/libavformat/demux.c:1599:17
#6 0x60a86049694e in LLVMFuzzerTestOneInput /src/ffmpeg/tools/target_dem_fuzzer.c:209:15
#7 0x60a860333a7d in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:619:13
[... 15 more frames — full trace in crash.log]
Reproduction
- Craft a TY file whose record table places a video record's PES header at the very end of the 128 KiB chunk buffer
- Deliver the file to the target (download, upload pipeline, transcoder, thumbnailer, etc.)
- av_read_frame() → ty_read_packet() → demux_video() calls ff_parse_pes_pts() on the boundary pointer, reading past the allocation
[No reproducer or sanitizer output attached — request from security-cvd@anthropic.com if needed.]
Acknowledgement
This vulnerability was discovered by Claude, Anthropic's AI assistant, and triaged by the Anthropic security team in collaboration with Anthropic Research. Please direct questions to security-cvd@anthropic.com and reference ANT-2026-SJ7ZVBQB.
Reference: ANT-2026-SJ7ZVBQB
Anthropic CVD Policy: https://www.anthropic.com/coordinated-vulnerability-disclosure
Triage and disclosure were performed by Ada Logics.
- Verdict
- true positive
- Severity
- medium
The change that resolved this finding.
diff --git a/libavformat/ty.c b/libavformat/ty.c
index c637c35e7ca64..9be027fcca35b 100644
--- a/libavformat/ty.c
+++ b/libavformat/ty.c
@@ -396,12 +396,16 @@ static int demux_video(AVFormatContext *s, TyRecHdr *rec_hdr, AVPacket *pkt)
int got_packet = 0;
if (subrec_type != 0x02 && subrec_type != 0x0c &&
- subrec_type != 0x08 && rec_size > 4) {
+ subrec_type != 0x08 && rec_size > 7) {
+
/* get the PTS from this packet if it has one.
* on S1, only 0x06 has PES. On S2, however, most all do.
* Do NOT Pass the PES Header to the MPEG2 codec */
es_offset1 = find_es_header(ty_VideoPacket, ty->chunk + ty->cur_chunk_pos, 5);
if (es_offset1 != -1) {
+ if (rec_size < es_offset1 + VIDEO_PTS_OFFSET + 5)
+ return AVERROR_INVALIDDATA;
+
ty->last_video_pts = ff_parse_pes_pts(
ty->chunk + ty->cur_chunk_pos + es_offset1 + VIDEO_PTS_OFFSET);
if (subrec_type != 0x06) {https://github.com/FFmpeg/FFmpeg/commit/4492ad7228a381c2f0c8b79d333a59c7657311c9
Dates from discovery through public reveal.
- 2026-03-24 Reported to tracker
- 2026-05-13 Sent to maintainer
- 2026-05-19 Maintainer acknowledged
- 2026-06-16 Patch released
- 2026-08-17 Publicly revealed
SHA-3-512 hash:
69e72e0559fea11f7d52c6014c97b53d664c439ed2cf9dc0507acf38fa2f6e9d7e20873be9a0ad3cc998b58b3ca3597a415bf96622ea308c0b55af3b29ff79c6
Committed 2026-05-13 10:55 PT
Revealed 2026-08-17 16:45 PT
Verify (download preimage.json)
Show preimage JSON
{
"ant_id": "ANT-2026-SJ7ZVBQB",
"bug_class": "Heap-buffer-overflow",
"claude_severity": "high",
"commit_sha": null,
"created_at": "2026-03-24T18:31:24+00:00",
"description": "While demuxing a crafted TiVo TY file, demux_video() in libavformat/ty.c:404 calls ff_parse_pes_pts() on a PES header located at the very end of the 128 KiB chunk buffer. ff_parse_pes_pts() unconditionally dereferences 5 bytes of timestamp data, and the pointer lands 0 bytes past the end of the 131200-byte heap allocation, producing a READ of size 1 beyond the buffer. An attacker controls the record layout and sizes in the TY container that position the PES header at the buffer boundary. The result is an out-of-bounds read that can crash the process or leak adjacent heap bytes into a parsed PTS value.",
"discovered_at": null,
"location": "mpeg.h:70",
"poc_sha256": null,
"preimage_version": 1,
"project": "ffmpeg",
"reproduction": [
"1. Craft a TY file whose record table places a video record's PES header at the very end of the 128 KiB chunk buffer",
"2. Deliver the file to the target (download, upload pipeline, transcoder, thumbnailer, etc.)",
"3. av_read_frame() → ty_read_packet() → demux_video() calls ff_parse_pes_pts() on the boundary pointer, reading past the allocation"
],
"technical_details": "ASAN: \"READ of size 1 at 0x747fe6227880 ... heap-buffer-overflow ... in ff_parse_pes_pts /src/ffmpeg/libavformat/mpeg.h:70:22\". The faulting address is exactly 0 bytes after a 131200-byte region, meaning demux_video() did not ensure at least 5 bytes remained in the chunk before invoking ff_parse_pes_pts() on the PES timestamp, so the inline helper reads past the allocation boundary.",
"title": "Heap-buffer-overflow in mpeg.h:70",
"vendor_severity": "medium"
}