Merged four commits:
commit fcf0ba06ae12ccd7c67cee3c8d948df15f946b85
Author: Erik de Castro Lopo <erikd@mega-nerd.com>
Date: Wed Nov 19 19:35:59 2014 -0800
src/libFACL/stream_decoder.c : Fail safely to avoid a heap overflow.
A file provided by the reporters caused the stream decoder to write to
un-allocated heap space resulting in a segfault. The solution is to
error out (by returning false from read_residual_partitioned_rice_())
instead of trying to continue to decode.
Fixes: CVE-2014-9028
Reported-by: Michele Spagnuolo,
Google Security Team <mikispag@google.com>
commit 5a365996d739bdf4711af51d9c2c71c8a5e14660
Author: Erik de Castro Lopo <erikd@mega-nerd.com>
Date: Thu Nov 27 11:55:11 2014 +1100
src/libFLAC/stream_decoder.c : Fail safely to avoid a heap overflow.
This fix is closely related to the fix for CVE-2014-9028. When that
fix went public Miroslav Lichvar noticed a similar potential problem
spot in the same function and was able to craft a file to trigger a
heap write overflow.
Reported-by : Miroslav Lichvar <mlichvar@redhat.com>
commit b4b2910bdca010808ccf2799f55562fa91f4347b
Author: Erik de Castro Lopo <erikd@mega-nerd.com>
Date: Wed Dec 10 18:54:16 2014 +1100
src/libFLAC/stream_decoder.c : Fix seek bug.
Janne Hyvärinen reported a problem with seeking as a result of the
fix for CVE-2014-9028. This is a different solution to the issue
that should not adversely affect seeking.
This version of the fix for the above CVE has been extensively fuzz
tested using afl (http://lcamtuf.coredump.cx/afl/).
Reported-by: Janne Hyvärinen <cse@sci.fi>
commit fed0dfa1086296df0af41ca8f0c6430d5ac75c87
Author: Miroslav Lichvar <mlichvar@redhat.com>
Date: Mon Dec 15 15:46:12 2014 +0100
src/libFLAC/stream_decoder.c : Rework fix for seeking bug.
To avoid crash caused by an unbound LPC decoding when predictor order is
larger than blocksize, the sanity check needs to be moved to the subframe
decoding functions.
Signed-off-by: Erik de Castro Lopo <erikd@mega-nerd.com>
diff -up flac-1.3.0/src/libFLAC/stream_decoder.c.cve-2014-9028 flac-1.3.0/src/libFLAC/stream_decoder.c
--- flac-1.3.0/src/libFLAC/stream_decoder.c.cve-2014-9028 2015-03-27 16:59:10.898884915 +0100
+++ flac-1.3.0/src/libFLAC/stream_decoder.c 2015-03-27 17:00:34.879125031 +0100
@@ -2550,6 +2550,11 @@ FLAC__bool read_subframe_fixed_(FLAC__St
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
return false; /* read_callback_ sets the state for us */
+ if(decoder->private_->frame.header.blocksize >> u32 < order) {
+ send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
+ decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
+ return true;
+ }
subframe->entropy_coding_method.data.partitioned_rice.order = u32;
subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel];
break;
@@ -2629,6 +2634,11 @@ FLAC__bool read_subframe_lpc_(FLAC__Stre
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
if(!FLAC__bitreader_read_raw_uint32(decoder->private_->input, &u32, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
return false; /* read_callback_ sets the state for us */
+ if(decoder->private_->frame.header.blocksize >> u32 < order) {
+ send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
+ decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
+ return true;
+ }
subframe->entropy_coding_method.data.partitioned_rice.order = u32;
subframe->entropy_coding_method.data.partitioned_rice.contents = &decoder->private_->partitioned_rice_contents[channel];
break;
@@ -2704,21 +2714,8 @@ FLAC__bool read_residual_partitioned_ric
const unsigned plen = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
const unsigned pesc = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
- /* sanity checks */
- if(partition_order == 0) {
- if(decoder->private_->frame.header.blocksize < predictor_order) {
- 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 {
- if(partition_samples < predictor_order) {
- send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC);
- decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
- return true;
- }
- }
+ /* invalid predictor and partition orders mush be handled in the callers */
+ FLAC__ASSERT(partition_order > 0? partition_samples >= predictor_order : decoder->private_->frame.header.blocksize >= predictor_order);
if(!FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(partitioned_rice_contents, flac_max(6u, partition_order))) {
decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;