oox/source/core/xmlfilterbase.cxx                         |   31 ++++++++++++--
 sw/qa/extras/ooxmlexport/data/tdf169072_illegalDates.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport21.cxx                |   13 +++++
 3 files changed, 40 insertions(+), 4 deletions(-)

New commits:
commit 4e472c35a83d5c3c89948811bdd8fcac5e335d85
Author:     Justin Luth <[email protected]>
AuthorDate: Thu Nov 6 21:17:18 2025 -0500
Commit:     Xisco Fauli <[email protected]>
CommitDate: Mon Nov 10 11:04:18 2025 +0100

    tdf#169072 ms export: valid date years are 1601 - 9999
    
    The dates in core.xml must fall in the range of 1601 - 9999.
    
    This applies to all docx files,
    and ECMA_376_1ST_EDITION (2007) versions of the other formats.
    
    No existing unit tests had ANY dates outside of that range.
    
    make CppunitTest_sw_ooxmlexport21 \
        CPPUNIT_TEST_NAME=testTdf169072_illegalDates
    
    Change-Id: Ic2c81d13a1a8ed9d2ce29f7fea761900aa2f2d20
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193552
    Reviewed-by: Justin Luth <[email protected]>
    Tested-by: Jenkins
    (cherry picked from commit 63bac9055e2e81e238af885c289e99b733d86d7a)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193724
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git a/oox/source/core/xmlfilterbase.cxx 
b/oox/source/core/xmlfilterbase.cxx
index f2d51de6c0e4..85defeea3dfd 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -566,6 +566,23 @@ OUString XmlFilterBase::addRelation( const Reference< 
XOutputStream >& rOutputSt
     return OUString();
 }
 
+static bool lcl_isValidDate(const util::DateTime& rTime, XmlFilterBase& rSelf)
+{
+    if (rTime.Year == 0)
+        return false;
+
+    // MS Office reports document as corrupt if core.xml contains any Year <= 
1600 or > 9999
+    // for the "package" URI (ECMA_376_1ST_EDITION or docx).
+    if (rTime.Year > 1600  && rTime.Year < 10000)
+        return true;
+
+    const bool bDocx = 
dynamic_cast<text::XTextDocument*>(rSelf.getModel().get());
+    if (bDocx || rSelf.getVersion() == oox::core::ECMA_376_1ST_EDITION)
+        return false;
+
+    return true;
+}
+
 static void
 writeElement( const FSHelperPtr& pDoc, sal_Int32 nXmlElement, 
std::u16string_view sValue )
 {
@@ -690,7 +707,9 @@ writeCoreProperties( XmlFilterBase& rSelf, const Reference< 
XDocumentProperties
     }
     if (!bRemoveUserInfo)
     {
-        writeElement(pCoreProps, FSNS(XML_dcterms, XML_created), 
xProperties->getCreationDate());
+        const util::DateTime aCreateDate = xProperties->getCreationDate();
+        if (lcl_isValidDate(aCreateDate, rSelf))
+            writeElement(pCoreProps, FSNS(XML_dcterms, XML_created), 
aCreateDate);
         writeElement(pCoreProps, FSNS(XML_dc, XML_creator), 
xProperties->getAuthor());
     }
     writeElement( pCoreProps, FSNS( XML_dc, XML_description ),      
xProperties->getDescription() );
@@ -708,9 +727,13 @@ writeCoreProperties( XmlFilterBase& rSelf, const 
Reference< XDocumentProperties
     if (!bRemoveUserInfo)
     {
         writeElement(pCoreProps, FSNS(XML_cp, XML_lastModifiedBy), 
xProperties->getModifiedBy());
-        writeElement(pCoreProps, FSNS(XML_cp, XML_lastPrinted), 
xProperties->getPrintDate());
-        writeElement(pCoreProps, FSNS(XML_dcterms, XML_modified),
-                     xProperties->getModificationDate());
+        const util::DateTime aPrintDate = xProperties->getPrintDate();
+        if (lcl_isValidDate(aPrintDate, rSelf))
+            writeElement(pCoreProps, FSNS(XML_cp, XML_lastPrinted), 
aPrintDate);
+
+        const util::DateTime aModifyDate = xProperties->getModificationDate();
+        if (lcl_isValidDate(aModifyDate, rSelf))
+            writeElement(pCoreProps, FSNS(XML_dcterms, XML_modified), 
aModifyDate);
     }
     if (!bRemovePersonalInfo)
     {
diff --git a/sw/qa/extras/ooxmlexport/data/tdf169072_illegalDates.docx 
b/sw/qa/extras/ooxmlexport/data/tdf169072_illegalDates.docx
new file mode 100644
index 000000000000..f3e7970c5621
Binary files /dev/null and 
b/sw/qa/extras/ooxmlexport/data/tdf169072_illegalDates.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
index 4ce0bdc00361..5ee973c1ebb6 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
@@ -820,6 +820,19 @@ CPPUNIT_TEST_FIXTURE(Test, testPersonalMetaData)
     pBatch->commit();
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf169072_illegalDates)
+{
+    // Given a document that MS Word reports as corrupt
+    loadAndSave("tdf169072_illegalDates.docx");
+
+    // Date Years MUST be greater than 1600 and less than 10,000
+    // so by dropping invalid entries, we have a document that MS Word can now 
cleanly open
+    xmlDocUniquePtr pXmlCore = parseExport(u"docProps/core.xml"_ustr);
+    assertXPathContent(pXmlCore, "/cp:coreProperties/dcterms:created", 
u"9999-10-10T13:07:54Z");
+    assertXPathContent(pXmlCore, "/cp:coreProperties/dcterms:modified", 
u"1601-01-01T13:09:08Z");
+    assertXPath(pXmlCore, "/cp:coreProperties/cp:lastPrinted", 0); // was 
1600-12-31T00:00:52Z
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testRemoveOnlyEditTimeMetaData)
 {
     // 1. Check we have the original edit time info

Reply via email to