Hello community,
here is the log from the commit of package cjs for openSUSE:Factory checked in at 2017-06-29 15:18:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/cjs (Old)
and /work/SRC/openSUSE:Factory/.cjs.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "cjs"
Thu Jun 29 15:18:01 2017 rev:6 rq:506912 version:3.4.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/cjs/cjs.changes 2017-05-27 13:13:10.319555640 +0200
+++ /work/SRC/openSUSE:Factory/.cjs.new/cjs.changes 2017-06-29 15:18:19.265863430 +0200
@@ -1,0 +2,10 @@
+Wed Jun 28 19:20:44 UTC 2017 - sor.alexei@meowr.ru
+
+- Update to version 3.4.2:
+ * tweener: Add undefined property check.
+ * tweener.js: Silence some additional warnings due to
+ missing/unused properties.
+ * object: Prevent use-after-free in signal connections.
+ * util-root: Require GjsMaybeOwned callback to reset.
+
+-------------------------------------------------------------------
Old:
----
cjs-3.4.1.tar.gz
New:
----
cjs-3.4.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ cjs.spec ++++++
--- /var/tmp/diff_new_pack.dF1nwc/_old 2017-06-29 15:18:21.137598845 +0200
+++ /var/tmp/diff_new_pack.dF1nwc/_new 2017-06-29 15:18:21.141598279 +0200
@@ -20,7 +20,7 @@
%define sover 0
%define typelib typelib-1_0-CjsPrivate-1_0
Name: cjs
-Version: 3.4.1
+Version: 3.4.2
Release: 0
Summary: JavaScript module used by Cinnamon
License: MIT and (MPL-1.1 or GPL-2.0+ or LGPL-2.1+)
++++++ cjs-3.4.1.tar.gz -> cjs-3.4.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cjs-3.4.1/cjs/jsapi-util-root.h new/cjs-3.4.2/cjs/jsapi-util-root.h
--- old/cjs-3.4.1/cjs/jsapi-util-root.h 2017-05-23 16:29:10.000000000 +0200
+++ new/cjs-3.4.2/cjs/jsapi-util-root.h 2017-06-26 12:19:31.000000000 +0200
@@ -170,11 +170,12 @@
* to remove it. */
m_has_weakref = false;
- /* The object is still live across this callback. */
+ /* The object is still live entering this callback. The callback
+ * must reset() this wrapper. */
if (m_notify)
m_notify(handle(), m_data);
-
- reset();
+ else
+ reset();
}
public:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cjs-3.4.1/configure.ac new/cjs-3.4.2/configure.ac
--- old/cjs-3.4.1/configure.ac 2017-05-23 16:29:10.000000000 +0200
+++ new/cjs-3.4.2/configure.ac 2017-06-26 12:19:31.000000000 +0200
@@ -3,7 +3,7 @@
m4_define(pkg_major_version, 3)
m4_define(pkg_minor_version, 4)
-m4_define(pkg_micro_version, 1)
+m4_define(pkg_micro_version, 2)
m4_define(pkg_version, pkg_major_version.pkg_minor_version.pkg_micro_version)
m4_define(pkg_int_version, (pkg_major_version * 100 + pkg_minor_version) * 100 + pkg_micro_version)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cjs-3.4.1/debian/changelog new/cjs-3.4.2/debian/changelog
--- old/cjs-3.4.1/debian/changelog 2017-05-23 16:29:10.000000000 +0200
+++ new/cjs-3.4.2/debian/changelog 2017-06-26 12:19:31.000000000 +0200
@@ -1,3 +1,17 @@
+cjs (3.4.2) sonya; urgency=medium
+
+ [ leigh123linux ]
+ * tweener: Add undefined property check (#45)
+
+ [ Michael Webster ]
+ * tweener.js: silence some additional warnings due to missing/unused properties.
+
+ [ leigh123linux ]
+ * object: Prevent use-after-free in signal connections
+ * util-root: Require GjsMaybeOwned callback to reset
+
+ -- Clement Lefebvre Mon, 26 Jun 2017 12:18:57 +0200
+
cjs (3.4.1) sonya; urgency=medium
[ Clement Lefebvre ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cjs-3.4.1/gi/object.cpp new/cjs-3.4.2/gi/object.cpp
--- old/cjs-3.4.1/gi/object.cpp 2017-05-23 16:29:10.000000000 +0200
+++ new/cjs-3.4.2/gi/object.cpp 2017-06-26 12:19:31.000000000 +0200
@@ -55,6 +55,8 @@
#include
#include
+typedef struct _ConnectData ConnectData;
+
struct ObjectInstance {
GIObjectInfo *info;
GObject *gobj; /* NULL if we are the prototype and not an instance */
@@ -62,7 +64,7 @@
GType gtype;
/* a list of all signal connections, used when tracing */
- GList *signals;
+ std::set signals;
/* the GObjectClass wrapped by this JS Object (only used for
prototypes) */
@@ -74,11 +76,11 @@
unsigned js_object_finalized : 1;
};
-typedef struct {
+struct _ConnectData {
ObjectInstance *obj;
- GList *link;
GClosure *closure;
-} ConnectData;
+ unsigned idle_invalidate_id;
+};
static std::stackJS::PersistentRootedObject object_init_list;
static GHashTable *class_init_properties;
@@ -93,7 +95,7 @@
GJS_DEFINE_PRIV_FROM_JS(ObjectInstance, gjs_object_instance_class)
static void disassociate_js_gobject (GObject *gobj);
-static void invalidate_all_signals (ObjectInstance *priv);
+
typedef enum {
SOME_ERROR_OCCURRED = false,
NO_SUCH_G_PROPERTY,
@@ -1220,6 +1222,21 @@
}
static void
+invalidate_all_signals(ObjectInstance *priv)
+{
+ /* Can't loop directly through the items, since invalidating an item's
+ * closure might have the effect of removing the item from the set in the
+ * invalidate notifier */
+ while (!priv->signals.empty()) {
+ /* This will also free cd, through the closure invalidation mechanism */
+ ConnectData *cd = *priv->signals.begin();
+ g_closure_invalidate(cd->closure);
+ /* Erase element if not already erased */
+ priv->signals.erase(cd);
+ }
+}
+
+static void
disassociate_js_gobject(GObject *gobj)
{
ObjectInstance *priv = get_object_qdata(gobj);
@@ -1374,43 +1391,44 @@
}
static void
-invalidate_all_signals(ObjectInstance *priv)
-{
- GList *iter, *next;
-
- for (iter = priv->signals; iter; ) {
- ConnectData *cd = (ConnectData*) iter->data;
- next = iter->next;
-
- /* This will also free cd and iter, through
- the closure invalidation mechanism */
- g_closure_invalidate(cd->closure);
-
- iter = next;
- }
-}
-
-static void
object_instance_trace(JSTracer *tracer,
JSObject *obj)
{
ObjectInstance *priv;
- GList *iter;
priv = (ObjectInstance *) JS_GetPrivate(obj);
if (priv == NULL)
return;
- for (iter = priv->signals; iter; iter = iter->next) {
- ConnectData *cd = (ConnectData *) iter->data;
-
+ for (ConnectData *cd : priv->signals)
gjs_closure_trace(cd->closure, tracer);
- }
for (auto vfunc : priv->vfuncs)
vfunc->js_function.trace(tracer, "ObjectInstance::vfunc");
}
+/* Removing the signal connection data from the list means that the object stops
+ * tracing the JS function objects belonging to the closures. Incremental GC
+ * does not allow that in the middle of a garbage collection. Therefore, we must
+ * do it in an idle handler.
+ */
+static gboolean
+signal_connection_invalidate_idle(void *user_data)
+{
+ auto cd = static_cast(user_data);
+ cd->obj->signals.erase(cd);
+ g_slice_free(ConnectData, cd);
+ return G_SOURCE_REMOVE;
+}
+
+static void
+signal_connection_invalidated(void *data,
+ GClosure *closure)
+{
+ auto cd = static_cast(data);
+ cd->idle_invalidate_id = g_idle_add(signal_connection_invalidate_idle, cd);
+}
+
static void
object_instance_finalize(JSFreeOp *fop,
JSObject *obj)
@@ -1434,7 +1452,31 @@
bool had_toggle_up;
bool had_toggle_down;
- invalidate_all_signals (priv);
+ /* We must invalidate all signal connections now, instead of in an idle
+ * handler, because the object will not exist anymore when we get
+ * around to the idle function. We originally needed to defer these
+ * invalidations to an idle function since the object needs to continue
+ * tracing its signal connections while GC is going on. However, once
+ * the object is finalized, it will not be tracing them any longer
+ * anyway, so it's safe to do them now.
+ *
+ * This is basically the same as invalidate_all_signals(), but does not
+ * defer the invalidation to an idle handler.
+ */
+ for (ConnectData *cd : priv->signals) {
+ /* First remove any pending invalidation, we are doing it now. */
+ if (cd->idle_invalidate_id > 0)
+ g_source_remove(cd->idle_invalidate_id);
+
+ /* We also have to remove the invalidate notifier, which would
+ * otherwise schedule a new pending invalidation. */
+ g_closure_remove_invalidate_notifier(cd->closure, cd,
+ signal_connection_invalidated);
+
+ g_closure_invalidate(cd->closure);
+ g_slice_free(ConnectData, cd);
+ }
+ priv->signals.clear();
if (G_UNLIKELY (priv->gobj->ref_count <= 0)) {
g_error("Finalizing proxy for an already freed object of type: %s.%s\n",
@@ -1568,29 +1610,6 @@
return proto;
}
-/* Removing the signal connection data from the list means that the object stops
- * tracing the JS function objects belonging to the closures. Incremental GC
- * does not allow that in the middle of a garbage collection. Therefore, we must
- * do it in an idle handler.
- */
-static gboolean
-signal_connection_invalidate_idle(void *user_data)
-{
- ConnectData *connect_data = (ConnectData *) user_data;
-
- connect_data->obj->signals = g_list_delete_link(connect_data->obj->signals,
- connect_data->link);
- g_slice_free(ConnectData, connect_data);
- return G_SOURCE_REMOVE;
-}
-
-static void
-signal_connection_invalidated(void *data,
- GClosure *closure)
-{
- g_idle_add(signal_connection_invalidate_idle, data);
-}
-
static bool
real_connect_func(JSContext *context,
unsigned argc,
@@ -1644,9 +1663,8 @@
goto out;
connect_data = g_slice_new(ConnectData);
- priv->signals = g_list_prepend(priv->signals, connect_data);
+ priv->signals.insert(connect_data);
connect_data->obj = priv;
- connect_data->link = priv->signals;
/* This is a weak reference, and will be cleared when the closure is invalidated */
connect_data->closure = closure;
g_closure_add_invalidate_notifier(closure, connect_data, signal_connection_invalidated);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cjs-3.4.1/modules/tweener/tweener.js new/cjs-3.4.2/modules/tweener/tweener.js
--- old/cjs-3.4.1/modules/tweener/tweener.js 2017-05-23 16:29:10.000000000 +0200
+++ new/cjs-3.4.2/modules/tweener/tweener.js 2017-06-26 12:19:31.000000000 +0200
@@ -508,6 +508,7 @@
if (scopes[i][istr] == undefined)
log("The property " + istr + " doesn't seem to be a normal object property of " + scopes[i] + " or a registered special property");
}
+ properties[istr].isSpecialProperty = false;
}
}
}
@@ -542,11 +543,11 @@
copyProperties[istr] = new PropertyInfo(properties[istr].valueStart,
properties[istr].valueComplete,
properties[istr].valueComplete,
- properties[istr].arrayIndex,
+ properties[istr].arrayIndex || 0,
{},
properties[istr].isSpecialProperty,
- properties[istr].modifierFunction,
- properties[istr].modifierParameters);
+ properties[istr].modifierFunction || null,
+ properties[istr].modifierParameters || null);
}
}
@@ -555,7 +556,7 @@
_ticker.getTime() + (((delay * 1000) + (time * 1000)) / _timeScale),
false,
transition,
- obj.transitionParams);
+ obj.transitionParams || null);
tween.properties = isCaller ? null : copyProperties;
tween.onStart = obj.onStart;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/cjs-3.4.1/test/gjs-test-rooting.cpp new/cjs-3.4.2/test/gjs-test-rooting.cpp
--- old/cjs-3.4.1/test/gjs-test-rooting.cpp 2017-05-23 16:29:10.000000000 +0200
+++ new/cjs-3.4.2/test/gjs-test-rooting.cpp 2017-06-26 12:19:31.000000000 +0200
@@ -13,6 +13,8 @@
bool finalized;
bool notify_called;
+
+ GjsMaybeOwned *obj; /* only used in callback test cases */
};
static void
@@ -220,6 +222,7 @@
g_assert_false(fx->notify_called);
g_assert_false(fx->finalized);
fx->notify_called = true;
+ fx->obj->reset();
}
static void
@@ -233,24 +236,24 @@
test_maybe_owned_notify_callback_called_on_context_destroy(GjsRootingFixture *fx,
gconstpointer unused)
{
- auto obj = new GjsMaybeOwned();
- obj->root(PARENT(fx)->cx, test_obj_new(fx), context_destroyed, fx);
+ fx->obj = new GjsMaybeOwned();
+ fx->obj->root(PARENT(fx)->cx, test_obj_new(fx), context_destroyed, fx);
gjs_unit_test_destroy_context(PARENT(fx));
g_assert_true(fx->notify_called);
- delete obj;
+ delete fx->obj;
}
static void
test_maybe_owned_object_destroyed_after_notify(GjsRootingFixture *fx,
gconstpointer unused)
{
- auto obj = new GjsMaybeOwned();
- obj->root(PARENT(fx)->cx, test_obj_new(fx), context_destroyed, fx);
+ fx->obj = new GjsMaybeOwned();
+ fx->obj->root(PARENT(fx)->cx, test_obj_new(fx), context_destroyed, fx);
gjs_unit_test_destroy_context(PARENT(fx));
g_assert_true(fx->finalized);
- delete obj;
+ delete fx->obj;
}
void