From 3f7ed312614649e2695b54b398475d32be4f64f3 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Wed, 8 Nov 2017 00:29:14 +0000 Subject: adpcm: fix stack overflow with >4 channels (CVE-2017-15372) --- src/adpcm.c | 8 +++++++- src/adpcm.h | 3 +++ src/wav.c | 5 ++++- 3 files changed, 14 insertions(+), 2 deletions(-) Index: sox/src/adpcm.c =================================================================== --- sox.orig/src/adpcm.c +++ sox/src/adpcm.c @@ -71,6 +71,11 @@ const short lsx_ms_adpcm_i_coef[7][2] = { 392,-232} }; +extern void *lsx_ms_adpcm_alloc(unsigned chans) +{ + return lsx_malloc(chans * sizeof(MsState_t)); +} + static inline sox_sample_t AdpcmDecode(sox_sample_t c, MsState_t *state, sox_sample_t sample1, sox_sample_t sample2) { @@ -102,6 +107,7 @@ static inline sox_sample_t AdpcmDecode(s /* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */ const char *lsx_ms_adpcm_block_expand_i( + void *priv, unsigned chans, /* total channels */ int nCoef, const short *coef, @@ -113,7 +119,7 @@ const char *lsx_ms_adpcm_block_expand_i( const unsigned char *ip; unsigned ch; const char *errmsg = NULL; - MsState_t state[4]; /* One decompressor state for each channel */ + MsState_t *state = priv; /* One decompressor state for each channel */ /* Read the four-byte header for each channel */ ip = ibuff; Index: sox/src/adpcm.h =================================================================== --- sox.orig/src/adpcm.h +++ sox/src/adpcm.h @@ -29,8 +29,11 @@ /* default coef sets */ extern const short lsx_ms_adpcm_i_coef[7][2]; +extern void *lsx_ms_adpcm_alloc(unsigned chans); + /* lsx_ms_adpcm_block_expand_i() outputs interleaved samples into one output buffer */ extern const char *lsx_ms_adpcm_block_expand_i( + void *priv, unsigned chans, /* total channels */ int nCoef, const short *coef, Index: sox/src/wav.c =================================================================== --- sox.orig/src/wav.c +++ sox/src/wav.c @@ -82,6 +82,7 @@ typedef struct { /* following used by *ADPCM wav files */ unsigned short nCoefs; /* ADPCM: number of coef sets */ short *lsx_ms_adpcm_i_coefs; /* ADPCM: coef sets */ + void *ms_adpcm_data; /* Private data of adpcm decoder */ unsigned char *packet; /* Temporary buffer for packets */ short *samples; /* interleaved samples buffer */ short *samplePtr; /* Pointer to current sample */ @@ -175,7 +176,7 @@ static unsigned short AdpcmReadBlock(so } } - errmsg = lsx_ms_adpcm_block_expand_i(ft->signal.channels, wav->nCoefs, wav->lsx_ms_adpcm_i_coefs, wav->packet, wav->samples, samplesThisBlock); + errmsg = lsx_ms_adpcm_block_expand_i(wav->ms_adpcm_data, ft->signal.channels, wav->nCoefs, wav->lsx_ms_adpcm_i_coefs, wav->packet, wav->samples, samplesThisBlock); if (errmsg) lsx_warn("%s", errmsg); @@ -791,6 +792,7 @@ static int startread(sox_format_t * ft) /* nCoefs, lsx_ms_adpcm_i_coefs used by adpcm.c */ wav->lsx_ms_adpcm_i_coefs = lsx_malloc(wav->nCoefs * 2 * sizeof(short)); + wav->ms_adpcm_data = lsx_ms_adpcm_alloc(wChannels); { int i, errct=0; for (i=0; len>=2 && i < 2*wav->nCoefs; i++) { @@ -1216,6 +1218,7 @@ static int stopread(sox_format_t * ft) free(wav->packet); free(wav->samples); free(wav->lsx_ms_adpcm_i_coefs); + free(wav->ms_adpcm_data); free(wav->comment); wav->comment = NULL;