diff options
author | Caolán McNamara <caolanm@redhat.com> | 2021-02-12 16:41:11 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2021-02-13 20:03:18 +0100 |
commit | d1b3571fba171279d70ccaa0dfec1871f04439af (patch) | |
tree | f4650357b06aa38acaccb7d15df00b6bfd06b7a6 /editeng | |
parent | 71fa2bc2061168b9a74cdb4b0428b00ea902666f (diff) |
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 <caolanm@redhat.com>
Diffstat (limited to 'editeng')
-rw-r--r-- | editeng/source/rtf/svxrtf.cxx | 48 |
1 files changed, 35 insertions, 13 deletions
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() |