summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2018-08-02 06:29:33 +0000
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>2018-08-16 07:50:31 +0000
commitc1726717bd22707c3d77d36afc16eb190b0c04ed (patch)
tree950e0436fc96a9e1a17158bc01bec18d3bd7dad6
parentc9f875bd770bf99ee61ba6b7098e5ca018925f82 (diff)
downloadgtk+-cherry-pick-5596feae.tar.gz
listbox: Store child iter in a variable when removingcherry-pick-5596feae
Unparenting a GtkListBoxRow can drop its last reference, which will free its memory. Right after unparenting, though, we were accessing the row's iter - which assumes that the row is still alive. This causes a crash when, for example, binding two or more models to the listbox. Fix that by storing the iter in a variable, and not trying to access it after unparenting. After unparenting, the variables that are potentially garbage were explicitly assigned NULL for clarity. Fixes https://gitlab.gnome.org/GNOME/gtk/issues/1258 (cherry picked from commit 5596feae9b51563a33f1bffc6a370e6ba556adb7)
-rw-r--r--gtk/gtklistbox.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c
index 6fc931498a..eed5abbadf 100644
--- a/gtk/gtklistbox.c
+++ b/gtk/gtklistbox.c
@@ -2480,6 +2480,7 @@ gtk_list_box_remove (GtkContainer *container,
gboolean was_visible;
gboolean was_selected;
GtkListBoxRow *row;
+ GSequenceIter *iter;
GSequenceIter *next;
was_visible = gtk_widget_get_visible (child);
@@ -2503,7 +2504,8 @@ gtk_list_box_remove (GtkContainer *container,
}
row = GTK_LIST_BOX_ROW (child);
- if (g_sequence_iter_get_sequence (ROW_PRIV (row)->iter) != priv->children)
+ iter = ROW_PRIV (row)->iter;
+ if (g_sequence_iter_get_sequence (iter) != priv->children)
{
g_warning ("Tried to remove non-child %p", child);
return;
@@ -2539,9 +2541,15 @@ gtk_list_box_remove (GtkContainer *container,
if (row == priv->drag_highlighted_row)
gtk_list_box_drag_unhighlight_row (box);
- next = gtk_list_box_get_next_visible (box, ROW_PRIV (row)->iter);
+ next = gtk_list_box_get_next_visible (box, iter);
gtk_widget_unparent (child);
- g_sequence_remove (ROW_PRIV (row)->iter);
+ g_sequence_remove (iter);
+
+ /* After unparenting, those values are garbage */
+ iter = NULL;
+ row = NULL;
+ child = NULL;
+
if (gtk_widget_get_visible (widget))
gtk_list_box_update_header (box, next);