diff --git a/taglib/ape/apeproperties.cpp b/taglib/ape/apeproperties.cpp index 4940edea..cf829fe5 100644 --- a/taglib/ape/apeproperties.cpp +++ b/taglib/ape/apeproperties.cpp @@ -221,12 +221,20 @@ void APE::Properties::analyzeOld() blocksPerFrame = 73728; else blocksPerFrame = 9216; + d->channels = header.toShort(4, false); d->sampleRate = header.toUInt(6, false); + const uint finalFrameBlocks = header.toUInt(22, false); - const uint totalBlocks - = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0; - d->length = totalBlocks / d->sampleRate; - d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; + + uint totalBlocks = 0; + if(totalFrames > 0) + totalBlocks = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks; + + if(d->sampleRate > 0) + d->length = totalBlocks / d->sampleRate; + + if(d->length > 0) + d->bitrate = ((d->streamLength * 8L) / d->length) / 1000; } diff --git a/taglib/ape/apetag.cpp b/taglib/ape/apetag.cpp index e1252193..22471d40 100644 --- a/taglib/ape/apetag.cpp +++ b/taglib/ape/apetag.cpp @@ -368,10 +368,13 @@ ByteVector APE::Tag::render() const void APE::Tag::parse(const ByteVector &data) { - uint pos = 0; - // 11 bytes is the minimum size for an APE item + if(data.size() < 11) + return; + + uint pos = 0; + for(uint i = 0; i < d->footer.itemCount() && pos <= data.size() - 11; i++) { APE::Item item; item.parse(data.mid(pos)); diff --git a/tests/data/longloop.ape b/tests/data/longloop.ape new file mode 100644 index 00000000..3800387a Binary files /dev/null and b/tests/data/longloop.ape differ diff --git a/tests/data/zerodiv.ape b/tests/data/zerodiv.ape new file mode 100644 index 00000000..683bc2dd Binary files /dev/null and b/tests/data/zerodiv.ape differ diff --git a/tests/test_ape.cpp b/tests/test_ape.cpp index c95ff0c2..e79e8f08 100644 --- a/tests/test_ape.cpp +++ b/tests/test_ape.cpp @@ -16,6 +16,7 @@ class TestAPE : public CppUnit::TestFixture CPPUNIT_TEST(testProperties399); CPPUNIT_TEST(testProperties396); CPPUNIT_TEST(testProperties390); + CPPUNIT_TEST(testFuzzedFiles); CPPUNIT_TEST_SUITE_END(); public: @@ -47,6 +48,15 @@ public: CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate()); } + void testFuzzedFiles() + { + APE::File f1(TEST_FILE_PATH_C("longloop.ape")); + CPPUNIT_ASSERT(f1.isValid()); + + APE::File f2(TEST_FILE_PATH_C("zerodiv.ape")); + CPPUNIT_ASSERT(f2.isValid()); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestAPE);