diff options
author | Caolán McNamara <caolanm@redhat.com> | 2019-04-26 17:26:09 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-04-26 22:18:14 +0200 |
commit | 05459943ce9375e6d8627b5b417c11049d26f15b (patch) | |
tree | 6dcb5779ae2bbc1877299835b419d3c048de185c /editeng/source | |
parent | b380c82491593d783ecd5469feda0220ec264db3 (diff) |
ofz#13491 SvxRTFItemStackType dtor excessive recurse depth
ofz#13491 SvxRTFItemStackType dtor recursively calls the dtor of its
m_pChildList. The recurse depth can grow sufficiently to trigger asan.
So breadth-first iterate through the nodes and make a flat vector of them which
can be iterated through in order of most distant from root first and release
their children linearly
Change-Id: Icc7d7130935a27595dae7b55cea41c6a53aed956
Reviewed-on: https://gerrit.libreoffice.org/71386
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'editeng/source')
-rw-r--r-- | editeng/source/rtf/svxrtf.cxx | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/editeng/source/rtf/svxrtf.cxx b/editeng/source/rtf/svxrtf.cxx index 2063ee16b728..4da3c6841263 100644 --- a/editeng/source/rtf/svxrtf.cxx +++ b/editeng/source/rtf/svxrtf.cxx @@ -18,6 +18,7 @@ */ #include <memory> +#include <queue> #include <tools/diagnose_ex.h> #include <rtl/tencinfo.h> #include <svl/itemiter.hxx> @@ -857,6 +858,7 @@ void SvxRTFParser::SetAllAttrOfStk() // end all Attr. and set it into doc { auto const& pStkSet = m_AttrSetList[--n]; SetAttrSet( *pStkSet ); + pStkSet->DropChildList(); m_AttrSetList.pop_back(); } } @@ -960,6 +962,44 @@ SvxRTFItemStackType::SvxRTFItemStackType( aAttrSet.Put( rCpy.aAttrSet ); } +/* ofz#13491 SvxRTFItemStackType dtor recursively + calls the dtor of its m_pChildList. The recurse + depth can grow sufficiently to trigger asan. + + So breadth-first iterate through the nodes + and make a flat vector of them which can + be iterated through in order of most + distant from root first and release + their children linearly +*/ +void SvxRTFItemStackType::DropChildList() +{ + if (!m_pChildList || m_pChildList->empty()) + return; + + std::vector<SvxRTFItemStackType*> bfs; + std::queue<SvxRTFItemStackType*> aQueue; + aQueue.push(this); + + while (!aQueue.empty()) + { + auto* front = aQueue.front(); + aQueue.pop(); + if (front->m_pChildList) + { + for (const auto& a : *front->m_pChildList) + aQueue.push(a.get()); + bfs.push_back(front); + } + } + + for (auto it = bfs.rbegin(); it != bfs.rend(); ++it) + { + SvxRTFItemStackType* pNode = *it; + pNode->m_pChildList.reset(); + } +} + SvxRTFItemStackType::~SvxRTFItemStackType() { if( pSttNd.get() != pEndNd ) |