From: Tsuda Kageyu Date: Wed, 2 Nov 2016 06:44:50 +0000 (+0900) Subject: Proper handling of MP4 atoms with zero length. X-Git-Tag: v1.12-beta-1~122^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f5ca097379b270d1f92368e283d30f8703161645;p=taglib Proper handling of MP4 atoms with zero length. If the size of an atom is 0, it designates the last atom which extends to the end of the file. --- diff --git a/taglib/mp4/mp4atom.cpp b/taglib/mp4/mp4atom.cpp index 5758173b..20709212 100644 --- a/taglib/mp4/mp4atom.cpp +++ b/taglib/mp4/mp4atom.cpp @@ -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(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 index 00000000..578d2ef7 Binary files /dev/null and b/tests/data/zero-length-mdat.m4a differ diff --git a/tests/test_mp4.cpp b/tests/test_mp4.cpp index dd36b21b..bc0ac01d 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -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);