From c83a443eb106e426901d0ba8a809eedcd24c42c5 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Wed, 21 Jun 2017 15:26:01 +0200 Subject: 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 --- sw/source/core/layout/calcmove.cxx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'sw') 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(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 -- cgit