package/CppunitTest_package2_test.mk                            |    3 
 package/inc/ZipFile.hxx                                         |   11 
 package/qa/cppunit/data/casing.docx                             |binary
 package/qa/cppunit/data/dd-deflated.docx                        |binary
 package/qa/cppunit/data/dd-stored.docx                          |binary
 package/qa/cppunit/data/dot-slash.docx                          |binary
 package/qa/cppunit/data/duplicate-files.odt                     |binary
 package/qa/cppunit/data/inner-gap.docx                          |binary
 package/qa/cppunit/data/overlap.docx                            |binary
 package/qa/cppunit/data/slash.odt                               |binary
 package/qa/cppunit/data/two-zips.docx                           |binary
 package/qa/cppunit/data/two-zips.odt                            |binary
 package/qa/cppunit/data/unicode-path.docx                       |binary
 package/qa/cppunit/data/unicode-path.odt                        |binary
 package/qa/cppunit/data/zip64-eocd.docx                         |binary
 package/qa/cppunit/test_zippackage.cxx                          |  390 
++++++++++
 package/source/zipapi/XUnbufferedStream.cxx                     |   17 
 package/source/zipapi/XUnbufferedStream.hxx                     |    4 
 package/source/zipapi/ZipFile.cxx                               |   38 
 package/source/zipapi/ZipOutputStream.cxx                       |    3 
 package/source/zippackage/ZipPackage.cxx                        |   12 
 package/source/zippackage/ZipPackageStream.cxx                  |   70 +
 package/source/zippackage/zipfileaccess.cxx                     |    4 
 sw/source/uibase/utlui/content.cxx                              |    4 
 xmlsecurity/CppunitTest_xmlsecurity_signing.mk                  |    1 
 xmlsecurity/qa/unit/signing/data/signature-forgery-cdh-lfh.docx |binary
 xmlsecurity/qa/unit/signing/signing.cxx                         |   35 
 27 files changed, 539 insertions(+), 53 deletions(-)

New commits:
commit d8891b19cc7a92feb672de61eea4c1df09a0c063
Author:     Michael Stahl <[email protected]>
AuthorDate: Tue Sep 17 17:05:21 2024 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Sep 17 17:05:21 2024 +0200

    sw: fix assert in SwContentTree::GetEntryLongDescription()
    
    Happens when called from a11y code, unclear what would have fixed it
    because the whole thing was completely reworked in commit
    5a2c0ab29719ac914d30d8789c0e386541702cbf so just avoid the crash here.
    
    Change-Id: Ia3c1a7ca6c0c4c07c5eca9e2a29aac594b9f2bc3

diff --git a/sw/source/uibase/utlui/content.cxx 
b/sw/source/uibase/utlui/content.cxx
index 891e786f63d9..d3db17cd9637 100644
--- a/sw/source/uibase/utlui/content.cxx
+++ b/sw/source/uibase/utlui/content.cxx
@@ -1021,8 +1021,8 @@ OUString SwContentTree::GetEntryLongDescription( 
SvTreeListEntry* pEntry ) const
     if( pEntry == nullptr)
         return OUString();
 
-    assert(pEntry->GetUserData() == nullptr || 
dynamic_cast<SwContent*>(static_cast<SwTypeNumber*>(pEntry->GetUserData())));
-    SwContent* pCnt = static_cast<SwContent*>(pEntry->GetUserData());
+    //??? assert(pEntry->GetUserData() == nullptr || 
dynamic_cast<SwContent*>(static_cast<SwTypeNumber*>(pEntry->GetUserData())));
+    SwContent* pCnt = 
dynamic_cast<SwContent*>(static_cast<SwTypeNumber*>(pEntry->GetUserData()));
     if( pCnt == nullptr || pCnt->GetParent() == nullptr)
         return OUString();
 
commit 90588519ca817c96467e3bae44810bd7c75c19a4
Author:     Michael Stahl <[email protected]>
AuthorDate: Fri Jul 5 13:57:16 2024 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Sep 17 15:07:46 2024 +0200

    package: add unit tests with invalid zip packages
    
    Change-Id: I687028391833ea48884912b0e5f586b95eee3244

diff --git a/package/CppunitTest_package2_test.mk 
b/package/CppunitTest_package2_test.mk
index 546da10deda6..206d8c7e1fb8 100644
--- a/package/CppunitTest_package2_test.mk
+++ b/package/CppunitTest_package2_test.mk
@@ -13,6 +13,7 @@ $(eval $(call gb_CppunitTest_CppunitTest,package2_test))
 
 $(eval $(call gb_CppunitTest_add_exception_objects,package2_test, \
     package/qa/cppunit/test_package \
+    package/qa/cppunit/test_zippackage \
 ))
 
 $(eval $(call gb_CppunitTest_use_libraries,package2_test, \
@@ -28,7 +29,9 @@ $(eval $(call gb_CppunitTest_use_sdk_api,package2_test))
 
 $(eval $(call gb_CppunitTest_use_components,package2_test,\
     configmgr/source/configmgr \
+    package/source/xstor/xstor \
     package/util/package2 \
+       sax/source/expatwrap/expwrap \
     ucb/source/core/ucb1 \
     ucb/source/ucp/file/ucpfile1 \
 ))
diff --git a/package/qa/cppunit/data/casing.docx 
b/package/qa/cppunit/data/casing.docx
new file mode 100644
index 000000000000..d8d0dffc71a6
Binary files /dev/null and b/package/qa/cppunit/data/casing.docx differ
diff --git a/package/qa/cppunit/data/dd-deflated.docx 
b/package/qa/cppunit/data/dd-deflated.docx
new file mode 100644
index 000000000000..a4638147ce91
Binary files /dev/null and b/package/qa/cppunit/data/dd-deflated.docx differ
diff --git a/package/qa/cppunit/data/dd-stored.docx 
b/package/qa/cppunit/data/dd-stored.docx
new file mode 100644
index 000000000000..41c19338821d
Binary files /dev/null and b/package/qa/cppunit/data/dd-stored.docx differ
diff --git a/package/qa/cppunit/data/dot-slash.docx 
b/package/qa/cppunit/data/dot-slash.docx
new file mode 100644
index 000000000000..d50cabcbdee2
Binary files /dev/null and b/package/qa/cppunit/data/dot-slash.docx differ
diff --git a/package/qa/cppunit/data/duplicate-files.odt 
b/package/qa/cppunit/data/duplicate-files.odt
new file mode 100644
index 000000000000..cc24f7024ad1
Binary files /dev/null and b/package/qa/cppunit/data/duplicate-files.odt differ
diff --git a/package/qa/cppunit/data/inner-gap.docx 
b/package/qa/cppunit/data/inner-gap.docx
new file mode 100644
index 000000000000..d8e9a232465c
Binary files /dev/null and b/package/qa/cppunit/data/inner-gap.docx differ
diff --git a/package/qa/cppunit/data/overlap.docx 
b/package/qa/cppunit/data/overlap.docx
new file mode 100644
index 000000000000..2d5d115ed800
Binary files /dev/null and b/package/qa/cppunit/data/overlap.docx differ
diff --git a/package/qa/cppunit/data/slash.odt 
b/package/qa/cppunit/data/slash.odt
new file mode 100644
index 000000000000..22c6443499af
Binary files /dev/null and b/package/qa/cppunit/data/slash.odt differ
diff --git a/package/qa/cppunit/data/two-zips.docx 
b/package/qa/cppunit/data/two-zips.docx
new file mode 100644
index 000000000000..720189b20ed9
Binary files /dev/null and b/package/qa/cppunit/data/two-zips.docx differ
diff --git a/package/qa/cppunit/data/two-zips.odt 
b/package/qa/cppunit/data/two-zips.odt
new file mode 100644
index 000000000000..36d90cb9d4d9
Binary files /dev/null and b/package/qa/cppunit/data/two-zips.odt differ
diff --git a/package/qa/cppunit/data/unicode-path.docx 
b/package/qa/cppunit/data/unicode-path.docx
new file mode 100644
index 000000000000..1855aa1e7408
Binary files /dev/null and b/package/qa/cppunit/data/unicode-path.docx differ
diff --git a/package/qa/cppunit/data/unicode-path.odt 
b/package/qa/cppunit/data/unicode-path.odt
new file mode 100644
index 000000000000..9edaaeb68809
Binary files /dev/null and b/package/qa/cppunit/data/unicode-path.odt differ
diff --git a/package/qa/cppunit/data/zip64-eocd.docx 
b/package/qa/cppunit/data/zip64-eocd.docx
new file mode 100644
index 000000000000..1a4dbd0d16b1
Binary files /dev/null and b/package/qa/cppunit/data/zip64-eocd.docx differ
diff --git a/package/qa/cppunit/test_zippackage.cxx 
b/package/qa/cppunit/test_zippackage.cxx
new file mode 100644
index 000000000000..57a2eb1fed74
--- /dev/null
+++ b/package/qa/cppunit/test_zippackage.cxx
@@ -0,0 +1,390 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <unotest/bootstrapfixturebase.hxx>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/embed/StorageFormats.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+
+using namespace ::com::sun::star;
+
+class ZipPackageTest : public test::BootstrapFixtureBase
+{
+};
+
+OUString const ZipPackage("com.sun.star.packages.comp.ZipPackage");
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testDuplicate)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/duplicate-files.odt"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testUnicodeODT)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/unicode-path.odt"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testUnicodeDOCX)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/unicode-path.docx"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testAbsolutePathODT)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/slash.odt"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testDotPathDOCX)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/dot-slash.docx"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testConcatODT)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/two-zips.odt"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testConcatDOCX)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/two-zips.docx"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testCaseInsensitiveDOCX)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/casing.docx"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::OFOPXML)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testOverlapDOCX)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/overlap.docx"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testInnerGapDOCX)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/inner-gap.docx"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testDataDescriptorDeflatedDOCX)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/dd-deflated.docx"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testDataDescriptorStoredDOCX)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/dd-stored.docx"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::OFOPXML)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::OFOPXML)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(ZipPackageTest, testZip64End)
+{
+    auto const 
url(m_directories.getURLFromSrc(u"/package/qa/cppunit/data/zip64-eocd.docx"));
+    uno::Sequence<uno::Any> const args{
+        uno::Any(url),
+        uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+    };
+
+    // don't load corrupted zip file
+    
CPPUNIT_ASSERT_THROW(m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+                             ZipPackage, args, m_xContext),
+                         css::packages::zip::ZipIOException);
+
+    try
+    {
+        uno::Sequence<uno::Any> const args2{
+            uno::Any(url), uno::Any(beans::NamedValue("RepairPackage", 
uno::Any(true))),
+            uno::Any(beans::NamedValue("StorageFormat", 
uno::Any(embed::StorageFormats::ZIP)))
+        };
+        
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(ZipPackage,
 args2,
+                                                                               
m_xContext);
+    }
+    catch (css::packages::zip::ZipIOException const&)
+    {
+        // check that this doesn't crash, it doesn't matter if it succeeds or 
not
+    }
+}
+
+//CPPUNIT_TEST_SUITE_REGISTRATION(...);
+//CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 903d9be09397ff061cc5c680a8f70f303e31e899
Author:     Michael Stahl <[email protected]>
AuthorDate: Wed Jul 3 18:00:38 2024 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Sep 17 15:07:46 2024 +0200

    xmlsecurity: add unit test with docx that can only be opened with repair
    
    Change-Id: I4f705dd2124383a90b69d04d8b2de0e37f83a495

diff --git a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk 
b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
index 9709b49e2b19..3ba11dd3b39c 100644
--- a/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
+++ b/xmlsecurity/CppunitTest_xmlsecurity_signing.mk
@@ -25,6 +25,7 @@ $(eval $(call 
gb_CppunitTest_use_libraries,xmlsecurity_signing, \
        sfx \
        test \
        tl \
+       ucbhelper \
        unotest \
        utl \
        xmlsecurity \
diff --git a/xmlsecurity/qa/unit/signing/data/signature-forgery-cdh-lfh.docx 
b/xmlsecurity/qa/unit/signing/data/signature-forgery-cdh-lfh.docx
new file mode 100644
index 000000000000..532705ecf0b5
Binary files /dev/null and 
b/xmlsecurity/qa/unit/signing/data/signature-forgery-cdh-lfh.docx differ
diff --git a/xmlsecurity/qa/unit/signing/signing.cxx 
b/xmlsecurity/qa/unit/signing/signing.cxx
index 96d233ad9027..66e0594ec9c6 100644
--- a/xmlsecurity/qa/unit/signing/signing.cxx
+++ b/xmlsecurity/qa/unit/signing/signing.cxx
@@ -24,6 +24,7 @@
 
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/document/MacroExecMode.hpp>
+#include <com/sun/star/document/BrokenPackageRequest.hpp>
 #include <com/sun/star/embed/XStorage.hpp>
 #include <com/sun/star/embed/XTransactedObject.hpp>
 #include <com/sun/star/frame/Desktop.hpp>
@@ -32,6 +33,7 @@
 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
 #include <com/sun/star/xml/crypto/SEInitializer.hpp>
+#include <com/sun/star/task/XInteractionApprove.hpp>
 
 #include <comphelper/processfactory.hxx>
 #include <comphelper/propertysequence.hxx>
@@ -53,6 +55,7 @@
 #include <biginteger.hxx>
 #include <certificate.hxx>
 #include <xsecctl.hxx>
+#include <ucbhelper/interceptedinteraction.hxx>
 #include <sfx2/docfile.hxx>
 #include <sfx2/docfilt.hxx>
 #include <officecfg/Office/Common.hxx>
@@ -1100,6 +1103,38 @@ CPPUNIT_TEST_FIXTURE(SigningTest, 
testODFUntrustedGoodGPG)
                                  SignatureState::NOTVALIDATED, nActual);
 }
 
+CPPUNIT_TEST_FIXTURE(SigningTest, testInvalidZIP)
+{
+// set RepairPackage via interaction handler, same as soffice does
+// - if it's passed to load the behavior is different, oddly enough.
+#if 0
+    std::vector<::ucbhelper::InterceptedInteraction::InterceptedRequest> 
interceptions{
+        { css::uno::Any(css::document::BrokenPackageRequest()),
+          cppu::UnoType<css::task::XInteractionApprove>::get(), 0 },
+    };
+    ::rtl::Reference<ucbhelper::InterceptedInteraction> pIH(new 
ucbhelper::InterceptedInteraction);
+    pIH->setInterceptions(std::move(interceptions));
+
+    uno::Sequence<beans::PropertyValue> args = { comphelper::makePropertyValue(
+        "InteractionHandler", uno::Reference<task::XInteractionHandler>(pIH)) 
};
+#endif
+    OUString const url(m_directories.getURLFromSrc(DATA_DIRECTORY)
+                       + "signature-forgery-cdh-lfh.docx");
+    mxComponent = mxDesktop->loadComponentFromURL(url, "_default", 0, {} 
/*args*/);
+    SfxBaseModel* pBaseModel = dynamic_cast<SfxBaseModel*>(mxComponent.get());
+    CPPUNIT_ASSERT(!pBaseModel); // old branch cannot repair DOCX
+#if 0
+    CPPUNIT_ASSERT(pBaseModel);
+    SfxObjectShell* pObjectShell = pBaseModel->GetObjectShell();
+    CPPUNIT_ASSERT(pObjectShell);
+    // the problem was that the document Zip structure is interpreted
+    // misleadingly in RepairPackage case, but signature was still returned
+    // as partially valid.
+    CPPUNIT_ASSERT_EQUAL(static_cast<int>(SignatureState::BROKEN),
+                         
static_cast<int>(pObjectShell->GetDocumentSignatureState()));
+#endif
+}
+
 /// Test a typical broken ODF signature where one stream is corrupted.
 CPPUNIT_TEST_FIXTURE(SigningTest, testODFBrokenStreamGPG)
 {
commit 20e0d15511382a72d3d40f6c7508aca395ecf357
Author:     Michael Stahl <[email protected]>
AuthorDate: Mon Sep 16 20:31:06 2024 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Sep 17 15:07:46 2024 +0200

    tdf#162866 package: fix loading AutoCorrect file with case-insensitive
    
    ... duplicates; the directory names of AutoCorrect entries are
    user-editable, so this needs to be supported.
    
    AutoCorrect uses an ODF package because the ODF document loading code
    requires the ODF document to be in an ODF storage with a MediaType
    property.
    
    AutoCorrect writes an empty mimetype file, and if such is present in an
    .odt file that is being loaded, existing checks will detect it as
    corrupted, so we can use this to check that the file is an AutoCorrect
    file and turn off the case-insensitive check.
    
    (regression from commit 4833f131243bdb409ddfaff8b4db87d4ed2af98f)
    
    Change-Id: I43887f7dad0c8cbb465b4c0f1c38bcc3244a7675
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173477
    Reviewed-by: Michael Stahl <[email protected]>
    Tested-by: Jenkins
    (cherry picked from commit 9012355a60bd88db582078e38123863a4959b72f)

diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx
index 00abe6ef7878..66bee71ea5d8 100644
--- a/package/inc/ZipFile.hxx
+++ b/package/inc/ZipFile.hxx
@@ -58,7 +58,7 @@ class ZipEnumeration;
 class ZipFile
 {
 public:
-    enum class Checks { Default, CheckInsensitive };
+    enum class Checks { Default, CheckInsensitive, TryCheckInsensitive };
 
 private:
     rtl::Reference<comphelper::RefCountedMutex> m_aMutexHolder;
diff --git a/package/source/zipapi/ZipFile.cxx 
b/package/source/zipapi/ZipFile.cxx
index 51f8599d4da7..54e63d670d8e 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -1315,6 +1315,17 @@ sal_Int32 ZipFile::readCEN()
                 SAL_INFO("package", "Duplicate CEN entry: \"" << aEntry.sPath 
<< "\"");
                 throw ZipException("Duplicate CEN entry");
             }
+            if (aEntries.empty() && m_Checks == Checks::TryCheckInsensitive)
+            {
+                if (aEntry.sPath == "mimetype" && aEntry.nSize == 0)
+                {   // tdf#162866 AutoCorrect uses ODF package, directories are
+                    m_Checks = Checks::Default; // user-defined => ignore!
+                }
+                else
+                {
+                    m_Checks = Checks::CheckInsensitive;
+                }
+            }
             // this is required for OOXML, but not for ODF
             auto const lowerPath(aEntry.sPath.toAsciiLowerCase());
             if (!m_EntriesInsensitive.insert(lowerPath).second && m_Checks == 
Checks::CheckInsensitive)
diff --git a/package/source/zippackage/ZipPackage.cxx 
b/package/source/zippackage/ZipPackage.cxx
index 0beb7968535e..37370c0f7e3f 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -803,7 +803,11 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< 
Any >& aArguments )
             {
                 m_pZipFile = std::make_unique<ZipFile>(m_aMutexHolder, 
m_xContentStream, m_xContext, true,
                     m_bForceRecovery,
-                    m_nFormat == embed::StorageFormats::ZIP ? 
ZipFile::Checks::Default : ZipFile::Checks::CheckInsensitive);
+                    m_nFormat == embed::StorageFormats::ZIP
+                        ? ZipFile::Checks::Default
+                        : m_nFormat == embed::StorageFormats::OFOPXML
+                            ? ZipFile::Checks::CheckInsensitive
+                            : ZipFile::Checks::TryCheckInsensitive);
                 getZipFileContents();
             }
             catch ( IOException & e )
@@ -1181,7 +1185,11 @@ void ZipPackage::ConnectTo( const uno::Reference< 
io::XInputStream >& xInStream
     else
         m_pZipFile = std::make_unique<ZipFile>(m_aMutexHolder, 
m_xContentStream, m_xContext, false,
             false,
-            m_nFormat == embed::StorageFormats::ZIP ? ZipFile::Checks::Default 
: ZipFile::Checks::CheckInsensitive);
+            m_nFormat == embed::StorageFormats::ZIP
+                ? ZipFile::Checks::Default
+                : m_nFormat == embed::StorageFormats::OFOPXML
+                    ? ZipFile::Checks::CheckInsensitive
+                    : ZipFile::Checks::TryCheckInsensitive);
 }
 
 namespace
commit 595152b82c4f6bf0c46422b4dfad680e376d19da
Author:     Michael Stahl <[email protected]>
AuthorDate: Thu Sep 12 18:24:27 2024 +0200
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Sep 17 15:07:46 2024 +0200

    tdf#162823 package: fix loss of ODF encrypted basic macros
    
    The problem is that there is a ZipEntry ZipPackageStream::aEntry which
    does not necessarily correspond to the values read from the Zip central
    directory, because of a call to ZipPackageStream::setSize() in
    ZipPackageStream::successfullyWritten() to override nSize and nMethod
    for encrypted entries.
    
    This triggers the consistency checks in readLOC(), where this aEntry is
    passed.
    
    Refactor things so that ZipPackageStream::aEntry and thus hopefully all
    ZipEntry instances correspond to the Zip file's central directory.
    
    For encrypted entries, store the decompressed size (which is read from
    manifest.xml) in m_nOwnStreamOrigSize and pass it as a separate
    parameter to the ZipFile functions that need it, and ultimately to
    XUnbufferedStream, resolving multiple TODO comments.
    
    (regression from commit efae4fc42d5fe3c0a69757226f38efc10d101194)
    
    Change-Id: Ib6ea32595c6027b98da9196a2e2bd0a99b62a983
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173273
    Reviewed-by: Michael Stahl <[email protected]>
    Tested-by: Jenkins
    (cherry picked from commit 33d55465d9f81863b88d649a46353cc4d19cd253)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173297
    Reviewed-by: Mike Kaganski <[email protected]>
    (cherry picked from commit d290716ba140cdb3282cd542d1cd6f12709ae06f)

diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx
index c65f42a637b0..00abe6ef7878 100644
--- a/package/inc/ZipFile.hxx
+++ b/package/inc/ZipFile.hxx
@@ -80,7 +80,7 @@ private:
             ZipEntry const & rEntry,
             const ::rtl::Reference < EncryptionData > &rData,
             sal_Int8 nStreamMode,
-            bool bDecrypt,
+            ::std::optional<sal_Int64> oDecryptedSize,
             const bool bUseBufferedStream = true,
             const OUString& aMediaType = OUString() );
 
@@ -118,7 +118,7 @@ public:
     css::uno::Reference< css::io::XInputStream > getRawData(
             ZipEntry& rEntry,
             const ::rtl::Reference < EncryptionData > &rData,
-            bool bDecrypt,
+            ::std::optional<sal_Int64> oDecryptedSize,
             const rtl::Reference<comphelper::RefCountedMutex>& aMutexHolder,
             const bool bUseBufferedStream = true );
 
@@ -159,18 +159,19 @@ public:
     css::uno::Reference< css::io::XInputStream > getInputStream(
             ZipEntry& rEntry,
             const ::rtl::Reference < EncryptionData > &rData,
-            bool bDecrypt,
+            ::std::optional<sal_Int64> oDecryptedSize,
             const rtl::Reference<comphelper::RefCountedMutex>& aMutexHolder );
 
     css::uno::Reference< css::io::XInputStream > getDataStream(
             ZipEntry& rEntry,
             const ::rtl::Reference < EncryptionData > &rData,
-            bool bDecrypt,
+            ::std::optional<sal_Int64> oEncryptedSize,
             const rtl::Reference<comphelper::RefCountedMutex>& aMutexHolder );
 
     css::uno::Reference< css::io::XInputStream > getWrappedRawStream(
             ZipEntry& rEntry,
             const ::rtl::Reference < EncryptionData > &rData,
+            sal_Int64 nDecryptedSize,
             const OUString& aMediaType,
             const rtl::Reference<comphelper::RefCountedMutex>& aMutexHolder );
 
diff --git a/package/source/zipapi/XUnbufferedStream.cxx 
b/package/source/zipapi/XUnbufferedStream.cxx
index 7697af0ff070..e30a30d84a6b 100644
--- a/package/source/zipapi/XUnbufferedStream.cxx
+++ b/package/source/zipapi/XUnbufferedStream.cxx
@@ -50,7 +50,7 @@ XUnbufferedStream::XUnbufferedStream(
                       Reference < XInputStream > const & xNewZipStream,
                       const ::rtl::Reference< EncryptionData >& rData,
                       sal_Int8 nStreamMode,
-                      bool bIsEncrypted,
+                      ::std::optional<sal_Int64> const oDecryptedSize,
                       const OUString& aMediaType,
                       bool bRecoveryMode )
 : maMutexHolder( aMutexHolder )
@@ -69,16 +69,17 @@ XUnbufferedStream::XUnbufferedStream(
 , mbCheckCRC(!bRecoveryMode && !utl::ConfigManager::IsFuzzing())
 {
     mnZipCurrent = maEntry.nOffset;
-    sal_Int64 nSize;
+    sal_Int64 nSize; // data size in the zip file
+    assert(maEntry.nMethod != STORED || maEntry.nCompressedSize == 
maEntry.nSize);
     if ( mbRawStream )
     {
-        mnZipSize = maEntry.nMethod == DEFLATED ? maEntry.nCompressedSize : 
maEntry.nSize;
+        mnZipSize = maEntry.nCompressedSize;
         nSize = mnZipSize;
     }
     else
     {
-        mnZipSize = maEntry.nSize;
-        nSize = maEntry.nMethod == DEFLATED ? maEntry.nCompressedSize : 
maEntry.nSize;
+        mnZipSize = oDecryptedSize ? *oDecryptedSize : maEntry.nSize;
+        nSize = maEntry.nCompressedSize;
     }
 
     if (mnZipSize < 0)
@@ -91,7 +92,7 @@ XUnbufferedStream::XUnbufferedStream(
         ((rData->m_aSalt.hasElements() && rData->m_nIterationCount != 0)
          ||
          rData->m_aKey.hasElements());
-    bool bMustDecrypt = nStreamMode == UNBUFF_STREAM_DATA && bHaveEncryptData 
&& bIsEncrypted;
+    bool bMustDecrypt = nStreamMode == UNBUFF_STREAM_DATA && bHaveEncryptData 
&& oDecryptedSize;
 
     if ( bMustDecrypt )
     {
@@ -99,7 +100,7 @@ XUnbufferedStream::XUnbufferedStream(
         mnBlockSize = ( rData->m_nEncAlg == 
xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 1 );
     }
 
-    if ( bHaveEncryptData && mbWrappedRaw && bIsEncrypted )
+    if (bHaveEncryptData && mbWrappedRaw && oDecryptedSize)
     {
         // if we have the data needed to decrypt it, but didn't want it 
decrypted (or
         // we couldn't decrypt it due to wrong password), then we prepend this
@@ -112,7 +113,7 @@ XUnbufferedStream::XUnbufferedStream(
                             rData->m_aDigest.getLength() +
                             aMediaType.getLength() * sizeof( sal_Unicode ) );
         sal_Int8 * pHeader = maHeader.getArray();
-        ZipFile::StaticFillHeader( rData, rEntry.nSize, aMediaType, pHeader );
+        ZipFile::StaticFillHeader(rData, *oDecryptedSize, aMediaType, pHeader);
         mnHeaderToRead = static_cast < sal_Int16 > ( maHeader.getLength() );
         mnZipSize += mnHeaderToRead;
     }
diff --git a/package/source/zipapi/XUnbufferedStream.hxx 
b/package/source/zipapi/XUnbufferedStream.hxx
index a864de48f2ba..a13bdee10159 100644
--- a/package/source/zipapi/XUnbufferedStream.hxx
+++ b/package/source/zipapi/XUnbufferedStream.hxx
@@ -19,6 +19,8 @@
 #ifndef INCLUDED_PACKAGE_SOURCE_ZIPAPI_XUNBUFFEREDSTREAM_HXX
 #define INCLUDED_PACKAGE_SOURCE_ZIPAPI_XUNBUFFEREDSTREAM_HXX
 
+#include <optional>
+
 #include <com/sun/star/lang/IllegalArgumentException.hpp>
 #include <com/sun/star/io/XSeekable.hpp>
 #include <com/sun/star/io/XInputStream.hpp>
@@ -69,7 +71,7 @@ public:
                  css::uno::Reference < css::io::XInputStream > const & 
xNewZipStream,
                  const ::rtl::Reference< EncryptionData >& rData,
                  sal_Int8 nStreamMode,
-                 bool bIsEncrypted,
+                 ::std::optional<sal_Int64> oDecryptedSize,
                  const OUString& aMediaType,
                  bool bRecoveryMode );
 
diff --git a/package/source/zipapi/ZipFile.cxx 
b/package/source/zipapi/ZipFile.cxx
index 15fd7c423de5..51f8599d4da7 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -624,14 +624,14 @@ uno::Reference< XInputStream > 
ZipFile::createStreamForZipEntry(
             ZipEntry const & rEntry,
             const ::rtl::Reference< EncryptionData > &rData,
             sal_Int8 nStreamMode,
-            bool bIsEncrypted,
+            ::std::optional<sal_Int64> const oDecryptedSize,
             const bool bUseBufferedStream,
             const OUString& aMediaType )
 {
     ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
 
     rtl::Reference< XUnbufferedStream > xSrcStream = new XUnbufferedStream(
-        m_xContext, aMutexHolder, rEntry, xStream, rData, nStreamMode, 
bIsEncrypted, aMediaType, bRecoveryMode);
+        m_xContext, aMutexHolder, rEntry, xStream, rData, nStreamMode, 
oDecryptedSize, aMediaType, bRecoveryMode);
 
     if (!bUseBufferedStream)
         return xSrcStream.get();
@@ -654,7 +654,7 @@ std::unique_ptr<ZipEnumeration> ZipFile::entries()
 
 uno::Reference< XInputStream > ZipFile::getInputStream( ZipEntry& rEntry,
         const ::rtl::Reference< EncryptionData > &rData,
-        bool bIsEncrypted,
+        ::std::optional<sal_Int64> const oDecryptedSize,
         const rtl::Reference<comphelper::RefCountedMutex>& aMutexHolder )
 {
     ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
@@ -669,19 +669,19 @@ uno::Reference< XInputStream > ZipFile::getInputStream( 
ZipEntry& rEntry,
 
     // if we have a digest, then this file is an encrypted one and we should
     // check if we can decrypt it or not
-    if ( bIsEncrypted && rData.is() && rData->m_aDigest.hasElements() )
+    if (oDecryptedSize && rData.is() && rData->m_aDigest.hasElements())
         bNeedRawStream = !hasValidPassword ( rEntry, rData );
 
     return createStreamForZipEntry ( aMutexHolder,
                                     rEntry,
                                     rData,
                                     bNeedRawStream ? UNBUFF_STREAM_RAW : 
UNBUFF_STREAM_DATA,
-                                    bIsEncrypted );
+                                    oDecryptedSize);
 }
 
 uno::Reference< XInputStream > ZipFile::getDataStream( ZipEntry& rEntry,
         const ::rtl::Reference< EncryptionData > &rData,
-        bool bIsEncrypted,
+        ::std::optional<sal_Int64> const oDecryptedSize,
         const rtl::Reference<comphelper::RefCountedMutex>& aMutexHolder )
 {
     ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
@@ -692,7 +692,7 @@ uno::Reference< XInputStream > ZipFile::getDataStream( 
ZipEntry& rEntry,
     // An exception must be thrown in case stream is encrypted and
     // there is no key or the key is wrong
     bool bNeedRawStream = false;
-    if ( bIsEncrypted )
+    if (oDecryptedSize)
     {
         // in case no digest is provided there is no way
         // to detect password correctness
@@ -712,12 +712,12 @@ uno::Reference< XInputStream > ZipFile::getDataStream( 
ZipEntry& rEntry,
                                     rEntry,
                                     rData,
                                     bNeedRawStream ? UNBUFF_STREAM_RAW : 
UNBUFF_STREAM_DATA,
-                                    bIsEncrypted );
+                                    oDecryptedSize);
 }
 
 uno::Reference< XInputStream > ZipFile::getRawData( ZipEntry& rEntry,
         const ::rtl::Reference< EncryptionData >& rData,
-        bool bIsEncrypted,
+        ::std::optional<sal_Int64> const oDecryptedSize,
         const rtl::Reference<comphelper::RefCountedMutex>& aMutexHolder,
         const bool bUseBufferedStream )
 {
@@ -726,12 +726,14 @@ uno::Reference< XInputStream > ZipFile::getRawData( 
ZipEntry& rEntry,
     if ( rEntry.nOffset <= 0 )
         readLOC( rEntry );
 
-    return createStreamForZipEntry ( aMutexHolder, rEntry, rData, 
UNBUFF_STREAM_RAW, bIsEncrypted, bUseBufferedStream );
+    return createStreamForZipEntry(aMutexHolder, rEntry, rData,
+            UNBUFF_STREAM_RAW, oDecryptedSize, bUseBufferedStream);
 }
 
 uno::Reference< XInputStream > ZipFile::getWrappedRawStream(
         ZipEntry& rEntry,
         const ::rtl::Reference< EncryptionData >& rData,
+        sal_Int64 const nDecryptedSize,
         const OUString& aMediaType,
         const rtl::Reference<comphelper::RefCountedMutex>& aMutexHolder )
 {
@@ -743,7 +745,8 @@ uno::Reference< XInputStream > ZipFile::getWrappedRawStream(
     if ( rEntry.nOffset <= 0 )
         readLOC( rEntry );
 
-    return createStreamForZipEntry ( aMutexHolder, rEntry, rData, 
UNBUFF_STREAM_WRAPPEDRAW, true, true, aMediaType );
+    return createStreamForZipEntry(aMutexHolder, rEntry, rData,
+            UNBUFF_STREAM_WRAPPEDRAW, nDecryptedSize, true, aMediaType);
 }
 
 sal_uInt64 ZipFile::readLOC(ZipEntry &rEntry)
diff --git a/package/source/zipapi/ZipOutputStream.cxx 
b/package/source/zipapi/ZipOutputStream.cxx
index 6bf3bd33f49e..fe3525d94e9a 100644
--- a/package/source/zipapi/ZipOutputStream.cxx
+++ b/package/source/zipapi/ZipOutputStream.cxx
@@ -86,7 +86,10 @@ void ZipOutputStream::rawCloseEntry( bool bEncrypt )
         writeEXT(*m_pCurrentEntry);
 
     if (bEncrypt)
+    {
         m_pCurrentEntry->nMethod = STORED;
+        assert(m_pCurrentEntry->nSize == m_pCurrentEntry->nCompressedSize);
+    }
 
     m_pCurrentEntry = nullptr;
 }
diff --git a/package/source/zippackage/ZipPackageStream.cxx 
b/package/source/zippackage/ZipPackageStream.cxx
index 745157cfd02e..43c6a02daa73 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -141,6 +141,10 @@ void ZipPackageStream::setZipEntryOnLoading( const 
ZipEntry &rInEntry )
 
     if ( aEntry.nMethod == STORED )
         m_bToBeCompressed = false;
+
+    // this is called first, parseManifest may overwrite it if it's encrypted
+    assert(m_nOwnStreamOrigSize == 0);
+    m_nOwnStreamOrigSize = aEntry.nSize;
 }
 
 uno::Reference< io::XInputStream > const & ZipPackageStream::GetOwnSeekStream()
@@ -543,14 +547,11 @@ bool ZipPackageStream::saveChild(
                     OSL_ENSURE( !m_bRawStream || !(bToBeCompressed || 
bToBeEncrypted), "The stream is already encrypted!" );
                     xSeek->seek ( m_bRawStream ? m_nMagicalHackPos : 0 );
                     ImplSetStoredData ( *pTempEntry, xStream );
-
-                    // TODO/LATER: Get rid of hacks related to switching of 
Flag Method and Size properties!
                 }
                 else if ( bToBeEncrypted )
                 {
                     // this is the correct original size
-                    pTempEntry->nSize = xSeek->getLength();
-                    m_nOwnStreamOrigSize = pTempEntry->nSize;
+                    m_nOwnStreamOrigSize = xSeek->getLength();
                 }
 
                 xSeek->seek ( 0 );
@@ -868,10 +869,6 @@ void ZipPackageStream::successfullyWritten( ZipEntry const 
*pEntry )
     // Then copy it back afterwards...
     aEntry = *pEntry;
 
-    // TODO/LATER: get rid of this hack ( the encrypted stream size property 
is changed during saving )
-    if ( m_bIsEncrypted )
-        setSize( m_nOwnStreamOrigSize );
-
     aEntry.nOffset *= -1;
 }
 
@@ -905,7 +902,13 @@ uno::Reference< io::XInputStream > 
ZipPackageStream::getRawData()
     {
         if ( IsPackageMember() )
         {
-            return m_rZipPackage.getZipFile().getRawData( aEntry, 
GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef(), 
false/*bUseBufferedStream*/ );
+            ::std::optional<sal_Int64> oDecryptedSize;
+            if (m_bIsEncrypted)
+            {
+                oDecryptedSize.emplace(m_nOwnStreamOrigSize);
+            }
+            return m_rZipPackage.getZipFile().getRawData( aEntry, 
GetEncryptionData(),
+                oDecryptedSize, m_rZipPackage.GetSharedMutexRef(), 
false/*bUseBufferedStream*/ );
         }
         else if ( GetOwnSeekStream().is() )
         {
@@ -932,7 +935,13 @@ uno::Reference< io::XInputStream > SAL_CALL 
ZipPackageStream::getInputStream()
     {
         if ( IsPackageMember() )
         {
-            return m_rZipPackage.getZipFile().getInputStream( aEntry, 
GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
+            ::std::optional<sal_Int64> oDecryptedSize;
+            if (m_bIsEncrypted)
+            {
+                oDecryptedSize.emplace(m_nOwnStreamOrigSize);
+            }
+            return m_rZipPackage.getZipFile().getInputStream(aEntry, 
GetEncryptionData(),
+                    oDecryptedSize, m_rZipPackage.GetSharedMutexRef());
         }
         else if ( GetOwnSeekStream().is() )
         {
@@ -967,9 +976,16 @@ uno::Reference< io::XInputStream > SAL_CALL 
ZipPackageStream::getDataStream()
     if ( IsPackageMember() )
     {
         uno::Reference< io::XInputStream > xResult;
+        ::std::optional<sal_Int64> oDecryptedSize;
+        if (m_bIsEncrypted)
+        {
+            oDecryptedSize.emplace(m_nOwnStreamOrigSize);
+        }
         try
         {
-            xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, 
GetEncryptionData(Bugs::None), m_bIsEncrypted, 
m_rZipPackage.GetSharedMutexRef() );
+            xResult = m_rZipPackage.getZipFile().getDataStream(aEntry,
+                GetEncryptionData(Bugs::None), oDecryptedSize,
+                m_rZipPackage.GetSharedMutexRef());
         }
         catch( const packages::WrongPasswordException& )
         {
@@ -978,7 +994,9 @@ uno::Reference< io::XInputStream > SAL_CALL 
ZipPackageStream::getDataStream()
                 SAL_WARN("package", "ZipPackageStream::getDataStream(): SHA1 
mismatch, trying fallbacks...");
                 try
                 {   // tdf#114939 try with legacy StarOffice SHA1 bug
-                    xResult = m_rZipPackage.getZipFile().getDataStream( 
aEntry, GetEncryptionData(Bugs::WrongSHA1), m_bIsEncrypted, 
m_rZipPackage.GetSharedMutexRef() );
+                    xResult = m_rZipPackage.getZipFile().getDataStream(aEntry,
+                        GetEncryptionData(Bugs::WrongSHA1), oDecryptedSize,
+                        m_rZipPackage.GetSharedMutexRef());
                     return xResult;
                 }
                 catch (const packages::WrongPasswordException&)
@@ -995,7 +1013,9 @@ uno::Reference< io::XInputStream > SAL_CALL 
ZipPackageStream::getDataStream()
 
                     // force SHA256 and see if that works
                     m_nImportedStartKeyAlgorithm = 
xml::crypto::DigestID::SHA256;
-                    xResult = m_rZipPackage.getZipFile().getDataStream( 
aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() 
);
+                    xResult = m_rZipPackage.getZipFile().getDataStream(aEntry,
+                        GetEncryptionData(), oDecryptedSize,
+                        m_rZipPackage.GetSharedMutexRef());
                     return xResult;
                 }
                 catch (const packages::WrongPasswordException&)
@@ -1008,7 +1028,9 @@ uno::Reference< io::XInputStream > SAL_CALL 
ZipPackageStream::getDataStream()
                 // workaround for the encrypted documents generated with the 
old OOo1.x bug.
                 if ( !m_bUseWinEncoding )
                 {
-                    xResult = m_rZipPackage.getZipFile().getDataStream( 
aEntry, GetEncryptionData(Bugs::WinEncodingWrongSHA1), m_bIsEncrypted, 
m_rZipPackage.GetSharedMutexRef() );
+                    xResult = m_rZipPackage.getZipFile().getDataStream(aEntry,
+                        GetEncryptionData(Bugs::WinEncodingWrongSHA1),
+                        oDecryptedSize, m_rZipPackage.GetSharedMutexRef());
                     m_bUseWinEncoding = true;
                 }
                 else
@@ -1044,7 +1066,8 @@ uno::Reference< io::XInputStream > SAL_CALL 
ZipPackageStream::getRawStream()
         if ( !m_bIsEncrypted || !GetEncryptionData().is() )
             throw packages::NoEncryptionException(THROW_WHERE );
 
-        return m_rZipPackage.getZipFile().getWrappedRawStream( aEntry, 
GetEncryptionData(), msMediaType, m_rZipPackage.GetSharedMutexRef() );
+        return m_rZipPackage.getZipFile().getWrappedRawStream(aEntry, 
GetEncryptionData(),
+            m_nOwnStreamOrigSize, msMediaType, 
m_rZipPackage.GetSharedMutexRef());
     }
     else if ( GetOwnSeekStream().is() )
     {
@@ -1099,7 +1122,13 @@ uno::Reference< io::XInputStream > SAL_CALL 
ZipPackageStream::getPlainRawStream(
 
     if ( IsPackageMember() )
     {
-        return m_rZipPackage.getZipFile().getRawData( aEntry, 
GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
+        ::std::optional<sal_Int64> oDecryptedSize;
+        if (m_bIsEncrypted)
+        {
+            oDecryptedSize.emplace(m_nOwnStreamOrigSize);
+        }
+        return m_rZipPackage.getZipFile().getRawData(aEntry, 
GetEncryptionData(),
+            oDecryptedSize, m_rZipPackage.GetSharedMutexRef());
     }
     else if ( GetOwnSeekStream().is() )
     {
@@ -1149,7 +1178,7 @@ void SAL_CALL ZipPackageStream::setPropertyValue( const 
OUString& aPropertyName,
     }
     else if ( aPropertyName == "Size" )
     {
-        if ( !( aValue >>= aEntry.nSize ) )
+        if (!(aValue >>= m_nOwnStreamOrigSize))
             throw IllegalArgumentException(THROW_WHERE "Wrong type for Size 
property!",
                                             uno::Reference< XInterface >(),
                                             2 );
@@ -1282,7 +1311,7 @@ Any SAL_CALL ZipPackageStream::getPropertyValue( const 
OUString& PropertyName )
     }
     else if ( PropertyName == "Size" )
     {
-        return Any(aEntry.nSize);
+        return Any(m_nOwnStreamOrigSize);
     }
     else if ( PropertyName == "Encrypted" )
     {
@@ -1310,10 +1339,9 @@ Any SAL_CALL ZipPackageStream::getPropertyValue( const 
OUString& PropertyName )
 
 void ZipPackageStream::setSize ( const sal_Int64 nNewSize )
 {
-    if ( aEntry.nCompressedSize != nNewSize )
-        aEntry.nMethod = DEFLATED;
-    aEntry.nSize = nNewSize;
+    m_nOwnStreamOrigSize = nNewSize;
 }
+
 OUString ZipPackageStream::getImplementationName()
 {
     return "ZipPackageStream";
diff --git a/package/source/zippackage/zipfileaccess.cxx 
b/package/source/zippackage/zipfileaccess.cxx
index f86a5fde9984..ec865f9f9878 100644
--- a/package/source/zippackage/zipfileaccess.cxx
+++ b/package/source/zippackage/zipfileaccess.cxx
@@ -267,7 +267,7 @@ uno::Any SAL_CALL OZipFileAccess::getByName( const 
OUString& aName )
     {
         xEntryStream  = m_pZipFile->getDataStream((*aIter).second,
                                                   ::rtl::Reference< 
EncryptionData >(),
-                                                  false,
+                                                  {},
                                                   m_aMutexHolder);
     }
     catch (const container::NoSuchElementException&)
@@ -389,7 +389,7 @@ uno::Reference< io::XInputStream > SAL_CALL 
OZipFileAccess::getStreamByPattern(
     {
         uno::Reference< io::XInputStream > xEntryStream( 
m_pZipFile->getDataStream( (*aIter).second,
                                                                                
     ::rtl::Reference< EncryptionData >(),
-                                                                               
     false,
+                                                                               
     {},
                                                                                
     m_aMutexHolder ) );
 
         if ( !xEntryStream.is() )
commit 16b8cec49d6be86fdf5606f615d70c5911858224
Author:     Caolán McNamara <[email protected]>
AuthorDate: Wed Sep 11 12:06:21 2024 +0100
Commit:     Michael Stahl <[email protected]>
CommitDate: Tue Sep 17 15:07:46 2024 +0200

    ofz: 22 byte .zip is min size
    
    at which point nPos is 0 on entering this test.
    
    If the buffer does not start with PK\x5\x6 then nPos is decremented
    before checking against 0, so nPos is -1 and doesn't throw as an
    unhandled .zip.
    
    Change-Id: I4a7fed6e863582324945a75bc077f6346ddd5c23
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173208
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <[email protected]>
    (cherry picked from commit d22d47e940da3bea13fe20199b5ab410d9d6ac50)

diff --git a/package/source/zipapi/ZipFile.cxx 
b/package/source/zipapi/ZipFile.cxx
index 77998bc09a7d..15fd7c423de5 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -987,11 +987,11 @@ std::tuple<sal_Int64, sal_Int64, sal_Int64> 
ZipFile::findCentralDirectory()
                 nEndPos = nPos + nEnd;
                 break;
             }
-            nPos--;
             if (nPos == 0)
             {
                 throw ZipException("Zip END signature not found!");
             }
+            nPos--;
         }
 
         aGrabber.seek(nEndPos + 4);

Reply via email to