[Libreoffice-commits] core.git: editeng/source include/editeng

Caolán McNamara (via logerrit) logerrit at kemper.freedesktop.org
Sat Feb 13 19:04:01 UTC 2021


 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 <caolanm at redhat.com>
AuthorDate: Fri Feb 12 16:41:11 2021 +0000
Commit:     Caolán McNamara <caolanm at 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 <caolanm at 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&,


More information about the Libreoffice-commits mailing list