1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
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,
|