Add residual limit checking

This patch adds a (fast) check in the bitreader to detect overflow
of the residual
This commit is contained in:
Martijn van Beurden 2022-04-04 20:13:44 +02:00
parent becba351f0
commit 1bec35e337
2 changed files with 21 additions and 4 deletions

View File

@ -804,6 +804,7 @@ FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, uint32_t *va
} }
#endif #endif
#if 0 /* unused */
FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, uint32_t parameter) FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, uint32_t parameter)
{ {
FLAC__uint32 lsbs = 0, msbs = 0; FLAC__uint32 lsbs = 0, msbs = 0;
@ -830,6 +831,7 @@ FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, uint3
return true; return true;
} }
#endif
/* this is by far the most heavily used reader call. it ain't pretty but it's fast */ /* this is by far the most heavily used reader call. it ain't pretty but it's fast */
FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], uint32_t nvals, uint32_t parameter) FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], uint32_t nvals, uint32_t parameter)
@ -837,7 +839,7 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[
/* try and get br->consumed_words and br->consumed_bits into register; /* try and get br->consumed_words and br->consumed_bits into register;
* must remember to flush them back to *br before calling other * must remember to flush them back to *br before calling other
* bitreader functions that use them, and before returning */ * bitreader functions that use them, and before returning */
uint32_t cwords, words, lsbs, msbs, x, y; uint32_t cwords, words, lsbs, msbs, x, y, limit;
uint32_t ucbits; /* keep track of the number of unconsumed bits in word */ uint32_t ucbits; /* keep track of the number of unconsumed bits in word */
brword b; brword b;
int *val, *end; int *val, *end;
@ -849,6 +851,8 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[
FLAC__ASSERT(parameter < 32); FLAC__ASSERT(parameter < 32);
/* the above two asserts also guarantee that the binary part never straddles more than 2 words, so we don't have to loop to read it */ /* the above two asserts also guarantee that the binary part never straddles more than 2 words, so we don't have to loop to read it */
limit = UINT32_MAX >> parameter; /* Maximal msbs that can occur with residual bounded to int32_t */
val = vals; val = vals;
end = vals + nvals; end = vals + nvals;
@ -857,7 +861,8 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[
/* read the unary MSBs and end bit */ /* read the unary MSBs and end bit */
if(!FLAC__bitreader_read_unary_unsigned(br, &msbs)) if(!FLAC__bitreader_read_unary_unsigned(br, &msbs))
return false; return false;
/* Checking limit here would be overzealous: coding UINT32_MAX
* with parameter == 0 would take 4GiB */
*val++ = (int)(msbs >> 1) ^ -(int)(msbs & 1); *val++ = (int)(msbs >> 1) ^ -(int)(msbs & 1);
} }
@ -898,6 +903,9 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[
ucbits = (ucbits - x - 1) % FLAC__BITS_PER_WORD; ucbits = (ucbits - x - 1) % FLAC__BITS_PER_WORD;
msbs = x; msbs = x;
if(x > limit)
return false;
/* read the binary LSBs */ /* read the binary LSBs */
x = (FLAC__uint32)(b >> (FLAC__BITS_PER_WORD - parameter)); /* parameter < 32, so we can cast to 32-bit uint32_t */ x = (FLAC__uint32)(b >> (FLAC__BITS_PER_WORD - parameter)); /* parameter < 32, so we can cast to 32-bit uint32_t */
if(parameter <= ucbits) { if(parameter <= ucbits) {

View File

@ -2899,8 +2899,17 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, uint32_
if(rice_parameter < pesc) { if(rice_parameter < pesc) {
partitioned_rice_contents->raw_bits[partition] = 0; partitioned_rice_contents->raw_bits[partition] = 0;
u = (partition == 0) ? partition_samples - predictor_order : partition_samples; u = (partition == 0) ? partition_samples - predictor_order : partition_samples;
if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)) if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)){
return false; /* read_callback_ sets the state for us */ if(decoder->protected_->state == FLAC__STREAM_DECODER_READ_FRAME) {
/* no error was set, read_callback_ didn't set it, so
* invalid rice symbol was found */
send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
return true;
}
else
return false; /* read_callback_ sets the state for us */
}
sample += u; sample += u;
} }
else { else {