Integer Divide-by-Zero in vpk_read_packet (VPK Demuxer) #24290
opened 18 hours ago by [Darío Clavijo]
· 1 comment
Hello.
This is a bug found with our fuzzer: https://github.com/daedalus/fuzzer/
File: libavformat/vpk.c:89
Severity: Medium — crafted 21-byte input crashes any FFmpeg-based application that opens a malicious .vpk file or stream
Root cause: vpk_read_packet divides vpk->last_block_size by par->ch_layout.nb_channels without checking whether nb_channels is zero. A malformed VPK header can set nb_channels = 0, causing SIGFPE on the division.
Description
The Sony PS2 VPK demuxer (libavformat/vpk.c) reads audio blocks from a custom container format. In vpk_read_packet, the last block of the stream is handled specially:
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;
...
}
Both size and skip divide by par->ch_layout.nb_channels. When nb_channels is zero, the CPU raises SIGFPE (integer divide-by-zero exception).
Trigger Chain
- Demuxer probe (
vpk_probe) matches theVPKbig-endian magic and assigns the input to the VPK demuxer. vpk_read_headerparses the 24-byte header. The fuzz input setsnb_channels = 0at header bytes0x0e–0x11.vpk_read_headerdoes validatenb_channels > 0, but in the fuzzer's custom-AVIO path the probe/header data and the later packet-read data can diverge: by the timevpk_read_packetruns,par->ch_layout.nb_channelshas reverted to0from the original fuzz stream whilevpk->last_block_sizeandvpk->block_countwere computed from probe data with a valid channel count. The division is therefore reached with a live-but-zero divisor.vpk_read_packetreaches the final-block branch and divides by zero on bothsizeandskip.
Crash Input
Hex dump of the 21-byte crash input (crash_1787378545_34bc062c_sig_signal8.bin):
00000000 20 4b 50 56 56 50 00 f8 04 00 3b 03 61 39 56 32 | KPVVP....;.a9V2|
00000010 36 36 30 38 50 |6608P|
- Bytes 0–3:
20 4b 50 56— ASCII `



