[epiphany] passwords-sync: Fix crash caused by serializing NULL usernames



commit e9dbd958a9e870038d2143fcd0d4911923405d20
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Tue Aug 8 02:58:47 2017 +0300

    passwords-sync: Fix crash caused by serializing NULL usernames
    
    https://bugzilla.gnome.org/show_bug.cgi?id=785947

 lib/sync/ephy-password-manager.c |   35 ++++++++++++++++++++++-----------
 lib/sync/ephy-password-record.c  |   39 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 60 insertions(+), 14 deletions(-)
---
diff --git a/lib/sync/ephy-password-manager.c b/lib/sync/ephy-password-manager.c
index 46f482e..19e46c7 100644
--- a/lib/sync/ephy-password-manager.c
+++ b/lib/sync/ephy-password-manager.c
@@ -244,8 +244,9 @@ ephy_password_manager_cache_remove (EphyPasswordManager *self,
 
   g_assert (EPHY_IS_PASSWORD_MANAGER (self));
   g_assert (self->cache);
-  g_assert (hostname);
-  g_assert (username);
+
+  if (!hostname || !username)
+    return;
 
   usernames = g_hash_table_lookup (self->cache, hostname);
   if (usernames) {
@@ -267,8 +268,9 @@ ephy_password_manager_cache_add (EphyPasswordManager *self,
 
   g_assert (EPHY_IS_PASSWORD_MANAGER (self));
   g_assert (self->cache);
-  g_assert (hostname);
-  g_assert (username);
+
+  if (!hostname || !username)
+    return;
 
   usernames = g_hash_table_lookup (self->cache, hostname);
   for (GSList *l = usernames; l && l->data; l = l->next) {
@@ -290,8 +292,7 @@ populate_cache_cb (GSList   *records,
     const char *hostname = ephy_password_record_get_hostname (record);
     const char *username = ephy_password_record_get_username (record);
 
-    if (username)
-      ephy_password_manager_cache_add (self, hostname, username);
+    ephy_password_manager_cache_add (self, hostname, username);
   }
 
   g_slist_free_full (records, g_object_unref);
@@ -433,8 +434,7 @@ ephy_password_manger_store_record (EphyPasswordManager *self,
                                      ephy_synchronizable_get_server_time_modified (EPHY_SYNCHRONIZABLE 
(record)));
   store_internal (ephy_password_record_get_password (record), attributes, NULL, NULL);
 
-  if (username)
-    ephy_password_manager_cache_add (self, hostname, username);
+  ephy_password_manager_cache_add (self, hostname, username);
 
   g_hash_table_unref (attributes);
 }
@@ -809,10 +809,21 @@ replace_existing_cb (GSList   *records,
 {
   ReplaceRecordAsyncData *data = (ReplaceRecordAsyncData *)user_data;
 
-  /* We only expect one matching record here. */
-  g_assert (g_slist_length (records) == 1);
-
-  ephy_password_manager_forget_record (data->manager, records->data, data->record);
+  for (GSList *l = records; l && l->data; l = l->next) {
+    /* NULL fields can cause the query to match other records too,
+     * so we need to make sure we have the record we've been looking for. */
+    if (!g_strcmp0 (ephy_password_record_get_hostname (records->data),
+                    ephy_password_record_get_hostname (data->record)) &&
+        !g_strcmp0 (ephy_password_record_get_username (records->data),
+                    ephy_password_record_get_username (data->record)) &&
+        !g_strcmp0 (ephy_password_record_get_username_field (records->data),
+                    ephy_password_record_get_username_field (data->record)) &&
+        !g_strcmp0 (ephy_password_record_get_password_field (records->data),
+                    ephy_password_record_get_password_field (data->record))) {
+      ephy_password_manager_forget_record (data->manager, records->data, data->record);
+      break;
+    }
+  }
 
   replace_record_async_data_free (data);
 }
diff --git a/lib/sync/ephy-password-record.c b/lib/sync/ephy-password-record.c
index 99060fd..9e08c9e 100644
--- a/lib/sync/ephy-password-record.c
+++ b/lib/sync/ephy-password-record.c
@@ -334,11 +334,46 @@ ephy_password_record_get_time_password_changed (EphyPasswordRecord *self)
   return self->time_password_changed;
 }
 
+static JsonNode *
+serializable_serialize_property (JsonSerializable *serializable,
+                                 const char       *name,
+                                 const GValue     *value,
+                                 GParamSpec       *pspec)
+{
+  /* Firefox expects null usernames as empty strings. */
+  if (!g_strcmp0 (name, "username") || !g_strcmp0 (name, "usernameField")) {
+    if (g_value_get_string (value) == NULL) {
+      JsonNode *node = json_node_new (JSON_NODE_VALUE);
+      json_node_set_string (node, "");
+      return node;
+    }
+  }
+
+  return json_serializable_default_serialize_property (serializable, name, value, pspec);
+}
+
+static gboolean
+serializable_deserialize_property (JsonSerializable *serializable,
+                                   const char       *name,
+                                   GValue           *value,
+                                   GParamSpec       *pspec,
+                                   JsonNode         *node)
+{
+  if (!g_strcmp0 (name, "username") || !g_strcmp0 (name, "usernameField")) {
+    if (!g_strcmp0 (json_node_get_string (node), "")) {
+      g_value_set_string (value, NULL);
+      return TRUE;
+    }
+  }
+
+  return json_serializable_default_deserialize_property (serializable, name, value, pspec, node);
+}
+
 static void
 json_serializable_iface_init (JsonSerializableIface *iface)
 {
-  iface->serialize_property = json_serializable_default_serialize_property;
-  iface->deserialize_property = json_serializable_default_deserialize_property;
+  iface->serialize_property = serializable_serialize_property;
+  iface->deserialize_property = serializable_deserialize_property;
 }
 
 static const char *


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