Editing keyboard shortcuts in gnome-terminal and mate-terminal creates use-after-free on grab object
Reported in Ubuntu Launchpad:
Main ubuntu bug for the problem: https://bugs.launchpad.net/ubuntu/+source/gtk+3.0/+bug/1438014
Reposting some results from https://bugs.launchpad.net/ubuntu/+source/mate-terminal/+bug/1667227 and https://bugs.launchpad.net/ubuntu/+source/gnome-terminal/+bug/1667232
Steps to reproduce
- Open mate-terminal or gnome-terminal
- Select menu "Edit" -> "Keyboard Shortcuts"
- Change some shortcuts several times, for example find "Help"->"Contents", click on default shortcut key "F1" to change it. Sometimes bug is triggered by pressing "Fn" key with some of Alt/Ctrl/Shift, sometimes by selecting Ctrl-Shift-W / Crtl-Shift-Alt-W
Current behavior
Crashes inside window_group_cleanup_grabs
g_type_check_instance_is_a (type_instance=type_instance@entry=0x2580c30, iface_type=<optimized out>) at /build/buildd/glib2.0-2.43.92/./gobject/gtype.c:4016
gtk_widget_get_toplevel (widget=0x2580c30) at /build/buildd/gtk+3.0-3.14.9/./gtk/gtkwidget.c:11382
window_group_cleanup_grabs (group=<optimized out>, window=window@entry=0x252a230) at /build/buildd/gtk+3.0-3.14.9/./gtk/gtkwindowgroup.c:110
gtk_window_group_add_window (window_group=0x27e5c40, window=0x252a230) at /build/buildd/gtk+3.0-3.14.9/./gtk/gtkwindowgroup.c:169
gtk_window_set_transient_for (window=0x252a230, parent=0x23ac7d0) at /build/buildd/gtk+3.0-3.14.9/./gtk/gtkwindow.c:3134
Warnings in console like
(mate-terminal:14703): Gtk-CRITICAL **: gtk_widget_get_toplevel: assertion 'GTK_IS_WIDGET (widget)' failed
Valgrind can detect "Invalid read of size 8" .. Address ...is 344 bytes inside a block of size 416 free'd
Expected outcome
Changed keyboard shortcut without crashes.
Version information
Ubuntu-MATE 17.04 "Zesty Zapus" - amd64
mate-terminal: 1.17.0-0ubuntu1
gnome-terminal: 3.20.2-1ubuntu5
gtk+ versions tested 3.16.7, 3.18.9, 3.20.9, 3.22.8
Additional information
This is use-after-free due to incorrect grab deregistration (gtk_grab_remove
tries to remove the grab not from the same window_group where it was added by gtk_grab_add
)
I think that this gnome-terminal grab use-after-free after editing keyboard shortcuts may be not related to the ubuntu/debian patch "debian/patches/016_no_offscreen_widgets_grabbing.patch". That patch only helps to report Critical to the log:
(mate-terminal:14703): Gtk-CRITICAL **: gtk_widget_get_toplevel: assertion 'GTK_IS_WIDGET (widget)' failed
Both gtk_grab_add
and gtk_grab_remove
calls gtk_main_get_window_group
function, but it returns different results for these two calls (more details at https://bugs.launchpad.net/ubuntu/+source/mate-terminal/+bug/1667227/comments/8)
static GtkWindowGroup *
gtk_main_get_window_group (GtkWidget *widget)
...
if (GTK_IS_WINDOW (toplevel))
return gtk_window_get_group (GTK_WINDOW (toplevel));
else
return gtk_window_get_group (NULL);
At the time of gtk_grab_add
(called from gtk_cell_renderer_accel_start_editing
which is called from gtk_cell_renderer_start_editing
) this widget had window = 0x0
and parent = 0x0
And at time of gtk_grab_remove
(called from gtk_cell_editable_event_box_key_press_event
) same widget had window = 0x555555e507e0
(parent = 0x555555e183f0
) which leads to incorrect deregistration of the grab (it was not deregistered; and the object was freed; stale pointer kept in another window group and accessed from window_group_cleanup_grabs
).
Parent of the widget was changed after gtk_grab_add
by gtk_tree_view_multipress_gesture_pressed
-> .. -> gtk_cell_area_activate_cell
-> gtk_cell_area_add_editable
-> ..signal.. -> gtk_tree_view_column_add_editable_callback
-> _gtk_tree_view_add_editable
-> gtk_tree_view_put
-> gtk_widget_set_parent
So, gtk_cell_area_activate_cell
of gtk+3 (3.22.7) has some kind of incorrect ordering of actions which broke gtk_grab_add
/ gtk_grab_remove
pair by calling gtk_grab_add
before setting correct window/widget parent
https://github.com/GNOME/gtk/blob/6cc08d60efeb02afc0d67982c3dc205dfd16d7cd/gtk/gtkcellarea.c#L3388
3428 gtk_cell_renderer_start_editing (renderer,
...
3444 gtk_cell_area_add_editable (area, priv->focus_cell, editable_widget, cell_area);
I was able to disable the crash with this quick (and incorrect) fix in with forcing of grab removal from gtk_window_get_group (NULL)
https://launchpadlibrarian.net/308873213/lp1667227_quick_fix_gtk_grab_remove.gtk+3.22.8.patch