[gjs] closure: Prevent use-after-free in closures
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] closure: Prevent use-after-free in closures
- Date: Wed, 21 Jun 2017 18:02:25 +0000 (UTC)
commit 41b78ae516946cb0753e44df4153dd227fd8a2e0
Author: Philip Chimento <philip chimento gmail com>
Date: Tue Jun 20 19:31:15 2017 -0700
closure: Prevent use-after-free in closures
Closures trace the function object that they call on, in order to keep
the function alive during garbage collection. When the closure is
invalidated, we break that link so the function can be garbage collected,
but we must do so in an idle function, since it is illegal to stop
tracing a GC-thing in the middle of GC.
However, this caused a possible use-after-free if the closure was
scheduled to stop tracing the function object, but the last reference on
the closure was dropped before the idle function could be run.
Similar to the recent fix in gi/object.cpp [commit 2593d3d], this avoids
use-after-free by cancelling any pending idle function in the finalize
notifier, and dropping the function object immediately.
https://bugzilla.gnome.org/show_bug.cgi?id=783935
gi/closure.cpp | 14 ++++++++++++--
1 files changed, 12 insertions(+), 2 deletions(-)
---
diff --git a/gi/closure.cpp b/gi/closure.cpp
index e3ef0ba..6352c7f 100644
--- a/gi/closure.cpp
+++ b/gi/closure.cpp
@@ -35,6 +35,7 @@
struct Closure {
JSContext *context;
GjsMaybeOwned<JSObject *> obj;
+ unsigned idle_clear_id;
};
struct GjsClosure {
@@ -129,6 +130,7 @@ closure_clear_idle(void *data)
closure->priv.obj.reset();
closure->priv.context = nullptr;
+ closure->priv.idle_clear_id = 0;
g_closure_unref(static_cast<GClosure *>(data));
return G_SOURCE_REMOVE;
@@ -174,7 +176,7 @@ closure_invalidated(gpointer data,
"removing our destroy notifier on global object)",
closure);
- g_idle_add(closure_clear_idle, closure);
+ c->idle_clear_id = g_idle_add(closure_clear_idle, closure);
g_closure_ref(closure);
}
@@ -183,7 +185,8 @@ closure_set_invalid(gpointer data,
GClosure *closure)
{
GJS_DEC_COUNTER(closure);
- g_idle_add(closure_clear_idle, closure);
+ Closure *c = &(reinterpret_cast<GjsClosure *>(closure))->priv;
+ c->idle_clear_id = g_idle_add(closure_clear_idle, closure);
g_closure_ref(closure);
}
@@ -193,6 +196,13 @@ closure_finalize(gpointer data,
{
Closure *self = &((GjsClosure*) closure)->priv;
+ if (self->idle_clear_id > 0) {
+ /* Remove any pending closure_clear_idle(), we are doing it
+ * immediately here. */
+ g_source_remove(self->idle_clear_id);
+ closure_clear_idle(closure);
+ }
+
self->~Closure();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]