sw/inc/deletelistener.hxx                 |   92 ++++++++++++++++++++++++++++++
 sw/qa/extras/layout/data/forcepoint92.doc |binary
 sw/qa/extras/layout/layout.cxx            |    3 
 sw/source/core/layout/tabfrm.cxx          |    8 ++
 4 files changed, 102 insertions(+), 1 deletion(-)

New commits:
commit c820483e2940e01823e549588b4b2ad34f919360
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Sun Mar 27 12:03:06 2022 +0100
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon May 16 12:39:14 2022 +0200

    forcepoint#92 fix crash on layout of specific doc
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132142
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132148
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 0d0cee5e48ca523f11540e9ae0ff022692fd9dca)
    
    Change-Id: Id40d25d05d10d641d071cddd2e1c84594ac777a6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133939
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/inc/deletelistener.hxx b/sw/inc/deletelistener.hxx
new file mode 100644
index 000000000000..bfdc0926d3b6
--- /dev/null
+++ b/sw/inc/deletelistener.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <svl/listener.hxx>
+#include <svl/lstner.hxx>
+#include "calbck.hxx"
+
+class SwDeleteListener final : public SwClient
+{
+private:
+    SwModify* m_pModify;
+
+    virtual void SwClientNotify(const SwModify&, const SfxHint& rHint) override
+    {
+        if (auto pLegacy = dynamic_cast<const sw::LegacyModifyHint*>(&rHint))
+        {
+            if (pLegacy->m_pOld && pLegacy->m_pOld->Which() == RES_OBJECTDYING)
+            {
+                m_pModify->Remove(this);
+                m_pModify = nullptr;
+            }
+        }
+    }
+
+public:
+    SwDeleteListener(SwModify& rModify)
+        : m_pModify(&rModify)
+    {
+        m_pModify->Add(this);
+    }
+
+    bool WasDeleted() const { return !m_pModify; }
+
+    virtual ~SwDeleteListener() override
+    {
+        if (!m_pModify)
+            return;
+        m_pModify->Remove(this);
+    }
+};
+
+class SvtDeleteListener final : public SvtListener
+{
+private:
+    bool bObjectDeleted;
+
+public:
+    explicit SvtDeleteListener(SvtBroadcaster& rNotifier)
+        : bObjectDeleted(false)
+    {
+        StartListening(rNotifier);
+    }
+
+    virtual void Notify(const SfxHint& rHint) override
+    {
+        if (rHint.GetId() == SfxHintId::Dying)
+            bObjectDeleted = true;
+    }
+
+    bool WasDeleted() const { return bObjectDeleted; }
+};
+
+class SfxDeleteListener final : public SfxListener
+{
+private:
+    bool bObjectDeleted;
+
+public:
+    explicit SfxDeleteListener(SfxBroadcaster& rNotifier)
+        : bObjectDeleted(false)
+    {
+        StartListening(rNotifier);
+    }
+
+    virtual void Notify(SfxBroadcaster& /*rBC*/, const SfxHint& rHint) override
+    {
+        if (rHint.GetId() == SfxHintId::Dying)
+            bObjectDeleted = true;
+    }
+
+    bool WasDeleted() const { return bObjectDeleted; }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/qa/extras/layout/data/forcepoint92.doc 
b/sw/qa/extras/layout/data/forcepoint92.doc
new file mode 100644
index 000000000000..49c4a7f11dfe
Binary files /dev/null and b/sw/qa/extras/layout/data/forcepoint92.doc differ
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index abd99aae8f70..bd394317ad41 100644
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -3056,6 +3056,9 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, 
testForcepointFootnoteFrame)
 //just care it doesn't crash/assert
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testN4LA0OHZ) { 
createDoc("LIBREOFFICE-N4LA0OHZ.rtf"); }
 
+//just care it doesn't crash/assert
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testForcepoint92) { 
createDoc("forcepoint92.doc"); }
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf118058)
 {
     SwDoc* pDoc = createDoc("tdf118058.fodt");
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 7e48a88f465c..16b503e42c8c 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -23,6 +23,7 @@
 #include <viewimp.hxx>
 #include <fesh.hxx>
 #include <swtable.hxx>
+#include <deletelistener.hxx>
 #include <dflyobj.hxx>
 #include <anchoreddrawobject.hxx>
 #include <fmtanchr.hxx>
@@ -2061,13 +2062,18 @@ void SwTabFrame::MakeAll(vcl::RenderContext* 
pRenderContext)
             }
             SwFootnoteBossFrame *pOldBoss = bFootnotesInDoc ? 
FindFootnoteBossFrame( true ) : nullptr;
             bool bReformat;
+            std::optional<SfxDeleteListener> oDeleteListener;
+            if (pOldBoss)
+                oDeleteListener.emplace(*pOldBoss);
             SwFrameDeleteGuard g(this);
             if ( MoveBwd( bReformat ) )
             {
+                SAL_WARN_IF(oDeleteListener && oDeleteListener->WasDeleted(), 
"sw.layout", "SwFootnoteBossFrame unexpectedly deleted");
+
                 aRectFnSet.Refresh(this);
                 bMovedBwd = true;
                 aNotify.SetLowersComplete( false );
-                if ( bFootnotesInDoc )
+                if (bFootnotesInDoc && !oDeleteListener->WasDeleted())
                     MoveLowerFootnotes( nullptr, pOldBoss, nullptr, true );
                 if ( bReformat || bKeep )
                 {

Reply via email to