From f5ca097379b270d1f92368e283d30f8703161645 Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Wed, 2 Nov 2016 15:44:50 +0900 Subject: [PATCH] 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. --- taglib/mp4/mp4atom.cpp | 10 ++++++++-- tests/data/zero-length-mdat.m4a | Bin 0 -> 4517 bytes tests/test_mp4.cpp | 10 ++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 tests/data/zero-length-mdat.m4a 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 0000000000000000000000000000000000000000..578d2ef7a8b000addc1e6d5ad9a6b12211f840b9 GIT binary patch literal 4517 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 HgBSiA+4#i{ literal 0 HcmV?d00001 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); -- 2.40.0