sw/qa/core/doc/data/header-footer-delete.docx |binary sw/qa/core/doc/doc.cxx | 10 ++++++++ sw/source/core/doc/docbm.cxx | 31 +++++++++++++------------- 3 files changed, 26 insertions(+), 15 deletions(-)
New commits: commit bd892f3ba96fae1f0a151734053da0b39ca69c86 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Oct 27 15:38:28 2022 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Oct 27 16:31:35 2022 +0200 crashtesting: fix PDF export of tdf98567-1.docx Importing tdf98567-1.docx crashed with debug STL since commit 47bc36c0f87ec2d0329260bcb98d62c7667a5dd1 (sw: make sure mark container is sorted before calling equal_range(), 2022-10-24). The problem is that sw::mark::MarkManager::deleteMark() calls DeregisterFromDoc(), which can call selection change listeners, which may mutate the container. Fix the problem by delaying the DeregisterFromDoc call using an ILazyDeleter for DDE bookmarks. Change-Id: Ia4e8ec379dc0c597db8fe5d91d55af09363350c4 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/141907 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/qa/core/doc/data/header-footer-delete.docx b/sw/qa/core/doc/data/header-footer-delete.docx new file mode 100644 index 000000000000..e6cc4273151d Binary files /dev/null and b/sw/qa/core/doc/data/header-footer-delete.docx differ diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx index 53ac1a9e2b45..4a7324e7905f 100644 --- a/sw/qa/core/doc/doc.cxx +++ b/sw/qa/core/doc/doc.cxx @@ -425,6 +425,16 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testBookmarkDeleteRedline) pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::ShowInsert); } +CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testHeaderFooterDelete) +{ + // Given a document with bookmarks in header/footers: + // When importing that document: + // Then make sure that we don't crash: + // Without the accompanying fix in place, this test would have crashed, an invalidated iterator + // was used in sw::mark::MarkManager::deleteMarks(). + createSwDoc(DATA_DIRECTORY, "header-footer-delete.docx"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx index 6db0b5b51862..3243a79c55ff 100644 --- a/sw/source/core/doc/docbm.cxx +++ b/sw/source/core/doc/docbm.cxx @@ -1219,6 +1219,21 @@ namespace sw::mark } }; + struct LazyDdeBookmarkDeleter : public IDocumentMarkAccess::ILazyDeleter + { + std::unique_ptr<DdeBookmark> m_pDdeBookmark; + SwDoc& m_rDoc; + LazyDdeBookmarkDeleter(DdeBookmark *const pDdeBookmark, SwDoc& rDoc) + : m_pDdeBookmark(pDdeBookmark), m_rDoc(rDoc) + { + assert(pDdeBookmark); + } + virtual ~LazyDdeBookmarkDeleter() override + { + m_pDdeBookmark->DeregisterFromDoc(m_rDoc); + } + }; + } std::unique_ptr<IDocumentMarkAccess::ILazyDeleter> @@ -1292,21 +1307,7 @@ namespace sw::mark DdeBookmark* const pDdeBookmark = dynamic_cast<DdeBookmark*>(pMark); if (pDdeBookmark) { - pDdeBookmark->DeregisterFromDoc(m_rDoc); - - // Update aI, possibly a selection listener invalidated the iterators of m_vAllMarks. - assureSortedMarkContainers(); - auto [it, endIt] = equal_range(m_vAllMarks.begin(), m_vAllMarks.end(), - pMark->GetMarkStart(), CompareIMarkStartsBefore()); - for (; it != endIt; ++it) - { - if (*it == pMark) - { - aI = m_vAllMarks.begin(); - std::advance(aI, std::distance<container_t::const_iterator>(aI, it)); - break; - } - } + ret.reset(new LazyDdeBookmarkDeleter(dynamic_cast<DdeBookmark*>(pMark), m_rDoc)); } m_vAllMarks.erase(aI);