Blob Blame History Raw
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;