sw/inc/pagedesc.hxx                 |    2 -
 sw/qa/extras/uiwriter/uiwriter7.cxx |   40 ++++++++++++++++++++++++++++++++++++
 sw/source/core/doc/docfmt.cxx       |   33 +++++++++++++++++++++++++++--
 sw/source/core/layout/pagedesc.cxx  |    2 -
 4 files changed, 73 insertions(+), 4 deletions(-)

New commits:
commit 4edcb059e9ccc1a3735ba09382cda0e764f49bac
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Nov 30 16:42:26 2023 +0900
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Tue Feb 27 14:43:37 2024 +0100

    sw: fix issue with copying stashed frame format
    
    When the PageDesc is copied from one document to another, we
    don't make sure the stashed FrameFormat(s) are also properly
    copied to the new document (which can happen at copy/paste). This
    can cause a crash if the stashed FrameFormats are accessed or
    destructed after the original document is destroyed.
    
    This fixes the issue so that when we detect the PageDesc belong
    to different documents, the stashed FrameFormats are copied just
    like the non-stashed FrameFormats (used for headers and footers).
    
    Change-Id: I948068dba4d39bb47c3725dfa8491c53c5833c7e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160065
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164011

diff --git a/sw/inc/pagedesc.hxx b/sw/inc/pagedesc.hxx
index 382bbb5f00cd..11bb347aa1fb 100644
--- a/sw/inc/pagedesc.hxx
+++ b/sw/inc/pagedesc.hxx
@@ -223,7 +223,7 @@ public:
     const SwFrameFormat* GetStashedFrameFormat(bool bHeader, bool bLeft, bool 
bFirst) const;
 
     /// Checks if the pagedescriptor has a stashed format according to the 
parameters or not.
-    bool HasStashedFormat(bool bHeader, bool bLeft, bool bFirst);
+    bool HasStashedFormat(bool bHeader, bool bLeft, bool bFirst) const;
 
     /// Gives the feature of removing the stashed format by hand if it is 
necessary.
     void RemoveStashedFormat(bool bHeader, bool bLeft, bool bFirst);
diff --git a/sw/qa/extras/uiwriter/uiwriter7.cxx 
b/sw/qa/extras/uiwriter/uiwriter7.cxx
index c3b70c8cad08..6715aa9dde00 100644
--- a/sw/qa/extras/uiwriter/uiwriter7.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter7.cxx
@@ -417,6 +417,46 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testTdf69282)
     xSourceDoc->dispose();
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testStashedHeaderFooter)
+{
+    createSwDoc();
+    SwDoc* pSourceDocument = getSwDoc();
+    uno::Reference<lang::XComponent> xSourceDocument = mxComponent;
+    mxComponent.clear();
+
+    createSwDoc();
+    SwDoc* pTargetDocument = getSwDoc();
+    uno::Reference<lang::XComponent> xTargetDocument = mxComponent;
+    mxComponent.clear();
+
+    // Source
+    SwPageDesc* pSourcePageDesc = pSourceDocument->MakePageDesc("SourceStyle");
+    pSourcePageDesc->ChgFirstShare(false);
+    CPPUNIT_ASSERT(!pSourcePageDesc->IsFirstShared());
+    pSourcePageDesc->StashFrameFormat(pSourcePageDesc->GetFirstMaster(), true, 
false, true);
+    pSourceDocument->ChgPageDesc("SourceStyle", *pSourcePageDesc);
+    CPPUNIT_ASSERT(pSourcePageDesc->HasStashedFormat(true, false, true));
+
+    // Target
+    SwPageDesc* pTargetPageDesc = pTargetDocument->MakePageDesc("TargetStyle");
+
+    // Copy source to target
+    pTargetDocument->CopyPageDesc(*pSourcePageDesc, *pTargetPageDesc);
+
+    // Check the stashed frame format is copied
+    CPPUNIT_ASSERT(pTargetPageDesc->HasStashedFormat(true, false, true));
+
+    // Check document instance
+    auto pSourceStashedFormat = pSourcePageDesc->GetStashedFrameFormat(true, 
false, true);
+    CPPUNIT_ASSERT_EQUAL(true, pSourceStashedFormat->GetDoc() == 
pSourceDocument);
+
+    auto pTargetStashedFormat = pTargetPageDesc->GetStashedFrameFormat(true, 
false, true);
+    CPPUNIT_ASSERT_EQUAL(true, pTargetStashedFormat->GetDoc() == 
pTargetDocument);
+
+    xSourceDocument->dispose();
+    xTargetDocument->dispose();
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest7, testTdf69282WithMirror)
 {
     createSwDoc();
diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx
index 9f0de6aa1e06..17eaf5418e61 100644
--- a/sw/source/core/doc/docfmt.cxx
+++ b/sw/source/core/doc/docfmt.cxx
@@ -1543,14 +1543,43 @@ void SwDoc::CopyPageDesc( const SwPageDesc& rSrcDesc, 
SwPageDesc& rDstDesc,
 
     // Copy the stashed formats as well between the page descriptors...
     for (bool bFirst : { true, false })
+    {
         for (bool bLeft : { true, false })
+        {
             for (bool bHeader : { true, false })
             {
                 if (!bLeft && !bFirst)
                     continue;
-                if (auto pStashedFormat = 
rSrcDesc.GetStashedFrameFormat(bHeader, bLeft, bFirst))
-                    rDstDesc.StashFrameFormat(*pStashedFormat, bHeader, bLeft, 
bFirst);
+
+                // Copy format only if it exists
+                if (auto pStashedFormatSrc = 
rSrcDesc.GetStashedFrameFormat(bHeader, bLeft, bFirst))
+                {
+                    if (pStashedFormatSrc->GetDoc() != this)
+                    {
+                        SwFrameFormat* pNewFormat = new 
SwFrameFormat(GetAttrPool(), "CopyDesc", GetDfltFrameFormat());
+
+                        SfxItemSet aAttrSet(pStashedFormatSrc->GetAttrSet());
+                        aAttrSet.ClearItem(RES_HEADER);
+                        aAttrSet.ClearItem(RES_FOOTER);
+
+                        pNewFormat->DelDiffs( aAttrSet );
+                        pNewFormat->SetFormatAttr( aAttrSet );
+
+                        if (bHeader)
+                            CopyHeader(*pStashedFormatSrc, *pNewFormat);
+                        else
+                            CopyFooter(*pStashedFormatSrc, *pNewFormat);
+
+                        rDstDesc.StashFrameFormat(*pNewFormat, bHeader, bLeft, 
bFirst);
+                    }
+                    else
+                    {
+                        rDstDesc.StashFrameFormat(*pStashedFormatSrc, bHeader, 
bLeft, bFirst);
+                    }
+                }
             }
+        }
+    }
 }
 
 void SwDoc::ReplaceStyles( const SwDoc& rSource, bool bIncludePageStyles )
diff --git a/sw/source/core/layout/pagedesc.cxx 
b/sw/source/core/layout/pagedesc.cxx
index d93b47517e5b..40a7b5865766 100644
--- a/sw/source/core/layout/pagedesc.cxx
+++ b/sw/source/core/layout/pagedesc.cxx
@@ -470,7 +470,7 @@ const SwFrameFormat* SwPageDesc::GetStashedFrameFormat(bool 
bHeader, bool bLeft,
     }
 }
 
-bool SwPageDesc::HasStashedFormat(bool bHeader, bool bLeft, bool bFirst)
+bool SwPageDesc::HasStashedFormat(bool bHeader, bool bLeft, bool bFirst) const
 {
     if (bHeader)
     {

Reply via email to