From 40fbde8f75cbda538eccec558cdb8c0c0a659c31 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Fri, 21 Jul 2017 12:01:01 +0200 Subject: tdf#108867 sw: fix dangling text box frame format pointers in Undo If the text box is removed, the SwFrameFormat of the drawing shape still retains a pointer to the frame SwFrameFormat, and the latter is owned by the SwUndoFlyBase. This is pretty bad, so try to clear & reset the connection between them in SwUndoFlyBase::InsFly() and DelFly(). Hopefully nothing will actually delete the drawing shape SwFrameFormat while the Undo object is alive. Note that when the SwUndoInsLayFormat is created when the text box is added, the GetOtherTextBoxFormat() returns null as it's set later, that's why the constructor can't do anything. Change-Id: Iae562b6f8f272e47b2b5cf8ee80778db15d29ce0 (cherry picked from commit 2e486daff35ab16e810bfdafb24b19bcbf2fe8cd) Reviewed-on: https://gerrit.libreoffice.org/40270 Tested-by: Jenkins Reviewed-by: Miklos Vajna --- sw/inc/frmfmt.hxx | 1 + sw/source/core/undo/undobj1.cxx | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/sw/inc/frmfmt.hxx b/sw/inc/frmfmt.hxx index 2dd3c81a52f8..6c2de6c35e20 100644 --- a/sw/inc/frmfmt.hxx +++ b/sw/inc/frmfmt.hxx @@ -61,6 +61,7 @@ class SW_DLLPUBLIC SwFrameFormat: public SwFormat friend class ::sw::DocumentLayoutManager; ///< Is allowed to call protected CTor. friend class SwFrameFormats; ///< Is allowed to update the list backref. friend class SwTextBoxHelper; + friend class SwUndoFlyBase; ///< calls SetOtherTextBoxFormat css::uno::WeakReference m_wXObject; diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx index 65b6db6aad38..b401f9e9db00 100644 --- a/sw/source/core/undo/undobj1.cxx +++ b/sw/source/core/undo/undobj1.cxx @@ -52,7 +52,13 @@ SwUndoFlyBase::SwUndoFlyBase( SwFrameFormat* pFormat, SwUndoId nUndoId ) SwUndoFlyBase::~SwUndoFlyBase() { if( bDelFormat ) // delete during an Undo? + { + if (pFrameFormat->GetOtherTextBoxFormat()) + { // clear that before delete + pFrameFormat->SetOtherTextBoxFormat(nullptr); + } delete pFrameFormat; + } } void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrame) @@ -107,6 +113,13 @@ void SwUndoFlyBase::InsFly(::sw::UndoRedoContext & rContext, bool bShowSelFrame) pCNd->GetTextNode()->InsertItem(aFormat, nCntPos, nCntPos, SetAttrMode::NOHINTEXPAND); } + if (pFrameFormat->GetOtherTextBoxFormat()) + { + // recklessly assume that this thing will live longer than the + // SwUndoFlyBase - not sure what could be done if that isn't the case... + pFrameFormat->GetOtherTextBoxFormat()->SetOtherTextBoxFormat(pFrameFormat); + } + pFrameFormat->MakeFrames(); if( bShowSelFrame ) @@ -146,6 +159,11 @@ void SwUndoFlyBase::DelFly( SwDoc* pDoc ) bDelFormat = true; // delete Format in DTOR pFrameFormat->DelFrames(); // destroy Frames + if (pFrameFormat->GetOtherTextBoxFormat()) + { // tdf#108867 clear that pointer + pFrameFormat->GetOtherTextBoxFormat()->SetOtherTextBoxFormat(nullptr); + } + // all Uno objects should now log themselves off { SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, pFrameFormat ); -- cgit v1.2.3