sw/inc/pagedesc.hxx                           |    2 -
 sw/qa/core/header_footer/HeaderFooterTest.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 963de9feb37105560fde14b44d992e47f341bb5b
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Nov 30 16:42:26 2023 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Fri Dec 1 05:07:42 2023 +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>

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/core/header_footer/HeaderFooterTest.cxx 
b/sw/qa/core/header_footer/HeaderFooterTest.cxx
index 8b78363a0c1b..b411632884e1 100644
--- a/sw/qa/core/header_footer/HeaderFooterTest.cxx
+++ b/sw/qa/core/header_footer/HeaderFooterTest.cxx
@@ -48,6 +48,46 @@ public:
     }
 };
 
+CPPUNIT_TEST_FIXTURE(HeaderFooterTest, 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(HeaderFooterTest, testNonFirstHeaderIsDisabled)
 {
     // related to tdf#127778
diff --git a/sw/source/core/doc/docfmt.cxx b/sw/source/core/doc/docfmt.cxx
index d5854b3633e6..57c42c529eb1 100644
--- a/sw/source/core/doc/docfmt.cxx
+++ b/sw/source/core/doc/docfmt.cxx
@@ -1540,14 +1540,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 edfee20aaef6..2b7882332789 100644
--- a/sw/source/core/layout/pagedesc.cxx
+++ b/sw/source/core/layout/pagedesc.cxx
@@ -477,7 +477,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