diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 09:29:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 09:29:03 +0000 |
commit | 5a7157d319477830426797532e02ac39d3b859f4 (patch) | |
tree | 3773f5ce209bee14a5643e98672e0f3828c71434 /package/source/zipapi | |
parent | Releasing progress-linux version 4:24.2.0-3~progress7.99u1. (diff) | |
download | libreoffice-5a7157d319477830426797532e02ac39d3b859f4.tar.xz libreoffice-5a7157d319477830426797532e02ac39d3b859f4.zip |
Merging upstream version 4:24.2.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'package/source/zipapi')
-rw-r--r-- | package/source/zipapi/ZipFile.cxx | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index 474b73ff53..3d382bd3a3 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -38,6 +38,7 @@ #include <rtl/digest.h> #include <sal/log.hxx> #include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> #include <osl/diagnose.h> #include <algorithm> @@ -1073,7 +1074,7 @@ sal_Int32 ZipFile::readCEN() if ( nTestSig != CENSIG ) throw ZipException("Invalid CEN header (bad signature)" ); - aMemGrabber.skipBytes ( 2 ); + sal_uInt16 versionMadeBy = aMemGrabber.ReadUInt16(); aEntry.nVersion = aMemGrabber.ReadInt16(); aEntry.nFlag = aMemGrabber.ReadInt16(); @@ -1093,7 +1094,8 @@ sal_Int32 ZipFile::readCEN() aEntry.nPathLen = aMemGrabber.ReadInt16(); aEntry.nExtraLen = aMemGrabber.ReadInt16(); nCommentLen = aMemGrabber.ReadInt16(); - aMemGrabber.skipBytes ( 8 ); + aMemGrabber.skipBytes ( 4 ); + sal_uInt32 externalFileAttributes = aMemGrabber.ReadUInt32(); sal_uInt64 nOffset = aMemGrabber.ReadUInt32(); if ( aEntry.nPathLen < 0 ) @@ -1132,6 +1134,15 @@ sal_Int32 ZipFile::readCEN() throw ZipException("Integer-overflow"); aMemGrabber.skipBytes(nCommentLen); + + // Is this a FAT-compatible empty entry? + if (aEntry.nSize == 0 && (versionMadeBy & 0xff00) == 0) + { + constexpr sal_uInt32 FILE_ATTRIBUTE_DIRECTORY = 16; + if (externalFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; // This is a directory entry, not a stream - skip it + } + aEntries[aEntry.sPath] = aEntry; } @@ -1253,6 +1264,7 @@ void ZipFile::recover() RTL_TEXTENCODING_UTF8 ); aEntry.nPathLen = static_cast< sal_Int16 >(aFileName.getLength()); } + aEntry.sPath = aEntry.sPath.replace('\\', '/'); // read 64bit header if (aEntry.nExtraLen > 0) @@ -1294,7 +1306,36 @@ void ZipFile::recover() aEntry.nSize = 0; } + // Do not add this entry, if it is empty and is a directory of + // an already existing entry + if (aEntry.nSize == 0 && aEntry.nCompressedSize == 0 + && std::find_if( + aEntries.begin(), aEntries.end(), + [path = OUString(aEntry.sPath + "/")](const auto& r) + { return r.first.startsWith(path); }) + != aEntries.end()) + { + nPos += 4; + continue; + } + aEntries.emplace( aEntry.sPath, aEntry ); + + // Drop any "directory" entry corresponding to this one's path; + // since we don't use central directory, we don't see external + // file attributes, so sanitize here + sal_Int32 i = 0; + for (OUString subdir = aEntry.sPath.getToken(0, '/', i); i >= 0; + subdir += OUString::Concat("/") + + o3tl::getToken(aEntry.sPath, 0, '/', i)) + { + if (auto it = aEntries.find(subdir); it != aEntries.end()) + { + // if not empty, let it fail later in ZipPackage::getZipFileContents + if (it->second.nSize == 0 && it->second.nCompressedSize == 0) + aEntries.erase(it); + } + } } } } |