[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.0' - sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Mon Aug 20 07:46:21 UTC 2018


 sw/source/core/doc/doc.cxx |   49 +++++++++++++++++++++++++++++----------------
 1 file changed, 32 insertions(+), 17 deletions(-)

New commits:
commit 53dfffb5ca85afa3c74b8e7a8f05cb4f2840c477
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Thu Aug 16 13:56:07 2018 +0300
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Mon Aug 20 09:46:01 2018 +0200

    tdf#119294: reimplement fix for tdf#118859
    
    When removing paragraphs with mail mere fields, both field type reference
    and node reference could get invalid, because field type will be destroyed
    when its last field is gone; and node will be destroyed if it is in a fly
    with anchor in another node which gets destroyed.
    
    To avoid use-after-delete, we will use an SwClient on field types, thus
    detecting if a collected field type got destroyed; iterating over fields
    using SwIterator is safe, because removing a node with fields would update
    the iterator.
    
    Change-Id: Id8b555ef7015b13ab70ebb41845d34c477ac6b31
    Reviewed-on: https://gerrit.libreoffice.org/59164
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit c883d5e073d2ac5b2d55126c929d7bf3e6d295e8)
    Reviewed-on: https://gerrit.libreoffice.org/59178
    Reviewed-by: Andras Timar <andras.timar at collabora.com>
    Tested-by: Andras Timar <andras.timar at collabora.com>

diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index 8d29d7872467..a594fe3d1a2c 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -45,6 +45,7 @@
 
 #include <comphelper/string.hxx>
 #include <comphelper/random.hxx>
+#include <o3tl/make_unique.hxx>
 #include <tools/urlobj.hxx>
 #include <tools/poly.hxx>
 #include <tools/multisel.hxx>
@@ -124,7 +125,6 @@
 
 #include <vector>
 #include <map>
-#include <set>
 #include <osl/diagnose.h>
 #include <osl/interlck.h>
 #include <vbahelper/vbaaccesshelper.hxx>
@@ -1341,8 +1341,9 @@ void RemoveOrDeleteContents(SwTextNode* pTextNd, IDocumentContentOperations& xOp
         xOperations.DelFullPara(aPam);
     }
 }
-// Returns the node pointer which needs to hide, or nullptr if this field does not hide a node
-SwTextNode* HandleHidingField(SwFormatField& rFormatField, const SwNodes& rNodes)
+// Returns if the data was actually modified
+bool HandleHidingField(SwFormatField& rFormatField, const SwNodes& rNodes,
+                       IDocumentContentOperations& xOperations)
 {
     SwTextNode* pTextNd;
     if (rFormatField.GetTextField()
@@ -1350,9 +1351,10 @@ SwTextNode* HandleHidingField(SwFormatField& rFormatField, const SwNodes& rNodes
         && pTextNd->GetpSwpHints() && pTextNd->IsHiddenByParaField()
         && &pTextNd->GetNodes() == &rNodes)
     {
-        return pTextNd;
+        RemoveOrDeleteContents(pTextNd, xOperations);
+        return true;
     }
-    return nullptr;
+    return false;
 }
 }
 
@@ -1391,25 +1393,38 @@ bool SwDoc::RemoveInvisibleContent()
     GetIDocumentUndoRedo().StartUndo( SwUndoId::UI_DELETE_INVISIBLECNTNT, nullptr );
 
     {
+        class FieldTypeGuard : public SwClient
+        {
+        public:
+            explicit FieldTypeGuard(SwFieldType* pType)
+                : SwClient(pType)
+            {
+            }
+            const SwFieldType* get() const
+            {
+                return static_cast<const SwFieldType*>(GetRegisteredIn());
+            }
+        };
         // Removing some nodes for one SwFieldIds::Database type might remove the type from
-        // document's field types, or try to remove already removed nodes, invalidating iterators.
-        // So, we need to create own list of nodes prior to removing them.
-        std::set<SwTextNode*> aHiddenNodes;
-        for (const auto* pType : *getIDocumentFieldsAccess().GetFieldTypes())
+        // document's field types, invalidating iterators. So, we need to create own list of
+        // matching types prior to processing them.
+        std::vector<std::unique_ptr<FieldTypeGuard>> aHidingFieldTypes;
+        for (SwFieldType* pType : *getIDocumentFieldsAccess().GetFieldTypes())
         {
             if (FieldCanHidePara(pType->Which()))
+                aHidingFieldTypes.push_back(o3tl::make_unique<FieldTypeGuard>(pType));
+        }
+        for (const auto& pTypeGuard : aHidingFieldTypes)
+        {
+            if (const SwFieldType* pType = pTypeGuard->get())
             {
                 SwIterator<SwFormatField, SwFieldType> aIter(*pType);
-                for (auto* pField = aIter.First(); pField; pField = aIter.Next())
-                    if (SwTextNode* pHiddenNode = HandleHidingField(*pField, GetNodes()))
-                        aHiddenNodes.insert(pHiddenNode);
+                for (SwFormatField* pFormatField = aIter.First(); pFormatField;
+                     pFormatField = aIter.Next())
+                    bRet |= HandleHidingField(*pFormatField, GetNodes(),
+                                              getIDocumentContentOperations());
             }
         }
-        for (SwTextNode* pHiddenNode : aHiddenNodes)
-        {
-            bRet = true;
-            RemoveOrDeleteContents(pHiddenNode, getIDocumentContentOperations());
-        }
     }
 
     // Remove any hidden paragraph (hidden text attribute)


More information about the Libreoffice-commits mailing list