package/inc/ZipFile.hxx                     |    3 +-
 package/source/zipapi/MemoryByteGrabber.hxx |    8 ++++++
 package/source/zipapi/ZipFile.cxx           |   37 +++++++++++++++++++++++++---
 3 files changed, 44 insertions(+), 4 deletions(-)

New commits:
commit 2d2935fc213d63f19404a55bfc2db2eba9eb0ce4
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Tue Jul 2 11:50:09 2024 +0200
Commit:     Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
CommitDate: Wed Jul 10 11:47:10 2024 +0200

    package: ZipFile: check Info-ZIP Unicode Path Extra Field
    
    Change-Id: I829eb449e8a0947341f066399be549f56b0f02da
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169882
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 67dca5a47d1be1b38edee7d0d81fa9adfce5a22e)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169929
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    (cherry picked from commit 1150584be851b311067ee6482f51da1ad3b12636)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/169954
    Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakan...@libreoffice.org>
    Tested-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>
    Reviewed-by: Christian Lohmaier <lohmaier+libreoff...@googlemail.com>

diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx
index 2d42ed403136..8bc726af8457 100644
--- a/package/inc/ZipFile.hxx
+++ b/package/inc/ZipFile.hxx
@@ -86,7 +86,8 @@ class ZipFile
     void recover();
     static void readExtraFields(MemoryByteGrabber& aMemGrabber, sal_Int16 
nExtraLen,
                                 sal_uInt64& nSize, sal_uInt64& nCompressedSize,
-                                sal_uInt64* nOffset);
+                                sal_uInt64* nOffset,
+                                OUString const* pCENFilenameToCheck);
 
 public:
 
diff --git a/package/source/zipapi/MemoryByteGrabber.hxx 
b/package/source/zipapi/MemoryByteGrabber.hxx
index d474be40cda5..dd876d66ebfa 100644
--- a/package/source/zipapi/MemoryByteGrabber.hxx
+++ b/package/source/zipapi/MemoryByteGrabber.hxx
@@ -49,6 +49,14 @@ public:
         mnCurrent += nBytesToSkip;
     }
 
+    sal_Int8 ReadUInt8()
+    {
+        if (mnCurrent + 1 > mnEnd)
+            return 0;
+        sal_uInt8 nInt8 = mpBuffer[mnCurrent++];
+        return nInt8;
+    }
+
     // XSeekable chained...
     sal_Int16 ReadInt16()
     {
diff --git a/package/source/zipapi/ZipFile.cxx 
b/package/source/zipapi/ZipFile.cxx
index b19ebaf2c5e2..e9a515bc85c7 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -36,6 +36,7 @@
 #include <comphelper/processfactory.hxx>
 #include <comphelper/threadpool.hxx>
 #include <rtl/digest.h>
+#include <rtl/crc.h>
 #include <sal/log.hxx>
 #include <o3tl/safeint.hxx>
 #include <o3tl/string_view.hxx>
@@ -1132,7 +1133,7 @@ sal_Int32 ZipFile::readCEN()
 
             if (aEntry.nExtraLen>0)
             {
-                readExtraFields(aMemGrabber, aEntry.nExtraLen, nSize, 
nCompressedSize, &nOffset);
+                readExtraFields(aMemGrabber, aEntry.nExtraLen, nSize, 
nCompressedSize, &nOffset, &aEntry.sPath);
             }
             aEntry.nCompressedSize = nCompressedSize;
             aEntry.nSize = nSize;
@@ -1176,7 +1177,8 @@ sal_Int32 ZipFile::readCEN()
 }
 
 void ZipFile::readExtraFields(MemoryByteGrabber& aMemGrabber, sal_Int16 
nExtraLen,
-                              sal_uInt64& nSize, sal_uInt64& nCompressedSize, 
sal_uInt64* nOffset)
+        sal_uInt64& nSize, sal_uInt64& nCompressedSize,
+        sal_uInt64* nOffset, OUString const*const pCENFilenameToCheck)
 {
     while (nExtraLen > 0) // Extensible data fields
     {
@@ -1201,6 +1203,35 @@ void ZipFile::readExtraFields(MemoryByteGrabber& 
aMemGrabber, sal_Int16 nExtraLe
             if (dataSize > nReadSize)
                 aMemGrabber.skipBytes(dataSize - nReadSize);
         }
+        // Info-ZIP Unicode Path Extra Field - pointless as we expect UTF-8 in 
CEN already
+        else if (nheaderID == 0x7075 && pCENFilenameToCheck) // ignore in 
recovery mode
+        {
+            if (aMemGrabber.remainingSize() < dataSize)
+            {
+                SAL_INFO("package", "Invalid Info-ZIP Unicode Path Extra 
Field: invalid TSize");
+                throw ZipException(u"Invalid Info-ZIP Unicode Path Extra 
Field"_ustr);
+            }
+            auto const nVersion = aMemGrabber.ReadUInt8();
+            if (nVersion != 1)
+            {
+                SAL_INFO("package", "Invalid Info-ZIP Unicode Path Extra 
Field: unexpected Version");
+                throw ZipException(u"Invalid Info-ZIP Unicode Path Extra 
Field"_ustr);
+            }
+            // this CRC32 is actually of the pCENFilenameToCheck
+            // so it's pointless to check it if we require the UnicodeName
+            // to be equal to the CEN name anyway (and pCENFilenameToCheck
+            // is already converted to UTF-16 here)
+            (void) aMemGrabber.ReadUInt32();
+            // this is required to be UTF-8
+            OUString const unicodePath(reinterpret_cast<char const 
*>(aMemGrabber.getCurrentPos()),
+                    dataSize - 5, RTL_TEXTENCODING_UTF8);
+            aMemGrabber.skipBytes(dataSize - 5);
+            if (unicodePath != *pCENFilenameToCheck)
+            {
+                SAL_INFO("package", "Invalid Info-ZIP Unicode Path Extra 
Field: unexpected UnicodeName");
+                throw ZipException(u"Invalid Info-ZIP Unicode Path Extra 
Field"_ustr);
+            }
+        }
         else
         {
             aMemGrabber.skipBytes(dataSize);
@@ -1303,7 +1334,7 @@ void ZipFile::recover()
                                     if (aEntry.nExtraLen > 0)
                                     {
                                         readExtraFields(aMemGrabberExtra, 
aEntry.nExtraLen, nSize,
-                                                        nCompressedSize, 
nullptr);
+                                                        nCompressedSize, 
nullptr, nullptr);
                                     }
                                 }
 

Reply via email to