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 777493 - g_mkdtemp() not introspectable
g_mkdtemp() not introspectable
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: general
2.51.x
Other Linux
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2017-01-19 13:55 UTC by Bastien Nocera
Modified: 2017-01-24 10:08 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
introspection: Skip g_mkdtemp() and friends (1.69 KB, patch)
2017-01-22 05:18 UTC, Philip Chimento
none Details | Review
introspection: Fix introspection for g_mkdtemp() and friends (1.82 KB, patch)
2017-01-23 04:41 UTC, Bastien Nocera
rejected Details | Review
gir: Update annotations from GLib git master (1.56 KB, patch)
2017-01-23 04:41 UTC, Bastien Nocera
rejected Details | Review
gfileutils: Fix g_mkdtemp*() API docs (1.92 KB, patch)
2017-01-23 04:50 UTC, Bastien Nocera
committed Details | Review
gfileutils: Mention g_dir_make_tmp() in g_mkdtemp*() docs (1.48 KB, patch)
2017-01-23 04:50 UTC, Bastien Nocera
none Details | Review
gfileutils: Mention g_dir_make_tmp() in g_mkdtemp*() docs (1.49 KB, patch)
2017-01-24 10:03 UTC, Bastien Nocera
committed Details | Review
introspection: Skip g_mkdtemp() and friends (1.75 KB, patch)
2017-01-24 10:06 UTC, Bastien Nocera
committed Details | Review

Description Bastien Nocera 2017-01-19 13:55:31 UTC
Using mozjs31-31.5.0-1.fc26.x86_64 from Fedora rawhide and gjs and gnome-shell from jhbuild, with the patch below applied on top of gnome-shell, I get a double-free when running gnome-shell-portal-helper (activated through "gapplication launch org.gnome.Shell.PortalHelper" after running the binary).

The patch:
diff --git a/js/portalHelper/main.js b/js/portalHelper/main.js
index 3984642..dbf32cb 100644
--- a/js/portalHelper/main.js
+++ b/js/portalHelper/main.js
@@ -63,8 +63,14 @@ const PortalWindow = new Lang.Class({
         this._doneCallback = doneCallback;
         this._lastRecheck = 0;
         this._recheckAtExit = false;
+        this._cacheDir = GLib.mkdtemp(GLib.get_tmp_dir() + "/XXXXXXXX");
 
-        this._webView = new WebKit.WebView();
+        print (this._cacheDir);
+        let dataManager = new WebKit.WebSite.data_manager({ base_data_directory: this._cacheDir,
+                                                            base_cache_directory: this._cacheDir });
+        let context = new WebKit.WebContext({ website_data_manager: dataManager });
+
+        this._webView = WebKit.WebView.new_with_context(context);
         this._webView.connect('decide-policy', Lang.bind(this, this._onDecidePolicy));
         this._webView.load_uri(url);
         this._webView.connect('notify::title', Lang.bind(this, this._syncTitle));

The crash:
  • #0 raise
    from /lib64/libc.so.6
  • #1 abort
    from /lib64/libc.so.6
  • #2 __libc_message
    from /lib64/libc.so.6
  • #3 free_check
    from /lib64/libc.so.6
  • #4 free
    from /lib64/libc.so.6
  • #5 g_free
    at /home/hadess/Projects/jhbuild/glib/glib/gmem.c line 189
  • #6 gjs_g_arg_release_internal
  • #7 gjs_g_argument_release_in_arg
    at /home/hadess/Projects/jhbuild/gjs/gi/arg.cpp line 3499
  • #8 gjs_invoke_c_function
    at /home/hadess/Projects/jhbuild/gjs/gi/function.cpp line 1147
  • #9 function_call
    at /home/hadess/Projects/jhbuild/gjs/gi/function.cpp line 1323
  • #10 js::CallJSNative
    at /usr/src/debug/mozjs-31.5.0/js/src/jscntxtinlines.h line 239
  • #11 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 475
  • #12 Interpret
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 2620
  • #13 js::RunScript
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 422
  • #14 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 494
  • #15 js_fun_apply
    at /usr/src/debug/mozjs-31.5.0/js/src/jsfun.cpp line 1020
  • #16 js::CallJSNative
    at /usr/src/debug/mozjs-31.5.0/js/src/jscntxtinlines.h line 239
  • #17 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 475
  • #18 Interpret
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 2620
  • #19 js::RunScript
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 422
  • #20 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 494
  • #21 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 531
  • #22 JS_CallFunctionValue
    at /usr/src/debug/mozjs-31.5.0/js/src/jsapi.cpp line 5064
  • #23 gjs_call_function_value
    at /home/hadess/Projects/jhbuild/gjs/gjs/jsapi-util.cpp line 660
  • #24 gjs_object_instance_constructor
    at /home/hadess/Projects/jhbuild/gjs/gi/object.cpp line 1475
  • #25 js::CallJSNative
  • #26 js::CallJSNativeConstructor
  • #27 js::InvokeConstructor
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 572
  • #28 js::InvokeConstructor
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 586
  • #29 js::DirectProxyHandler::construct
    at /usr/src/debug/mozjs-31.5.0/js/src/jsproxy.cpp line 475
  • #30 js::Proxy::construct
    at /usr/src/debug/mozjs-31.5.0/js/src/jsproxy.cpp line 2742
  • #31 js::proxy_Construct
    at /usr/src/debug/mozjs-31.5.0/js/src/jsproxy.cpp line 3135
  • #32 js::CallJSNative
  • #33 js::CallJSNativeConstructor
  • #34 js::InvokeConstructor
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 572
  • #35 Interpret
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 2617
  • #36 js::RunScript
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 422
  • #37 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 494
  • #38 js_fun_apply
    at /usr/src/debug/mozjs-31.5.0/js/src/jsfun.cpp line 1020
  • #39 js::CallJSNative
    at /usr/src/debug/mozjs-31.5.0/js/src/jscntxtinlines.h line 239
  • #40 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 475
  • #41 Interpret
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 2620
  • #42 js::RunScript
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 422
  • #43 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 494
  • #44 js_fun_apply
    at /usr/src/debug/mozjs-31.5.0/js/src/jsfun.cpp line 1020
  • #45 js::CallJSNative
    at /usr/src/debug/mozjs-31.5.0/js/src/jscntxtinlines.h line 239
  • #46 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 475
  • #47 Interpret
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 2620
  • #48 js::RunScript
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 422
  • #49 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 494
  • #50 js_fun_apply
    at /usr/src/debug/mozjs-31.5.0/js/src/jsfun.cpp line 1020
  • #51 js::CallJSNative
    at /usr/src/debug/mozjs-31.5.0/js/src/jscntxtinlines.h line 239
  • #52 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 475
  • #53 Interpret
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 2620
  • #54 js::RunScript
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 422
  • #55 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 494
  • #56 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 531
  • #57 JS_CallFunctionValue
    at /usr/src/debug/mozjs-31.5.0/js/src/jsapi.cpp line 5064
  • #58 gjs_callback_closure
    at /home/hadess/Projects/jhbuild/gjs/gi/function.cpp line 292
  • #59 ffi_closure_unix64_inner
    from /lib64/libffi.so.6
  • #60 ffi_closure_unix64
    from /lib64/libffi.so.6
  • #61 g_cclosure_marshal_VOID__VOID
    at /home/hadess/Projects/jhbuild/glib/gobject/gmarshal.c line 875
  • #62 g_type_class_meta_marshal
    at /home/hadess/Projects/jhbuild/glib/gobject/gclosure.c line 997
  • #63 g_closure_invoke
    at /home/hadess/Projects/jhbuild/glib/gobject/gclosure.c line 804
  • #64 signal_emit_unlocked_R
    at /home/hadess/Projects/jhbuild/glib/gobject/gsignal.c line 3673
  • #65 g_signal_emit_valist
    at /home/hadess/Projects/jhbuild/glib/gobject/gsignal.c line 3391
  • #66 g_signal_emit_by_name
    at /home/hadess/Projects/jhbuild/glib/gobject/gsignal.c line 3487
  • #67 g_application_impl_method_call
    at /home/hadess/Projects/jhbuild/glib/gio/gapplicationimpl-dbus.c line 195
  • #68 call_in_idle_cb
    at /home/hadess/Projects/jhbuild/glib/gio/gdbusconnection.c line 4836
  • #69 g_idle_dispatch
    at /home/hadess/Projects/jhbuild/glib/glib/gmain.c line 5558
  • #70 g_main_dispatch
    at /home/hadess/Projects/jhbuild/glib/glib/gmain.c line 3206
  • #71 g_main_context_dispatch
    at /home/hadess/Projects/jhbuild/glib/glib/gmain.c line 3869
  • #72 g_main_context_iterate
    at /home/hadess/Projects/jhbuild/glib/glib/gmain.c line 3942
  • #73 g_main_context_iteration
    at /home/hadess/Projects/jhbuild/glib/glib/gmain.c line 4003
  • #74 g_application_run
    at /home/hadess/Projects/jhbuild/glib/gio/gapplication.c line 2381
  • #75 ffi_call_unix64
    from /lib64/libffi.so.6
  • #76 ffi_call
    from /lib64/libffi.so.6
  • #77 gjs_invoke_c_function
    at /home/hadess/Projects/jhbuild/gjs/gi/function.cpp line 1002
  • #78 function_call
    at /home/hadess/Projects/jhbuild/gjs/gi/function.cpp line 1323
  • #79 js::CallJSNative
    at /usr/src/debug/mozjs-31.5.0/js/src/jscntxtinlines.h line 239
  • #80 js::Invoke
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 475
  • #81 Interpret
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 2620
  • #82 js::RunScript
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 422
  • #83 js::ExecuteKernel
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 630
  • #84 js::Execute
    at /usr/src/debug/mozjs-31.5.0/js/src/vm/Interpreter.cpp line 667
  • #85 Evaluate
    at /usr/src/debug/mozjs-31.5.0/js/src/jsapi.cpp line 4864
  • #86 Evaluate
    at /usr/src/debug/mozjs-31.5.0/js/src/jsapi.cpp line 4903
  • #87 JS::Evaluate
  • #88 gjs_eval_with_scope
  • #89 gjs_context_eval
  • #90 main
    at /home/hadess/Projects/jhbuild/gnome-shell/src/gnome-shell-portal-helper.c line 39

Comment 1 Philip Chimento 2017-01-20 02:22:07 UTC
This may be another instance of https://bugs.webkit.org/show_bug.cgi?id=116672, but I've recently gotten another report of rawhide GJS crashing, so I'll check this out before claiming it's WebKit's fault :-)
Comment 2 Philip Chimento 2017-01-22 05:18:11 UTC
Here's a shorter reproducer:

const GLib = imports.gi.GLib;
GLib.mkdtemp("XXXXXX");

GJS is confused by the return value and the input argument sharing the same memory, which cannot be represented correctly with a GObject introspection annotation.

I see there are these two closed bugs as well indicating that it is not intended to be fixed:

https://bugzilla.gnome.org/show_bug.cgi?id=679351
https://bugzilla.gnome.org/show_bug.cgi?id=679362

I would suggest using GLib.Dir.make_tmp() instead.

g_mkdtemp() and friends should be annotated (skip) in my opinion. So here's a GLib patch and I'll move the bug over to GLib.
Comment 3 Philip Chimento 2017-01-22 05:18:38 UTC
Created attachment 343973 [details] [review]
introspection: Skip g_mkdtemp() and friends

Based on bugs [1] and [2], gobject-introspection does not handle this
modify-input-and-return pattern correctly, and is not going to.
Therefore, these functions should be skipped in introspection.

[1] https://bugzilla.gnome.org/show_bug.cgi?id=679351
[2] https://bugzilla.gnome.org/show_bug.cgi?id=679362
Comment 4 Bastien Nocera 2017-01-22 16:25:27 UTC
(In reply to Philip Chimento from comment #2)
> Here's a shorter reproducer:
> 
> const GLib = imports.gi.GLib;
> GLib.mkdtemp("XXXXXX");
> 
> GJS is confused by the return value and the input argument sharing the same
> memory, which cannot be represented correctly with a GObject introspection
> annotation.
> 
> I see there are these two closed bugs as well indicating that it is not
> intended to be fixed:
> 
> https://bugzilla.gnome.org/show_bug.cgi?id=679351
> https://bugzilla.gnome.org/show_bug.cgi?id=679362
> 
> I would suggest using GLib.Dir.make_tmp() instead.
> 
> g_mkdtemp() and friends should be annotated (skip) in my opinion. So here's
> a GLib patch and I'll move the bug over to GLib.

Would also be nice to mention g_dir_make_tmp() in the docs for the functions you're marking as skip. It would never have occurred to me to look for this, especially as g_dir_make_tmp() doesn't take a GDir...
Comment 5 Emmanuele Bassi (:ebassi) 2017-01-22 16:46:27 UTC
I'm not entirely sure I agree with skipping the function - even though it is a pretty C-oriented API.

The way `g_mkdtemp()` works is by replacing the six XXXXXX characters in the template buffer with something else; it does not allocate a new string and discard the old one. Using `inout` as the annotation should work.

(In reply to Bastien Nocera from comment #4)

Since you're already use `g_get_tmp_dir()` and GIO, you probably want to use `g_file_new_tmp()` instead: 

  https://developer.gnome.org/gio/stable/GFile.html#g-file-new-tmp

> Would also be nice to mention g_dir_make_tmp() in the docs for the functions
> you're marking as skip. It would never have occurred to me to look for this,
> especially as g_dir_make_tmp() doesn't take a GDir...

This should happen regardless...
Comment 6 Bastien Nocera 2017-01-23 04:41:01 UTC
Created attachment 344012 [details] [review]
introspection: Fix introspection for g_mkdtemp() and friends

Mark g_mkdtemp(), g_mkstemp() and the _full() versions as having "inout"
parameters, making them usable through introspection.
Comment 7 Bastien Nocera 2017-01-23 04:41:27 UTC
Created attachment 344013 [details] [review]
gir: Update annotations from GLib git master
Comment 8 Bastien Nocera 2017-01-23 04:50:31 UTC
That's 2 patches for glib and gobject-introspection, respectively, but gjs still crashes. The valgrind errors make it look like a plain bug in gjs.
Comment 9 Bastien Nocera 2017-01-23 04:50:46 UTC
Created attachment 344014 [details] [review]
gfileutils: Fix g_mkdtemp*() API docs

Don't refer to g_mkdtemp() when documenting g_mkdtemp_full() and
speaking about the function itself, and remove mention of flags in
aforementioned g_mkdtemp_full(), as it doesn't have such an argument
(but g_mkstemp_full() does).
Comment 10 Bastien Nocera 2017-01-23 04:50:53 UTC
Created attachment 344015 [details] [review]
gfileutils: Mention g_dir_make_tmp() in g_mkdtemp*() docs
Comment 11 Philip Chimento 2017-01-23 05:11:39 UTC
There's still no way using g-i annotation to indicate that (In reply to Emmanuele Bassi (:ebassi) from comment #5)
> I'm not entirely sure I agree with skipping the function - even though it is
> a pretty C-oriented API.
> 
> The way `g_mkdtemp()` works is by replacing the six XXXXXX characters in the
> template buffer with something else; it does not allocate a new string and
> discard the old one. Using `inout` as the annotation should work.

I'm not convinced yet. There's still no way to use g-i annotations to indicate that the (out) parameter and the return value point to the same memory. I think we at least need to have a (transfer none) annotation on the return value so that GJS/PyGObject are forced to copy it. Or is it even possible to (skip) the return value?

Otherwise you can end up with two JS/Python strings that point to the same memory. (In JS at least this is possible to have, but the problem is there's no way for the binding to know about it.)

However, I'm inclined to agree with Colin here [1] and say that these functions are not introspectable, since it's really a C convenience API and we already have good bindable alternatives.

[1] https://bugzilla.gnome.org/show_bug.cgi?id=679351#c5
Comment 12 Bastien Nocera 2017-01-23 08:18:30 UTC
(In reply to Philip Chimento from comment #11)
<snip>
> Otherwise you can end up with two JS/Python strings that point to the same
> memory. (In JS at least this is possible to have, but the problem is there's
> no way for the binding to know about it.)

Didn't think about that, so fair point on making those functions "(skip)".
Comment 13 Philip Withnall 2017-01-23 10:25:09 UTC
Review of attachment 344014 [details] [review]:

Ack.
Comment 14 Philip Withnall 2017-01-23 10:29:48 UTC
Review of attachment 344015 [details] [review]:

::: glib/gfileutils.c
@@ +1434,3 @@
  *
+ * If you are going to be creating a temporary directory inside the
+ * preferred directory for temporary files, you might want to use

‘preferred system directory’ perhaps? Otherwise this raises the question of ‘preferred by whom’.
Comment 15 Bastien Nocera 2017-01-23 13:29:21 UTC
(In reply to Philip Withnall from comment #14)
> Review of attachment 344015 [details] [review] [review]:
> 
> ::: glib/gfileutils.c
> @@ +1434,3 @@
>   *
> + * If you are going to be creating a temporary directory inside the
> + * preferred directory for temporary files, you might want to use
> 
> ‘preferred system directory’ perhaps? Otherwise this raises the question of
> ‘preferred by whom’.

It's the same expression used in the documentation for g_dir_make_tmp().
Comment 16 Bastien Nocera 2017-01-23 13:33:47 UTC
Comment on attachment 344014 [details] [review]
gfileutils: Fix g_mkdtemp*() API docs

Attachment 344014 [details] pushed as bc83612 - gfileutils: Fix g_mkdtemp*() API docs
Comment 17 Philip Withnall 2017-01-23 13:55:55 UTC
(In reply to Bastien Nocera from comment #15)
> (In reply to Philip Withnall from comment #14)
> > Review of attachment 344015 [details] [review] [review] [review]:
> > 
> > ::: glib/gfileutils.c
> > @@ +1434,3 @@
> >   *
> > + * If you are going to be creating a temporary directory inside the
> > + * preferred directory for temporary files, you might want to use
> > 
> > ‘preferred system directory’ perhaps? Otherwise this raises the question of
> > ‘preferred by whom’.
> 
> It's the same expression used in the documentation for g_dir_make_tmp().

Yeah, I’m wondering that should be clarified too. I’m open to a second opinion. If we decide to ignore my review comment here, the patch is a_c-n as far as I’m concerned.
Comment 18 Bastien Nocera 2017-01-24 10:03:41 UTC
Created attachment 344101 [details] [review]
gfileutils: Mention g_dir_make_tmp() in g_mkdtemp*() docs
Comment 19 Bastien Nocera 2017-01-24 10:06:36 UTC
Created attachment 344102 [details] [review]
introspection: Skip g_mkdtemp() and friends

Based on bugs [1] and [2], gobject-introspection does not handle the
same string being 1) returned from an inout argument and 2) returned
as the function's return value, and is not going to.
Therefore, these functions should be skipped in introspection.

[1] https://bugzilla.gnome.org/show_bug.cgi?id=679351
[2] https://bugzilla.gnome.org/show_bug.cgi?id=679362
Comment 20 Bastien Nocera 2017-01-24 10:07:51 UTC
Attachment 344101 [details] pushed as 810a6eb - gfileutils: Mention g_dir_make_tmp() in g_mkdtemp*() docs
Attachment 344102 [details] pushed as 4fbcd18 - introspection: Skip g_mkdtemp() and friends