diff options
author | Michael Stahl <Michael.Stahl@cib.de> | 2019-06-21 16:48:08 +0200 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-06-24 16:15:22 +0200 |
commit | 1914932e2fd0598508823464765f3b1ac31236a1 (patch) | |
tree | 98b735a8505c6cf883f1db0884d130c1c11c7176 /sw | |
parent | 955add820ecc160647657de308492a0650527221 (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.cxx | 30 |
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); } |