sw: layout: fix crash when deleting page with section being formatted

This crashes only when calling storeToURL() with writer_pdf_Export?

There is a text frame 112, followed by section frame 126, which contains
table frame 127.

The section frame 126 is being formatted, which in
SwFrame::PrepareMake() formats its prev, text frame 112.

This does MoveBwd() and in SwContentFrame::MakeAll() formats its next,
tab frame 127.

This also does MoveBwd() and then there is this really odd condition in
SwTabFrame::Paste() where it calls SwFrame::CheckPageDescs() if it
*doesn't* have a RES_PAGEDESC item and the page has a non-default page
style - this condition remains inexplicable since initial CVS import.

Then CheckPageDesc() sees the (next) page is empty and deletes it.

So check in sw::IsPageFrameEmpty() that there aren't any sections with
IsDeleteForbidden() set.

(regression from commit b9ef71476f)

Change-Id: I3c64fe40fabffc255c4146a35c678ce6a1cc09c9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133222
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
This commit is contained in:
Michael Stahl
2022-04-21 11:03:38 +02:00
parent 368b1e070a
commit 85aa57359b
3 changed files with 24 additions and 0 deletions
+1
View File
@@ -100,6 +100,7 @@ public:
SwPrintData const*const pPrintData = nullptr ) const override;
const SwFrame *Lower() const { return m_pLower; }
SwFrame *Lower() { return m_pLower; }
bool ContainsDeleteForbiddenLayFrame() const;
const SwContentFrame *ContainsContent() const;
inline SwContentFrame *ContainsContent();
const SwCellFrame *FirstCell() const;
+21
View File
@@ -165,6 +165,27 @@ const SwFrame *SwLayoutFrame::ContainsAny( const bool _bInvestigateFootnoteForSe
return nullptr;
}
bool SwLayoutFrame::ContainsDeleteForbiddenLayFrame() const
{
if (IsDeleteForbidden())
{
return true;
}
for (SwFrame const* pFrame = Lower(); pFrame; pFrame = pFrame->GetNext())
{
if (!pFrame->IsLayoutFrame())
{
continue;
}
SwLayoutFrame const*const pLay(static_cast<SwLayoutFrame const*>(pFrame));
if (pLay->ContainsDeleteForbiddenLayFrame())
{
return true;
}
}
return false;
}
const SwFrame* SwFrame::GetLower() const
{
return IsLayoutFrame() ? static_cast<const SwLayoutFrame*>(this)->Lower() : nullptr;
+2
View File
@@ -1026,6 +1026,8 @@ bool IsPageFrameEmpty(SwPageFrame const& rPage)
rPage.FindFootnoteCont() ||
(nullptr != (pBody = rPage.FindBodyCont()) &&
( pBody->ContainsContent() ||
// check for section frames that are being formatted on the stack
rPage.ContainsDeleteForbiddenLayFrame() ||
// #i47580#
// Do not delete page if there's an empty tabframe
// left. I think it might be correct to use ContainsAny()