Kaydet (Commit) cc5916cd authored tarafından Michael Stahl's avatar Michael Stahl

tdf#124675 sw: fix crash when moving SwTextFrame in table to prev page

The problem is that the SwTabFrame and SwRowFrame that are being
iterated are deleted:

 7 SwFrame::DestroyFrame(SwFrame*) (pFrame=0x79052c0) at sw/source/core/layout/ssfrm.cxx:386
 8 SwTabFrame::RemoveFollowFlowLine() (this=0x5bf07d0) at sw/source/core/layout/tabfrm.cxx:907
 9 SwTabFrame::MakeAll(OutputDevice*) (this=0x5bf07d0) at sw/source/core/layout/tabfrm.cxx:1839
10 SwFrame::PrepareMake(OutputDevice*) (this=0x5bf07d0) at sw/source/core/layout/calcmove.cxx:344
11 SwFrame::Calc(OutputDevice*) const (this=0x5bf07d0) at sw/source/core/layout/trvlfrm.cxx:1790
12 SwFrame::PrepareMake(OutputDevice*) (this=0x603a570) at sw/source/core/layout/calcmove.cxx:247
13 SwFrame::Calc(OutputDevice*) const (this=0x603a570) at sw/source/core/layout/trvlfrm.cxx:1790
14 SwFrame::PrepareMake(OutputDevice*) (this=0x5daf120) at sw/source/core/layout/calcmove.cxx:247
15 SwFrame::Calc(OutputDevice*) const (this=0x5daf120) at sw/source/core/layout/trvlfrm.cxx:1790
16 SwFrame::PrepareMake(OutputDevice*) (this=0x6005ca0) at sw/source/core/layout/calcmove.cxx:247
17 SwFrame::Calc(OutputDevice*) const (this=0x6005ca0) at sw/source/core/layout/trvlfrm.cxx:1790
18 SwFrame::MakePos() (this=0x6094330) at sw/source/core/layout/calcmove.cxx:490
19 SwTextFrame::MakePos() (this=0x6094330) at sw/source/core/text/frmform.cxx:343
20 SwContentFrame::MakeAll(OutputDevice*) (this=0x6094330) at sw/source/core/layout/calcmove.cxx:1346
21 SwFrame::OptPrepareMake() (this=0x6094330) at sw/source/core/layout/calcmove.cxx:368
22 SwFrame::OptCalc() const (this=0x6094330) at sw/source/core/inc/frame.hxx:1060
23 SwLayAction::FormatLayout(OutputDevice*, SwLayoutFrame*, bool) (this=0x7ffc6da48350, pLay=0x8a349c0, bAddRect=false) at sw/source/core/layout/layact.cxx:1362
24 SwLayAction::FormatLayout(OutputDevice*, SwLayoutFrame*, bool) (this=0x7ffc6da48350, pLay=0x79052c0, bAddRect=false) at sw/source/core/layout/layact.cxx:1357
25 SwLayAction::FormatLayoutTab(SwTabFrame*, bool) (this=0x7ffc6da48350, pTab=0x7a9c300, bAddRect=false) at sw/source/core/layout/layact.cxx:1569
26 SwLayAction::FormatLayout(OutputDevice*, SwLayoutFrame*, bool) (this=0x7ffc6da48350, pLay=0x7c30300, bAddRect=true) at sw/source/core/layout/layact.cxx:1354
27 SwLayAction::FormatLayout(OutputDevice*, SwLayoutFrame*, bool) (this=0x7ffc6da48350, pLay=0x79e1780, bAddRect=true) at sw/source/core/layout/layact.cxx:1357
28 SwLayAction::InternalAction(OutputDevice*) (this=0x7ffc6da48350) at sw/source/core/layout/layact.cxx:546

They are deleted because the last SwTextFrame was moved via MoveBwd() to
the previous page, and is formatted there.
(regression from commit 18765b9f)

Prevent this via:

* delete-guard for the SwRowFrame - causing RemoveFollowFlowLine() to
  return early (also, let it return false, so the Join() isn't even
  called, although that doesn't make a difference in practice because
  of the next item:)

* join-guard for the SwTabFrame - otherwise tabfrm.cxx:2199 will Join()
  it anyway

This means that when the page with the follow-frame is done formatting,
the empty SwTabFrame with no SwTextFrame in it will remain.  Fortunately
this is not a problem, because due to the moving, the previous page will
be invalid and layact.cxx:613 will iterate to the previous page and
format it again; then tabfrm:2199 of the master SwTabFrame will detect
that the follow SwTabFrame is empty and Join() it.

Change-Id: I2cca89d63b81e7d4909319fa4feab2f5d67a6ff3
Reviewed-on: https://gerrit.libreoffice.org/71996
Tested-by: Jenkins
Reviewed-by: 's avatarMichael Stahl <Michael.Stahl@cib.de>
üst f8b4d371
......@@ -1582,9 +1582,11 @@ bool SwLayAction::FormatLayoutTab( SwTabFrame *pTab, bool bAddRect )
// format lowers, only if table frame is valid
if ( pTab->isFrameAreaDefinitionValid() )
{
FlowFrameJoinLockGuard tabG(pTab); // tdf#124675 prevent Join() if pTab becomes empty
SwLayoutFrame *pLow = static_cast<SwLayoutFrame*>(pTab->Lower());
while ( pLow )
{
SwFrameDeleteGuard rowG(pLow); // tdf#124675 prevent RemoveFollowFlowLine()
bChanged |= FormatLayout( m_pImp->GetShell()->GetOut(), pLow, bAddRect );
if ( IsAgain() )
return false;
......
......@@ -859,7 +859,7 @@ bool SwTabFrame::RemoveFollowFlowLine()
if (pFollowFlowLine->IsDeleteForbidden())
{
SAL_WARN("sw.layout", "Cannot remove in-use Follow Flow Line");
return true;
return false;
}
// Move content
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment