[gcr/wip/fix-hashtable-ordering-assumption: 2/2] gck-mock: Also store objects in the order they are taken



commit 947718be15b325627ad576b7d9fac9f0c5f9b5ed
Author: Iain Lane <iainl gnome org>
Date:   Wed Feb 6 17:39:24 2019 +0000

    gck-mock: Also store objects in the order they are taken
    
    With GLib 2.59, gnome-keyring's `test-login-auto` test fails:
    
      Gcr-CRITICAL **: 14:34:24.126: expected prompt property 'choice-label'
      to be "Automatically unlock this keyring whenever I\342\200\231m
      logged in", but it is instead ""
    
    This is because, in `mock_secret_C_Initialize()` we assign two sets of
    fields to the mock module, one with `CKA_G_LOGIN_COLLECTION` → `CK_TRUE`
    and one with it pointing to `CK_FALSE`.
    
    This variable is used to decide, via `is_login_keyring()`, whether to call
    `setup_unlock_keyring_login()` or `setup_unlock_keyring_other()`. The
    first one sets `choice-label` to the empty string. The second one is
    what we want, and upgrading GLib made it flip.
    
    The reason is the same as the previous fix: the mock-secret-store
    expects to be able to insert items into a hash table and then iterate it
    and get them out in the same order. That was never guaranteed, and now
    doesn't happen.
    
    Let's keep a parallel list which keeps track of the order things were
    added. And then instead of iterating the hash table, we iterate this
    list.
    
    This is a backport of 7aba0e6aadd75fc688bf7f086a620e4dc41da6d0 from
    gnome-keyring.

 gck/gck-mock.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 61 insertions(+), 14 deletions(-)
---
diff --git a/gck/gck-mock.c b/gck/gck-mock.c
index 30b5462..50a033c 100644
--- a/gck/gck-mock.c
+++ b/gck/gck-mock.c
@@ -73,6 +73,7 @@ typedef struct _Session {
 static guint unique_identifier = 100;
 static GHashTable *the_sessions = NULL;
 static GHashTable *the_objects = NULL;
+static GSList *the_objects_list = NULL;
 
 enum {
        PRIVATE_KEY_CAPITALIZE = 3,
@@ -116,6 +117,39 @@ lookup_object (Session *session,
        return NULL;
 }
 
+typedef struct {
+       guint handle;
+       GckAttributes *template; /* owned by the_objects */
+} ObjectData;
+
+       static gint
+list_find_handle (gconstpointer l, gconstpointer r)
+{
+       guint handle;
+       ObjectData *item;
+
+       handle = GPOINTER_TO_UINT (r);
+       item = (ObjectData *) l;
+
+       if (item->handle == handle)
+               return 0;
+
+       return -1;
+}
+
+static void
+insert_template (guint handle, GckAttributes *template)
+{
+       ObjectData *data;
+
+       data = g_new0 (ObjectData, 1);
+       data->handle = handle;
+       data->template = template;
+
+       g_hash_table_insert (the_objects, GUINT_TO_POINTER (handle), template);
+       the_objects_list = g_slist_append (the_objects_list, data);
+}
+
 CK_OBJECT_HANDLE
 gck_mock_module_add_object (GckAttributes *attrs)
 {
@@ -137,7 +171,7 @@ gck_mock_module_add_object (GckAttributes *attrs)
                gck_attributes_unref (attrs);
                attrs = gck_attributes_ref_sink (gck_builder_end (&builder));
        }
-       g_hash_table_insert (the_objects, GUINT_TO_POINTER (handle), attrs);
+       insert_template (handle, attrs);
 
        return handle;
 }
@@ -150,14 +184,16 @@ gck_mock_module_enumerate_objects (CK_SESSION_HANDLE handle, GckMockEnumerator f
        gpointer key;
        gpointer value;
        Session *session;
+       ObjectData *data;
+       GSList *l = NULL;
 
        g_assert (the_objects);
        g_assert (func);
 
        /* Token objects */
-       g_hash_table_iter_init (&iter, the_objects);
-       while (g_hash_table_iter_next (&iter, &key, &value)) {
-               if (!(func) (GPOINTER_TO_UINT (key), value, user_data))
+       for (l = the_objects_list; l != NULL; l = l->next) {
+               data = (ObjectData *) l->data;
+               if (!(func) (data->handle, data->template, user_data))
                        return;
        }
 
@@ -318,8 +354,8 @@ gck_mock_C_Initialize (CK_VOID_PTR pInitArgs)
        gck_builder_init (&builder);
        gck_builder_add_ulong (&builder, CKA_CLASS, CKO_DATA);
        gck_builder_add_string (&builder, CKA_LABEL, "TEST LABEL");
-       g_hash_table_insert (the_objects, GUINT_TO_POINTER (2),
-                            gck_attributes_ref_sink (gck_builder_end (&builder)));
+       insert_template (2,
+                        gck_attributes_ref_sink (gck_builder_end (&builder)));
 
        /* Private capitalize key */
        value = CKM_MOCK_CAPITALIZE;
@@ -333,8 +369,8 @@ gck_mock_C_Initialize (CK_VOID_PTR pInitArgs)
        gck_builder_add_boolean (&builder, CKA_DERIVE, CK_TRUE);
        gck_builder_add_string (&builder, CKA_VALUE, "value");
        gck_builder_add_string (&builder, CKA_GNOME_UNIQUE, "unique1");
-       g_hash_table_insert (the_objects, GUINT_TO_POINTER (PRIVATE_KEY_CAPITALIZE),
-                            gck_attributes_ref_sink (gck_builder_end (&builder)));
+       insert_template (PRIVATE_KEY_CAPITALIZE,
+                        gck_attributes_ref_sink (gck_builder_end (&builder)));
 
        /* Public capitalize key */
        value = CKM_MOCK_CAPITALIZE;
@@ -345,7 +381,7 @@ gck_mock_C_Initialize (CK_VOID_PTR pInitArgs)
        gck_builder_add_boolean (&builder, CKA_PRIVATE, CK_FALSE);
        gck_builder_add_string (&builder, CKA_VALUE, "value");
        gck_builder_add_string (&builder, CKA_GNOME_UNIQUE, "unique2");
-       g_hash_table_insert (the_objects, GUINT_TO_POINTER (PUBLIC_KEY_CAPITALIZE), gck_builder_end 
(&builder));
+       insert_template (PUBLIC_KEY_CAPITALIZE, gck_builder_end (&builder));
 
        /* Private prefix key */
        value = CKM_MOCK_PREFIX;
@@ -357,8 +393,8 @@ gck_mock_C_Initialize (CK_VOID_PTR pInitArgs)
        gck_builder_add_boolean (&builder, CKA_ALWAYS_AUTHENTICATE, CK_TRUE);
        gck_builder_add_string (&builder, CKA_VALUE, "value");
        gck_builder_add_string (&builder, CKA_GNOME_UNIQUE, "unique3");
-       g_hash_table_insert (the_objects, GUINT_TO_POINTER (PRIVATE_KEY_PREFIX),
-                            gck_attributes_ref_sink (gck_builder_end (&builder)));
+       insert_template (PRIVATE_KEY_PREFIX,
+                        gck_attributes_ref_sink (gck_builder_end (&builder)));
 
        /* Private prefix key */
        value = CKM_MOCK_PREFIX;
@@ -369,8 +405,8 @@ gck_mock_C_Initialize (CK_VOID_PTR pInitArgs)
        gck_builder_add_boolean (&builder, CKA_PRIVATE, CK_FALSE);
        gck_builder_add_string (&builder, CKA_VALUE, "value");
        gck_builder_add_string (&builder, CKA_GNOME_UNIQUE, "unique4");
-       g_hash_table_insert (the_objects, GUINT_TO_POINTER (PUBLIC_KEY_PREFIX),
-                            gck_attributes_ref_sink (gck_builder_end (&builder)));
+       insert_template (PUBLIC_KEY_PREFIX,
+                        gck_attributes_ref_sink (gck_builder_end (&builder)));
 
        logged_in = FALSE;
        initialized = TRUE;
@@ -423,6 +459,9 @@ gck_mock_C_Finalize (CK_VOID_PTR pReserved)
        g_hash_table_destroy (the_objects);
        the_objects = NULL;
 
+       g_slist_free_full (the_objects_list, g_free);
+       the_objects_list = NULL;
+
        g_hash_table_destroy (the_sessions);
        the_sessions = NULL;
 
@@ -888,7 +927,7 @@ gck_mock_C_CreateObject (CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
 
        *phObject = ++unique_identifier;
        if (gck_attributes_find_boolean (attrs, CKA_TOKEN, &token) && token)
-               g_hash_table_insert (the_objects, GUINT_TO_POINTER (*phObject), attrs);
+               insert_template (*phObject, attrs);
        else
                g_hash_table_insert (session->objects, GUINT_TO_POINTER (*phObject), attrs);
 
@@ -916,6 +955,7 @@ gck_mock_C_DestroyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
 {
        GckAttributes *attrs;
        Session *session;
+       GSList *list;
        gboolean priv;
 
        session = g_hash_table_lookup (the_sessions, GUINT_TO_POINTER (hSession));
@@ -930,6 +970,13 @@ gck_mock_C_DestroyObject (CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
        }
 
        g_hash_table_remove (the_objects, GUINT_TO_POINTER (hObject));
+       do {
+               list = g_slist_find_custom (the_objects_list, GUINT_TO_POINTER (hObject), list_find_handle);
+               if (list != NULL) {
+                       g_free (list->data);
+                       the_objects_list = g_slist_delete_link (the_objects_list, list);
+               }
+       } while (list != NULL);
        g_hash_table_remove (session->objects, GUINT_TO_POINTER (hObject));
 
        return CKR_OK;


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