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 ebfb4bab..c8d65723 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -58,6 +58,7 @@ class TestMP4 : public CppUnit::TestFixture CPPUNIT_TEST(testPropertiesMovement); CPPUNIT_TEST(testFuzzedFile); CPPUNIT_TEST(testRepeatedSave); + CPPUNIT_TEST(testWithZeroLengthAtom); CPPUNIT_TEST_SUITE_END(); public: @@ -448,6 +449,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);