diff options
author | Michael Stahl <mstahl@redhat.com> | 2017-04-03 14:28:56 +0200 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2017-04-03 14:46:38 +0200 |
commit | 8a5374f2fdbd1e15c107133f55930cbc431edbd5 (patch) | |
tree | b7bf002eb17888da34612e1527206ad0a9ce4120 | |
parent | fb5331971379f7d71413364e9d62f8264033ac67 (diff) |
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
-rw-r--r-- | sw/source/core/layout/laycache.cxx | 61 |
1 files changed, 53 insertions, 8 deletions
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 |