From e463d14f2e483f21ab14b18a7c84574e60691fd0 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Thu, 8 Jan 2015 13:05:56 +0900 Subject: [PATCH] Check for EOF to fix a segfault while parsing fuzzed MPC files. --- taglib/mpc/mpcproperties.cpp | 37 ++++++++++++++++++++++++------------ tests/data/segfault2.mpc | 1 + tests/test_mpc.cpp | 7 +++++++ 3 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 tests/data/segfault2.mpc diff --git a/taglib/mpc/mpcproperties.cpp b/taglib/mpc/mpcproperties.cpp index ac9d1b45..128eff42 100644 --- a/taglib/mpc/mpcproperties.cpp +++ b/taglib/mpc/mpcproperties.cpp @@ -155,30 +155,36 @@ int MPC::Properties::albumPeak() const // private members //////////////////////////////////////////////////////////////////////////////// -unsigned long readSize(File *file, TagLib::uint &sizelength) +unsigned long readSize(File *file, TagLib::uint &sizeLength, bool &eof) { + sizeLength = 0; + eof = false; + unsigned char tmp; unsigned long size = 0; do { - ByteVector b = file->readBlock(1); + const ByteVector b = file->readBlock(1); + if(b.isEmpty()) { + eof = true; + break; + } + tmp = b[0]; size = (size << 7) | (tmp & 0x7F); - sizelength++; + sizeLength++; } while((tmp & 0x80)); return size; } -unsigned long readSize(const ByteVector &data, TagLib::uint &sizelength) +unsigned long readSize(const ByteVector &data, TagLib::uint &pos) { unsigned char tmp; unsigned long size = 0; - unsigned long pos = 0; do { tmp = data[pos++]; size = (size << 7) | (tmp & 0x7F); - sizelength++; } while((tmp & 0x80) && (pos < data.size())); return size; } @@ -192,10 +198,17 @@ void MPC::Properties::readSV8(File *file) bool readSH = false, readRG = false; while(!readSH && !readRG) { - ByteVector packetType = file->readBlock(2); - uint packetSizeLength = 0; - unsigned long packetSize = readSize(file, packetSizeLength); - unsigned long dataSize = packetSize - 2 - packetSizeLength; + const ByteVector packetType = file->readBlock(2); + + uint packetSizeLength; + bool eof; + const unsigned long packetSize = readSize(file, packetSizeLength, eof); + if(eof) { + debug("MPC::Properties::readSV8() - Reached to EOF."); + break; + } + + const unsigned long dataSize = packetSize - 2 - packetSizeLength; const ByteVector data = file->readBlock(dataSize); if(data.size() != dataSize) { @@ -217,13 +230,13 @@ void MPC::Properties::readSV8(File *file) TagLib::uint pos = 4; d->version = data[pos]; pos += 1; - d->sampleFrames = readSize(data.mid(pos), pos); + d->sampleFrames = readSize(data, pos); if(pos > dataSize - 3) { debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt."); break; } - ulong begSilence = readSize(data.mid(pos), pos); + ulong begSilence = readSize(data, pos); if(pos > dataSize - 2) { debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt."); break; diff --git a/tests/data/segfault2.mpc b/tests/data/segfault2.mpc new file mode 100644 index 00000000..fcfa982f --- /dev/null +++ b/tests/data/segfault2.mpc @@ -0,0 +1 @@ +MPCKSH \ No newline at end of file diff --git a/tests/test_mpc.cpp b/tests/test_mpc.cpp index 1204b0c2..0589740f 100644 --- a/tests/test_mpc.cpp +++ b/tests/test_mpc.cpp @@ -20,6 +20,7 @@ class TestMPC : public CppUnit::TestFixture CPPUNIT_TEST(testFuzzedFile1); CPPUNIT_TEST(testFuzzedFile2); CPPUNIT_TEST(testFuzzedFile3); + CPPUNIT_TEST(testFuzzedFile4); CPPUNIT_TEST_SUITE_END(); public: @@ -82,6 +83,12 @@ public: CPPUNIT_ASSERT(f.isValid()); } + void testFuzzedFile4() + { + MPC::File f(TEST_FILE_PATH_C("segfault2.mpc")); + CPPUNIT_ASSERT(f.isValid()); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestMPC); -- 2.40.0