From 4833f131243bdb409ddfaff8b4db87d4ed2af98f Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Tue, 9 Jul 2024 17:22:15 +0200 Subject: [PATCH] package: ZipFile: don't accept duplicate entries (case insensitive) This is required for OOXML, but not for ODF. Unclear if there are use cases for this with ODF, can add some conditions if it turns out to be a problem. Change-Id: I3810da5c2273574135d133b4a9bbad98dc97af44 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170223 Tested-by: Jenkins Reviewed-by: Michael Stahl --- package/inc/ZipFile.hxx | 4 ++++ package/source/zipapi/ZipFile.cxx | 22 +++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx index b2f3e6ecf131..8828d929273f 100644 --- a/package/inc/ZipFile.hxx +++ b/package/inc/ZipFile.hxx @@ -30,6 +30,7 @@ #include "EncryptionData.hxx" #include +#include class MemoryByteGrabber; namespace com::sun::star { @@ -50,10 +51,13 @@ namespace rtl class ZipEnumeration; + class ZipFile { rtl::Reference m_aMutexHolder; + std::unordered_set m_EntriesInsensitive; + EntryHash aEntries; ByteGrabber aGrabber; ZipUtils::Inflater aInflater; diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index fa8d74b37b80..f7713b8665c1 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -94,6 +94,7 @@ ZipFile::ZipFile( rtl::Reference aMutexHolder, if (bInitialise && readCEN() == -1 ) { aEntries.clear(); + m_EntriesInsensitive.clear(); throw ZipException( u"stream data looks to be broken"_ustr ); } } @@ -118,6 +119,7 @@ ZipFile::ZipFile( rtl::Reference< comphelper::RefCountedMutex > aMutexHolder, else if ( readCEN() == -1 ) { aEntries.clear(); + m_EntriesInsensitive.clear(); throw ZipException(u"stream data looks to be broken"_ustr ); } } @@ -1156,15 +1158,19 @@ sal_Int32 ZipFile::readCEN() continue; // This is a directory entry, not a stream - skip it } - if (auto it = aEntries.find(aEntry.sPath); it == aEntries.end()) - { - aEntries[aEntry.sPath] = aEntry; - } - else + if (aEntries.find(aEntry.sPath) != aEntries.end()) { SAL_INFO("package", "Duplicate CEN entry: \"" << aEntry.sPath << "\""); throw ZipException(u"Duplicate CEN entry"_ustr); } + // this is required for OOXML, but not for ODF + auto const lowerPath(aEntry.sPath.toAsciiLowerCase()); + if (!m_EntriesInsensitive.insert(lowerPath).second) + { + SAL_INFO("package", "Duplicate CEN entry (case insensitive): \"" << aEntry.sPath << "\""); + throw ZipException(u"Duplicate CEN entry (case insensitive)"_ustr); + } + aEntries[aEntry.sPath] = aEntry; } if (nCount != nTotal) @@ -1335,6 +1341,12 @@ void ZipFile::HandlePK34(std::span data, sal_Int64 dataOffset, s != aEntries.end()) return; + auto const lowerPath(aEntry.sPath.toAsciiLowerCase()); + if (m_EntriesInsensitive.find(lowerPath) != m_EntriesInsensitive.end()) + { // this is required for OOXML, but not for ODF + return; + } + m_EntriesInsensitive.insert(lowerPath); aEntries.emplace(aEntry.sPath, aEntry); // Drop any "directory" entry corresponding to this one's path; since we don't use