svx/source/svdraw/svdedxv.cxx |   33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

New commits:
commit 74bb076ea1b7ab3645a1e0c25eca42d649e59937
Author:     Andras Timar <[email protected]>
AuthorDate: Thu Feb 26 13:46:51 2026 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Fri Feb 27 09:07:31 2026 +0100

    svx: fix SIGSEGV in SdrEndTextEdit OutlinerView cleanup (LOKit multi-view)
    
    Fix a crash in VclReferenceBase::acquire() during SdrEndTextEdit's
    outliner view cleanup loop in multi-user LOKit Impress sessions. The
    window obtained from an OutlinerView could already be freed before
    VclPtr construction.
    
    Four fixes:
    
    - lcl_RemoveTextEditOutlinerViews: iterate backwards instead of forwards
      to avoid skipping entries when RemoveView shifts the array. Also use
      RemoveView by index instead of by pointer.
    
    - SdrEndTextEdit: hold pTEWin as VclPtr instead of raw pointer, so the
      text edit window stays alive after mpTextEditWin is cleared and until
      the SetCursor call.
    
    - SdrEndTextEdit cleanup loop: guard invalidation with a
      pWin->isDisposed() check, so we skip invalidation for windows that
      were destroyed during the orphan window between mxWeakTextEditObj
      clear and the cleanup loop.
    
    - DeleteDeviceFromPaintView: delete the OutlinerView after removing it
      from the outliner, fixing a memory leak.
    
    Change-Id: Ia8910efac9616df0c1e1f6597570a9a03fbe9a8d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200425
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx
index 6cd139c86e6f..b55f2db11844 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -255,13 +255,14 @@ void lcl_RemoveTextEditOutlinerViews(SdrObjEditView 
const* pThis, SdrPageView co
             return;
 
         SdrOutliner* pOutliner = pView->GetTextEditOutliner();
-        for (size_t nView = 0; nView < pOutliner->GetViewCount(); ++nView)
+        for (size_t nView = pOutliner->GetViewCount(); nView > 0;)
         {
+            nView--;
             OutlinerView* pOutlinerView = pOutliner->GetView(nView);
             if (pOutlinerView->GetWindow()->GetOutDev() != pOutputDevice)
                 continue;
 
-            pOutliner->RemoveView(pOutlinerView);
+            pOutliner->RemoveView(nView);
             delete pOutlinerView;
         }
     });
@@ -1644,7 +1645,7 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool 
bDontDeleteReally)
 
     SdrEndTextEditKind eRet = SdrEndTextEditKind::Unchanged;
     rtl::Reference<SdrTextObj> pTEObj = mxWeakTextEditObj.get();
-    vcl::Window* pTEWin = mpTextEditWin;
+    VclPtr<vcl::Window> pTEWin = mpTextEditWin;
     OutlinerView* pTEOutlinerView = mpTextEditOutlinerView;
     vcl::Cursor* pTECursorBuffer = m_pTextEditCursorBuffer;
     SdrUndoManager* pUndoEditUndoManager = nullptr;
@@ -1863,17 +1864,20 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool 
bDontDeleteReally)
                 // may not own the zeroth one
                 delete pOLV;
             }
-            aRect.Union(m_aTextEditArea);
-            aRect.Union(m_aMinTextEditArea);
-            aRect = pWin->LogicToPixel(aRect);
-            aRect.AdjustLeft(-nMorePix);
-            aRect.AdjustTop(-nMorePix);
-            aRect.AdjustRight(nMorePix);
-            aRect.AdjustBottom(nMorePix);
-            aRect = pWin->PixelToLogic(aRect);
-            InvalidateOneWin(*pWin->GetOutDev(), aRect);
-            pWin->GetOutDev()->SetFillColor();
-            pWin->GetOutDev()->SetLineColor(COL_BLACK);
+            if (pWin && !pWin->isDisposed())
+            {
+                aRect.Union(m_aTextEditArea);
+                aRect.Union(m_aMinTextEditArea);
+                aRect = pWin->LogicToPixel(aRect);
+                aRect.AdjustLeft(-nMorePix);
+                aRect.AdjustTop(-nMorePix);
+                aRect.AdjustRight(nMorePix);
+                aRect.AdjustBottom(nMorePix);
+                aRect = pWin->PixelToLogic(aRect);
+                InvalidateOneWin(*pWin->GetOutDev(), aRect);
+                pWin->GetOutDev()->SetFillColor();
+                pWin->GetOutDev()->SetLineColor(COL_BLACK);
+            }
         }
         // and now the Outliner itself
         if (!mbTextEditDontDelete)
@@ -2596,6 +2600,7 @@ void 
SdrObjEditView::DeleteDeviceFromPaintView(OutputDevice& rOldDev)
             if (pOLV && pOLV->GetWindow() == rOldDev.GetOwnerWindow())
             {
                 mpTextEditOutliner->RemoveView(i);
+                delete pOLV;
             }
         }
     }

Reply via email to