Fix fuzzer_decoder timeouts

fuzzer_decoder was running into timeouts because it triggered the
gap-filling for broken frames with 5*192000 samples and a blocksize
of 1, causing the write callback to be called 960000 times. Doing
this several times in one file caused a single fuzz run to take
> 60 seconds

This commit limits the minimum blocksize to 16 samples, and the
maximum number of frames emitted to 50

Credit: Oss-Fuzz
Issue: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=47193
This commit is contained in:
Martijn van Beurden 2022-05-28 22:13:23 +02:00
parent 9e425621cc
commit 95064f9f08
1 changed files with 8 additions and 3 deletions

View File

@ -2120,14 +2120,19 @@ FLAC__bool read_frame_(FLAC__StreamDecoder *decoder, FLAC__bool *got_a_frame, FL
* channels and bits_per_sample, but it is quite rare */ * channels and bits_per_sample, but it is quite rare */
if(decoder->private_->last_frame.header.sample_rate == decoder->private_->frame.header.sample_rate && if(decoder->private_->last_frame.header.sample_rate == decoder->private_->frame.header.sample_rate &&
decoder->private_->last_frame.header.channels == decoder->private_->frame.header.channels && decoder->private_->last_frame.header.channels == decoder->private_->frame.header.channels &&
decoder->private_->last_frame.header.bits_per_sample == decoder->private_->frame.header.bits_per_sample) { decoder->private_->last_frame.header.bits_per_sample == decoder->private_->frame.header.bits_per_sample &&
decoder->private_->last_frame.header.blocksize >= 16) {
FLAC__Frame empty_frame; FLAC__Frame empty_frame;
empty_frame.header = decoder->private_->last_frame.header; empty_frame.header = decoder->private_->last_frame.header;
empty_frame.footer.crc = 0; empty_frame.footer.crc = 0;
/* No repairs larger than 5 seconds are made, to not unexpectedly create /* No repairs larger than 5 seconds or 50 frames are made, to not
* enormous files when one of the headers was corrupt after all */ * unexpectedly create enormous files when one of the headers was
* corrupt after all */
if(padding_samples_needed > (5*empty_frame.header.sample_rate)) if(padding_samples_needed > (5*empty_frame.header.sample_rate))
padding_samples_needed = 5*empty_frame.header.sample_rate; padding_samples_needed = 5*empty_frame.header.sample_rate;
if(padding_samples_needed > (50*empty_frame.header.blocksize))
padding_samples_needed = 50*empty_frame.header.blocksize;
while(padding_samples_needed){ while(padding_samples_needed){
empty_frame.header.number.sample_number += empty_frame.header.blocksize; empty_frame.header.number.sample_number += empty_frame.header.blocksize;
if(padding_samples_needed < empty_frame.header.blocksize) if(padding_samples_needed < empty_frame.header.blocksize)