ANT-2026-SJ7ZVBQB · ffmpeg/ffmpeg

heap-buffer-overflow medium

Severity Claude high · Security research firm medium · Maintainer -

Discovered by Claude Opus 4.6

REPORT

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

  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

[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

SECURITY RESEARCH FIRM ANALYSIS

Triage and disclosure were performed by Ada Logics.

Verdict
true positive
Severity
medium
UPSTREAM FIX

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

TIMELINE

Dates from discovery through public reveal.

  1. 2026-03-24 Reported to tracker
  2. 2026-05-13 Sent to maintainer
  3. 2026-05-19 Maintainer acknowledged
  4. 2026-06-16 Patch released
  5. 2026-08-17 Publicly revealed
PROVENANCE

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"
}