sw/source/core/layout/laycache.cxx | 61 ++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-)
New commits: commit 8a5374f2fdbd1e15c107133f55930cbc431edbd5 Author: Michael Stahl <mst...@redhat.com> Date: Mon Apr 3 14:28:56 2017 +0200 tdf#106237 sw: do some basic sanity checking on layout-cache The bugdoc, with claimed generator AOO4.1.1 on Windows, contains a bogus layout-cache: debug:26706:1: nType P nIndex 29 2147483647 debug:26706:1: nType P nIndex 66 2147483647 debug:26706:1: nType P nIndex 105 2147483647 debug:26706:1: nType P nIndex 142 2147483647 debug:26706:1: nType P nIndex 178 2147483647 debug:26706:1: nType P nIndex 205 2147483647 debug:26706:1: nType P nIndex 229 2147483647 debug:26706:1: nType T nIndex 314 65535 Due to a loop-control this causes incorrect pagination if CalcLayout() is called only once. It should look like this: debug:26765:1: nType T nIndex 382 65535 debug:26765:1: nType T nIndex 790 65535 In this case we can easily detect that the indexes and types in the layout-cache are bogus by checking against the node types, so do that in SwLayHelper::SwLayHelper(). Change-Id: I7091af49a8c29bf0a11ceff0be9ba84b1f710fdb diff --git a/sw/source/core/layout/laycache.cxx b/sw/source/core/layout/laycache.cxx index 8a5beb52f327..b74f2bb163aa 100644 --- a/sw/source/core/layout/laycache.cxx +++ b/sw/source/core/layout/laycache.cxx @@ -454,6 +454,51 @@ SwActualSection::SwActualSection( SwActualSection *pUp, } } +namespace { + +bool sanityCheckLayoutCache(SwLayCacheImpl const& rCache, + SwNodes const& rNodes, sal_uLong nNodeIndex) +{ + auto const nStartOfContent(rNodes.GetEndOfContent().StartOfSectionNode()->GetIndex()); + nNodeIndex -= nStartOfContent; + auto const nMaxIndex(rNodes.GetEndOfContent().GetIndex() - nStartOfContent); + for (sal_uInt16 nIndex = 0; nIndex < rCache.size(); ++nIndex) + { + auto const nBreakIndex(rCache.GetBreakIndex(nIndex)); + if (nBreakIndex < nNodeIndex || nMaxIndex <= nBreakIndex) + { + SAL_WARN("sw.core.layout", + "invalid node index in layout-cache: " << nBreakIndex); + return false; + } + auto const nBreakType(rCache.GetBreakType(nIndex)); + switch (nBreakType) + { + case SW_LAYCACHE_IO_REC_PARA: + if (!rNodes[nBreakIndex + nStartOfContent]->IsTextNode()) + { + SAL_WARN("sw.core.layout", + "invalid node of type 'P' in layout-cache"); + return false; + } + break; + case SW_LAYCACHE_IO_REC_TABLE: + if (!rNodes[nBreakIndex + nStartOfContent]->IsTableNode()) + { + SAL_WARN("sw.core.layout", + "invalid node of type 'T' in layout-cache"); + return false; + } + break; + default: + assert(false); // Read shouldn't have inserted that + } + } + return true; +} + +} // namespace + /** helper class, which utilizes the layout cache information * to distribute the document content to the right pages. * It's used by the InsertCnt_(..)-function. @@ -478,19 +523,19 @@ SwLayHelper::SwLayHelper( SwDoc *pD, SwFrame* &rpF, SwFrame* &rpP, SwPageFrame* pImpl = pDoc->GetLayoutCache() ? pDoc->GetLayoutCache()->LockImpl() : nullptr; if( pImpl ) { - nMaxParaPerPage = 1000; - nStartOfContent = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode() - ->GetIndex(); - nNodeIndex -= nStartOfContent; - nIndex = 0; - while( nIndex < pImpl->size() && pImpl->GetBreakIndex( nIndex ) < nNodeIndex ) + SwNodes const& rNodes(pDoc->GetNodes()); + if (sanityCheckLayoutCache(*pImpl, rNodes, nNodeIndex)) { - ++nIndex; + nIndex = 0; + nStartOfContent = rNodes.GetEndOfContent().StartOfSectionNode()->GetIndex(); + nMaxParaPerPage = 1000; } - if( nIndex >= pImpl->size() ) + else { pDoc->GetLayoutCache()->UnlockImpl(); pImpl = nullptr; + nIndex = USHRT_MAX; + nStartOfContent = USHRT_MAX; } } else _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits