Description: CVE-2019-7572, CVE-2019-7574
 CVE-2019-7572: a buffer over-read in IMA_ADPCM_nibble in audio/SDL_wave.c.
 CVE-2019-7574: a heap-based buffer over-read in IMA_ADPCM_decode in audio/SDL_wave.c.

---
Author: Abhijith PA <abhijith@debian.org>
Origin: https://bugzilla-attachments.libsdl.org/attachment.cgi?id=3610
        https://bugzilla.libsdl.org/attachment.cgi?id=3612
        https://bugzilla.libsdl.org/attachment.cgi?id=3618
Bug: https://bugzilla.libsdl.org/show_bug.cgi?id=4496
     https://bugzilla.libsdl.org/show_bug.cgi?id=4495
Last-Update: <2018-03-05>

Index: libsdl1.2-1.2.15/src/audio/SDL_wave.c
===================================================================
--- libsdl1.2-1.2.15.orig/src/audio/SDL_wave.c
+++ libsdl1.2-1.2.15/src/audio/SDL_wave.c
@@ -264,6 +264,14 @@ static Sint32 IMA_ADPCM_nibble(struct IM
 	};
 	Sint32 delta, step;
 
+	/* Clamp index value. The inital value can be invalid. */
+	if ( state->index > 88 ) {
+		state->index = 88;
+	} else
+	if ( state->index < 0 ) {
+		state->index = 0;
+	}
+
 	/* Compute difference and new sample value */
 	step = step_table[state->index];
 	delta = step >> 3;
@@ -275,12 +283,6 @@ static Sint32 IMA_ADPCM_nibble(struct IM
 
 	/* Update index value */
 	state->index += index_table[nybble];
-	if ( state->index > 88 ) {
-		state->index = 88;
-	} else
-	if ( state->index < 0 ) {
-		state->index = 0;
-	}
 
 	/* Clamp output sample */
 	if ( state->sample > max_audioval ) {
@@ -323,7 +325,7 @@ static void Fill_IMA_ADPCM_block(Uint8 *
 static int IMA_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
 {
 	struct IMA_ADPCM_decodestate *state;
-	Uint8 *freeable, *encoded, *decoded;
+	Uint8 *freeable, *encoded, *encoded_end, *decoded, *decoded_end;
 	Sint32 encoded_len, samplesleft;
 	unsigned int c, channels;
 
@@ -339,6 +341,7 @@ static int IMA_ADPCM_decode(Uint8 **audi
 	/* Allocate the proper sized output buffer */
 	encoded_len = *audio_len;
 	encoded = *audio_buf;
+	encoded_end = encoded + encoded_len;
 	freeable = *audio_buf;
 	*audio_len = (encoded_len/IMA_ADPCM_state.wavefmt.blockalign) * 
 				IMA_ADPCM_state.wSamplesPerBlock*
@@ -349,11 +352,13 @@ static int IMA_ADPCM_decode(Uint8 **audi
 		return(-1);
 	}
 	decoded = *audio_buf;
+	decoded_end = decoded + *audio_len;
 
 	/* Get ready... Go! */
 	while ( encoded_len >= IMA_ADPCM_state.wavefmt.blockalign ) {
 		/* Grab the initial information for this block */
 		for ( c=0; c<channels; ++c ) {
+			if (encoded + 4 > encoded_end) goto invalid_size;
 			/* Fill the state information for this block */
 			state[c].sample = ((encoded[1]<<8)|encoded[0]);
 			encoded += 2;
@@ -367,6 +372,7 @@ static int IMA_ADPCM_decode(Uint8 **audi
 			}
 
 			/* Store the initial sample we start with */
+			if (decoded + 2 > decoded_end) goto invalid_size;
 			decoded[0] = (Uint8)(state[c].sample&0xFF);
 			decoded[1] = (Uint8)(state[c].sample>>8);
 			decoded += 2;
@@ -376,6 +382,9 @@ static int IMA_ADPCM_decode(Uint8 **audi
 		samplesleft = (IMA_ADPCM_state.wSamplesPerBlock-1)*channels;
 		while ( samplesleft > 0 ) {
 			for ( c=0; c<channels; ++c ) {
+                                if (encoded + 4 > encoded_end) goto invalid_size;
+				if (decoded + 4 * 4 * channels > decoded_end)
+                                              goto invalid_size;
 				Fill_IMA_ADPCM_block(decoded, encoded,
 						c, channels, &state[c]);
 				encoded += 4;
@@ -387,6 +396,10 @@ static int IMA_ADPCM_decode(Uint8 **audi
 	}
 	SDL_free(freeable);
 	return(0);
+	invalid_size:
+	SDL_SetError("Unexpected chunk length for an IMA ADPCM decoder");
+	SDL_free(freeable);
+	return(-1);
 }
 
 SDL_AudioSpec * SDL_LoadWAV_RW (SDL_RWops *src, int freesrc,
