summaryrefslogtreecommitdiff
path: root/editeng
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2019-04-26 17:26:09 +0100
committerCaolán McNamara <caolanm@redhat.com>2019-04-26 22:18:14 +0200
commit05459943ce9375e6d8627b5b417c11049d26f15b (patch)
tree6dcb5779ae2bbc1877299835b419d3c048de185c /editeng
parentb380c82491593d783ecd5469feda0220ec264db3 (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')
-rw-r--r--editeng/source/rtf/svxrtf.cxx40
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 )