summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2017-04-19 17:49:04 -0300
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2017-04-19 18:59:02 -0300
commit48997c88618757c7859a11cc5285b35aca2d5d36 (patch)
tree43d7d59577b47b7a91151ea8982fcb2667cb4138
parent1e0bbae1c1934aa1ef8cf38b6e387b56d6dd303a (diff)
downloadgjs-48997c88618757c7859a11cc5285b35aca2d5d36.tar.gz
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
-rw-r--r--gi/object.cpp7
1 files changed, 6 insertions, 1 deletions
diff --git a/gi/object.cpp b/gi/object.cpp
index 2f353a0d..d98c1260 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -1152,6 +1152,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 ||
@@ -1163,10 +1165,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