summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2019-06-21 16:48:08 +0200
committerCaolán McNamara <caolanm@redhat.com>2019-06-24 16:15:22 +0200
commit1914932e2fd0598508823464765f3b1ac31236a1 (patch)
tree98b735a8505c6cf883f1db0884d130c1c11c7176 /sw
parent955add820ecc160647657de308492a0650527221 (diff)
tdf#125741 sw: avoid joining table frames in SwFrame::PrepareCursor()
The problem is that the PrepareCursor() is called on a frame in a nested table, and the inner table is joined by its predecessor... 0x6120010a3348 is located 136 bytes inside of 296-byte region [0x6120010a32c0,0x6120010a33e8) freed by thread T0 here: #1 SwTabFrame::~SwTabFrame() sw/source/core/layout/tabfrm.cxx:143:1 #2 SwFrame::DestroyFrame(SwFrame*) sw/source/core/layout/ssfrm.cxx:389:9 #3 SwTabFrame::Join() sw/source/core/layout/tabfrm.cxx:1379:9 #4 SwTabFrame::MakeAll(OutputDevice*) sw/source/core/layout/tabfrm.cxx:1870:9 #5 SwFrame::PrepareMake(OutputDevice*) sw/source/core/layout/calcmove.cxx:364:5 #6 SwFrame::Calc(OutputDevice*) const sw/source/core/layout/trvlfrm.cxx:1791:37 #7 lcl_InnerCalcLayout(SwFrame*, long, bool) sw/source/core/layout/tabfrm.cxx:1584:21 #8 lcl_InnerCalcLayout(SwFrame*, long, bool) sw/source/core/layout/tabfrm.cxx:1586:25 #9 lcl_InnerCalcLayout(SwFrame*, long, bool) sw/source/core/layout/tabfrm.cxx:1586:25 #10 lcl_RecalcRow(SwRowFrame*, long) sw/source/core/layout/tabfrm.cxx:1621:16 #11 SwTabFrame::MakeAll(OutputDevice*) sw/source/core/layout/tabfrm.cxx:2410:21 #12 SwFrame::PrepareMake(OutputDevice*) sw/source/core/layout/calcmove.cxx:364:5 #13 SwFrame::Calc(OutputDevice*) const sw/source/core/layout/trvlfrm.cxx:1791:37 #14 SwFrame::PrepareCursor() sw/source/core/layout/calcmove.cxx:481:5 #15 SwFrame::PrepareCursor() sw/source/core/layout/calcmove.cxx:397:21 #16 SwFrame::PrepareCursor() sw/source/core/layout/calcmove.cxx:397:21 #17 SwFrame::PrepareCursor() sw/source/core/layout/calcmove.cxx:397:21 #18 SwFrame::PrepareCursor() sw/source/core/layout/calcmove.cxx:397:21 #19 SwFrame::PrepareCursor() sw/source/core/layout/calcmove.cxx:397:21 #20 SwFrame::PrepareCursor() sw/source/core/layout/calcmove.cxx:397:21 #21 SwCursorShell::UpdateCursor(unsigned short, bool) sw/source/core/crsr/crsrsh.cxx:1851:25 #22 SwCursorShell::EndAction(bool, bool) sw/source/core/crsr/crsrsh.cxx:269:5 #23 SwCursorShell::EndCursorMove(bool) sw/source/core/crsr/crsrsh.cxx:305:5 #24 SwLayIdle::SwLayIdle(SwRootFrame*, SwViewShellImp*) sw/source/core/layout/layact.cxx:2238:35 After the paste, the formatting goes only until SwLayAction::IsShortCut() exits early because the previous visible page is formatted - but the cursor position was moved downward and is no longer visible, so we get an idle-layout later where UpdateCursor() triggers more formatting... So prevent the use-after-free with some more guards, which isn't the most elegant solution, but with 4 levels of nested tables elegant solutions are in short supply... (apparently a regression from the SwFlowFrame::MoveBwd() change in 18765b9fa739337d2d891513f6e2fb7c3ce23b50) Change-Id: Ie166d3b58fe84c3e4808b52202802a471fa81026 Reviewed-on: https://gerrit.libreoffice.org/74518 Tested-by: Jenkins Reviewed-by: Michael Stahl <Michael.Stahl@cib.de> (cherry picked from commit a23661bfe02d81bd9c1f1e04c59384d19cc61726) Reviewed-on: https://gerrit.libreoffice.org/74632 Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sw')
-rw-r--r--sw/source/core/layout/calcmove.cxx30
1 files changed, 16 insertions, 14 deletions
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx
index 871f77a2f96e..6e6c3e500543 100644
--- a/sw/source/core/layout/calcmove.cxx
+++ b/sw/source/core/layout/calcmove.cxx
@@ -393,32 +393,37 @@ void SwFrame::PrepareCursor()
StackHack aHack;
if( GetUpper() && !GetUpper()->IsSctFrame() )
{
- GetUpper()->PrepareCursor();
- GetUpper()->Calc(getRootFrame()->GetCurrShell() ? getRootFrame()->GetCurrShell()->GetOut() : nullptr);
-
- OSL_ENSURE( GetUpper(), ":-( Layout unstable (Upper gone)." );
- if ( !GetUpper() )
- return;
-
const bool bCnt = IsContentFrame();
const bool bTab = IsTabFrame();
bool bNoSect = IsInSct();
- bool bOldTabLock = false, bFoll;
+ boost::optional<FlowFrameJoinLockGuard> tabGuard;
+ boost::optional<SwFrameDeleteGuard> rowGuard;
SwFlowFrame* pThis = bCnt ? static_cast<SwContentFrame*>(this) : nullptr;
if ( bTab )
{
- bOldTabLock = static_cast<SwTabFrame*>(this)->IsJoinLocked();
- ::PrepareLock( static_cast<SwTabFrame*>(this) );
+ tabGuard.emplace(static_cast<SwTabFrame*>(this)); // tdf#125741
pThis = static_cast<SwTabFrame*>(this);
}
+ else if (IsRowFrame())
+ {
+ rowGuard.emplace(this); // tdf#125741 keep this alive
+ }
else if( IsSctFrame() )
{
pThis = static_cast<SwSectionFrame*>(this);
bNoSect = false;
}
- bFoll = pThis && pThis->IsFollow();
+
+ GetUpper()->PrepareCursor();
+ GetUpper()->Calc(getRootFrame()->GetCurrShell() ? getRootFrame()->GetCurrShell()->GetOut() : nullptr);
+
+ OSL_ENSURE( GetUpper(), ":-( Layout unstable (Upper gone)." );
+ if ( !GetUpper() )
+ return;
+
+ bool const bFoll = pThis && pThis->IsFollow();
SwFrame *pFrame = GetUpper()->Lower();
while ( pFrame != this )
@@ -473,9 +478,6 @@ void SwFrame::PrepareCursor()
GetUpper()->Calc(getRootFrame()->GetCurrShell()->GetOut());
OSL_ENSURE( GetUpper(), "Layout unstable (Upper gone III)." );
-
- if ( bTab && !bOldTabLock )
- ::PrepareUnlock( static_cast<SwTabFrame*>(this) );
}
Calc(getRootFrame()->GetCurrShell() ? getRootFrame()->GetCurrShell()->GetOut() : nullptr);
}