AI-built fuzzer finds divide-by-zero bug in FFmpeg's VPK demuxer
A 21-byte input crashes any FFmpeg-based application that opens a malicious .vpk file. The flaw is DoS, with no code execution, and already has a fix PR.

An integer divide-by-zero bug in FFmpeg's VPK demuxer was reported on August 27, 2026, on the project's Forgejo by Darío Clavijo. The flaw allows a .vpk file (or a stream that identifies itself as VPK) of just 21 bytes to crash any application that uses FFmpeg's libraries to open untrusted media. What caught the community's attention wasn't just the bug itself, but how it was found: a fuzzer partially written with AI.
What Exactly Breaks
The root of the problem is in libavformat/vpk.c:89, inside vpk_read_packet. The demuxer for the VPK audio format (from Sony's PS2) handles the last block of the stream specially and divides two values by par->ch_layout.nb_channels:
if (vpk->current_block == vpk->block_count) {
unsigned size = vpk->last_block_size / par->ch_layout.nb_channels;
unsigned skip = (par->block_align - vpk->last_block_size)
/ par->ch_layout.nb_channels;
...
}When nb_channels is zero, the CPU raises SIGFPE (integer divide-by-zero exception) and the process dies. According to the report, vpk_read_header even validates that nb_channels > 0, but in the fuzzer's custom AVIO path, the data used during probing and the data read later during packet reading can diverge: last_block_size and block_count end up calculated with a valid channel count, while nb_channels goes back to zero at the moment of the division.
The input that triggers the flaw is this 21-byte dump:
00000000 20 4b 50 56 56 50 00 f8 04 00 3b 03 61 39 56 32
00000010 36 36 30 38 50The first bytes match VPK's big-endian magic, which causes avformat_open_input to auto-detect the format and route it to the vulnerable demuxer. The bytes at 0x0e-0x11 (00 00 00 00) zero out the channel count, which is the trigger.
Is It Serious? Depends on What You Process
The author himself classifies the severity as medium and summarizes it like this in the report's exploitability table:
| Factor | Assessment | |---|---| | Determinism | Deterministic, 21 bytes, a single code path | | Trigger depth | Shallow: avformat_open_input detects the format via the magic | | Preconditions | None: self-contained input, no network, no heap setup | | Signal type | SIGFPE (divide by zero), not memory corruption | | Memory safety | No OOB read/write, no use-after-free, no NULL deref | | Scope | Any app that calls avformat_open_input + av_read_frame on untrusted data |
In other words: it's a denial-of-service (DoS) primitive, not a direct path to code execution. There's no controlled write or arbitrary read adjacent to the failing instruction. For those building software in Brazil, the practical takeaway is direct: if your backend uses FFmpeg (via libavformat) to process user-uploaded media (video thumbnails, upload transcoding, metadata extraction), a hostile file posing as VPK can crash the worker that reads it. It's worth remembering that media uploads are a classic vector in content platforms, and FFmpeg runs underneath a good chunk of that pipeline.
The Proposed Fix
The suggested fix is a guard at the top of vpk_read_packet, consistent with the validation that already exists in vpk_read_header:
if (par->ch_layout.nb_channels == 0)
return AVERROR_INVALIDDATA;Instead of SIGFPE, the read returns a clean error (-22, AVERROR_INVALIDDATA). The report also includes a regression test with the 21-byte input expecting exactly this return value. Later in the issue, member Jun Zhao pointed out that it appears to be the same problem already discussed on the ffmpeg-devel mailing list in November 2024 and referenced a pull request (#24297) that closes the issue. If you maintain your own copy of FFmpeg or have a build pinned to an older version, this is the kind of small patch worth tracking until it lands in the release branches.
The Debate: Is an AI Fuzzer Worth It?
The Hacker News thread about the discovery revolved less around the bug and more around the method. The recurring criticism is that generating invalid input is the easiest part of fuzzing. As 12j3afAv wrote:
"Generating an incorrect input file seems to be the easiest task of all for any fuzzer. Generating correct input to get deep into the call stack and then finding something is the hard part."
>
There were also those who reinforced that the result, however modest, has value. For cpriest, the interesting part isn't the tool's origin: "The interesting part isn't 'AI wrote the fuzzer.' It's that a cheap random harness still hits classical bugs in ancient parsers. Keep the corpus; throw away the hype," he wrote in his comment. Another reader, ks2052, raised a code hygiene question that runs through the case: "[...] can't you just mark all '/' as potential divide by zero errors? I guess sometimes developers think they 'know' some variable won't be zero, but unless it checked explicitly or by the compiler, that shouldn't be trusted," he pondered.
The report's numbers give a sense of the computational effort: the crash appeared after 495,211 runs, with a corpus of 13,188 entries, over 10h 43m of fuzzing. It's the logic that dabinat describes in the thread: sending an agent on an open-ended bug hunt is cheap because, if it doesn't find anything, the cost is just machine time, not a paid developer's time.
What Remains Open
The issue remains open at the time of publication, with the fix PR referenced but still pending merge and backport to the release branches listed in the project. It also remains open how far other versions and demuxers with similar patterns of unchecked division are exposed, a point that the very observation that the problem had already been discussed in 2024 suggests isn't isolated. If you depend on FFmpeg to process third-party media, today's practical step is to map where libavformat touches untrusted input and track the release that incorporates the guard.
Translated from the Brazilian Portuguese original · Read the original
Perplexity swaps DynamoDB for in-house database and cuts latency by 5x
The company behind the AI-powered search engine migrated its serving layer to CobbleDB, an internal database written in Rust, and cut batch read latency by up to 5x while saving at least 20% on storage.