Integer Divide-by-Zero in vpk_read_packet (VPK Demuxer) #24290
Labels
No labels
avcodec
avdevice
avfilter
avformat
avutil
backport/release/4.3
backport/release/4.4
backport/release/5.0
backport/release/5.1
backport/release/6.0
backport/release/6.1
backport/release/7.0
backport/release/7.1
backport/release/8.0
backport/release/8.1
backport/release/9.0
CLI
doc
Forgejo Fairy
swresample
swscale
vulkan
API
API major
bug
enhancement
fix/bug
fix/regression
GSoC
GSoC-Qualification
help wanted
important
LGTM
meta
needs backport
needs docs
needs fate test
needs info
needs sample
needs testing
new
question
regression
repro
flaky
repro
no
repro
no(env)
repro
yes
resolution
duplicate
resolution
external
resolution
fixed
resolution
invalid
resolution
wontfix
security
No milestone
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
FFmpeg/FFmpeg#24290
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Hello.
This is a bug found with our fuzzer: https://github.com/daedalus/fuzzer/
File:
libavformat/vpk.c:89Severity: Medium — crafted 21-byte input crashes any FFmpeg-based application that opens a malicious
.vpkfile or streamRoot cause:
vpk_read_packetdividesvpk->last_block_sizebypar->ch_layout.nb_channelswithout checking whethernb_channelsis zero. A malformed VPK header can setnb_channels = 0, causingSIGFPEon the division.Description
The Sony PS2 VPK demuxer (
libavformat/vpk.c) reads audio blocks from a custom container format. Invpk_read_packet, the last block of the stream is handled specially:Both
sizeandskipdivide bypar->ch_layout.nb_channels. Whennb_channelsis zero, the CPU raisesSIGFPE(integer divide-by-zero exception).Trigger Chain
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):20 4b 50 56— ASCII" KPV", which is the VPK big-endian magicVPKbyte-reversed across a word boundary00 00 00 00—nb_channels = 0, the crash triggerGDB Backtrace
Crash Metadata
SIGFPE(returncode −8)0x7ffff48a66d7(instruction itself)0x7fffffffcce036e65f4009ba0cabd704c2a52b21bd33Exploitability Assessment
avformat_open_inputauto-detects format from magicavformat_open_input+av_read_frameon untrusted dataThe divide-by-zero is a denial-of-service primitive. There is no controlled write or arbitrary read adjacent to the faulting instruction. The input can be embedded in a
.vpkfile or a container that identifies itself as VPK to trigger the crash in any FFmpeg-linked application.Suggested Fix
Add a guard at the top of
vpk_read_packetto reject zero-channel streams cleanly:This is consistent with the existing validation in
vpk_read_header(if (st->codecpar->ch_layout.nb_channels <= 0) return AVERROR_INVALIDDATA;) and returns a clean error instead ofSIGFPE.Regression Test
It seems to be the same issue as the one discussed in https://ffmpeg.org/pipermail/ffmpeg-devel/2024-November/335598.html.