diff --git a/taglib/mpc/mpcproperties.cpp b/taglib/mpc/mpcproperties.cpp index a162b8ee..ac9d1b45 100644 --- a/taglib/mpc/mpcproperties.cpp +++ b/taglib/mpc/mpcproperties.cpp @@ -206,13 +206,28 @@ void MPC::Properties::readSV8(File *file) if(packetType == "SH") { // Stream Header // http://trac.musepack.net/wiki/SV8Specification#StreamHeaderPacket + + if(dataSize <= 5) { + debug("MPC::Properties::readSV8() - \"SH\" packet is too short to parse."); + break; + } + readSH = true; TagLib::uint pos = 4; d->version = data[pos]; pos += 1; d->sampleFrames = readSize(data.mid(pos), pos); + if(pos > dataSize - 3) { + debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt."); + break; + } + ulong begSilence = readSize(data.mid(pos), pos); + if(pos > dataSize - 2) { + debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt."); + break; + } const ushort flags = data.toUShort(pos, true); pos += 2; @@ -230,6 +245,12 @@ void MPC::Properties::readSV8(File *file) else if (packetType == "RG") { // Replay Gain // http://trac.musepack.net/wiki/SV8Specification#ReplaygainPacket + + if(dataSize <= 9) { + debug("MPC::Properties::readSV8() - \"RG\" packet is too short to parse."); + break; + } + readRG = true; int replayGainVersion = data[0]; diff --git a/tests/data/segfault.mpc b/tests/data/segfault.mpc new file mode 100644 index 00000000..2c7e29fb Binary files /dev/null and b/tests/data/segfault.mpc differ diff --git a/tests/test_mpc.cpp b/tests/test_mpc.cpp index c79d0a8c..1204b0c2 100644 --- a/tests/test_mpc.cpp +++ b/tests/test_mpc.cpp @@ -19,6 +19,7 @@ class TestMPC : public CppUnit::TestFixture CPPUNIT_TEST(testPropertiesSV4); CPPUNIT_TEST(testFuzzedFile1); CPPUNIT_TEST(testFuzzedFile2); + CPPUNIT_TEST(testFuzzedFile3); CPPUNIT_TEST_SUITE_END(); public: @@ -75,6 +76,12 @@ public: CPPUNIT_ASSERT(f.isValid()); } + void testFuzzedFile3() + { + MPC::File f(TEST_FILE_PATH_C("segfault.mpc")); + CPPUNIT_ASSERT(f.isValid()); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestMPC);