Invalid memory accesses if keeping a GtkNativeDialog not alive long enough
This is an easy mistake people seem to make all the time with bindings that do automatic memory management, because unlike other widgets they are not kept alive by GTK.
User code has to explicitly keep the native dialog around or otherwise it will be immediately unreffed and finalized, like below in the corresponding C code.
While it's a logic bug in user code (the dialog should be kept alive), this shouldn't cause invalid memory accesses that potentially lead to crashes.
#include <gtk/gtk.h>
static void
build_ui (GtkApplication * app)
{
GtkWidget *window = gtk_application_window_new (app);
gtk_window_present (GTK_WINDOW (window));
GtkFileChooserNative *chooser = gtk_file_chooser_native_new ("Save File",
GTK_WINDOW (window),
GTK_FILE_CHOOSER_ACTION_SAVE,
"_Save",
"_Cancel");
gtk_native_dialog_show (GTK_NATIVE_DIALOG (chooser));
g_object_unref (chooser);
}
int
main (int argc, char *argv[])
{
GtkApplication *app = gtk_application_new (NULL, G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (build_ui), NULL);
return g_application_run (G_APPLICATION (app), argc, argv);
}
valgrind complains about the following, some users reported that it even segfaults.
Gtk-Message: 16:25:32.534: GtkDialog mapped without a transient parent. This is discouraged.
==71531== Invalid read of size 1
==71531== at 0x4C16E44: network_enumeration_next_files_finished (gtkplacesview.c:1006)
==71531== by 0x519E526: next_async_callback_wrapper (gfileenumerator.c:305)
==71531== by 0x51E42E8: g_task_return_now (gtask.c:1215)
==71531== by 0x51E4DDA: g_task_return.part.0 (gtask.c:1285)
==71531== by 0x93D268F: _g_task_return_pointer_idle_cb (gdaemonfileenumerator.c:386)
==71531== by 0x5589C3E: g_main_dispatch (gmain.c:3325)
==71531== by 0x5589C3E: g_main_context_dispatch (gmain.c:4043)
==71531== by 0x5589FE7: g_main_context_iterate.constprop.0 (gmain.c:4119)
==71531== by 0x558A09E: g_main_context_iteration (gmain.c:4184)
==71531== by 0x5212424: g_application_run (gapplication.c:2559)
==71531== by 0x10938B: main (tset.c:38)
==71531== Address 0xa5091c8 is 616 bytes inside a block of size 632 free'd
==71531== at 0x48399AB: free (vg_replace_malloc.c:538)
==71531== by 0x53446A3: g_type_free_instance (gtype.c:1939)
==71531== by 0x4C16E43: network_enumeration_next_files_finished (gtkplacesview.c:1002)
==71531== by 0x519E526: next_async_callback_wrapper (gfileenumerator.c:305)
==71531== by 0x51E42E8: g_task_return_now (gtask.c:1215)
==71531== by 0x51E4DDA: g_task_return.part.0 (gtask.c:1285)
==71531== by 0x93D268F: _g_task_return_pointer_idle_cb (gdaemonfileenumerator.c:386)
==71531== by 0x5589C3E: g_main_dispatch (gmain.c:3325)
==71531== by 0x5589C3E: g_main_context_dispatch (gmain.c:4043)
==71531== by 0x5589FE7: g_main_context_iterate.constprop.0 (gmain.c:4119)
==71531== by 0x558A09E: g_main_context_iteration (gmain.c:4184)
==71531== by 0x5212424: g_application_run (gapplication.c:2559)
==71531== by 0x10938B: main (tset.c:38)
==71531== Block was alloc'd at
==71531== at 0x483877F: malloc (vg_replace_malloc.c:307)
==71531== by 0x558FC18: g_malloc (gmem.c:106)
==71531== by 0x55A7C3D: g_slice_alloc (gslice.c:1069)
==71531== by 0x55A82A9: g_slice_alloc0 (gslice.c:1095)
==71531== by 0x534434B: g_type_create_instance (gtype.c:1839)
==71531== by 0x532A604: g_object_new_internal (gobject.c:1939)
==71531== by 0x532BB0C: g_object_new_with_properties (gobject.c:2107)
==71531== by 0x532C5E0: g_object_new (gobject.c:1779)
==71531== by 0x4985C2F: _gtk_builder_construct (gtkbuilder.c:847)
==71531== by 0x4987B9C: builder_construct (gtkbuilderparser.c:468)
==71531== by 0x4987B9C: builder_construct (gtkbuilderparser.c:453)
==71531== by 0x498A46A: end_element (gtkbuilderparser.c:1933)
==71531== by 0x498A46A: end_element (gtkbuilderparser.c:1836)
==71531== by 0x4987CB9: proxy_end_element (gtkbuilderparser.c:101)
Edited by Sebastian Dröge