sw/source/core/crsr/crsrsh.cxx | 16 ++++++++++++++++ sw/source/core/crsr/swcrsr.cxx | 14 +++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-)
New commits: commit adef72f8411a49920a75d3ceee7c1dc61ca0a470 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Wed Oct 18 15:17:29 2023 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Wed Oct 18 20:18:03 2023 +0200 sw: fix stack overflow on kde45196-1.html Previously, the shell cursor was put onto a SwGrfNode in the top left corner, which is invalid, but didn't crash immediately. With commit b20ca8d951e8205c8b963c6b7407f984053b4094 the cursor is instead put onto the first SwTextNode in the body, which happens to be in a table, and the entire table is hidden; this causes an infinite recursion in SwCursorShell::UpdateCursorPos() because GetModelPositionForViewPoint() no longer moves it to SwGrfNode. So try to move the cursor out of a hidden node, which requires an additional change in SwCursor::IsSelOvr() to allow moving from a node without a frame to another node without a frame. Change-Id: Ia33c7b558755f7e8b65ea3ff2c46aea20be577dd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158119 Tested-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index 84f0ba59072a..04b263cda754 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -1803,6 +1803,22 @@ void SwCursorShell::UpdateCursorPos() GetLayout()->GetModelPositionForViewPoint( pShellCursor->GetPoint(), pShellCursor->GetPtPos(), &aTmpState ); pShellCursor->DeleteMark(); + // kde45196-1.html: try to get to a non-hidden paragraph, there must + // be one in the document body + while (isInHiddenTextFrame(pShellCursor)) + { + if (!pShellCursor->MovePara(GoNextPara, fnParaStart)) + { + break; + } + } + while (isInHiddenTextFrame(pShellCursor)) + { + if (!pShellCursor->MovePara(GoPrevPara, fnParaStart)) + { + break; + } + } } auto* pDoc = GetDoc(); if (pDoc) diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx index 4349fac21b2f..8d0246bed14f 100644 --- a/sw/source/core/crsr/swcrsr.cxx +++ b/sw/source/core/crsr/swcrsr.cxx @@ -331,6 +331,7 @@ bool SwCursor::IsSelOvr(SwCursorSelOverFlags const eFlags) if( pNd->IsContentNode() && !dynamic_cast<SwUnoCursor*>(this) ) { const SwContentFrame* pFrame = static_cast<const SwContentNode*>(pNd)->getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ); + // ^ null if ( (SwCursorSelOverFlags::ChangePos & eFlags) //allowed to change position if it's a bad one && pFrame && pFrame->isFrameAreaDefinitionValid() && !pFrame->getFrameArea().Height() //a bad zero height position @@ -400,9 +401,16 @@ bool SwCursor::IsSelOvr(SwCursorSelOverFlags const eFlags) if( !pFrame ) { - DeleteMark(); - RestoreSavePos(); - return true; // we need a frame + assert(!m_vSavePos.empty()); + SwContentNode const*const pSaveNode(rNds[m_vSavePos.back().nNode]->GetContentNode()); + // if the old position already didn't have a frame, allow moving + // anyway, hope the caller can handle that + if (pSaveNode && pSaveNode->getLayoutFrame(rDoc.getIDocumentLayoutAccess().GetCurrentLayout())) + { + DeleteMark(); + RestoreSavePos(); + return true; // we need a frame + } } }