From: Anthony Hurtado <[email protected]>

vpk_read_packet() divides vpk->last_block_size and
(par->block_align - vpk->last_block_size) by
par->ch_layout.nb_channels without checking for zero.

While vpk_read_header() validates nb_channels > 0, the codec
parameters may become zero through format probing misidentification
(VPK probe score is 2/3 of AVPROBE_SCORE_MAX) or codec parameter
reset, causing SIGFPE.

Fix by:
- Checking nb_channels != 0 before division in vpk_read_packet
- Returning EOF for empty last blocks (last_block_size == 0)
- Validating block_count > 0 in vpk_read_header
- Validating last_block_size <= block_align in vpk_read_header

Found by fuzzing with libFuzzer + AddressSanitizer. Reproduces with
10 distinct inputs.

Signed-off-by: Anthony Hurtado <[email protected]>
---
 libavformat/vpk.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/libavformat/vpk.c b/libavformat/vpk.c
index f6270a1..7ad0ebe 100644
--- a/libavformat/vpk.c
+++ b/libavformat/vpk.c
@@ -68,7 +68,11 @@ static int vpk_read_header(AVFormatContext *s)
     if (samples_per_block <= 0)
         return AVERROR_INVALIDDATA;
     vpk->block_count       = (st->duration + (samples_per_block - 1)) / 
samples_per_block;
+    if (!vpk->block_count)
+        return AVERROR_INVALIDDATA;
     vpk->last_block_size   = (st->duration % samples_per_block) * 16 * 
st->codecpar->ch_layout.nb_channels / 28;
+    if (vpk->last_block_size > (unsigned)st->codecpar->block_align)
+        return AVERROR_INVALIDDATA;
 
     if (offset < avio_tell(s->pb))
         return AVERROR_INVALIDDATA;
@@ -87,6 +91,10 @@ static int vpk_read_packet(AVFormatContext *s, AVPacket *pkt)
 
     vpk->current_block++;
     if (vpk->current_block == vpk->block_count) {
+        if (!par->ch_layout.nb_channels)
+            return AVERROR_INVALIDDATA;
+        if (!vpk->last_block_size)
+            return AVERROR_EOF;
         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;
         uint64_t pos = avio_tell(s->pb);
-- 
2.47.3


_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to