editeng/source/rtf/svxrtf.cxx | 48 ++++++++++++++++++++++++++++++------------ include/editeng/svxrtf.hxx | 4 +-- 2 files changed, 37 insertions(+), 15 deletions(-)
New commits: commit d1b3571fba171279d70ccaa0dfec1871f04439af Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Fri Feb 12 16:41:11 2021 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Sat Feb 13 20:03:18 2021 +0100 ofz#29461 flatten SetAttrSet recursion Change-Id: I39a2364371981a177af8ca8dd679038c9543523c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/110828 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/editeng/source/rtf/svxrtf.cxx b/editeng/source/rtf/svxrtf.cxx index 17ef94553ec5..7c1d885323e3 100644 --- a/editeng/source/rtf/svxrtf.cxx +++ b/editeng/source/rtf/svxrtf.cxx @@ -848,14 +848,42 @@ void SvxRTFParser::SetAllAttrOfStk() // end all Attr. and set it into doc for (size_t n = m_AttrSetList.size(); n; ) { auto const& pStkSet = m_AttrSetList[--n]; - SetAttrSet( *pStkSet ); - pStkSet->DropChildList(); + + /* + ofz#29461 SetAttrSet recursively calls SetAttrSet on pStkSet's + 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 linearly + */ + auto bfs = pStkSet->GetBreadthFirstList(); + for (auto it = bfs.begin(); it != bfs.end(); ++it) + { + SvxRTFItemStackType* pNode = *it; + SetAttrSet(*pNode, false); + } + + /* + ofz#13491 SvxRTFItemStackType dtor recursively calls the dtor of its + m_pChildList. The recurse depth can grow sufficiently to trigger + asan. + + iterate through flat-view of those nodes in order of most distant + from root first and release them linearly + */ + for (auto it = bfs.rbegin(); it != bfs.rend(); ++it) + { + SvxRTFItemStackType* pNode = *it; + pNode->m_pChildList.reset(); + } + m_AttrSetList.pop_back(); } } // sets all the attributes that are different from the current -void SvxRTFParser::SetAttrSet( SvxRTFItemStackType &rSet ) +void SvxRTFParser::SetAttrSet(SvxRTFItemStackType &rSet, bool bRecurse) { // Was DefTab never read? then set to default if( !bIsSetDfltTab ) @@ -867,7 +895,7 @@ void SvxRTFParser::SetAttrSet( SvxRTFItemStackType &rSet ) SetAttrInDoc( rSet ); // then process all the children - if (rSet.m_pChildList) + if (bRecurse && rSet.m_pChildList) for (size_t n = 0; n < rSet.m_pChildList->size(); ++n) SetAttrSet( *(*rSet.m_pChildList)[ n ] ); } @@ -963,12 +991,10 @@ SvxRTFItemStackType::SvxRTFItemStackType( distant from root first and release their children linearly */ -void SvxRTFItemStackType::DropChildList() +std::vector<SvxRTFItemStackType*> SvxRTFItemStackType::GetBreadthFirstList() { - if (!m_pChildList || m_pChildList->empty()) - return; - std::vector<SvxRTFItemStackType*> bfs; + std::queue<SvxRTFItemStackType*> aQueue; aQueue.push(this); @@ -984,11 +1010,7 @@ void SvxRTFItemStackType::DropChildList() } } - for (auto it = bfs.rbegin(); it != bfs.rend(); ++it) - { - SvxRTFItemStackType* pNode = *it; - pNode->m_pChildList.reset(); - } + return bfs; } SvxRTFItemStackType::~SvxRTFItemStackType() diff --git a/include/editeng/svxrtf.hxx b/include/editeng/svxrtf.hxx index faff107c1496..70e996068459 100644 --- a/include/editeng/svxrtf.hxx +++ b/include/editeng/svxrtf.hxx @@ -197,7 +197,7 @@ class EDITENG_DLLPUBLIC SvxRTFParser : public SvRTFParser void ClearStyleAttr_( SvxRTFItemStackType& rStkType ); // Sets all the attributes that are different from the current - void SetAttrSet( SvxRTFItemStackType &rSet ); + void SetAttrSet(SvxRTFItemStackType &rSet, bool bRecurse = true); void SetDefault( int nToken, int nValue ); // Execute pard / plain @@ -309,7 +309,7 @@ class SvxRTFItemStackType void Add(std::unique_ptr<SvxRTFItemStackType>); void Compress( const SvxRTFParser& ); - void DropChildList(); + std::vector<SvxRTFItemStackType*> GetBreadthFirstList(); public: SvxRTFItemStackType(const SvxRTFItemStackType&, const EditPosition&, _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits