gvdb-reader: drop gvdb_table_walk()

The attempt at the simple method for preventing unbounded recursion
proved to be insufficient due to the existence of dconf databases in the
wild that violated the rule (leading to the entire content of the
database being scrapped).  It also still had the ugly assert for less
than 64 levels of recursion that could have been hit by a determined
advisary.

gvdb_table_get_names() allows the dconf-service to do everything it
needs without the troubles associated with the walk approach.
This commit is contained in:
Ryan Lortie 2012-07-09 15:23:39 -04:00
parent d9577f100b
commit fc37611a97
2 changed files with 0 additions and 146 deletions

View File

@ -348,18 +348,6 @@ gvdb_table_lookup (GvdbTable *file,
return NULL;
}
static const struct gvdb_hash_item *
gvdb_table_get_item (GvdbTable *table,
guint32_le item_no)
{
guint32 item_no_native = guint32_from_le (item_no);
if G_LIKELY (item_no_native < table->n_hash_items)
return table->hash_items + item_no_native;
return NULL;
}
static gboolean
gvdb_table_list_from_item (GvdbTable *table,
const struct gvdb_hash_item *item,
@ -798,118 +786,3 @@ gvdb_table_is_valid (GvdbTable *table)
{
return !!*table->data;
}
/**
* gvdb_table_walk:
* @table: a #GvdbTable
* @key: a key corresponding to a list
* @open_func: the #GvdbWalkOpenFunc
* @value_func: the #GvdbWalkValueFunc
* @close_func: the #GvdbWalkCloseFunc
* @user_data: data to pass to the callbacks
*
* Looks up the list at @key and iterate over the items in it.
*
* First, @open_func is called to signal that we are starting to iterate over
* the list. Then the list is iterated. When all items in the list have been
* iterated over, the @close_func is called.
*
* When iterating, if a given item in the list is a value then @value_func is
* called.
*
* If a given item in the list is itself a list then @open_func is called. If
* that function returns %TRUE then the walk begins iterating the items in the
* sublist, until there are no more items, at which point a matching
* @close_func call is made. If @open_func returns %FALSE then no iteration of
* the sublist occurs and no corresponding @close_func call is made.
**/
void
gvdb_table_walk (GvdbTable *table,
const gchar *key,
GvdbWalkOpenFunc open_func,
GvdbWalkValueFunc value_func,
GvdbWalkCloseFunc close_func,
gpointer user_data)
{
const struct gvdb_hash_item *item;
const guint32_le *pointers[64];
const guint32_le *enders[64];
gsize name_lengths[64];
gint index = 0;
item = gvdb_table_lookup (table, key, 'L');
name_lengths[0] = 0;
pointers[0] = NULL;
enders[0] = NULL;
goto start_here;
while (index)
{
close_func (name_lengths[index], user_data);
index--;
while (pointers[index] < enders[index])
{
const gchar *name;
gsize name_len;
item = gvdb_table_get_item (table, *pointers[index]++);
start_here:
if (item != NULL && (name = gvdb_table_item_get_key (table, item, &name_len)))
{
if (item->type == 'L')
{
const guint32_le *dir;
guint length;
if (gvdb_table_list_from_item (table, item, &dir, &length))
{
/* In order to avoid files with recursive contents
* we impose the rule that a directory's data must
* follow the data of any directory pointing to
* it.
*
* If we discover that our newly-discovered
* directory follows the one we're traversing now
* then bail out.
*/
if (dir <= pointers[index])
continue;
if (open_func (name, name_len, user_data))
{
index++;
g_assert (index < 64);
name_lengths[index] = name_len;
pointers[index] = dir;
enders[index] = pointers[index] + length;
}
}
}
else if (item->type == 'v')
{
GVariant *value;
value = gvdb_table_value_from_item (table, item);
if (value != NULL)
{
if (table->byteswapped)
{
GVariant *tmp;
tmp = g_variant_byteswap (value);
g_variant_unref (value);
value = tmp;
}
value_func (name, name_len, value, user_data);
g_variant_unref (value);
}
}
}
}
}
}

View File

@ -65,28 +65,9 @@ GVariant * gvdb_table_get_value (GvdbTab
G_GNUC_INTERNAL
gboolean gvdb_table_has_value (GvdbTable *table,
const gchar *key);
G_GNUC_INTERNAL
gboolean gvdb_table_is_valid (GvdbTable *table);
typedef void (*GvdbWalkValueFunc) (const gchar *name,
gsize name_len,
GVariant *value,
gpointer user_data);
typedef gboolean (*GvdbWalkOpenFunc) (const gchar *name,
gsize name_len,
gpointer user_data);
typedef void (*GvdbWalkCloseFunc) (gsize name_len,
gpointer user_data);
G_GNUC_INTERNAL
void gvdb_table_walk (GvdbTable *table,
const gchar *key,
GvdbWalkOpenFunc open_func,
GvdbWalkValueFunc value_func,
GvdbWalkCloseFunc close_func,
gpointer user_data);
G_END_DECLS
#endif /* __gvdb_reader_h__ */