summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2017-07-27 17:52:59 +0200
committerCaolán McNamara <caolanm@redhat.com>2017-08-02 10:17:09 +0200
commit2af9630349011a192b21b65c49c91d64a5562fdf (patch)
treeb5b01c0ee6a4ac097c8bb6a93319b18926377788
parente86f049b0bfede337c875e5f62d27186fcace37f (diff)
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 (cherry picked from commit b1ad2ee35647ccd46b0bdb96c5ded09710e307be) Reviewed-on: https://gerrit.libreoffice.org/40503 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--sw/source/core/layout/calcmove.cxx10
1 files changed, 9 insertions, 1 deletions
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx
index 56886e4a95c7..24484b3e8104 100644
--- a/sw/source/core/layout/calcmove.cxx
+++ b/sw/source/core/layout/calcmove.cxx
@@ -1251,6 +1251,9 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
SwRectFnSet aRectFnSet(this);
+ SwFrame const* pMoveBwdPre(nullptr);
+ bool isMoveBwdPreValid(false);
+
while ( !mbValidPos || !mbValidSize || !mbValidPrtArea )
{
// - loop prevention
@@ -1272,7 +1275,7 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
GetUpper()->ResetCompletePaint();
// The predecessor was invalidated, so this is obsolete as well now.
OSL_ENSURE( pPre, "missing old Prev" );
- if( !pPre->IsSctFrame() )
+ if ((pPre == pMoveBwdPre && isMoveBwdPreValid) && !pPre->IsSctFrame())
::ValidateSz( pPre );
}
bMoveable = IsMoveable();
@@ -1405,6 +1408,9 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
// To prevent oscillations/loops, check that this has not just
// flowed forwards.
bool bDummy;
+ auto const pTemp(GetIndPrev());
+ auto const bTemp(pTemp && pTemp->GetValidSizeFlag()
+ && pTemp->GetValidPrtAreaFlag());
if ( !lcl_Prev( this ) &&
!bMovedFwd &&
( bMoveable || ( bFly && !bTab ) ) &&
@@ -1412,6 +1418,8 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
&& MoveBwd( bDummy ) )
{
aRectFnSet.Refresh(this);
+ pMoveBwdPre = pTemp;
+ isMoveBwdPreValid = bTemp;
bMovedBwd = true;
bFormatted = false;
if ( bKeep && bMoveable )