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
+            }
         }
     }
 

Reply via email to