sw/source/core/doc/docdesc.cxx | 132 ++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 60 deletions(-)
New commits: commit 89b0d94850aeda0a97907945538e4d5f41bac970 Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Wed Jun 1 12:02:36 2022 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Wed Jun 1 14:18:47 2022 +0200 sw: fix crash in SwDoc::CopyMasterHeader and SwDoc::CopyMasterFooter Similar to 3eda5d345f14f8926358df7b425c452a8a165c7d "tdf#149184 DOCX: fix crash removing footer, then saving to doc" check that GetHeaderFormat and GetFooterFormat are not nullptr Also restructure the code a bit to reduce the scope of pRight See https://crashreport.libreoffice.org/stats/signature/SwDoc::CopyMasterHeader(SwPageDesc%20const%20&,SwFormatHeader%20const%20&,SwPageDesc%20&,bool,bool) and https://crashreport.libreoffice.org/stats/signature/SwDoc::CopyMasterFooter(SwPageDesc%20const%20&,SwFormatFooter%20const%20&,SwPageDesc%20&,bool,bool) Change-Id: Ia30d06593124d90b88f7d26ed7be9a5d7a64872c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135230 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/sw/source/core/doc/docdesc.cxx b/sw/source/core/doc/docdesc.cxx index d22fee74ca79..1ba9d86b480f 100644 --- a/sw/source/core/doc/docdesc.cxx +++ b/sw/source/core/doc/docdesc.cxx @@ -268,8 +268,6 @@ void SwDoc::CopyMasterHeader(const SwPageDesc &rChged, const SwFormatHeader &rHe } else { - const SwFrameFormat *pRight = rHead.GetHeaderFormat(); - const SwFormatContent &aRCnt = pRight->GetContent(); const SwFormatContent &aCnt = rFormatHead.GetHeaderFormat()->GetContent(); if (!aCnt.GetContentIdx()) @@ -277,36 +275,44 @@ void SwDoc::CopyMasterHeader(const SwPageDesc &rChged, const SwFormatHeader &rHe const SwFrameFormat& rChgedFrameFormat = getConstFrameFormat(rChged, bLeft, bFirst); rDescFrameFormat.SetFormatAttr( rChgedFrameFormat.GetHeader() ); } - else if ((*aRCnt.GetContentIdx() == *aCnt.GetContentIdx()) || - // The ContentIdx is _always_ different when called from - // SwDocStyleSheet::SetItemSet, because it deep-copies the - // PageDesc. So check if it was previously shared. - (bFirst ? rDesc.IsFirstShared() : rDesc.IsHeaderShared())) + else { - SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(), - bFirst ? "First header" : "Left header", - GetDfltFrameFormat() ); - ::lcl_DescSetAttr( *pRight, *pFormat, false ); - // The section which the right header attribute is pointing - // is copied, and the Index to the StartNode is set to - // the left or first header attribute. - SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() ); - SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmp, SwHeaderStartNode ); - SwNodeRange aRange( aRCnt.GetContentIdx()->GetNode(), SwNodeOffset(0), - *aRCnt.GetContentIdx()->GetNode().EndOfSectionNode() ); - aTmp = *pSttNd->EndOfSectionNode(); - GetNodes().Copy_( aRange, aTmp, false ); - aTmp = *pSttNd; - GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, nullptr, aTmp); - SwPaM const source(aRange.aStart, aRange.aEnd); - SwPosition dest(aTmp); - sw::CopyBookmarks(source, dest); - pFormat->SetFormatAttr( SwFormatContent( pSttNd ) ); - rDescFrameFormat.SetFormatAttr( SwFormatHeader( pFormat ) ); + const SwFrameFormat *pRight = rHead.GetHeaderFormat(); + if (!pRight) + return; + const SwFormatContent &aRCnt = pRight->GetContent(); + + if ((*aRCnt.GetContentIdx() == *aCnt.GetContentIdx()) || + // The ContentIdx is _always_ different when called from + // SwDocStyleSheet::SetItemSet, because it deep-copies the + // PageDesc. So check if it was previously shared. + (bFirst ? rDesc.IsFirstShared() : rDesc.IsHeaderShared())) + { + SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(), + bFirst ? "First header" : "Left header", + GetDfltFrameFormat() ); + ::lcl_DescSetAttr( *pRight, *pFormat, false ); + // The section which the right header attribute is pointing + // is copied, and the Index to the StartNode is set to + // the left or first header attribute. + SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() ); + SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmp, SwHeaderStartNode ); + SwNodeRange aRange( aRCnt.GetContentIdx()->GetNode(), SwNodeOffset(0), + *aRCnt.GetContentIdx()->GetNode().EndOfSectionNode() ); + aTmp = *pSttNd->EndOfSectionNode(); + GetNodes().Copy_( aRange, aTmp, false ); + aTmp = *pSttNd; + GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, nullptr, aTmp); + SwPaM const source(aRange.aStart, aRange.aEnd); + SwPosition dest(aTmp); + sw::CopyBookmarks(source, dest); + pFormat->SetFormatAttr( SwFormatContent( pSttNd ) ); + rDescFrameFormat.SetFormatAttr( SwFormatHeader( pFormat ) ); + } + else + ::lcl_DescSetAttr( *pRight, + *const_cast<SwFrameFormat*>(rFormatHead.GetHeaderFormat()), false ); } - else - ::lcl_DescSetAttr( *pRight, - *const_cast<SwFrameFormat*>(rFormatHead.GetHeaderFormat()), false ); } } } @@ -343,44 +349,50 @@ void SwDoc::CopyMasterFooter(const SwPageDesc &rChged, const SwFormatFooter &rFo } else { - const SwFrameFormat *pRight = rFoot.GetFooterFormat(); - const SwFormatContent &aRCnt = pRight->GetContent(); const SwFormatContent &aLCnt = rFormatFoot.GetFooterFormat()->GetContent(); if( !aLCnt.GetContentIdx() ) { const SwFrameFormat& rChgedFrameFormat = getConstFrameFormat(rChged, bLeft, bFirst); rDescFrameFormat.SetFormatAttr( rChgedFrameFormat.GetFooter() ); } - else if ((*aRCnt.GetContentIdx() == *aLCnt.GetContentIdx()) || - // The ContentIdx is _always_ different when called from - // SwDocStyleSheet::SetItemSet, because it deep-copies the - // PageDesc. So check if it was previously shared. - (bFirst ? rDesc.IsFirstShared() : rDesc.IsFooterShared())) + else { - SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(), - bFirst ? "First footer" : "Left footer", - GetDfltFrameFormat() ); - ::lcl_DescSetAttr( *pRight, *pFormat, false ); - // The section to which the right footer attribute is pointing - // is copied, and the Index to the StartNode is set to - // the left footer attribute. - SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() ); - SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmp, SwFooterStartNode ); - SwNodeRange aRange( aRCnt.GetContentIdx()->GetNode(), SwNodeOffset(0), - *aRCnt.GetContentIdx()->GetNode().EndOfSectionNode() ); - aTmp = *pSttNd->EndOfSectionNode(); - GetNodes().Copy_( aRange, aTmp, false ); - aTmp = *pSttNd; - GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, nullptr, aTmp); - SwPaM const source(aRange.aStart, aRange.aEnd); - SwPosition dest(aTmp); - sw::CopyBookmarks(source, dest); - pFormat->SetFormatAttr( SwFormatContent( pSttNd ) ); - rDescFrameFormat.SetFormatAttr( SwFormatFooter( pFormat ) ); + const SwFrameFormat *pRight = rFoot.GetFooterFormat(); + if (!pRight) + return; + const SwFormatContent &aRCnt = pRight->GetContent(); + + if ((*aRCnt.GetContentIdx() == *aLCnt.GetContentIdx()) || + // The ContentIdx is _always_ different when called from + // SwDocStyleSheet::SetItemSet, because it deep-copies the + // PageDesc. So check if it was previously shared. + (bFirst ? rDesc.IsFirstShared() : rDesc.IsFooterShared())) + { + SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(), + bFirst ? "First footer" : "Left footer", + GetDfltFrameFormat() ); + ::lcl_DescSetAttr( *pRight, *pFormat, false ); + // The section to which the right footer attribute is pointing + // is copied, and the Index to the StartNode is set to + // the left footer attribute. + SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() ); + SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmp, SwFooterStartNode ); + SwNodeRange aRange( aRCnt.GetContentIdx()->GetNode(), SwNodeOffset(0), + *aRCnt.GetContentIdx()->GetNode().EndOfSectionNode() ); + aTmp = *pSttNd->EndOfSectionNode(); + GetNodes().Copy_( aRange, aTmp, false ); + aTmp = *pSttNd; + GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, nullptr, aTmp); + SwPaM const source(aRange.aStart, aRange.aEnd); + SwPosition dest(aTmp); + sw::CopyBookmarks(source, dest); + pFormat->SetFormatAttr( SwFormatContent( pSttNd ) ); + rDescFrameFormat.SetFormatAttr( SwFormatFooter( pFormat ) ); + } + else + ::lcl_DescSetAttr( *pRight, + *const_cast<SwFrameFormat*>(rFormatFoot.GetFooterFormat()), false ); } - else - ::lcl_DescSetAttr( *pRight, - *const_cast<SwFrameFormat*>(rFormatFoot.GetFooterFormat()), false ); } } }