summaryrefslogtreecommitdiff
path: root/sw/source/core/layout/calcmove.cxx
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2017-06-21 15:26:01 +0200
committerMichael Stahl <mstahl@redhat.com>2017-06-22 09:53:06 +0200
commitc83a443eb106e426901d0ba8a809eedcd24c42c5 (patch)
tree1e9727430d63607f2797a3aeb9b3ccaf1b405445 /sw/source/core/layout/calcmove.cxx
parent9dcb767c5bdccdf6606240afd6aa2c6bd3dcc9f4 (diff)
tdf#101821 sw: fix another layout footnote use-after-free
In SwContentFrame::MakeAll() the pPre (previous frame) is deleted in a call to MoveFwd(). This SwTextFrame is inside of a footnote, and the SwFlowFrame::CutTree() for whatever reason wants to format all of the SwTextFrames inside the same SwFootnoteFrame, which causes the pPre to be joined with another one. Let's try to avoid that by checking that it's still in the layout after the call to MoveFwd(); on the one hand it's not obvious that this frame is important enough that it should be kept alive with ForbidDelete(), on the other hand i have no idea if simply removing the ValidateSz() call would introduce new loops or whatever. Invalid read of size 4 at 0x414E8D14: SwFrame::IsSctFrame() const (frame.hxx:1018) by 0x41A85A29: SwContentFrame::MakeAll(OutputDevice*) (calcmove.cxx:1713) by 0x41A7F499: SwFrame::OptPrepareMake() (calcmove.cxx:368) by 0x41ADF0CF: SwFrame::OptCalc() const (frame.hxx:892) by 0x41ADCC07: SwLayAction::FormatContent_(SwContentFrame const*, SwPageFrame const*) (layact.cxx:1789) by 0x41ADC195: SwLayAction::FormatContent(SwPageFrame const*) (layact.cxx:1620) by 0x41AD88DE: SwLayAction::InternalAction(OutputDevice*) (layact.cxx:760) by 0x41AD7080: SwLayAction::Action(OutputDevice*) (layact.cxx:351) by 0x41ADE32E: SwLayIdle::SwLayIdle(SwRootFrame*, SwViewShellImp*) (layact.cxx:2133) by 0x41FFC97E: SwViewShell::LayoutIdle() (viewsh.cxx:711) Address 0x530ccf80 is 160 bytes inside a block of size 264 free'd at 0x4C2ED4A: free (vg_replace_malloc.c:530) by 0x4E5BCD0: rtl_freeMemory_SYSTEM(void*) (alloc_global.cxx:271) by 0x4E5C00A: rtl_freeMemory (alloc_global.cxx:341) by 0x4E5AAA0: rtl_cache_free (alloc_cache.cxx:1231) by 0xEFC9A6F: FixedMemPool::Free(void*) (mempool.cxx:49) by 0x41CA7DFA: SwTextFrame::operator delete(void*, unsigned long) (txtfrm.hxx:377) by 0x41C9F7B6: SwTextFrame::~SwTextFrame() (txtfrm.cxx:415) by 0x41B5B74C: SwFrame::DestroyFrame(SwFrame*) (ssfrm.cxx:391) by 0x41C1589A: SwTextFrame::JoinFrame() (frmform.cxx:656) by 0x41C153B1: SwTextFrame::AdjustFollow_(SwTextFormatter&, int, int, unsigned char) (frmform.cxx:555) by 0x41C172E1: SwTextFrame::FormatAdjust(SwTextFormatter&, WidowsAndOrphans&, int, bool) (frmform.cxx:1108) by 0x41C18D5E: SwTextFrame::Format_(SwTextFormatter&, SwTextFormatInfo&, bool) (frmform.cxx:1550) by 0x41C19340: SwTextFrame::Format_(OutputDevice*, SwParaPortion*) (frmform.cxx:1660) by 0x41C19CD8: SwTextFrame::Format(OutputDevice*, SwBorderAttrs const*) (frmform.cxx:1807) by 0x41A847A1: SwContentFrame::MakeAll(OutputDevice*) (calcmove.cxx:1393) by 0x41A7F211: SwFrame::PrepareMake(OutputDevice*) (calcmove.cxx:346) by 0x41B75758: SwFrame::Calc(OutputDevice*) const (trvlfrm.cxx:1761) by 0x41A973E7: SwFlowFrame::CutTree(SwFrame*) (flowfrm.cxx:424) by 0x41A979AE: SwFlowFrame::MoveSubTree(SwLayoutFrame*, SwFrame*) (flowfrm.cxx:592) by 0x41ACFB69: SwContentFrame::MoveFootnoteCntFwd(bool, SwFootnoteBossFrame*) (ftnfrm.cxx:2756) by 0x41A9B78E: SwFlowFrame::MoveFwd(bool, bool, bool) (flowfrm.cxx:1813) by 0x41A85864: SwContentFrame::MakeAll(OutputDevice*) (calcmove.cxx:1681) by 0x41A7F499: SwFrame::OptPrepareMake() (calcmove.cxx:368) by 0x41ADF0CF: SwFrame::OptCalc() const (frame.hxx:892) by 0x41ADCC07: SwLayAction::FormatContent_(SwContentFrame const*, SwPageFrame const*) (layact.cxx:1789) by 0x41ADC195: SwLayAction::FormatContent(SwPageFrame const*) (layact.cxx:1620) by 0x41AD88DE: SwLayAction::InternalAction(OutputDevice*) (layact.cxx:760) by 0x41AD7080: SwLayAction::Action(OutputDevice*) (layact.cxx:351) by 0x41ADE32E: SwLayIdle::SwLayIdle(SwRootFrame*, SwViewShellImp*) (layact.cxx:2133) by 0x41FFC97E: SwViewShell::LayoutIdle() (viewsh.cxx:711) Change-Id: I35b27a32608d4dcf98e0933cce76ce5ddb1c09d9
Diffstat (limited to 'sw/source/core/layout/calcmove.cxx')
-rw-r--r--sw/source/core/layout/calcmove.cxx20
1 files changed, 20 insertions, 0 deletions
diff --git a/sw/source/core/layout/calcmove.cxx b/sw/source/core/layout/calcmove.cxx
index 56886e4a95c7..2fdbb6b4f62f 100644
--- a/sw/source/core/layout/calcmove.cxx
+++ b/sw/source/core/layout/calcmove.cxx
@@ -1681,6 +1681,26 @@ void SwContentFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
if ( !bMovedFwd && !MoveFwd( bMakePage, false ) )
bMakePage = false;
aRectFnSet.Refresh(this);
+ if (!bMovedFwd && bFootnote && GetIndPrev() != pPre)
+ { // SwFlowFrame::CutTree() could have formatted and deleted pPre
+ auto const pPrevFootnoteFrame(static_cast<SwFootnoteFrame const*>(GetUpper())->GetMaster());
+ bool bReset = true;
+ if (pPrevFootnoteFrame)
+ { // use GetIndNext() in case there are sections
+ for (auto p = pPrevFootnoteFrame->Lower(); p; p = p->GetIndNext())
+ {
+ if (p == pPre)
+ {
+ bReset = false;
+ break;
+ }
+ }
+ }
+ if (bReset)
+ {
+ pPre = nullptr;
+ }
+ }
// If MoveFwd moves the paragraph to the next page, a following
// paragraph, which contains footnotes can cause the old upper