From 83f5910e5703edccee77d6aaf554fd1586fe1e49 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Mon, 16 Nov 2020 13:08:48 +0100 Subject: (related tdf#134298) sw: layout: avoid infinite loop in InternalAction() The condition IsInterrupt() && pPage && (m_nCheckPageNum != USHRT_MAX) isn't handled properly and the while loop will never terminate with the fix for tdf#134298 in several UITest_writer_tests*. If m_nCheckPageNum is set, then it must result in a call to CheckPageDescs() here; it's a member of SwLayAction so won't survive until the next idle layout invocation. There is a funny history of these loop conditions with commit 9eff9e699e17cc5a8a25895bd28dc8e4ceb8071e and cee296066ab780217395201ab84c2150c8840d25 so we can only hope this time we got it right... Change-Id: I91b63540bf4280296d747cb8e841594f8dd3b140 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105927 Tested-by: Jenkins Reviewed-by: Michael Stahl (cherry picked from commit 094ee3955ee81e1bc631d50cc216cbb17a777839) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114096 Tested-by: Michael Stahl Reviewed-by: Michael Stahl --- sw/source/core/layout/layact.cxx | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx index 174e15699e46..50d5b1fa6b7a 100644 --- a/sw/source/core/layout/layact.cxx +++ b/sw/source/core/layout/layact.cxx @@ -450,15 +450,19 @@ void SwLayAction::InternalAction(OutputDevice* pRenderContext) sal_uInt16 nPercentPageNum = 0; while ( (pPage && !IsInterrupt()) || m_nCheckPageNum != USHRT_MAX ) { - if (!pPage && m_nCheckPageNum != USHRT_MAX) + // note: this is the only place that consumes and resets m_nCheckPageNum + if ((IsInterrupt() || !pPage) && m_nCheckPageNum != USHRT_MAX) { - SwPageFrame *pPg = static_cast(m_pRoot->Lower()); - while (pPg && pPg->GetPhyPageNum() < m_nCheckPageNum) - pPg = static_cast(pPg->GetNext()); - if (pPg) - pPage = pPg; - if (!pPage) - break; + if (!pPage || m_nCheckPageNum < pPage->GetPhyPageNum()) + { + SwPageFrame *pPg = static_cast(m_pRoot->Lower()); + while (pPg && pPg->GetPhyPageNum() < m_nCheckPageNum) + pPg = static_cast(pPg->GetNext()); + if (pPg) + pPage = pPg; + if (!pPage) + break; + } SwPageFrame *pTmp = pPage->GetPrev() ? static_cast(pPage->GetPrev()) : pPage; -- cgit