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 e0e59aae287268cb633df340e565647ec8c14cb2 Author: Attila Szűcs <[email protected]> AuthorDate: Wed Jun 22 14:43:04 2022 +0200 Commit: Xisco Fauli <[email protected]> CommitDate: Fri Jun 24 11:34:46 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 <[email protected]> Reviewed-by: László Németh <[email protected]> (cherry picked from commit c84c43320cc66152b00c0c0dad8b65de8a4b9015) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136320 Tested-by: Jenkins Reviewed-by: Xisco Fauli <[email protected]> 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 a458f4d765e6..beb3e049d94c 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.
