framework/qa/cppunit/data/empty.fodp  |    2 ++
 framework/qa/cppunit/dispatchtest.cxx |   32 ++++++++++++++++++++++++++++++++
 sfx2/inc/unoctitm.hxx                 |    7 ++++++-
 sfx2/source/control/unoctitm.cxx      |   21 +++++++++++++++++++++
 4 files changed, 61 insertions(+), 1 deletion(-)

New commits:
commit 7cbd6d768d282077053c354254315f3dc89bf254
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Jun 30 13:26:59 2021 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed Jun 30 18:40:27 2021 +0200

    sfx2: try to fix lifecycle of SfxOfficeDispatch
    
    This can be created either from the global SfxApplication, or from a
    SfxViewFrame.
    
    Particularly in the latter case, the SfxDispatcher and SfxBindings
    members are owned by SfxViewFrame, so in case that is destroyed, the
    SfxOfficeDispatch must clear its pointers.
    
    It looks like the member pointers are checked before access already
    everywhere, so just listen at the SfxViewFrame.
    
    Change-Id: If08825734e94dd54e32cb77546684fd583c336ec
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118162
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/framework/qa/cppunit/data/empty.fodp 
b/framework/qa/cppunit/data/empty.fodp
new file mode 100644
index 000000000000..3c2a4cf2cda5
--- /dev/null
+++ b/framework/qa/cppunit/data/empty.fodp
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
office:version="1.2" 
office:mimetype="application/vnd.oasis.opendocument.presentation"><office:body><office:presentation><draw:page/></office:presentation></office:body></office:document>
diff --git a/framework/qa/cppunit/dispatchtest.cxx 
b/framework/qa/cppunit/dispatchtest.cxx
index 586c4af3b9b0..2f21a71b005e 100644
--- a/framework/qa/cppunit/dispatchtest.cxx
+++ b/framework/qa/cppunit/dispatchtest.cxx
@@ -15,6 +15,7 @@
 #include <com/sun/star/frame/DispatchHelper.hpp>
 #include <com/sun/star/frame/XDispatchProviderInterceptor.hpp>
 #include <com/sun/star/frame/XInterceptorInfo.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
 
 #include <comphelper/processfactory.hxx>
 #include <rtl/ref.hxx>
@@ -199,6 +200,37 @@ CPPUNIT_TEST_FIXTURE(DispatchTest, testInterception)
     // This was 1: MyInterceptor::queryDispatch() was called for .uno:Italic.
     CPPUNIT_ASSERT_EQUAL(0, pInterceptor->getUnexpected());
 }
+
+constexpr OUStringLiteral DATA_DIRECTORY = u"/framework/qa/cppunit/data/";
+
+CPPUNIT_TEST_FIXTURE(DispatchTest, testSfxOfficeDispatchDispose)
+{
+    // this test doesn't work with a new document because of aURL.Main check 
in SfxBaseController::dispatch()
+    mxComponent = loadFromDesktop(m_directories.getURLFromSrc(DATA_DIRECTORY) 
+ "empty.fodp",
+                                  
"com.sun.star.presentation.PresentationDocument");
+    uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xModel.is());
+    uno::Reference<frame::XController> 
xController(xModel->getCurrentController());
+    CPPUNIT_ASSERT(xController.is());
+    uno::Reference<frame::XDispatchProvider> xFrame(xController->getFrame(), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT(xFrame.is());
+
+    uno::Reference<util::XURLTransformer> 
xParser(util::URLTransformer::create(mxComponentContext));
+    util::URL url;
+    url.Complete = xModel->getURL() + "#dummy";
+    xParser->parseStrict(url);
+
+    uno::Reference<frame::XDispatch> xDisp(xFrame->queryDispatch(url, "", 0));
+    CPPUNIT_ASSERT(xDisp.is());
+
+    mxComponent->dispose();
+
+    util::URL urlSlot;
+    urlSlot.Complete = "slot:5598";
+    xParser->parseStrict(urlSlot);
+    // crashed with UAF
+    xDisp->dispatch(urlSlot, {});
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sfx2/inc/unoctitm.hxx b/sfx2/inc/unoctitm.hxx
index 805ff22b3124..9e6bc19da488 100644
--- a/sfx2/inc/unoctitm.hxx
+++ b/sfx2/inc/unoctitm.hxx
@@ -25,6 +25,7 @@
 #include <cppuhelper/interfacecontainer.hxx>
 #include <cppuhelper/weakref.hxx>
 
+#include <svl/lstner.hxx>
 #include <sfx2/ctrlitem.hxx>
 #include <osl/mutex.hxx>
 
@@ -101,7 +102,9 @@ public:
     SfxDispatcher*          GetDispatcher_Impl();
 };
 
-class SfxDispatchController_Impl final : public SfxControllerItem
+class SfxDispatchController_Impl final
+    : public SfxControllerItem
+    , public SfxListener
 {
     css::util::URL              aDispatchURL;
     SfxDispatcher*              pDispatcher;
@@ -126,6 +129,8 @@ public:
                                                     const css::util::URL& rURL 
);
                         virtual ~SfxDispatchController_Impl() override;
 
+    virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
+
     static OUString getSlaveCommand( const css::util::URL& rURL );
 
     void                StateChanged( sal_uInt16 nSID, SfxItemState eState, 
const SfxPoolItem* pState, SfxSlotServer const * pServ );
diff --git a/sfx2/source/control/unoctitm.cxx b/sfx2/source/control/unoctitm.cxx
index 50034333bcd5..58bdc6179008 100644
--- a/sfx2/source/control/unoctitm.cxx
+++ b/sfx2/source/control/unoctitm.cxx
@@ -323,6 +323,27 @@ SfxDispatchController_Impl::SfxDispatchController_Impl(
         BindInternal_Impl( nSlot, pBindings );
         pBindings->LEAVEREGISTRATIONS();
     }
+    assert(pDispatcher);
+    assert(SfxApplication::Get()->GetAppDispatcher_Impl() == pDispatcher
+        || pDispatcher->GetFrame() != nullptr);
+    if (pDispatcher->GetFrame())
+    {
+        StartListening(*pDispatcher->GetFrame());
+    }
+    else
+    {
+        StartListening(*SfxApplication::Get());
+    }
+}
+
+void SfxDispatchController_Impl::Notify(SfxBroadcaster& rBC, SfxHint const& 
rHint)
+{
+    if (rHint.GetId() == SfxHintId::Dying)
+    {   // both pBindings and pDispatcher are dead if SfxViewFrame is dead
+        pBindings = nullptr;
+        pDispatcher = nullptr;
+        EndListening(rBC);
+    }
 }
 
 SfxDispatchController_Impl::~SfxDispatchController_Impl()
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to