sw/source/core/crsr/crsrsh.cxx | 16 ++++++++++++++++ sw/source/core/crsr/swcrsr.cxx | 14 +++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-)
New commits: commit 92d75686181349f4b79aef413a070ab8335f97b9 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Wed Oct 18 15:17:29 2023 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Wed Oct 18 22:22:06 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> (cherry picked from commit fa4fe53aa775cdc50eec715f4bd88469fe5e0d32) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158048 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> 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 + } } }