sw/qa/core/unocore/unocore.cxx | 53 ++++++++++++++++++++++++++++++++++++++ sw/source/core/unocore/unoobj.cxx | 7 +++++ 2 files changed, 60 insertions(+)
New commits: commit 440179cfce5aafa7f480bfea48984451553f8e84 Author: László Németh <nem...@numbertext.org> AuthorDate: Tue Jun 20 19:02:20 2023 +0200 Commit: László Németh <nem...@numbertext.org> CommitDate: Wed Jun 21 10:55:19 2023 +0200 tdf#155951 sw: fix crash using XTextRange::getString() in selectionChanged() XTextRange::getString() triggered selection change event, resulting infinite recursion, when getString() used in selectionChanged() of the listener. Steps to reproduce (used by the unit test, too): Add a XSelectionChangeListener to the document with a selectionChanged() calling the getString() of the selected text range. Select a word in the document editor using the Ctrl-Shift-arrow keys. Change-Id: I87a0f60cee3663f5303d6eb6980058ccdcc373e1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153356 Tested-by: Jenkins Reviewed-by: László Németh <nem...@numbertext.org> (cherry picked from commit 0534715608aad7cc68f83ad4b72d8be0a35d0d6f) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153345 diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index a1e931e75fb4..199da2e72a79 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -15,6 +15,8 @@ #include <com/sun/star/text/XTextViewCursorSupplier.hpp> #include <com/sun/star/text/XDependentTextField.hpp> #include <com/sun/star/document/XDocumentInsertable.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/text/XTextViewCursorSupplier.hpp> #include <comphelper/propertyvalue.hxx> #include <comphelper/sequenceashashmap.hxx> @@ -912,6 +914,57 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testConvertToTextFrame) CPPUNIT_ASSERT_EQUAL(aPaM.GetPoint()->nNode, aFrame3Anchor); } +namespace +{ +/// This selection listener calls XTextRange::getString() on a selection change, which triggered +/// a new selection change event by accident, resulting infinite recursion and crash +struct SelectionChangeListener : public cppu::WeakImplHelper<view::XSelectionChangeListener> +{ +public: + SelectionChangeListener(); + // view::XSelectionChangeListener + void SAL_CALL selectionChanged(const lang::EventObject& rEvent) override; + + // lang::XEventListener + void SAL_CALL disposing(const lang::EventObject& rSource) override; +}; +} + +SelectionChangeListener::SelectionChangeListener() {} + +void SelectionChangeListener::selectionChanged(const lang::EventObject& rEvent) +{ + uno::Reference<view::XSelectionSupplier> xSelectionSupplier(rEvent.Source, uno::UNO_QUERY); + css::uno::Reference<css::container::XIndexAccess> xSelection(xSelectionSupplier->getSelection(), + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xSelection->getCount()); + css::uno::Reference<css::text::XTextRange> xTextRange(xSelection->getByIndex(0), + css::uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT(xTextRange->getString().startsWith("test")); +} + +void SelectionChangeListener::disposing(const lang::EventObject& /*rSource*/) {} + +CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testTdf155951) +{ + createSwDoc(); + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + xText->insertString(xCursor, "test", /*bAbsorb=*/false); + + uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); + uno::Reference<view::XSelectionSupplier> xController(xModel->getCurrentController(), + uno::UNO_QUERY); + xController->addSelectionChangeListener(new SelectionChangeListener()); + + // This crashed here because of infinite recursion + dispatchCommand(mxComponent, ".uno:WordLeftSel", {}); + + // this needs to wait for dispatching (trigger also a second selection change) + xText->insertString(xCursor, "test", /*bAbsorb=*/false); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx index 2e65cf97bfcd..ccbcc536a75e 100644 --- a/sw/source/core/unocore/unoobj.cxx +++ b/sw/source/core/unocore/unoobj.cxx @@ -74,6 +74,8 @@ #include <comphelper/propertyvalue.hxx> #include <comphelper/servicehelper.hxx> #include <comphelper/profilezone.hxx> +#include <comphelper/flagguard.hxx> +#include <swmodule.hxx> using namespace ::com::sun::star; @@ -158,6 +160,11 @@ void SwUnoCursorHelper::GetTextFromPam(SwPaM & rPam, OUString & rBuffer, const bool bOldShowProgress = xWrt->m_bShowProgress; xWrt->m_bShowProgress = false; xWrt->m_bHideDeleteRedlines = pLayout && pLayout->IsHideRedlines(); + // tdf#155951 SwWriter::Write calls EndAllAction, and that + // called SelectShell(), triggering selection change event, which + // resulted infinite recursion, if selectionChanged() calls + // XTextRange::getString() e.g. on the selected range. + ::comphelper::FlagRestorationGuard g(g_bNoInterrupt, true); if( ! aWriter.Write( xWrt ).IsError() ) {