]> granicus.if.org Git - taglib/commitdiff
Check for EOF to fix a segfault while parsing fuzzed MPC files.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Thu, 8 Jan 2015 04:05:56 +0000 (13:05 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Mon, 16 Feb 2015 16:22:39 +0000 (01:22 +0900)
taglib/mpc/mpcproperties.cpp
tests/data/segfault2.mpc [new file with mode: 0644]
tests/test_mpc.cpp

index ac9d1b45e296fe68aa88e8318d4550290aad4282..128eff42361e639c961c3a5e7a3eb4b647862cdf 100644 (file)
@@ -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 (file)
index 0000000..fcfa982
--- /dev/null
@@ -0,0 +1 @@
+MPCKSH
\ No newline at end of file
index 1204b0c2b9cf45ceb300d5b35a655df00329ab33..0589740f80bd52c175fe9385531b22f265859a96 100644 (file)
@@ -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);