From 5166b8309e1fec33d5122de360ba212ad3107a2c Mon Sep 17 00:00:00 2001 From: John Darrington Date: Mon, 19 Nov 2012 11:15:49 +0100 Subject: [PATCH] Fix possible memory corruption when creating dialogs with selectors. The PsppireSelector widget's class structure contains a map of selectors indexed by the source widget with which they are associated. Until now, that map was never depopulated. This could have caused problems if newly created widgets happened to use the same address as old, destroyed ones. This change removes selectors from the map upon destruction. --- src/ui/gui/psppire-selector.c | 67 +++++++++++++++++++++++++++++++++-- src/ui/gui/psppire-selector.h | 1 + 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/ui/gui/psppire-selector.c b/src/ui/gui/psppire-selector.c index f32cd3edae..372ef3c531 100644 --- a/src/ui/gui/psppire-selector.c +++ b/src/ui/gui/psppire-selector.c @@ -131,10 +131,43 @@ psppire_selector_get_type (void) static GObjectClass * parent_class = NULL; + + +#define SELECTOR_DEBUGGING 0 + +static void +dump_hash_entry (gpointer key, gpointer value, gpointer obj) +{ + GList *item = NULL; + g_print ("Source %p; ", key); + + for (item = g_list_first (value); + item != NULL; + item = g_list_next (item)) + { + g_print ("%p(%p) ", item->data, item); + } + g_print ("\n"); +} + +/* This function is for debugging only */ +void +psppire_selector_show_map (PsppireSelector *obj) +{ + PsppireSelectorClass *class = g_type_class_peek (PSPPIRE_SELECTOR_TYPE); + + g_print ("%s %p\n", __FUNCTION__, obj); + g_hash_table_foreach (class->source_hash, dump_hash_entry, obj); +} + + + static void psppire_selector_dispose (GObject *obj) { PsppireSelector *sel = PSPPIRE_SELECTOR (obj); + PsppireSelectorClass *class = g_type_class_peek (PSPPIRE_SELECTOR_TYPE); + GList *list; if (sel->dispose_has_run) return; @@ -142,6 +175,21 @@ psppire_selector_dispose (GObject *obj) /* Make sure dispose does not run twice. */ sel->dispose_has_run = TRUE; + /* Remove ourself from the source map. If we are the only entry for this source + widget, that will result in an empty list for the source. In that case, we + remove the entire entry too. */ + if ((list = g_hash_table_lookup (class->source_hash, sel->source))) + { + GList *newlist = g_list_remove_link (list, sel->source_litem); + g_list_free (sel->source_litem); + if (newlist == NULL) + g_hash_table_remove (class->source_hash, sel->source); + else + g_hash_table_replace (class->source_hash, sel->source, newlist); + + sel->source_litem = NULL; + } + g_object_unref (sel->dest); g_object_unref (sel->source); @@ -407,6 +455,8 @@ psppire_selector_init (PsppireSelector *selector) selector->row_activate_id = 0; selector->source_select_id = 0; + + selector->source_litem = NULL; } @@ -726,8 +776,15 @@ set_tree_view_source (PsppireSelector *selector) if ( ! (list = g_hash_table_lookup (class->source_hash, selector->source))) { + /* Base case: This widget is currently not the source of + any selector. Create a hash entry and make this selector + the first selector in the list */ + list = g_list_append (list, selector); g_hash_table_insert (class->source_hash, selector->source, list); + + /* Save the list item so that it can be removed later */ + selector->source_litem = list; } else { /* Append this selector to the list and push the @@ -736,9 +793,15 @@ set_tree_view_source (PsppireSelector *selector) if ( NULL == g_list_find (list, selector) ) { if ( selector->primary_requested ) - list = g_list_prepend (list, selector); + { + list = g_list_prepend (list, selector); + selector->source_litem = list; + } else - list = g_list_append (list, selector); + { + list = g_list_append (list, selector); + selector->source_litem = g_list_last (list); + } g_hash_table_replace (class->source_hash, selector->source, list); } } diff --git a/src/ui/gui/psppire-selector.h b/src/ui/gui/psppire-selector.h index f71c3fe21f..33f96c21aa 100644 --- a/src/ui/gui/psppire-selector.h +++ b/src/ui/gui/psppire-selector.h @@ -98,6 +98,7 @@ struct _PsppireSelector gulong source_select_id ; gboolean primary_requested; + GList *source_litem; }; struct _PsppireSelectorClass -- 2.30.2