On Sat, 28 Nov 2009, Stefan Fritsch wrote:
Matthias was right, there is a confusion between samples and frames. I have
completed the patch and added a few sanity checks. Reviewers are wellcome.
Sorry, I attached the wrong file (a broken version). Now I have the right
one...#! /bin/sh /usr/share/dpatch/dpatch-run
## 22_CVE-2008-5824.dpatch by Stefan Fritsch <s...@debian.org>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Remove confusion between samples per block and frames perl block, to
## DP: avoid buffer overflow (probably samplesPerBlock should be renamed to
## DP: FramesPerBlock). Add sanity checks inspired by sox source code.
@DPATCH@
diff -urNad audiofile-0.2.6~/libaudiofile/modules/msadpcm.c
audiofile-0.2.6/libaudiofile/modules/msadpcm.c
--- audiofile-0.2.6~/libaudiofile/modules/msadpcm.c 2004-03-06
07:39:23.000000000 +0100
+++ audiofile-0.2.6/libaudiofile/modules/msadpcm.c 2009-11-28
16:44:59.863411251 +0100
@@ -129,8 +129,7 @@
ms_adpcm_state *state[2];
/* Calculate the number of bytes needed for decoded data. */
- outputLength = msadpcm->samplesPerBlock * sizeof (int16_t) *
- msadpcm->track->f.channelCount;
+ outputLength = msadpcm->samplesPerBlock * sizeof (int16_t);
channelCount = msadpcm->track->f.channelCount;
@@ -180,8 +179,8 @@
The first two samples have already been 'decoded' in
the block header.
*/
- samplesRemaining = (msadpcm->samplesPerBlock - 2) *
- msadpcm->track->f.channelCount;
+ samplesRemaining = msadpcm->samplesPerBlock
+ - 2 * msadpcm->track->f.channelCount;
while (samplesRemaining > 0)
{
diff -urNad audiofile-0.2.6~/libaudiofile/wave.c
audiofile-0.2.6/libaudiofile/wave.c
--- audiofile-0.2.6~/libaudiofile/wave.c 2009-11-28 16:44:59.722415268
+0100
+++ audiofile-0.2.6/libaudiofile/wave.c 2009-11-28 16:45:08.642428937 +0100
@@ -199,11 +199,13 @@
case WAVE_FORMAT_ADPCM:
{
u_int16_t bitsPerSample, extraByteCount,
- samplesPerBlock, numCoefficients;
+ samplesPerBlock, numCoefficients,
+ framesPerBlock;
int i;
AUpvlist pv;
long l;
void *v;
+ int minBlockLength;
if (track->f.channelCount != 1 &&
track->f.channelCount != 2)
@@ -216,11 +218,33 @@
af_fread(&bitsPerSample, 1, 2, fp);
bitsPerSample = LENDIAN_TO_HOST_INT16(bitsPerSample);
+ if (bitsPerSample != 4)
+ {
+ _af_error(AF_BAD_WIDTH,
+ "bad sample width of %hd bits",
+ bitsPerSample);
+ return AF_FAIL;
+ }
+
af_fread(&extraByteCount, 1, 2, fp);
extraByteCount = LENDIAN_TO_HOST_INT16(extraByteCount);
- af_fread(&samplesPerBlock, 1, 2, fp);
- samplesPerBlock =
LENDIAN_TO_HOST_INT16(samplesPerBlock);
+ af_fread(&framesPerBlock, 1, 2, fp);
+ framesPerBlock = LENDIAN_TO_HOST_INT16(framesPerBlock);
+
+ minBlockLength = 7 * channelCount; /* header */
+ if (framesPerBlock > 2)
+ minBlockLength += ( ( framesPerBlock - 2 ) *
channelCount + 1) / 2;
+
+ if (blockAlign < minBlockLength)
+ {
+ _af_error(AF_BAD_FRAMECNT,
+ "blockAlign %hd too small for %hd
samplesPerBlock",
+ blockAlign, samplesPerBlock);
+ return AF_FAIL;
+ }
+
+ samplesPerBlock = framesPerBlock *channelCount;
af_fread(&numCoefficients, 1, 2, fp);
numCoefficients =
LENDIAN_TO_HOST_INT16(numCoefficients);
@@ -242,6 +266,7 @@
wave->msadpcmCoefficients[i][1] = a1;
}
+
track->f.sampleWidth = 16;
track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP;
track->f.compressionType = AF_COMPRESSION_MS_ADPCM;
@@ -277,18 +302,44 @@
{
AUpvlist pv;
long l;
+ int minBlockLength;
u_int16_t bitsPerSample, extraByteCount,
- samplesPerBlock;
+ samplesPerBlock, framesPerBlock;
af_fread(&bitsPerSample, 1, 2, fp);
bitsPerSample = LENDIAN_TO_HOST_INT16(bitsPerSample);
+ if (bitsPerSample != 4)
+ {
+ _af_error(AF_BAD_WIDTH,
+ "bad sample width of %hd bits",
+ bitsPerSample);
+ return AF_FAIL;
+ }
+
af_fread(&extraByteCount, 1, 2, fp);
extraByteCount = LENDIAN_TO_HOST_INT16(extraByteCount);
- af_fread(&samplesPerBlock, 1, 2, fp);
- samplesPerBlock =
LENDIAN_TO_HOST_INT16(samplesPerBlock);
+ af_fread(&framesPerBlock, 1, 2, fp);
+ framesPerBlock = LENDIAN_TO_HOST_INT16(framesPerBlock);
+ samplesPerBlock = framesPerBlock * channelCount;
+
+ /* per channel, ima has blocks of len 4, the 1st has
1st sample, the others
+ * up to 8 samples per block,
+ * so number of later blocks is (nsamp-1 + 7)/8, total
blocks/chan is
+ * (nsamp-1+7)/8 + 1 = (nsamp+14)/8
+ */
+
+ minBlockLength = ( framesPerBlock + 14 )/8 * 4 *
channelCount;
+
+ if (blockAlign < minBlockLength)
+ {
+ _af_error(AF_BAD_FRAMECNT,
+ "blockAlign %hd too small for %hd
samplesPerBlock",
+ blockAlign, samplesPerBlock);
+ return AF_FAIL;
+ }
track->f.sampleWidth = 16;
track->f.sampleFormat = AF_SAMPFMT_TWOSCOMP;