avcodec/bonk: decode multiple passes in intlist_read() at once

This makes the worst case much faster

Fixes: Timeout
Fixes: 51363/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_BONK_fuzzer-5660734784143360
Fixes: 57957/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_BONK_fuzzer-5874095467397120

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
pull/389/head
Michael Niedermayer 2 years ago
parent e734e16544
commit 957106a24d
No known key found for this signature in database
GPG Key ID: B18E8928B3948D64
  1. 17
      libavcodec/bonk.c

@ -155,6 +155,7 @@ static int intlist_read(BonkContext *s, int *buf, int entries, int base_2_part)
int n_zeros = 0, step = 256, dominant = 0; int n_zeros = 0, step = 256, dominant = 0;
int pos = 0, level = 0; int pos = 0, level = 0;
BitCount *bits = s->bits; BitCount *bits = s->bits;
int passes = 1;
memset(buf, 0, entries * sizeof(*buf)); memset(buf, 0, entries * sizeof(*buf));
if (base_2_part) { if (base_2_part) {
@ -216,24 +217,28 @@ static int intlist_read(BonkContext *s, int *buf, int entries, int base_2_part)
x = 0; x = 0;
n_zeros = 0; n_zeros = 0;
for (i = 0; n_zeros < entries; i++) { for (i = 0; n_zeros < entries; i++) {
if (x >= max_x)
return AVERROR_INVALIDDATA;
if (pos >= entries) { if (pos >= entries) {
pos = 0; pos = 0;
level += 1 << low_bits; level += passes << low_bits;
passes = 1;
if (bits[x].bit && bits[x].count > entries - n_zeros)
passes = bits[x].count / (entries - n_zeros);
} }
if (level > 1 << 16) if (level > 1 << 16)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
if (x >= max_x)
return AVERROR_INVALIDDATA;
if (buf[pos] >= level) { if (buf[pos] >= level) {
if (bits[x].bit) if (bits[x].bit)
buf[pos] += 1 << low_bits; buf[pos] += passes << low_bits;
else else
n_zeros++; n_zeros++;
bits[x].count--; av_assert1(bits[x].count >= passes);
bits[x].count -= passes;
x += bits[x].count == 0; x += bits[x].count == 0;
} }

Loading…
Cancel
Save