package/inc/ZipFile.hxx           |    4 ++++
 package/source/zipapi/ZipFile.cxx |   24 ++++++++++++++++++------
 2 files changed, 22 insertions(+), 6 deletions(-)

New commits:
commit 92564a17fe68066f6e9135c6f79fb6319b192f22
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Tue Jul 9 17:22:15 2024 +0200
Commit:     Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
CommitDate: Wed Jul 10 17:10:09 2024 +0200

    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 <michael.st...@allotropia.de>
    (cherry picked from commit 4833f131243bdb409ddfaff8b4db87d4ed2af98f)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170282
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>

diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx
index 8bc726af8457..d9910fde92a9 100644
--- a/package/inc/ZipFile.hxx
+++ b/package/inc/ZipFile.hxx
@@ -29,6 +29,8 @@
 #include "HashMaps.hxx"
 #include "EncryptionData.hxx"
 
+#include <unordered_set>
+
 class MemoryByteGrabber;
 namespace com::sun::star {
     namespace uno { class XComponentContext; }
@@ -52,6 +54,8 @@ class ZipFile
 {
     rtl::Reference<comphelper::RefCountedMutex> m_aMutexHolder;
 
+    std::unordered_set<OUString> m_EntriesInsensitive;
+
     EntryHash       aEntries;
     ByteGrabber     aGrabber;
     ZipUtils::Inflater aInflater;
diff --git a/package/source/zipapi/ZipFile.cxx 
b/package/source/zipapi/ZipFile.cxx
index c7e10cb06e39..1e1ab575dcfe 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -94,6 +94,7 @@ ZipFile::ZipFile( rtl::Reference<comphelper::RefCountedMutex> 
aMutexHolder,
     if (bInitialise && readCEN() == -1 )
     {
         aEntries.clear();
+        m_EntriesInsensitive.clear();
         throw ZipException( "stream data looks to be broken" );
     }
 }
@@ -118,6 +119,7 @@ ZipFile::ZipFile( rtl::Reference< 
comphelper::RefCountedMutex > aMutexHolder,
         else if ( readCEN() == -1 )
         {
             aEntries.clear();
+            m_EntriesInsensitive.clear();
             throw ZipException("stream data looks to be broken" );
         }
     }
@@ -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)
@@ -1373,7 +1379,13 @@ void ZipFile::recover()
                                         nPos += 4;
                                         continue;
                                     }
-
+                                    auto const 
lowerPath(aEntry.sPath.toAsciiLowerCase());
+                                    if (m_EntriesInsensitive.find(lowerPath) 
!= m_EntriesInsensitive.end())
+                                    {   // this is required for OOXML, but not 
for ODF
+                                        nPos += 4;
+                                        continue;
+                                    }
+                                    m_EntriesInsensitive.insert(lowerPath);
                                     aEntries.emplace( aEntry.sPath, aEntry );
 
                                     // Drop any "directory" entry 
corresponding to this one's path;

Reply via email to