[libgnome-keyring] Fix issue where an operation could be cancelled or completed twice



commit 627895abba1b34fbd436968f775134cc5f62754c
Author: Stef Walter <stefw gnome org>
Date:   Tue Jan 31 13:46:03 2012 +0100

    Fix issue where an operation could be cancelled or completed twice
    
     * Ensure that an operation can only be completed or cancelled
       once. Depending on circumstances, this could cause access
       to freed memory.

 library/gkr-callback.c  |   21 ++++++++++++++++-----
 library/gkr-callback.h  |    3 +++
 library/gkr-operation.c |   12 +++++++-----
 3 files changed, 26 insertions(+), 10 deletions(-)
---
diff --git a/library/gkr-callback.c b/library/gkr-callback.c
index 5c45d22..acaa705 100644
--- a/library/gkr-callback.c
+++ b/library/gkr-callback.c
@@ -96,16 +96,27 @@ gkr_callback_invoke_op_string (GkrCallback *cb, const gchar *value)
 }
 
 void
-gkr_callback_invoke_res (GkrCallback *cb, GnomeKeyringResult res)
+gkr_callback_invoke_res (GkrCallback *cb,
+                         GnomeKeyringResult res)
 {
-	gint type;
-
-	g_assert (cb);
-	g_assert (cb->callback);
+	g_assert (cb != NULL);
+	g_assert (cb->callback != NULL);
 
 	if (cb->operation && !gkr_operation_set_result (cb->operation, res))
 		return;
 
+	gkr_callback_invoke_bare (cb, res);
+}
+
+void
+gkr_callback_invoke_bare (GkrCallback *cb,
+                          GnomeKeyringResult res)
+{
+	gint type;
+
+	g_assert (cb != NULL);
+	g_assert (cb->callback != NULL);
+
 	/* When successful can only call one kind of callback */
 	if (res == GNOME_KEYRING_RESULT_OK) {
 		g_assert (cb->type == GKR_CALLBACK_RES);
diff --git a/library/gkr-callback.h b/library/gkr-callback.h
index 1c66cbf..bec9440 100644
--- a/library/gkr-callback.h
+++ b/library/gkr-callback.h
@@ -74,6 +74,9 @@ void         gkr_callback_invoke_op_session       (GkrCallback *cb,
 void         gkr_callback_invoke_op_string        (GkrCallback *cb,
                                                    const gchar *value);
 
+void         gkr_callback_invoke_bare             (GkrCallback *cb,
+                                                   GnomeKeyringResult res);
+
 void         gkr_callback_invoke_res              (GkrCallback *cb,
                                                    GnomeKeyringResult res);
 
diff --git a/library/gkr-operation.c b/library/gkr-operation.c
index d3792b3..fc3ecc9 100644
--- a/library/gkr-operation.c
+++ b/library/gkr-operation.c
@@ -218,8 +218,7 @@ gkr_operation_set_result (GkrOperation *op, GnomeKeyringResult res)
 {
 	g_assert (op);
 	g_assert ((int) res != INCOMPLETE);
-	g_atomic_int_compare_and_exchange (&op->result, INCOMPLETE, res);
-	return g_atomic_int_get (&op->result) == res; /* Success when already set to res */
+	return g_atomic_int_compare_and_exchange (&op->result, INCOMPLETE, res);
 }
 
 static void
@@ -237,7 +236,7 @@ on_complete (GkrOperation *op)
 	/* Free all the other callbacks */
 	operation_clear_callbacks (op);
 
-	gkr_callback_invoke_res (cb, gkr_operation_get_result (op));
+	gkr_callback_invoke_bare (cb, gkr_operation_get_result (op));
 	gkr_callback_free (cb);
 }
 
@@ -366,8 +365,8 @@ callback_with_message (GkrOperation *op, DBusMessage *message)
 {
 	GkrCallback *cb;
 
-	g_assert (op);
-	g_assert (message);
+	g_assert (op != NULL);
+	g_assert (message != NULL);
 
 	cb = g_queue_peek_head (&op->callbacks);
 	g_assert (cb);
@@ -390,6 +389,9 @@ on_pending_call_notify (DBusPendingCall *pending, void *user_data)
 	gkr_debug ("%p: notified: %p", op, pending);
 	g_assert (pending == op->pending);
 
+	if ((int) gkr_operation_get_result (op) != INCOMPLETE)
+		return;
+
 	reply = dbus_pending_call_steal_reply (pending);
 	g_return_if_fail (reply);
 



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