]> granicus.if.org Git - taglib/commitdiff
Fix a possible out-of-bounds access in SynchData::decode().
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Fri, 19 Feb 2016 11:58:09 +0000 (20:58 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Fri, 19 Feb 2016 11:58:09 +0000 (20:58 +0900)
This also avoids an extra memory copy.

taglib/mpeg/id3v2/id3v2synchdata.cpp
tests/test_synchdata.cpp

index ddcd95b3899a7e5a43a6a547b231f49ada1e7543..2aa9999932263c5ddbd19284f368c1d088865d2e 100644 (file)
@@ -77,26 +77,22 @@ ByteVector SynchData::decode(const ByteVector &data)
   // We have this optimized method instead of using ByteVector::replace(),
   // since it makes a great difference when decoding huge unsynchronized frames.
 
-  if(data.size() < 2)
-    return data;
+  ByteVector result(data.size());
 
-  ByteVector result = data;
+  ByteVector::ConstIterator src = data.begin();
+  ByteVector::Iterator dst = result.begin();
 
-  char *begin = result.data();
-  char *end = begin + result.size();
-
-  char *dst = begin;
-  const char *src = begin;
-
-  do {
+  while(src < data.end() - 1) {
     *dst++ = *src++;
 
     if(*(src - 1) == '\xff' && *src == '\x00')
       src++;
+  }
 
-  } while(src < end);
+  if(src < data.end())
+    *dst++ = *src++;
 
-  result.resize(static_cast<unsigned int>(dst - begin));
+  result.resize(static_cast<unsigned int>(dst - result.begin()));
 
   return result;
 }
index bbd74d8b0e9e9db17c488ebe9137ec5da21f866a..b4ec40969d25216e5f8196a93493e9ec4ddda885 100644 (file)
@@ -41,6 +41,7 @@ class TestID3v2SynchData : public CppUnit::TestFixture
   CPPUNIT_TEST(testDecode1);
   CPPUNIT_TEST(testDecode2);
   CPPUNIT_TEST(testDecode3);
+  CPPUNIT_TEST(testDecode4);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -113,6 +114,14 @@ public:
     CPPUNIT_ASSERT_EQUAL(ByteVector("\xff\xff", 2), a);
   }
 
+  void testDecode4()
+  {
+    ByteVector a("\xff\xff\xff", 3);
+    a = ID3v2::SynchData::decode(a);
+    CPPUNIT_ASSERT_EQUAL((unsigned int)3, a.size());
+    CPPUNIT_ASSERT_EQUAL(ByteVector("\xff\xff\xff", 3), a);
+  }
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestID3v2SynchData);