sw/qa/extras/tiledrendering/tiledrendering.cxx |   42 +++++++++++++++++++++++++
 sw/source/core/undo/docundo.cxx                |    2 -
 2 files changed, 43 insertions(+), 1 deletion(-)

New commits:
commit 4f898ec696938b8e1078f63945ab1dd97c2c8a71
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed May 24 15:40:35 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Thu May 25 11:46:45 2023 +0200

    sw: fix wrong downcast in UndoManager::IsViewUndoActionIndependent()
    
    In case a user types in one view, an other user types in an other view,
    finally the first user deletes, then getting the undo state resulted in
    a memory corruption.
    
    This went wrong in commit 2875c65946e59f5dd7968155463bf00bd71d440b (sw,
    out of order undo: allow a subset of a non-empty redo list, 2021-11-11),
    the intention was to check if we have a redo item and it has the
    expected type, but we checked the type of an earlier undo action that
    belongs to the view.
    
    Fix the problem by checking the type of the correct undo action, this
    was probably a copy&paste error of mine.
    
    Resolves <https://github.com/CollaboraOnline/online/issues/6412>.
    
    Change-Id: I6cb2a081067695a045d86b4ef427cc5a76c0f9c4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152204
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    (cherry picked from commit f0a9d4d4eea6562e98fd92a2797d16504e1d4db5)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152216
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx 
b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index cb5bb20d5365..fa37a2e70f82 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -1279,6 +1279,48 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, 
testUndoReorderingRedo)
     SfxViewShell::Current()->setLibreOfficeKitViewCallback(nullptr);
 }
 
+CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testUndoReorderingRedo2)
+{
+    // Create two views.
+    SwXTextDocument* pXTextDocument = createDoc();
+    SwWrtShell* pWrtShell1 = pXTextDocument->GetDocShell()->GetWrtShell();
+    int nView1 = SfxLokHelper::getView();
+    int nView2 = SfxLokHelper::createView();
+    
pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+    SwWrtShell* pWrtShell2 = pXTextDocument->GetDocShell()->GetWrtShell();
+
+    // Type in the first view.
+    SfxLokHelper::setView(nView1);
+    pWrtShell1->SttEndDoc(/*bStt=*/true);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'f', 0);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'f', 0);
+    Scheduler::ProcessEventsToIdle();
+
+    // Type to the same paragraph in the second view.
+    SfxLokHelper::setView(nView2);
+    pWrtShell2->SttEndDoc(/*bStt=*/true);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 's', 0);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 's', 0);
+    Scheduler::ProcessEventsToIdle();
+
+    // Delete in the first view and undo.
+    SfxLokHelper::setView(nView1);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, 
awt::Key::BACKSPACE);
+    pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::BACKSPACE);
+    Scheduler::ProcessEventsToIdle();
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+    Scheduler::ProcessEventsToIdle();
+
+    // Query the undo state, now that a "delete" is on the redo stack and an 
"insert" belongs to the
+    // view on the undo stack, so the types are different.
+    SwUndoId nUndoId(SwUndoId::EMPTY);
+    // Without the accompanying fix in place, this test would have failed with:
+    // runtime error: downcast which does not point to an object of type 
'const SwUndoInsert'
+    // note: object is of type 'SwUndoDelete'
+    // in an UBSan build.
+    pWrtShell1->GetLastUndoInfo(nullptr, &nUndoId, &pWrtShell1->GetView());
+}
+
 CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testUndoReorderingMulti)
 {
     // Create two views and a document of 2 paragraphs.
diff --git a/sw/source/core/undo/docundo.cxx b/sw/source/core/undo/docundo.cxx
index 84fcd4fe5bb6..a9efc248259a 100644
--- a/sw/source/core/undo/docundo.cxx
+++ b/sw/source/core/undo/docundo.cxx
@@ -416,7 +416,7 @@ bool UndoManager::IsViewUndoActionIndependent(const SwView* 
pView, sal_uInt16& r
     for (size_t i = 0; i < GetRedoActionCount(); ++i)
     {
         auto pRedoAction = dynamic_cast<const SwUndo*>(GetRedoAction(i));
-        if (!pRedoAction || pViewSwAction->GetId() != SwUndoId::TYPING)
+        if (!pRedoAction || pRedoAction->GetId() != SwUndoId::TYPING)
         {
             return false;
         }

Reply via email to