Blob Blame History Raw
From 073a95859c73a12852b0480c64a1a39deac50b15 Mon Sep 17 00:00:00 2001
From: Stef Walter <stefw@gnome.org>
Date: Wed, 30 Jul 2014 15:51:41 +0200
Subject: [PATCH] search-provider: Don't assume handles are still valid

We were crashing when we got back search provider handles from
the shell for objects that no longer existed.

We can't just call gcr_collection_contains() as it assumes that
it's receiving a valid GObject.

So hold a table of all the handles we've returned and update
it via weak references.

https://bugzilla.gnome.org/show_bug.cgi?id=733957
---
 libseahorse/seahorse-search-provider.c | 49 +++++++++++++++++++++++++++-------
 1 file changed, 40 insertions(+), 9 deletions(-)

diff --git a/libseahorse/seahorse-search-provider.c b/libseahorse/seahorse-search-provider.c
index 7133314..ec9a24d 100644
--- a/libseahorse/seahorse-search-provider.c
+++ b/libseahorse/seahorse-search-provider.c
@@ -44,6 +44,7 @@ struct _SeahorseSearchProvider {
 
 	SeahorsePredicate base_predicate;
 	GcrCollection *collection;
+	GHashTable *handles;
 };
 
 struct _SeahorseSearchProviderClass {
@@ -113,6 +114,16 @@ init_predicate (SeahorsePredicate  *predicate,
 	predicate->custom_target = terms;
 }
 
+static void
+on_object_gone (gpointer data,
+		GObject *where_the_object_was)
+{
+	GHashTable *handles = data;
+	gchar *str = g_strdup_printf ("%p", (gpointer)where_the_object_was);
+	g_hash_table_remove (handles, str);
+	g_free (str);
+}
+
 static gboolean
 handle_get_initial_result_set (SeahorseShellSearchProvider2 *skeleton,
                                GDBusMethodInvocation        *invocation,
@@ -133,6 +144,10 @@ handle_get_initial_result_set (SeahorseShellSearchProvider2 *skeleton,
 		if (seahorse_predicate_match (&predicate, l->data)) {
 			char *str = g_strdup_printf("%p", l->data);
 
+			if (!g_hash_table_contains (self->handles, str)) {
+				g_hash_table_insert (self->handles, g_strdup (str), l->data);
+				g_object_weak_ref (l->data, on_object_gone, self->handles);
+			}
 			g_ptr_array_add (array, str);
 		}
 	}
@@ -168,9 +183,8 @@ handle_get_subsearch_result_set (SeahorseShellSearchProvider2 *skeleton,
 	for (i = 0; previous_results[i]; i++) {
 		GObject *object;
 
-		sscanf (previous_results[i], "%p", &object);
-
-		if (!gcr_collection_contains (self->collection, object)) {
+		object = g_hash_table_lookup (self->handles, previous_results[i]);
+		if (!object || !gcr_collection_contains (self->collection, object)) {
 			/* Bogus value */
 			continue;
 		}
@@ -208,9 +222,8 @@ handle_get_result_metas (SeahorseShellSearchProvider2 *skeleton,
 	for (i = 0; results[i]; i++) {
 		GObject *object;
 
-		sscanf (results[i], "%p", &object);
-
-		if (!gcr_collection_contains (self->collection, object)) {
+		object = g_hash_table_lookup (self->handles, results[i]);
+		if (!object || !gcr_collection_contains (self->collection, object)) {
 			/* Bogus value */
 			continue;
 		}
@@ -266,9 +279,8 @@ handle_activate_result (SeahorseShellSearchProvider2 *skeleton,
 	GObject *object;
 	SeahorseKeyManager *key_manager;
 
-	sscanf (identifier, "%p", &object);
-
-	if (!gcr_collection_contains (self->collection, object) ||
+	object = g_hash_table_lookup (self->handles, identifier);
+	if (!object || !gcr_collection_contains (self->collection, object) ||
 	    !SEAHORSE_IS_VIEWABLE (object)) {
 		/* Bogus value */
 		return TRUE;
@@ -381,6 +393,8 @@ seahorse_search_provider_init (SeahorseSearchProvider *self)
 	filtered = seahorse_collection_new_for_predicate (base,
 	                                                  &self->base_predicate, NULL);
 	self->collection = GCR_COLLECTION (filtered);
+
+	self->handles = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 }
 
 gboolean
@@ -422,11 +436,28 @@ seahorse_search_provider_dispose (GObject *object)
 }
 
 static void
+seahorse_search_provider_finalize (GObject *object)
+{
+	SeahorseSearchProvider *self = SEAHORSE_SEARCH_PROVIDER (object);
+	GHashTableIter iter;
+	gpointer value;
+
+	g_hash_table_iter_init (&iter, self->handles);
+	while (g_hash_table_iter_next (&iter, NULL, &value))
+		g_object_weak_unref (value, on_object_gone, self->handles);
+	g_hash_table_destroy (self->handles);
+
+	G_OBJECT_CLASS (seahorse_search_provider_parent_class)->finalize (object);
+}
+
+
+static void
 seahorse_search_provider_class_init (SeahorseSearchProviderClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
 	object_class->dispose = seahorse_search_provider_dispose;
+	object_class->finalize = seahorse_search_provider_finalize;
 }
 
 SeahorseSearchProvider *
-- 
2.1.0