--- audiofile-0.3.6.old/libaudiofile/WAVE.cpp +++ audiofile-0.3.6/libaudiofile/WAVE.cpp @@ -281,6 +281,12 @@ /* numCoefficients should be at least 7. */ assert(numCoefficients >= 7 && numCoefficients <= 255); + if (numCoefficients < 7 || numCoefficients > 255) + { + _af_error(AF_BAD_HEADER, + "Bad number of coefficients"); + return AF_FAIL; + } m_msadpcmNumCoefficients = numCoefficients; @@ -326,6 +332,7 @@ { _af_error(AF_BAD_NOT_IMPLEMENTED, "IMA ADPCM compression supports only 4 bits per sample"); + return AF_FAIL; } int bytesPerBlock = (samplesPerBlock + 14) / 8 * 4 * channelCount; @@ -333,6 +340,7 @@ { _af_error(AF_BAD_CODEC_CONFIG, "Invalid samples per block for IMA ADPCM compression"); + return AF_FAIL; } track->f.sampleWidth = 16; --- audiofile-0.3.6.old/libaudiofile/modules/BlockCodec.cpp +++ audiofile-0.3.6/libaudiofile/modules/BlockCodec.cpp @@ -47,13 +47,14 @@ // Read the compressed data. ssize_t bytesRead = read(m_inChunk->buffer, m_bytesPerPacket * blockCount); - int blocksRead = bytesRead >= 0 ? bytesRead / m_bytesPerPacket : 0; + int blocksRead = (bytesRead >= 0 && m_bytesPerPacket > 0) ? bytesRead / m_bytesPerPacket : 0; // Decompress into m_outChunk. for (int i=0; i(m_inChunk->buffer) + i * m_bytesPerPacket, - static_cast(m_outChunk->buffer) + i * m_framesPerPacket * m_track->f.channelCount); + if (decodeBlock(static_cast(m_inChunk->buffer) + i * m_bytesPerPacket, + static_cast(m_outChunk->buffer) + i * m_framesPerPacket * m_track->f.channelCount)==0) + break; framesRead += m_framesPerPacket; } --- audiofile-0.3.6.old/libaudiofile/modules/IMA.cpp +++ audiofile-0.3.6/libaudiofile/modules/IMA.cpp @@ -169,7 +169,7 @@ if (encoded[1] & 0x80) m_adpcmState[c].previousValue -= 0x10000; - m_adpcmState[c].index = encoded[2]; + m_adpcmState[c].index = clamp(encoded[2], 0, 88); *decoded++ = m_adpcmState[c].previousValue; @@ -210,7 +210,7 @@ predictor -= 0x10000; state.previousValue = clamp(predictor, MIN_INT16, MAX_INT16); - state.index = encoded[1] & 0x7f; + state.index = clamp(encoded[1] & 0x7f, 0, 88); encoded += 2; for (int n=0; n>=1; + ++position; + } + return position; +} + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +bool multiplyCheckOverflow(int a, int b, int *result) +{ +#if (defined __GNUC__ && __GNUC__ >= 5) || ( __clang__ && __has_builtin(__builtin_mul_overflow)) + return __builtin_mul_overflow(a, b, result); +#else + if (firstBitSet(a)+firstBitSet(b)>31) // int is signed, so we can't use 32 bits + return true; + *result = a * b; + return false; +#endif +} + + // Compute a linear PCM value from the given differential coded value. static int16_t decodeSample(ms_adpcm_state &state, - uint8_t code, const int16_t *coefficient) + uint8_t code, const int16_t *coefficient, bool *ok=NULL) { int linearSample = (state.sample1 * coefficient[0] + state.sample2 * coefficient[1]) >> 8; + int delta; linearSample += ((code & 0x08) ? (code - 0x10) : code) * state.delta; linearSample = clamp(linearSample, MIN_INT16, MAX_INT16); - int delta = (state.delta * adaptationTable[code]) >> 8; + if (multiplyCheckOverflow(state.delta, adaptationTable[code], &delta)) + { + if (ok) *ok=false; + _af_error(AF_BAD_COMPRESSION, "Error decoding sample"); + return 0; + } + delta >>= 8; if (delta < 16) delta = 16; state.delta = delta; state.sample2 = state.sample1; state.sample1 = linearSample; + if (ok) *ok=true; return static_cast(linearSample); } @@ -212,13 +248,16 @@ { uint8_t code; int16_t newSample; + bool ok; code = *encoded >> 4; - newSample = decodeSample(*state[0], code, coefficient[0]); + newSample = decodeSample(*state[0], code, coefficient[0], &ok); + if (!ok) return 0; *decoded++ = newSample; code = *encoded & 0x0f; - newSample = decodeSample(*state[1], code, coefficient[1]); + newSample = decodeSample(*state[1], code, coefficient[1], &ok); + if (!ok) return 0; *decoded++ = newSample; encoded++; --- audiofile-0.3.6.old/libaudiofile/modules/ModuleState.cpp +++ audiofile-0.3.6/libaudiofile/modules/ModuleState.cpp @@ -402,7 +402,7 @@ addModule(new Transform(outfc, in.pcm, out.pcm)); if (in.channelCount != out.channelCount) - addModule(new ApplyChannelMatrix(infc, isReading, + addModule(new ApplyChannelMatrix(outfc, isReading, in.channelCount, out.channelCount, in.pcm.minClip, in.pcm.maxClip, track->channelMatrix)); --- audiofile-0.3.6.old/libaudiofile/modules/SimpleModule.h +++ audiofile-0.3.6/libaudiofile/modules/SimpleModule.h @@ -123,7 +123,7 @@ typedef typename IntTypes::UnsignedType UnsignedType; static const int kScaleBits = (Format + 1) * CHAR_BIT - 1; - static const int kMinSignedValue = -1 << kScaleBits; + static const int kMinSignedValue = 0-(1U< { --- audiofile-0.3.6.old/sfcommands/sfconvert.c +++ audiofile-0.3.6/sfcommands/sfconvert.c @@ -45,6 +45,33 @@ void usageerror (void); bool copyaudiodata (AFfilehandle infile, AFfilehandle outfile, int trackid); +int firstBitSet(int x) +{ + int position=0; + while (x!=0) + { + x>>=1; + ++position; + } + return position; +} + +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + +bool multiplyCheckOverflow(int a, int b, int *result) +{ +#if (defined __GNUC__ && __GNUC__ >= 5) || ( __clang__ && __has_builtin(__builtin_mul_overflow)) + return __builtin_mul_overflow(a, b, result); +#else + if (firstBitSet(a)+firstBitSet(b)>31) // int is signed, so we can't use 32 bits + return true; + *result = a * b; + return false; +#endif +} + int main (int argc, char **argv) { if (argc == 2) @@ -323,8 +350,11 @@ { int frameSize = afGetVirtualFrameSize(infile, trackid, 1); - const int kBufferFrameCount = 65536; - void *buffer = malloc(kBufferFrameCount * frameSize); + int kBufferFrameCount = 65536; + int bufferSize; + while (multiplyCheckOverflow(kBufferFrameCount, frameSize, &bufferSize)) + kBufferFrameCount /= 2; + void *buffer = malloc(bufferSize); AFframecount totalFrames = afGetFrameCount(infile, AF_DEFAULT_TRACK); AFframecount totalFramesWritten = 0; --- audiofile-0.3.6.old/test/FloatToInt.cpp +++ audiofile-0.3.6/test/FloatToInt.cpp @@ -115,7 +115,7 @@ EXPECT_EQ(readData[i], expectedData[i]); } -static const int32_t kMinInt24 = -1<<23; +static const int32_t kMinInt24 = 0-(1U<<23); static const int32_t kMaxInt24 = (1<<23) - 1; TEST_F(FloatToIntTest, Int24) --- audiofile-0.3.6.old/test/IntToFloat.cpp +++ audiofile-0.3.6/test/IntToFloat.cpp @@ -117,7 +117,7 @@ EXPECT_EQ(readData[i], expectedData[i]); } -static const int32_t kMinInt24 = -1<<23; +static const int32_t kMinInt24 = 0-(1U<<23); static const int32_t kMaxInt24 = (1<<23) - 1; TEST_F(IntToFloatTest, Int24) --- audiofile-0.3.6.old/test/Makefile.am +++ audiofile-0.3.6/test/Makefile.am @@ -26,6 +26,7 @@ VirtualFile \ floatto24 \ query2 \ + sixteen-stereo-to-eight-mono \ sixteen-to-eight \ testchannelmatrix \ testdouble \ @@ -139,6 +140,7 @@ printmarkers_LDADD = $(LIBAUDIOFILE) -lm sixteen_to_eight_SOURCES = sixteen-to-eight.c TestUtilities.cpp TestUtilities.h +sixteen_stereo_to_eight_mono_SOURCES = sixteen-stereo-to-eight-mono.c TestUtilities.cpp TestUtilities.h testchannelmatrix_SOURCES = testchannelmatrix.c TestUtilities.cpp TestUtilities.h --- audiofile-0.3.6.old/test/NeXT.cpp +++ audiofile-0.3.6/test/NeXT.cpp @@ -37,13 +37,13 @@ #include "TestUtilities.h" -const char kDataUnspecifiedLength[] = +const signed char kDataUnspecifiedLength[] = { '.', 's', 'n', 'd', 0, 0, 0, 24, // offset of 24 bytes - 0xff, 0xff, 0xff, 0xff, // unspecified length + -1, -1, -1, -1, // unspecified length 0, 0, 0, 3, // 16-bit linear - 0, 0, 172, 68, // 44100 Hz + 0, 0, -84, 68, // 44100 Hz (0xAC44) 0, 0, 0, 1, // 1 channel 0, 1, 0, 1, @@ -57,13 +57,13 @@ 0, 55 }; -const char kDataTruncated[] = +const signed char kDataTruncated[] = { '.', 's', 'n', 'd', 0, 0, 0, 24, // offset of 24 bytes 0, 0, 0, 20, // length of 20 bytes 0, 0, 0, 3, // 16-bit linear - 0, 0, 172, 68, // 44100 Hz + 0, 0, -84, 68, // 44100 Hz (0xAC44) 0, 0, 0, 1, // 1 channel 0, 1, 0, 1, @@ -152,13 +152,13 @@ ASSERT_EQ(::unlink(testFileName.c_str()), 0); } -const char kDataZeroChannels[] = +const signed char kDataZeroChannels[] = { '.', 's', 'n', 'd', 0, 0, 0, 24, // offset of 24 bytes 0, 0, 0, 2, // 2 bytes 0, 0, 0, 3, // 16-bit linear - 0, 0, 172, 68, // 44100 Hz + 0, 0, -84, 68, // 44100 Hz (0xAC44) 0, 0, 0, 0, // 0 channels 0, 1 }; --- audiofile-0.3.6.old/test/Sign.cpp +++ audiofile-0.3.6/test/Sign.cpp @@ -116,7 +116,7 @@ EXPECT_EQ(readData[i], expectedData[i]); } -static const int32_t kMinInt24 = -1<<23; +static const int32_t kMinInt24 = 0-(1U<<23); static const int32_t kMaxInt24 = (1<<23) - 1; static const uint32_t kMaxUInt24 = (1<<24) - 1; --- audiofile-0.3.6.old/test/TestUtilities.cpp +++ audiofile-0.3.6/test/TestUtilities.cpp @@ -21,8 +21,8 @@ #include "TestUtilities.h" #include -#include #include +#include #include bool createTemporaryFile(const std::string &prefix, std::string *path) @@ -35,12 +35,12 @@ return true; } -bool createTemporaryFile(const char *prefix, char *path) +bool createTemporaryFile(const char *prefix, char **path) { - snprintf(path, PATH_MAX, "/tmp/%s-XXXXXX", prefix); - int fd = ::mkstemp(path); - if (fd < 0) - return false; - ::close(fd); - return true; + *path = NULL; + std::string pathString; + bool result = createTemporaryFile(prefix, &pathString); + if (result) + *path = ::strdup(pathString.c_str()); + return result; } --- audiofile-0.3.6.old/test/TestUtilities.h +++ audiofile-0.3.6/test/TestUtilities.h @@ -53,7 +53,7 @@ #include -bool createTemporaryFile(const char *prefix, char *path); +bool createTemporaryFile(const char *prefix, char **path); #ifdef __cplusplus } --- audiofile-0.3.6.old/test/floatto24.c +++ audiofile-0.3.6/test/floatto24.c @@ -86,8 +86,8 @@ afInitChannels(setup, AF_DEFAULT_TRACK, 1); afInitSampleFormat(setup, AF_DEFAULT_TRACK, AF_SAMPFMT_FLOAT, 32); - char testFileName[PATH_MAX]; - if (!createTemporaryFile("floatto24", testFileName)) + char *testFileName; + if (!createTemporaryFile("floatto24", &testFileName)) { fprintf(stderr, "Could not create temporary file.\n"); exit(EXIT_FAILURE); @@ -182,6 +182,7 @@ } unlink(testFileName); + free(testFileName); exit(EXIT_SUCCESS); } --- audiofile-0.3.6.old/test/sixteen-stereo-to-eight-mono.c +++ audiofile-0.3.6/test/sixteen-stereo-to-eight-mono.c @@ -0,0 +1,118 @@ +/* + Audio File Library + + Copyright 2000, Silicon Graphics, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* + sixteen-stereo-to-eight-mono.c + + This program tests the conversion from 2-channel 16-bit integers to + 1-channel 8-bit integers. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include "TestUtilities.h" + +int main (int argc, char **argv) +{ + AFfilehandle file; + AFfilesetup setup; + int16_t frames16[] = {14298, 392, 3923, -683, 958, -1921}; + int8_t frames8[] = {28, 6, -2}; + int i, frameCount = 3; + int8_t byte; + AFframecount result; + + setup = afNewFileSetup(); + + afInitFileFormat(setup, AF_FILE_WAVE); + + afInitSampleFormat(setup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16); + afInitChannels(setup, AF_DEFAULT_TRACK, 2); + + char *testFileName; + if (!createTemporaryFile("sixteen-to-eight", &testFileName)) + { + fprintf(stderr, "Could not create temporary file.\n"); + exit(EXIT_FAILURE); + } + + file = afOpenFile(testFileName, "w", setup); + if (file == AF_NULL_FILEHANDLE) + { + fprintf(stderr, "could not open file for writing\n"); + exit(EXIT_FAILURE); + } + + afFreeFileSetup(setup); + + afWriteFrames(file, AF_DEFAULT_TRACK, frames16, frameCount); + + afCloseFile(file); + + file = afOpenFile(testFileName, "r", AF_NULL_FILESETUP); + if (file == AF_NULL_FILEHANDLE) + { + fprintf(stderr, "could not open file for reading\n"); + exit(EXIT_FAILURE); + } + + afSetVirtualSampleFormat(file, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 8); + afSetVirtualChannels(file, AF_DEFAULT_TRACK, 1); + + for (i=0; i