diff --git a/taglib/mp4/mp4file.cpp b/taglib/mp4/mp4file.cpp index f8e87fdb..a14db53d 100644 --- a/taglib/mp4/mp4file.cpp +++ b/taglib/mp4/mp4file.cpp @@ -40,6 +40,35 @@ namespace return std::none_of(list.begin(), list.end(), [](const auto &a) { return a->length == 0 || !checkValid(a->children); }); } + + bool checkRootLevelAtoms(MP4::AtomList &list) + { + bool moovValid = false; + for(auto it = list.begin(); it != list.end(); ++it) { + bool invalid = (*it)->length == 0 || !checkValid((*it)->children); + if(!moovValid && !invalid && (*it)->name == "moov") { + moovValid = true; + } + if(invalid) { + if(moovValid && (*it)->name != "moof") { + // Only the root level atoms "moov" and (if present) "moof" are + // modified. If they are valid, ignore following invalid root level + // atoms as trailing garbage. + while(it != list.end()) { + delete *it; + it = list.erase(it); + } + return true; + } + else { + return false; + } + } + } + + return true; + } + } // namespace class MP4::File::FilePrivate @@ -127,7 +156,7 @@ MP4::File::read(bool readProperties) return; d->atoms = std::make_unique(this); - if(!checkValid(d->atoms->atoms)) { + if(!checkRootLevelAtoms(d->atoms->atoms)) { setValid(false); return; } diff --git a/tests/test_mp4.cpp b/tests/test_mp4.cpp index 6921a0e2..79cb8645 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -602,10 +602,7 @@ public: void testFuzzedFile() { MP4::File f(TEST_FILE_PATH_C("infloop.m4a")); - // The file has an invalid atom length of 2775 in the last atom - // ("free", offset 0xc521, 00000ad7 66726565), whereas the remaining file - // length is 2727 bytes, therefore the file is now considered invalid. - CPPUNIT_ASSERT(!f.isValid()); + CPPUNIT_ASSERT(f.isValid()); } void testRepeatedSave()