tdf#163818 package: fix recovery of zip entry local header with ...

... compressed size = 0.

The problem is that vector::data() on a vector of size 0 returns
nullptr, and osl_readFile into a nullptr buffer returns E_INVAL, which
causes an exception to be thrown.

Catch the exception, so that there is a chance to read the values from
the data descriptor instead.

(regression from commit 32cad89592
 and/or commit a6ad198d09)

Change-Id: I9b2d9a930997146faf224d8033955b142fe93f58
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176289
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
Tested-by: Jenkins
This commit is contained in:
Michael Stahl 2024-11-08 18:08:58 +01:00
parent 950cd20f5f
commit 80cda6954a
3 changed files with 40 additions and 11 deletions

Binary file not shown.

View file

@ -425,6 +425,28 @@ CPPUNIT_TEST_FIXTURE(ZipPackageTest, testTdf163341)
m_xContext);
}
CPPUNIT_TEST_FIXTURE(ZipPackageTest, testTdf163818)
{
auto const url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/tdf163818.odg"));
uno::Sequence<uno::Any> const args{
uno::Any(url),
uno::Any(beans::NamedValue("StorageFormat", uno::Any(embed::StorageFormats::PACKAGE)))
};
// unclear if this should be allowed?
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
ZipPackage, args, m_xContext),
css::packages::zip::ZipIOException);
// recovery should work
uno::Sequence<uno::Any> const args2{
uno::Any(url), uno::Any(beans::NamedValue(u"RepairPackage"_ustr, uno::Any(true))),
uno::Any(beans::NamedValue("StorageFormat", uno::Any(embed::StorageFormats::ZIP)))
};
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage, args2,
m_xContext);
}
//CPPUNIT_TEST_SUITE_REGISTRATION(...);
//CPPUNIT_PLUGIN_IMPLEMENT();

View file

@ -1856,20 +1856,27 @@ bool ZipFile::checkSizeAndCRC( const ZipEntry& aEntry )
{
::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
sal_Int32 nCRC = 0;
sal_Int64 nSize = 0;
if( aEntry.nMethod == STORED )
return ( getCRC( aEntry.nOffset, aEntry.nSize ) == aEntry.nCrc );
if (aEntry.nCompressedSize < 0)
try
{
sal_Int32 nCRC = 0;
sal_Int64 nSize = 0;
if( aEntry.nMethod == STORED )
return ( getCRC( aEntry.nOffset, aEntry.nSize ) == aEntry.nCrc );
if (aEntry.nCompressedSize < 0)
{
SAL_WARN("package", "bogus compressed size of: " << aEntry.nCompressedSize);
return false;
}
getSizeAndCRC( aEntry.nOffset, aEntry.nCompressedSize, &nSize, &nCRC );
return ( aEntry.nSize == nSize && aEntry.nCrc == nCRC );
}
catch (uno::Exception const&)
{
SAL_WARN("package", "bogus compressed size of: " << aEntry.nCompressedSize);
return false;
}
getSizeAndCRC( aEntry.nOffset, aEntry.nCompressedSize, &nSize, &nCRC );
return ( aEntry.nSize == nSize && aEntry.nCrc == nCRC );
}
sal_Int32 ZipFile::getCRC( sal_Int64 nOffset, sal_Int64 nSize )