After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 761659 - Crash invoking signal handler with array + length param
Crash invoking signal handler with array + length param
Status: RESOLVED FIXED
Product: gjs
Classification: Bindings
Component: general
1.45.x
Other Mac OS
: Normal normal
: ---
Assigned To: gjs-maint
gjs-maint
Depends on:
Blocks:
 
 
Reported: 2016-02-07 04:20 UTC by Philip Chimento
Modified: 2016-02-09 07:17 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gi: Marshal variable array-typed signal arguments (10.68 KB, patch)
2016-02-07 04:20 UTC, Philip Chimento
none Details | Review
tests: Add regression test for signal w. array+len (11.40 KB, patch)
2016-02-07 04:35 UTC, Philip Chimento
committed Details | Review
gi: Marshal variable array-typed signal arguments (10.69 KB, patch)
2016-02-09 06:18 UTC, Philip Chimento
committed Details | Review

Description Philip Chimento 2016-02-07 04:20:27 UTC
When connected to a signal whose parameters include an array with separate length parameter, GJS crashes if the signal is ever emitted.

Here's an example:

    const Gio = imports.gi.Gio;
    let app = new Gio.Application({
        application_id: 'com.example.Application',
        flags: Gio.ApplicationFlags.HANDLES_OPEN,
    });
    app.connect('open', function () {});
    app.run(['foo', 'bar', 'baz']);

The crash is an assertion failure in gjs_array_from_fixed_size_array(), which shouldn't be called on an array with length parameter. Indeed, the calling code at arg.cpp:2801 has this comment: "arrays with length are handled outside of this function."

Here's a patch that adds tests for this case and fixes the problem in the signal marshaller.

Note I added a few commented-out tests as well, since it's still not possible to _emit_ a signal with array + length param from within GJS, but this patch makes it possible to  _handle_ such a signal emitted from C.
Comment 1 Philip Chimento 2016-02-07 04:20:58 UTC
Created attachment 320563 [details] [review]
gi: Marshal variable array-typed signal arguments

It can happen that we need to marshal a closure parameter which is a
GValue holding a pointer to an array, with the array length passed in as
a separate parameter. For example, GApplication::open is such a signal.

Previously, the pointer GValue would be sent to
gjs_value_from_g_value_internal() which sends it on to
gjs_value_from_g_argument(), which states in its code that arrays with
explicit length parameters should be handled elsewhere. Normally they are
indeed handled elsewhere (see e.g. gjs_invoke_c_function() in
function.cpp) but in closure_marshal() they are not.

This adds code to closure_marshal() that handles that case, also removing
the length parameter from the arguments passed to the closure.

It also adds some tests for this case (requires update to
gobject-introspection) and a similar case that was until now untested,
namely passing an array with length parameter out of an introspected
function.

Lastly, it adds some asserts to gjs_value_from_g_value_internal() and
gjs_value_from_g_argument() which try to give a hint what's going wrong
when you call those functions without having checked for this case.
Comment 2 Philip Chimento 2016-02-07 04:35:36 UTC
Created attachment 320564 [details] [review]
tests: Add regression test for signal w. array+len

This is a regression test for marshalling callback arguments from signals
with an array parameter and separate length parameter into closures in
the introspected language.
Comment 3 Cosimo Cecchi 2016-02-08 22:02:37 UTC
Review of attachment 320563 [details] [review]:

Looks mostly good - some comments below.

::: gi/value.cpp
@@ +203,3 @@
+     * before we invoke the closure.
+     */
+    skip = g_new0(gboolean, argc);

Could you use g_newa() here like elsewhere in the function to avoid hitting the memory allocator?

@@ +212,3 @@
+    if (signal_info && argc > 1) {
+        /* Start at argument 1, skip the instance parameter */
+    for(i = 0; i < argc; i++)

You could avoid the argc > 1 condition in the outer if block, as this won't run anyway.

@@ +228,3 @@
+        }
+
+            GIArgInfo *arg_info;

It looks like this is leaked when argc == 1
Comment 4 Cosimo Cecchi 2016-02-08 22:04:09 UTC
Review of attachment 320564 [details] [review]:

Looks good.
Comment 5 Philip Chimento 2016-02-09 06:18:57 UTC
Created attachment 320685 [details] [review]
gi: Marshal variable array-typed signal arguments

It can happen that we need to marshal a closure parameter which is a
GValue holding a pointer to an array, with the array length passed in as
a separate parameter. For example, GApplication::open is such a signal.

Previously, the pointer GValue would be sent to
gjs_value_from_g_value_internal() which sends it on to
gjs_value_from_g_argument(), which states in its code that arrays with
explicit length parameters should be handled elsewhere. Normally they are
indeed handled elsewhere (see e.g. gjs_invoke_c_function() in
function.cpp) but in closure_marshal() they are not.

This adds code to closure_marshal() that handles that case, also removing
the length parameter from the arguments passed to the closure.

It also adds some tests for this case (requires update to
gobject-introspection) and a similar case that was until now untested,
namely passing an array with length parameter out of an introspected
function.

Lastly, it adds some asserts to gjs_value_from_g_value_internal() and
gjs_value_from_g_argument() which try to give a hint what's going wrong
when you call those functions without having checked for this case.
Comment 6 Philip Chimento 2016-02-09 06:20:55 UTC
(In reply to Cosimo Cecchi from comment #3)
> ::: gi/value.cpp
> @@ +228,3 @@
> +        }
> +
> +            GIArgInfo *arg_info;
> 
> It looks like this is leaked when argc == 1

Removing the argc > 1 condition fixed this leak without actually changing anything.

Thanks for the review, here's the updated patch.
Comment 7 Philip Chimento 2016-02-09 06:23:44 UTC
Comment on attachment 320564 [details] [review]
tests: Add regression test for signal w. array+len

Attachment 320564 [details] pushed as cd355e8 - tests: Add regression test for signal w. array+len
Comment 8 Cosimo Cecchi 2016-02-09 06:36:41 UTC
Review of attachment 320685 [details] [review]:

Thanks, looks good.
Comment 9 Philip Chimento 2016-02-09 07:16:56 UTC
Attachment 320685 [details] pushed as 67d7d2d - gi: Marshal variable array-typed signal arguments