]> granicus.if.org Git - taglib/commitdiff
Proper handling of MP4 atoms with zero length.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Wed, 2 Nov 2016 06:44:50 +0000 (15:44 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Wed, 2 Nov 2016 06:44:50 +0000 (15:44 +0900)
If the size of an atom is 0, it designates the last atom which extends to the end of the file.

taglib/mp4/mp4atom.cpp
tests/data/zero-length-mdat.m4a [new file with mode: 0644]
tests/test_mp4.cpp

index 5758173bcf98acd9704dc84a850e69060ab5cb9d..20709212e652fe012a7f809a662b67ba79b7395c 100644 (file)
@@ -54,10 +54,15 @@ MP4::Atom::Atom(File *file)
 
   length = header.toUInt();
 
-  if(length == 1) {
+  if(length == 0) {
+    // The last atom which extends to the end of the file.
+    length = file->length() - offset;
+  }
+  else if(length == 1) {
+    // The atom has a 64-bit length.
     const long long longLength = file->readBlock(8).toLongLong();
     if(longLength <= LONG_MAX) {
-      // The atom has a 64-bit length, but it's actually a 31-bit value or long is 64-bit.
+      // The actual length fits in long. That's always the case if long is 64-bit.
       length = static_cast<long>(longLength);
     }
     else {
@@ -67,6 +72,7 @@ MP4::Atom::Atom(File *file)
       return;
     }
   }
+
   if(length < 8) {
     debug("MP4: Invalid atom size");
     length = 0;
diff --git a/tests/data/zero-length-mdat.m4a b/tests/data/zero-length-mdat.m4a
new file mode 100644 (file)
index 0000000..578d2ef
Binary files /dev/null and b/tests/data/zero-length-mdat.m4a differ
index dd36b21b590347d7e078871c9a9b9836b987d576..bc0ac01d7f41585d6a201d4905aa4297cbfcab77 100644 (file)
@@ -57,6 +57,7 @@ class TestMP4 : public CppUnit::TestFixture
   CPPUNIT_TEST(testProperties);
   CPPUNIT_TEST(testFuzzedFile);
   CPPUNIT_TEST(testRepeatedSave);
+  CPPUNIT_TEST(testWithZeroLengthAtom);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -395,6 +396,15 @@ public:
     CPPUNIT_ASSERT_EQUAL(2862L, f.find("0123456789"));
     CPPUNIT_ASSERT_EQUAL(-1L, f.find("0123456789", 2863));
   }
+
+  void testWithZeroLengthAtom()
+  {
+    MP4::File f(TEST_FILE_PATH_C("zero-length-mdat.m4a"));
+    CPPUNIT_ASSERT(f.isValid());
+    CPPUNIT_ASSERT_EQUAL(1115, f.audioProperties()->lengthInMilliseconds());
+    CPPUNIT_ASSERT_EQUAL(22050, f.audioProperties()->sampleRate());
+  }
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestMP4);