summaryrefslogtreecommitdiff
path: root/editeng
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2021-02-12 16:41:11 +0000
committerCaolán McNamara <caolanm@redhat.com>2021-02-13 20:03:18 +0100
commitd1b3571fba171279d70ccaa0dfec1871f04439af (patch)
treef4650357b06aa38acaccb7d15df00b6bfd06b7a6 /editeng
parent71fa2bc2061168b9a74cdb4b0428b00ea902666f (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.cxx48
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()