[gjs/gnome-3-24] object: Avoid modifying weak_pointer_list while iterating it



commit d32ac778305913bc89ee35f7e7f42b50a9c1f2e4
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Wed Apr 19 17:49:04 2017 -0300

    object: Avoid modifying weak_pointer_list while iterating it
    
    Inside update_heap_wrapper_weak_pointers(), we disassociate the
    object while iterating over weak_pointer_list. It is possible,
    however, that that disassociating the object causes the weak
    pointer to be disposed, which will then call wrapped_gobj_dispose_notify(),
    which will modify weak_pointer_list again, while the update_heap...
    function is still iterating.
    
    This will left weak_pointer_list with a dangling pointer and
    will cause a crash.
    
    Fix that by storing the to-be-disassociated objects in a temporary
    list, wait for the iteration over weak_pointer_list finish, and
    then disassociate it.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=781194

 gi/object.cpp |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index a87c5f9..1017eec 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -1323,6 +1323,8 @@ static void
 update_heap_wrapper_weak_pointers(JSRuntime *rt,
                                   gpointer   data)
 {
+    std::vector<GObject *> to_be_disassociated;
+
     for (auto iter = weak_pointer_list.begin(); iter != weak_pointer_list.end(); ) {
         ObjectInstance *priv = *iter;
         if (priv->keep_alive.rooted() || priv->keep_alive == nullptr ||
@@ -1334,10 +1336,13 @@ update_heap_wrapper_weak_pointers(JSRuntime *rt,
              * the weak pointer list first, since the disassociation
              * may also cause it to be erased.)
              */
+            to_be_disassociated.push_back(priv->gobj);
             iter = weak_pointer_list.erase(iter);
-            disassociate_js_gobject(priv->gobj);
         }
     }
+
+    for (GObject *gobj : to_be_disassociated)
+        disassociate_js_gobject(gobj);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]