tdf#160984 sw continuous endnotes: fix crash on loading forum-mso-en-7731.docx

Regression from commit 1ae5ea3f78cca11ba18f2dd1a06f875263336a3b
(tdf#160984 sw continuous endnotes: enable DOCX import, 2024-05-21), the
bugdoc crashed in SwSectionFrame::GetEndSectFormat_().

What seems to happen is that the first endnote is added to page 1, then
more content is inserted, so the endnote is moved to page 2, which
leaves an empty endnote section on page 1, which is marked for deletion
in SwSectionFrame::MakeAll(), and will be deleted in
SwRootFrame::DeleteEmptySct_(). At some point (after marking for
deletion, before deletion) SwFootnoteBossFrame::AppendFootnote() tries
to find the first endnote section in the layout, and finds this section,
but it crashes because there is no SwSection attached to it, as marking
for deletion in SwSectionFrame::DelEmpty() clears that.

Fix the problem by ignoring to-be-deleted sections in
SwFootnoteBossFrame::AppendFootnote(): this way a new, usable section
will be created and the to-be-deleted section go away as the layout
finishes.

An alternative would be to check for SwSectionFrame::GetSection()
earlier, as we iterate on pages (hoping that this way we find a later
page that has a not-dead endnote section), but that leads to 6 pages
instead of 4 pages for the bugdoc, so don't go that way.

Change-Id: I9a21cbccb5a088314520c7ade55dbdf9966d1265
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168084
Reviewed-by: Miklos Vajna <[email protected]>
Tested-by: Jenkins
diff --git a/sw/qa/core/layout/data/inline-endnote-section-delete.docx b/sw/qa/core/layout/data/inline-endnote-section-delete.docx
new file mode 100644
index 0000000..bf3d3e6
--- /dev/null
+++ b/sw/qa/core/layout/data/inline-endnote-section-delete.docx
Binary files differ
diff --git a/sw/qa/core/layout/ftnfrm.cxx b/sw/qa/core/layout/ftnfrm.cxx
index a7640e2..98387be 100644
--- a/sw/qa/core/layout/ftnfrm.cxx
+++ b/sw/qa/core/layout/ftnfrm.cxx
@@ -17,6 +17,8 @@
#include <rootfrm.hxx>
#include <view.hxx>
#include <wrtsh.hxx>
#include <bodyfrm.hxx>
#include <sectfrm.hxx>

/// Covers sw/source/core/layout/ftnfrm.cxx fixes.
class Test : public SwModelTestBase
@@ -122,4 +124,33 @@ CPPUNIT_TEST_FIXTURE(Test, testInlineEndnotePosition)
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(269), nEndnoteContTopMargin);
}

CPPUNIT_TEST_FIXTURE(Test, testInlineEndnoteSectionDelete)
{
    // Given a document, ContinuousEndnotes is true, 3 pages, endnodes start on page 2:
    // When laying out that document:
    createSwDoc("inline-endnote-section-delete.docx");

    // First page: just body text:
    SwDoc* pDoc = getSwDoc();
    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
    auto pPage = pLayout->Lower()->DynCastPageFrame();
    CPPUNIT_ASSERT(pPage->GetLower()->IsBodyFrame());
    auto pBodyFrame = static_cast<SwBodyFrame*>(pPage->GetLower());
    CPPUNIT_ASSERT(!pBodyFrame->GetLastLower()->IsSctFrame());
    // Second page: ends with endnotes:
    pPage = pPage->GetNext()->DynCastPageFrame();
    CPPUNIT_ASSERT(pPage->GetLower()->IsBodyFrame());
    pBodyFrame = static_cast<SwBodyFrame*>(pPage->GetLower());
    CPPUNIT_ASSERT(pBodyFrame->GetLastLower()->IsSctFrame());
    auto pSection = static_cast<SwSectionFrame*>(pBodyFrame->GetLastLower());
    CPPUNIT_ASSERT(pSection->IsEndNoteSection());
    // Third page: just endnotes:
    pPage = pPage->GetNext()->DynCastPageFrame();
    CPPUNIT_ASSERT(pPage->GetLower()->IsBodyFrame());
    pBodyFrame = static_cast<SwBodyFrame*>(pPage->GetLower());
    CPPUNIT_ASSERT(pBodyFrame->GetLower()->IsSctFrame());
    pSection = static_cast<SwSectionFrame*>(pBodyFrame->GetLower());
    CPPUNIT_ASSERT(pSection->IsEndNoteSection());
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx
index 548d822..bb35d1c 100644
--- a/sw/source/core/layout/ftnfrm.cxx
+++ b/sw/source/core/layout/ftnfrm.cxx
@@ -1626,7 +1626,9 @@ void SwFootnoteBossFrame::AppendFootnote( SwContentFrame *pRef, SwTextFootnote *
                pEndnoteSection = pPage->GetEndNoteSection();
            }
            // If there are no endnotes sections yet, create one at the end of the document.
            if (!pEndnoteSection)
            // Ignore sections which are already marked for deletion, they don't have an SwSection
            // anymore, so not usable for us.
            if (!pEndnoteSection || !pEndnoteSection->GetSection())
            {
                SwSection* pSwSection = pDoc->GetEndNoteInfo().GetSwSection(*pDoc);
                pEndnoteSection = new SwSectionFrame(*pSwSection, pPage);