[glib] g_settings_list_children: only list viable schemas



commit 27898916d42f0e827cf2e99c12ab7bcd0a3712a9
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Aug 8 18:50:21 2013 +0200

    g_settings_list_children: only list viable schemas
    
    Don't return children with invalid schemas from
    g_settings_list_children() (ie: missing schemas or mismatched paths).
    This prevents gsettings list-recursively from crashing when broken
    schemas are installed on the system.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=705688

 gio/gsettingsschema.c |   56 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 55 insertions(+), 1 deletions(-)
---
diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c
index 3592836..fe43b89 100644
--- a/gio/gsettingsschema.c
+++ b/gio/gsettingsschema.c
@@ -701,7 +701,61 @@ g_settings_schema_list (GSettingsSchema *schema,
 
       for (i = 0; i < len; i++)
         if (list[i][0] != '.')
-          schema->items[j++] = g_quark_from_string (list[i]);
+          {
+            if (g_str_has_suffix (list[i], "/"))
+              {
+                /* This is a child.  Check to make sure that
+                 * instantiating the child would actually work before we
+                 * return it from list() and cause a crash.
+                 */
+                GSettingsSchemaSource *source;
+                GVariant *child_schema;
+                GvdbTable *child_table;
+
+                child_schema = gvdb_table_get_raw_value (schema->table, list[i]);
+                if (!child_schema)
+                  continue;
+
+                child_table = NULL;
+
+                for (source = schema_sources; source; source = source->parent)
+                  if ((child_table = gvdb_table_get_table (source->table, g_variant_get_string 
(child_schema, NULL))))
+                    break;
+
+                g_variant_unref (child_schema);
+
+                /* Schema is not found -> don't add it to the list */
+                if (child_table == NULL)
+                  continue;
+
+                /* Make sure the schema is relocatable or at the
+                 * expected path
+                 */
+                if (gvdb_table_has_value (child_table, ".path"))
+                  {
+                    GVariant *path;
+                    gchar *expected;
+                    gboolean same;
+
+                    path = gvdb_table_get_raw_value (child_table, ".path");
+                    expected = g_strconcat (schema->path, list[i], NULL);
+                    same = g_str_equal (expected, g_variant_get_string (path, NULL));
+                    g_variant_unref (path);
+                    g_free (expected);
+
+                    if (!same)
+                      {
+                        gvdb_table_unref (child_table);
+                        continue;
+                      }
+                  }
+
+                gvdb_table_unref (child_table);
+                /* Else, it's good... */
+              }
+
+            schema->items[j++] = g_quark_from_string (list[i]);
+          }
       schema->n_items = j;
 
       g_strfreev (list);


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