diff options
-rw-r--r-- | editeng/source/rtf/svxrtf.cxx | 40 | ||||
-rw-r--r-- | include/editeng/svxrtf.hxx | 5 |
2 files changed, 43 insertions, 2 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 ) diff --git a/include/editeng/svxrtf.hxx b/include/editeng/svxrtf.hxx index 9d01ca41a0ff..a2de114fffaa 100644 --- a/include/editeng/svxrtf.hxx +++ b/include/editeng/svxrtf.hxx @@ -309,10 +309,11 @@ class EDITENG_DLLPUBLIC SvxRTFItemStackType void Add(std::unique_ptr<SvxRTFItemStackType>); void Compress( const SvxRTFParser& ); + void DropChildList(); public: - SvxRTFItemStackType( const SvxRTFItemStackType&, const EditPosition&, - bool bCopyAttr ); + SvxRTFItemStackType(const SvxRTFItemStackType&, const EditPosition&, + bool bCopyAttr); ~SvxRTFItemStackType(); //cmc, I'm very suspicious about SetStartPos, it doesn't change //its children's starting position, and the implementation looks |