diff --git a/package/qa/cppunit/data/tdf166862.odt b/package/qa/cppunit/data/tdf166862.odt new file mode 100644 index 000000000000..814bebe670d7 Binary files /dev/null and b/package/qa/cppunit/data/tdf166862.odt differ diff --git a/package/qa/cppunit/test_zippackage.cxx b/package/qa/cppunit/test_zippackage.cxx index f296802e4524..94b8c616400f 100644 --- a/package/qa/cppunit/test_zippackage.cxx +++ b/package/qa/cppunit/test_zippackage.cxx @@ -483,6 +483,24 @@ CPPUNIT_TEST_FIXTURE(ZipPackageTest, testDataDescriptorDirectory) CPPUNIT_ASSERT_EQUAL(sal_Int64(899), xStream->getPropertyValue(u"Size"_ustr).get()); } +CPPUNIT_TEST_FIXTURE(ZipPackageTest, testTdf166862) +{ + // This package is broken; but the actual issue was incorrect CRC calculation for an image + OUString aURL = m_directories.getURLFromSrc(u"/package/qa/cppunit/data/tdf166862.odt"); + uno::Sequence args{ uno::Any(aURL), uno::Any(beans::NamedValue{ u"RepairPackage"_ustr, + uno::Any(true) }) }; + + auto xMgr = m_xContext->getServiceManager(); + + auto xZip(xMgr->createInstanceWithArgumentsAndContext(ZipPackage, args, m_xContext) + .queryThrow()); + static constexpr OUString picURL = u"Pictures/1000000000000596000000AE0BDDB537.jpg"_ustr; + CPPUNIT_ASSERT(xZip->hasByHierarchicalName(picURL)); + auto aPic = xZip->getByHierarchicalName(picURL).queryThrow(); + // Before the fix, this was 0: the size was reset because of unmatched CRC + CPPUNIT_ASSERT_EQUAL(sal_Int64(43886), aPic->getPropertyValue(u"Size"_ustr).get()); +} + //CPPUNIT_TEST_SUITE_REGISTRATION(...); //CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index ec749c86314a..5e903627d763 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -1943,12 +1943,13 @@ sal_Int32 ZipFile::getCRC( sal_Int64 nOffset, sal_Int64 nSize ) std::vector aBuffer(nBlockSize); aGrabber.seek( nOffset ); - sal_Int32 nRead; - for (sal_Int64 ind = 0; - (nRead = aGrabber.readBytes( aBuffer.data(), nBlockSize )) && ind * nBlockSize < nSize; - ++ind) + sal_Int64 nRead = 0; + while (nRead < nSize) { - aCRC.updateSegment(aBuffer.data(), nRead); + sal_Int64 nToRead = std::min(nSize - nRead, nBlockSize); + sal_Int64 nReadThisTime = aGrabber.readBytes(aBuffer.data(), nToRead); + aCRC.updateSegment(aBuffer.data(), nReadThisTime); + nRead += nReadThisTime; } return aCRC.getValue();