sc/qa/unit/uicalc/data/tdf149502_HangOnDeletingSheet1.ods |binary
 sc/qa/unit/uicalc/uicalc.cxx                              |   17 ++++++++++++++
 sc/source/core/data/document.cxx                          |    7 +++++
 3 files changed, 24 insertions(+)

New commits:
commit 954d119db932434dc976ef739c643be0d9c7023c
Author:     Attila Szűcs <szucs.atti...@nisz.hu>
AuthorDate: Wed Jun 22 14:43:04 2022 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Thu Jun 23 15:34:02 2022 +0200

    tdf#149502 sc: crash fix: Change in Table destruction
    
    Postpone ScTable destruction a bit, when ScTable::nTab is synchronized
    with ScDocument::maTabs[] to avoid crashing.
    
    Before the fix random crashing occurred if the ScTable::nTab was
    already updated when ~ScTable() called, but the ScDocument::maTabs[]
    was not reordered yet, so nTab could have pointed to the actually
    deleted table in mTabs[].
    
    Co-authored-by: Tibor Nagy (NISZ)
    
    Change-Id: I2ac1450e3483ab334b4e20ac2598c2191e0135c9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136284
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sc/qa/unit/uicalc/data/tdf149502_HangOnDeletingSheet1.ods 
b/sc/qa/unit/uicalc/data/tdf149502_HangOnDeletingSheet1.ods
new file mode 100644
index 000000000000..e34a75c32308
Binary files /dev/null and 
b/sc/qa/unit/uicalc/data/tdf149502_HangOnDeletingSheet1.ods differ
diff --git a/sc/qa/unit/uicalc/uicalc.cxx b/sc/qa/unit/uicalc/uicalc.cxx
index a6f648ce9766..2e48f42f2e73 100644
--- a/sc/qa/unit/uicalc/uicalc.cxx
+++ b/sc/qa/unit/uicalc/uicalc.cxx
@@ -1512,6 +1512,23 @@ CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf86166)
     CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(1), pDoc->GetTableCount());
 }
 
+CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf149502_HangOnDeletingSheet1)
+{
+    ScModelObj* pModelObj = createDoc("tdf149502_HangOnDeletingSheet1.ods");
+    ScDocument* pDoc = pModelObj->GetDocument();
+    CPPUNIT_ASSERT(pDoc);
+
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(4), pDoc->GetTableCount());
+
+    uno::Sequence<beans::PropertyValue> aArgs(
+        comphelper::InitPropertySequence({ { "Index", uno::Any(sal_uInt16(0)) 
} }));
+
+    // Before the fix in place, this test frozen here
+    dispatchCommand(mxComponent, ".uno:Remove", aArgs);
+
+    CPPUNIT_ASSERT_EQUAL(static_cast<SCTAB>(3), pDoc->GetTableCount());
+}
+
 CPPUNIT_TEST_FIXTURE(ScUiCalcTest, testTdf149503)
 {
     ScModelObj* pModelObj = createDoc("tdf149503.xls");
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 15f44a1ef4d5..db6500e5b390 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -727,7 +727,14 @@ bool ScDocument::DeleteTab( SCTAB nTab )
                     if (pTab)
                         pTab->UpdateDeleteTab(aCxt);
 
+                // tdf#149502 make sure ScTable destructor called after the 
erase is finished, when
+                // maTabs[x].nTab==x is true again, as it should be always 
true.
+                // In the end of maTabs.erase, maTabs indexes change, but nTab 
updated before erase.
+                // ~ScTable expect that maTabs[x].nTab==x so it shouldn't be 
called during erase.
+                ScTableUniquePtr pErasedTab = std::move(maTabs[nTab]);
                 maTabs.erase(maTabs.begin() + nTab);
+                delete pErasedTab.release();
+
                 // UpdateBroadcastAreas must be called between UpdateDeleteTab,
                 // which ends listening, and StartAllListeners, to not modify
                 // areas that are to be inserted by starting listeners.

Reply via email to