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); } }