Skip to content

Commit c68e000

Browse files
committed
CVE-2019-7575: Fix a buffer overwrite in MS_ADPCM_decode
If a WAV format defines shorter audio stream and decoded MS ADPCM data chunk is longer, decoding continued past the output audio buffer. This fix is based on a patch from <https://bugzilla.libsdl.org/show_bug.cgi?id=4492>. https://bugzilla.libsdl.org/show_bug.cgi?id=4493 CVE-2019-7575 Signed-off-by: Petr P?sa? <ppisar@redhat.com>
1 parent 9e69d60 commit c68e000

File tree

1 file changed

+8
-5
lines changed

1 file changed

+8
-5
lines changed

src/audio/SDL_wave.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ static Sint32 MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state,
122122
static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
123123
{
124124
struct MS_ADPCM_decodestate *state[2];
125-
Uint8 *freeable, *encoded, *encoded_end, *decoded;
125+
Uint8 *freeable, *encoded, *encoded_end, *decoded, *decoded_end;
126126
Sint32 encoded_len, samplesleft;
127127
Sint8 nybble, stereo;
128128
Sint16 *coeff[2];
@@ -142,14 +142,15 @@ static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
142142
return(-1);
143143
}
144144
decoded = *audio_buf;
145+
decoded_end = decoded + *audio_len;
145146

146147
/* Get ready... Go! */
147148
stereo = (MS_ADPCM_state.wavefmt.channels == 2);
148149
state[0] = &MS_ADPCM_state.state[0];
149150
state[1] = &MS_ADPCM_state.state[stereo];
150151
while ( encoded_len >= MS_ADPCM_state.wavefmt.blockalign ) {
151152
/* Grab the initial information for this block */
152-
if (encoded + 7 + (stereo ? 7 : 0) > encoded_end) goto too_short;
153+
if (encoded + 7 + (stereo ? 7 : 0) > encoded_end) goto invalid_size;
153154
state[0]->hPredictor = *encoded++;
154155
if ( stereo ) {
155156
state[1]->hPredictor = *encoded++;
@@ -179,6 +180,7 @@ static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
179180
coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor];
180181

181182
/* Store the two initial samples we start with */
183+
if (decoded + 4 + (stereo ? 4 : 0) > decoded_end) goto invalid_size;
182184
decoded[0] = state[0]->iSamp2&0xFF;
183185
decoded[1] = state[0]->iSamp2>>8;
184186
decoded += 2;
@@ -200,7 +202,8 @@ static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
200202
samplesleft = (MS_ADPCM_state.wSamplesPerBlock-2)*
201203
MS_ADPCM_state.wavefmt.channels;
202204
while ( samplesleft > 0 ) {
203-
if (encoded + 1 > encoded_end) goto too_short;
205+
if (encoded + 1 > encoded_end) goto invalid_size;
206+
if (decoded + 4 > decoded_end) goto invalid_size;
204207

205208
nybble = (*encoded)>>4;
206209
new_sample = MS_ADPCM_nibble(state[0],nybble,coeff[0]);
@@ -223,8 +226,8 @@ static int MS_ADPCM_decode(Uint8 **audio_buf, Uint32 *audio_len)
223226
}
224227
SDL_free(freeable);
225228
return(0);
226-
too_short:
227-
SDL_SetError("Too short chunk for a MS ADPCM decoder");
229+
invalid_size:
230+
SDL_SetError("Unexpected chunk length for a MS ADPCM decoder");
228231
SDL_free(freeable);
229232
return(-1);
230233
invalid_predictor:

0 commit comments

Comments
 (0)