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

tdf#108991 sw: fix crash due to not formatted but "valid" SwTextFrame

SwTextNode::EraseText() on the paragraph at the start of the
selection notifies the SwTextFrame:

0  in SwFrame::ImplInvalidateSize() (this=0x3088a20) at sw/source/core/layout/wsfrm.cxx:1568
1  in SwFrame::InvalidateSize() (this=0x3088a20) at sw/source/core/inc/frame.hxx:849
2  in SwTextFrame::InvalidateRange_(SwCharRange const&, long) (this=0x3088a20, aRange=..., nD=-62) at sw/source/core/text/txtfrm.cxx:741
3  in SwTextFrame::InvalidateRange(SwCharRange const&, long) (this=0x3088a20, aRange=..., nD=-62) at sw/source/core/text/txtfrm.cxx:708
4  in SwTextFrame::Modify(SfxPoolItem const*, SfxPoolItem const*) (this=0x3088a20, pOld=0x0, pNew=0x7ffc8da38c50) at sw/source/core/text/txtfrm.cxx:1005
5  in SwClient::SwClientNotify(SwModify const&, SfxHint const&) (this=0x3088a20, rHint=...) at sw/source/core/attr/calbck.cxx:67
6  in SwModify::CallSwClientNotify(SfxHint const&) const (this=0x2f05550, rHint=...) at sw/inc/calbck.hxx:355
7  in SwModify::ModifyBroadcast(SfxPoolItem const*, SfxPoolItem const*) (this=0x2f05550, pOldValue=0x0, pNewValue=0x7ffc8da38c50) at sw/inc/calbck.hxx:176
8  in SwModify::NotifyClients(SfxPoolItem const*, SfxPoolItem const*) (this=0x2f05550, pOldValue=0x0, pNewValue=0x7ffc8da38c50) at sw/source/core/attr/calbck.cxx:142
9  in SwTextNode::EraseText(SwIndex const&, int, SwInsertFlags) (this=0x2f05550, rIdx=SwIndex (offset 1), nCount=62, nMode=SwInsertFlags::DEFAULT) at sw/source/core/txtnode/ndtxt.cxx:2355
10 in SwUndoDelete::SaveContent(SwPosition const*, SwPosition const*, SwTextNode*, SwTextNode*) (this=0x3052950, pStt=0x7ffc8da390b8, pEnd=0x7ffc8da39100, pSttTextNd=0x2f05550, pEndTextNd=0x2faefe0) at sw/source/core/undo/undel.cxx:387

However, at this point the first page, which contains this paragraph, is
not visible; so the Action that is created in ViewShell::ImplEndAction()
will skip over the first page and start at the 2nd page, which is the
first visible one.

Now it happens that the last paragraph in the document has a page break
on it, and formatting it causes it to move forward (a new page to be
inserted and the empty 2nd page to be deleted).

Unfortunately it then decides to reset the mbValidSize flag on the
preceding SwTextFrame, assuming that it was set by its own moving
forward, and not already set before.

0  in ValidateSz(SwFrame*) (pFrame=0x3088a20) at sw/source/core/layout/calcmove.cxx:1082
1  in SwContentFrame::MakeAll(OutputDevice*) (this=0x308b4a0) at sw/source/core/layout/calcmove.cxx:1276
2  in SwFrame::PrepareMake(OutputDevice*) (this=0x308b4a0, pRenderContext=0x306f850) at sw/source/core/layout/calcmove.cxx:346
3  in SwFrame::Calc(OutputDevice*) const (this=0x308b4a0, pRenderContext=0x306f850) at sw/source/core/layout/trvlfrm.cxx:1760
4  in SwLayAction::IsShortCut(SwPageFrame*&) (this=0x7ffc8da394a0, prPage=@0x7ffc8da392b8: 0x7491e30) at sw/source/core/layout/layact.cxx:1085
5  in SwLayAction::InternalAction(OutputDevice*) (this=0x7ffc8da394a0, pRenderContext=0x306f850) at sw/source/core/layout/layact.cxx:490
6  in SwLayAction::Action(OutputDevice*) (this=0x7ffc8da394a0, pRenderContext=0x306f850) at sw/source/core/layout/layact.cxx:351
7  in SwViewShell::ImplEndAction(bool) (this=0x30829c0, bIdleEnd=false) at sw/source/core/view/viewsh.cxx:278
8  in SwViewShell::EndAction(bool) (this=0x30829c0, bIdleEnd=false) at sw/inc/viewsh.hxx:605
9  in SwCursorShell::EndAction(bool, bool) (this=0x30829c0, bIdleEnd=false, DoSetPosX=false) at sw/source/core/crsr/crsrsh.cxx:258
10 in SwActContext::~SwActContext() (this=0x7ffc8da396a0, __in_chrg=<optimized out>) at sw/source/core/edit/edws.cxx:159
11 in SwWrtShell::DelRight() (this=0x30829c0) at sw/source/uibase/wrtsh/delete.cxx:260

So at the end of the Action, the first page is still not valid, and
the SwTextFrame has mbValidPos = false, but it does have
mbValidSize = true.

Then when the SwCursorShell::UpdateCursor() calls
SwViewShell::MakeVisible(), which creates another Action, the
SwTextFrame is not formatted and its SwTextPortions do not match
the paragraph text content, which is the cause of the crash.

Change-Id: I6e8153c574469a94d190fda8bc3007d17a474c7f
üst af78fa5f
...@@ -1251,6 +1251,9 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) ...@@ -1251,6 +1251,9 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
SwRectFnSet aRectFnSet(this); SwRectFnSet aRectFnSet(this);
SwFrame const* pMoveBwdPre(nullptr);
bool isMoveBwdPreValid(false);
while ( !mbValidPos || !mbValidSize || !mbValidPrtArea ) while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
{ {
// - loop prevention // - loop prevention
...@@ -1272,7 +1275,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) ...@@ -1272,7 +1275,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
GetUpper()->ResetCompletePaint(); GetUpper()->ResetCompletePaint();
// The predecessor was invalidated, so this is obsolete as well now. // The predecessor was invalidated, so this is obsolete as well now.
OSL_ENSURE( pPre, "missing old Prev" ); OSL_ENSURE( pPre, "missing old Prev" );
if( !pPre->IsSctFrame() ) if ((pPre == pMoveBwdPre && isMoveBwdPreValid) && !pPre->IsSctFrame())
::ValidateSz( pPre ); ::ValidateSz( pPre );
} }
bMoveable = IsMoveable(); bMoveable = IsMoveable();
...@@ -1405,6 +1408,9 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) ...@@ -1405,6 +1408,9 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
// To prevent oscillations/loops, check that this has not just // To prevent oscillations/loops, check that this has not just
// flowed forwards. // flowed forwards.
bool bDummy; bool bDummy;
auto const pTemp(GetIndPrev());
auto const bTemp(pTemp && pTemp->GetValidSizeFlag()
&& pTemp->GetValidPrtAreaFlag());
if ( !lcl_Prev( this ) && if ( !lcl_Prev( this ) &&
!bMovedFwd && !bMovedFwd &&
( bMoveable || ( bFly && !bTab ) ) && ( bMoveable || ( bFly && !bTab ) ) &&
...@@ -1412,6 +1418,8 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) ...@@ -1412,6 +1418,8 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
&& MoveBwd( bDummy ) ) && MoveBwd( bDummy ) )
{ {
aRectFnSet.Refresh(this); aRectFnSet.Refresh(this);
pMoveBwdPre = pTemp;
isMoveBwdPreValid = bTemp;
bMovedBwd = true; bMovedBwd = true;
bFormatted = false; bFormatted = false;
if ( bKeep && bMoveable ) if ( bKeep && bMoveable )
......
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