[glom/spread-table] EggSpreadTable: forall(): Avoid use of invalid GList items.



commit f1ee7616b26b0f2c847e52aa37568ecec0b16f6d
Author: Murray Cumming <murrayc murrayc com>
Date:   Mon Nov 8 14:56:45 2010 +0100

    EggSpreadTable: forall(): Avoid use of invalid GList items.
    
    * glom/utility_widgets/eggspreadtable/eggspreadtable.c
    (egg_spread_table_forall):
    Use (and later free) a copy of the list, because the callback could call
    egg_spread_table_remove() which would change the list, causing us to use a
    list->next that is no longer valid. This fixes a problem found by valgrind.
    I don't know why other Gtk containers don't need to do this, though their
    code seems to do the same thing.

 ChangeLog                                          |   12 ++++++++++++
 .../eggspreadtable/eggspreadtable.c                |   15 ++++++++++++---
 2 files changed, 24 insertions(+), 3 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 32530e0..54189b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2010-11-08  Murray Cumming  <murrayc murrayc com>
 
+	EggSpreadTable: forall(): Avoid use of invalid GList items.
+
+	* glom/utility_widgets/eggspreadtable/eggspreadtable.c
+	(egg_spread_table_forall):
+	Use (and later free) a copy of the list, because the callback could call
+	egg_spread_table_remove() which would change the list, causing us to use a
+	list->next that is no longer valid. This fixes a problem found by valgrind.
+	I don't know why other Gtk containers don't need to do this, though their
+	code seems to do the same thing.
+
+2010-11-08  Murray Cumming  <murrayc murrayc com>
+
 	Added test_flowtablewithfields.
 
 	* Makefile_tests.am:
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtable.c b/glom/utility_widgets/eggspreadtable/eggspreadtable.c
index 2e9170e..61556c9 100644
--- a/glom/utility_widgets/eggspreadtable/eggspreadtable.c
+++ b/glom/utility_widgets/eggspreadtable/eggspreadtable.c
@@ -864,10 +864,19 @@ egg_spread_table_forall (GtkContainer *container,
 {
   EggSpreadTable        *table = EGG_SPREAD_TABLE (container);
   EggSpreadTablePrivate *priv = table->priv;
-  GList                 *list;
+  GList                 *list = NULL;
 
-  for (list = priv->children; list; list = list->next)
-    (* callback) ((GtkWidget *)list->data, callback_data);
+  /* We use a copy of the list,
+   * because the callback could call egg_spread_table_remove(),
+   * which would change the list, causing us to use a list->next that
+   * is no longer valid.
+   */
+  for (list = g_list_copy(priv->children); list; list = list->next)
+  {
+    (* callback) (widget, callback_data);
+  }
+
+  g_list_free(list);
 }
 
 static GType



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]