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 0460ff325f334e78bbebf7cf46a794611ac35916 Author: Justin Luth <[email protected]> AuthorDate: Thu Nov 6 21:17:18 2025 -0500 Commit: Miklos Vajna <[email protected]> CommitDate: Mon Nov 10 08:45:46 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 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193607 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx index f100bea439c9..4869f27015a3 100644 --- a/oox/source/core/xmlfilterbase.cxx +++ b/oox/source/core/xmlfilterbase.cxx @@ -570,6 +570,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 ) { @@ -719,7 +736,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() ); @@ -737,9 +756,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 b7a31a6833bf..16d0eeeb4a55 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx @@ -815,6 +815,19 @@ CPPUNIT_TEST_FIXTURE(Test, testPersonalMetaData) assertXPath(pCoreDoc, "/cp:coreProperties/cp:revision", 0); } +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 +} + DECLARE_OOXMLEXPORT_TEST(testTdf126533_noPageBitmap, "tdf126533_noPageBitmap.docx") { // given a document with a v:background bitmap, but no w:background fillcolor
