[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - sc/inc sc/qa sc/source
Miklos Vajna (via logerrit)
logerrit at kemper.freedesktop.org
Thu Jul 8 06:39:59 UTC 2021
sc/inc/address.hxx | 26 +++++++++++++-------------
sc/qa/unit/data/xlsx/invalid-named-range.xlsx |binary
sc/qa/unit/subsequent_export-test.cxx | 19 +++++++++++++++++++
sc/source/filter/inc/defnamesbuffer.hxx | 1 +
sc/source/filter/oox/defnamesbuffer.cxx | 22 ++++++++++++++++++++++
5 files changed, 55 insertions(+), 13 deletions(-)
New commits:
commit 4873bb10c136a503be00bd73d1e7c4ec66e9a10c
Author: Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Mon Jul 5 12:29:18 2021 +0200
Commit: Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 8 08:39:26 2021 +0200
XLSX import: fix handling of named ranges referring to PathMissing sheets
In case xl/externalLinks/externalLink1.xml refers to a sheet where type
is PathMissing, then both <sheetName> and <sheetData> gets ignored on
import. Make sure to also ignore named ranges referring to such external
documents.
The resulting named range was just a string anyway, and exporting this
back to XLSX results in Excel marking the whole file as corrupted.
(cherry picked from commit db1c8df98a23d687d6806f371bdd416dd1b84589)
Conflicts:
sc/qa/unit/subsequent_export-test2.cxx
Change-Id: Ifde07b5e59fba371f1f8ab3e82861c6997c6dbf0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118551
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
Reviewed-by: Luboš Luňák <l.lunak at collabora.com>
diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx
index 4b2ad09691ba..8f3b6830e030 100644
--- a/sc/inc/address.hxx
+++ b/sc/inc/address.hxx
@@ -494,7 +494,7 @@ inline bool ValidAddress( const ScAddress& rAddress, SCCOL nMaxCol = MAXCOL, SCR
}
// ScRange
-class SAL_WARN_UNUSED ScRange final
+class SAL_WARN_UNUSED SC_DLLPUBLIC ScRange final
{
public:
ScAddress aStart;
@@ -551,18 +551,18 @@ public:
inline bool In( const ScAddress& ) const; ///< is Address& in Range?
inline bool In( const ScRange& ) const; ///< is Range& in Range?
- SC_DLLPUBLIC ScRefFlags Parse( const OUString&, const ScDocument&,
+ ScRefFlags Parse( const OUString&, const ScDocument&,
const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
ScAddress::ExternalInfo* pExtInfo = nullptr,
const css::uno::Sequence<css::sheet::ExternalLinkInfo>* pExternalLinks = nullptr,
const OUString* pErrRef = nullptr );
- SC_DLLPUBLIC ScRefFlags ParseAny( const OUString&, const ScDocument&,
+ ScRefFlags ParseAny( const OUString&, const ScDocument&,
const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
- SC_DLLPUBLIC ScRefFlags ParseCols( const ScDocument& rDoc,
+ ScRefFlags ParseCols( const ScDocument& rDoc,
const OUString&,
const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
- SC_DLLPUBLIC void ParseRows( const ScDocument& rDoc,
+ void ParseRows( const ScDocument& rDoc,
const OUString&,
const ScAddress::Details& rDetails = ScAddress::detailsOOOa1 );
@@ -614,14 +614,14 @@ public:
@returns
String contains formatted cell range in address convention
*/
- SC_DLLPUBLIC OUString Format( const ScDocument& rDocument,
+ OUString Format( const ScDocument& rDocument,
ScRefFlags nFlags = ScRefFlags::ZERO,
const ScAddress::Details& rDetails = ScAddress::detailsOOOa1,
bool bFullAddressNotation = false ) const;
inline void GetVars( SCCOL& nCol1, SCROW& nRow1, SCTAB& nTab1,
SCCOL& nCol2, SCROW& nRow2, SCTAB& nTab2 ) const;
- SC_DLLPUBLIC void PutInOrder();
+ void PutInOrder();
/**
@param rErrorRange
@@ -630,18 +630,18 @@ public:
@param pDocument
The document for the maximum defined sheet number.
*/
- [[nodiscard]] SC_DLLPUBLIC bool Move( SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
+ [[nodiscard]] bool Move( SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
ScRange& rErrorRange, const ScDocument* pDocument = nullptr );
/** Same as Move() but with sticky end col/row anchors. */
- [[nodiscard]] SC_DLLPUBLIC bool MoveSticky( const ScDocument& rDoc, SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
+ [[nodiscard]] bool MoveSticky( const ScDocument& rDoc, SCCOL aDeltaX, SCROW aDeltaY, SCTAB aDeltaZ,
ScRange& rErrorRange );
- SC_DLLPUBLIC void IncColIfNotLessThan(const ScDocument& rDoc, SCCOL nStartCol, SCCOL nOffset);
- SC_DLLPUBLIC void IncRowIfNotLessThan(const ScDocument& rDoc, SCROW nStartRow, SCROW nOffset);
+ void IncColIfNotLessThan(const ScDocument& rDoc, SCCOL nStartCol, SCCOL nOffset);
+ void IncRowIfNotLessThan(const ScDocument& rDoc, SCROW nStartRow, SCROW nOffset);
- SC_DLLPUBLIC void ExtendTo( const ScRange& rRange );
- SC_DLLPUBLIC bool Intersects( const ScRange& rRange ) const; // do two ranges intersect?
+ void ExtendTo( const ScRange& rRange );
+ bool Intersects( const ScRange& rRange ) const; // do two ranges intersect?
ScRange Intersection( const ScRange& rOther ) const;
diff --git a/sc/qa/unit/data/xlsx/invalid-named-range.xlsx b/sc/qa/unit/data/xlsx/invalid-named-range.xlsx
new file mode 100644
index 000000000000..53feabec382f
Binary files /dev/null and b/sc/qa/unit/data/xlsx/invalid-named-range.xlsx differ
diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx
index 3b5e3903290a..f75b81c1a277 100644
--- a/sc/qa/unit/subsequent_export-test.cxx
+++ b/sc/qa/unit/subsequent_export-test.cxx
@@ -283,6 +283,7 @@ public:
void testTdf139258_rotated_image();
void testCheckboxFormControlXlsxExport();
void testButtonFormControlXlsxExport();
+ void testInvalidNamedRange();
CPPUNIT_TEST_SUITE(ScExportTest);
CPPUNIT_TEST(test);
@@ -464,6 +465,7 @@ public:
CPPUNIT_TEST(testTdf139258_rotated_image);
CPPUNIT_TEST(testCheckboxFormControlXlsxExport);
CPPUNIT_TEST(testButtonFormControlXlsxExport);
+ CPPUNIT_TEST(testInvalidNamedRange);
CPPUNIT_TEST_SUITE_END();
@@ -5894,6 +5896,23 @@ void ScExportTest::testButtonFormControlXlsxExport()
assertXPathContent(pDoc, "//x:anchor/x:to/xdr:row", "7");
}
+void ScExportTest::testInvalidNamedRange()
+{
+ // Given a document which has a named range (myname) that refers to the "1" external link, but
+ // the link's type is xlPathMissing, when importing that document:
+ ScDocShellRef xDocSh = loadDoc(u"invalid-named-range.", FORMAT_XLSX);
+ CPPUNIT_ASSERT(xDocSh.is());
+
+ // Then make sure that named range is ignored, as "1" can't be resolved, and exporting it back
+ // to XLSX (without the xlPathMissing link) would corrupt the document:
+ uno::Reference<beans::XPropertySet> xDocProps(xDocSh->GetModel(), uno::UNO_QUERY);
+ uno::Reference<container::XNameAccess> xNamedRanges(xDocProps->getPropertyValue("NamedRanges"),
+ uno::UNO_QUERY);
+ // Without the fix in place, this test would have failed, we didn't ignore the problematic named
+ // range on import.
+ CPPUNIT_ASSERT(!xNamedRanges->hasByName("myname"));
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/filter/inc/defnamesbuffer.hxx b/sc/source/filter/inc/defnamesbuffer.hxx
index 77ee38fd5ccb..67c5930682ae 100644
--- a/sc/source/filter/inc/defnamesbuffer.hxx
+++ b/sc/source/filter/inc/defnamesbuffer.hxx
@@ -118,6 +118,7 @@ public:
sal_Int32 getTokenIndex() const { return mnTokenIndex; }
/** Tries to resolve the defined name to an absolute cell range. */
bool getAbsoluteRange( ScRange& orRange ) const;
+ bool isValid(const css::uno::Sequence<css::sheet::ExternalLinkInfo>& rExternalLinks) const;
private:
typedef ::std::unique_ptr< StreamDataSequence > StreamDataSeqPtr;
diff --git a/sc/source/filter/oox/defnamesbuffer.cxx b/sc/source/filter/oox/defnamesbuffer.cxx
index 733d4790f8ff..769e36f24939 100644
--- a/sc/source/filter/oox/defnamesbuffer.cxx
+++ b/sc/source/filter/oox/defnamesbuffer.cxx
@@ -238,6 +238,23 @@ void DefinedName::createNameObject( sal_Int32 nIndex )
mnTokenIndex = nIndex;
}
+bool DefinedName::isValid(
+ const css::uno::Sequence<css::sheet::ExternalLinkInfo>& rExternalLinks) const
+{
+ ScRange aRange;
+ OUString aExternDocName;
+ OUString aStartTabName;
+ OUString aEndTabName;
+ ScRefFlags nFlags = ScRefFlags::VALID | ScRefFlags::TAB_VALID;
+ aRange.Parse_XL_Header(maModel.maFormula.getStr(), getScDocument(), aExternDocName,
+ aStartTabName, aEndTabName, nFlags, /*bOnlyAcceptSingle=*/false,
+ &rExternalLinks);
+ // aExternDocName is something like 'file:///path/to/my.xlsx' in the valid case, and it's an int
+ // when it's invalid.
+ bool bInvalidExternalRef = aExternDocName.toInt32() > 0;
+ return !bInvalidExternalRef;
+}
+
std::unique_ptr<ScTokenArray> DefinedName::getScTokens(
const css::uno::Sequence<css::sheet::ExternalLinkInfo>& rExternalLinks )
{
@@ -356,6 +373,11 @@ void DefinedNamesBuffer::finalizeImport()
int index = 0;
for( DefinedNameRef& xDefName : maDefNames )
{
+ if (!xDefName->isValid(getExternalLinks().getLinkInfos()))
+ {
+ continue;
+ }
+
xDefName->createNameObject( ++index );
// map by sheet index and original model name
maModelNameMap[ SheetNameKey( xDefName->getLocalCalcSheet(), xDefName->getUpcaseModelName() ) ] = xDefName;
More information about the Libreoffice-commits
mailing list