summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartijn van Beurden <mvanb1@gmail.com>2022-04-04 20:13:44 +0200
committerMartijn van Beurden <mvanb1@gmail.com>2022-05-11 10:34:49 +0200
commit1bec35e33757fc38261b0acfa3c032e720d2baf0 (patch)
treeae22c765196c04d50ad01551c8905d561a624bc5
parentbecba351f00b2f09a39590264dfbb11b84c9fcba (diff)
downloadflac-1bec35e33757fc38261b0acfa3c032e720d2baf0.tar.gz
Add residual limit checking
This patch adds a (fast) check in the bitreader to detect overflow of the residual
-rw-r--r--src/libFLAC/bitreader.c12
-rw-r--r--src/libFLAC/stream_decoder.c13
2 files changed, 21 insertions, 4 deletions
diff --git a/src/libFLAC/bitreader.c b/src/libFLAC/bitreader.c
index aec255bf..1b6e63f6 100644
--- a/src/libFLAC/bitreader.c
+++ b/src/libFLAC/bitreader.c
@@ -804,6 +804,7 @@ FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, uint32_t *va
}
#endif
+#if 0 /* unused */
FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, uint32_t parameter)
{
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;
}
+#endif
/* 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)
@@ -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;
* must remember to flush them back to *br before calling other
* 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 */
brword b;
int *val, *end;
@@ -849,6 +851,8 @@ FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[
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 */
+ limit = UINT32_MAX >> parameter; /* Maximal msbs that can occur with residual bounded to int32_t */
+
val = vals;
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 */
if(!FLAC__bitreader_read_unary_unsigned(br, &msbs))
return false;
-
+ /* Checking limit here would be overzealous: coding UINT32_MAX
+ * with parameter == 0 would take 4GiB */
*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;
msbs = x;
+ if(x > limit)
+ return false;
+
/* read the binary LSBs */
x = (FLAC__uint32)(b >> (FLAC__BITS_PER_WORD - parameter)); /* parameter < 32, so we can cast to 32-bit uint32_t */
if(parameter <= ucbits) {
diff --git a/src/libFLAC/stream_decoder.c b/src/libFLAC/stream_decoder.c
index 2213cfee..fb1042a3 100644
--- a/src/libFLAC/stream_decoder.c
+++ b/src/libFLAC/stream_decoder.c
@@ -2899,8 +2899,17 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, uint32_
if(rice_parameter < pesc) {
partitioned_rice_contents->raw_bits[partition] = 0;
u = (partition == 0) ? partition_samples - predictor_order : partition_samples;
- 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(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)){
+ 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;
}
else {