From c57c9efe6f76ef7974695d75ecbc5a025ef322b2 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Tue, 15 Jun 2010 10:50:42 -0400 Subject: [PATCH] Attribute bug-fixes Rectify an assumption that nodes are ordered according to offset - since this assumption was not true, attributes ended up being not ordered either and the bsearch() when looking up attributes failed mysteriously. Instead of making such assumptions, simply sort the list of nodes we want to extract attributes from. The total attribute size computation was wrong as we didn't properly descend into subnodes. This resulted in memory access violations when writing the typelib (because not enough data was allocated). Instead of having a separate function for this, just include the attribute size in the existing function. See https://bugzilla.gnome.org/show_bug.cgi?id=571548 Signed-off-by: David Zeuthen --- girmodule.c | 31 ++++++++++++++++++++----------- girnode.c | 14 ++++---------- girnode.h | 3 +-- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/girmodule.c b/girmodule.c index b380912b5..ae40d5f5b 100644 --- a/girmodule.c +++ b/girmodule.c @@ -192,6 +192,16 @@ write_attributes (GIrModule *module, return wdata.count; } +static gint +node_cmp_offset_func (gconstpointer a, + gconstpointer b) +{ + const GIrNode *na = a; + const GIrNode *nb = b; + return na->offset - nb->offset; +} + + GTypelib * g_ir_module_build_typelib (GIrModule *module, GList *modules) @@ -209,7 +219,7 @@ g_ir_module_build_typelib (GIrModule *module, guint32 size, offset, offset2, old_offset; GHashTable *strings; GHashTable *types; - GList *offset_ordered_nodes; + GList *nodes_with_attributes; char *dependencies; guchar *data; @@ -242,7 +252,7 @@ g_ir_module_build_typelib (GIrModule *module, _g_irnode_init_stats (); strings = g_hash_table_new (g_str_hash, g_str_equal); types = g_hash_table_new (g_str_hash, g_str_equal); - offset_ordered_nodes = NULL; + nodes_with_attributes = NULL; n_entries = g_list_length (module->entries); g_message ("%d entries (%d local), %d dependencies\n", n_entries, n_local_entries, @@ -258,7 +268,6 @@ g_ir_module_build_typelib (GIrModule *module, GIrNode *node = e->data; size += g_ir_node_get_full_size (node); - size += g_ir_node_get_attribute_size (node); /* Also reset the offset here */ node->offset = 0; @@ -350,10 +359,10 @@ g_ir_module_build_typelib (GIrModule *module, g_hash_table_destroy (types); /* Reset the cached offsets */ - for (link = offset_ordered_nodes; link; link = link->next) + for (link = nodes_with_attributes; link; link = link->next) ((GIrNode *) link->data)->offset = 0; - g_list_free (offset_ordered_nodes); + g_list_free (nodes_with_attributes); strings = NULL; g_free (data); @@ -387,12 +396,12 @@ g_ir_module_build_typelib (GIrModule *module, build.modules = modules; build.strings = strings; build.types = types; - build.offset_ordered_nodes = offset_ordered_nodes; + build.nodes_with_attributes = nodes_with_attributes; build.n_attributes = header->n_attributes; build.data = data; g_ir_node_build_typelib (node, NULL, &build, &offset, &offset2); - offset_ordered_nodes = build.offset_ordered_nodes; + nodes_with_attributes = build.nodes_with_attributes; header->n_attributes = build.n_attributes; if (offset2 > old_offset + g_ir_node_get_full_size (node)) @@ -402,7 +411,8 @@ g_ir_module_build_typelib (GIrModule *module, entry++; } - offset_ordered_nodes = g_list_reverse (offset_ordered_nodes); + /* GIBaseInfo expects the AttributeBlob array to be sorted on the field (offset) */ + nodes_with_attributes = g_list_sort (nodes_with_attributes, node_cmp_offset_func); g_message ("header: %d entries, %d attributes", header->n_entries, header->n_attributes); @@ -413,10 +423,9 @@ g_ir_module_build_typelib (GIrModule *module, header->attributes = offset; offset2 = offset + header->n_attributes * header->attribute_blob_size; - for (e = offset_ordered_nodes; e; e = e->next) + for (e = nodes_with_attributes; e; e = e->next) { GIrNode *node = e->data; - write_attributes (module, node, strings, data, &offset, &offset2); } @@ -429,7 +438,7 @@ g_ir_module_build_typelib (GIrModule *module, g_hash_table_destroy (strings); g_hash_table_destroy (types); - g_list_free (offset_ordered_nodes); + g_list_free (nodes_with_attributes); return typelib; } diff --git a/girnode.c b/girnode.c index 0f5223fa0..fbdcdf965 100644 --- a/girnode.c +++ b/girnode.c @@ -573,7 +573,7 @@ add_attribute_size (gpointer key, gpointer value, gpointer data) *size_p += ALIGN_VALUE (strlen (value_str) + 1, 4); } -/* returns the full size of the blob including variable-size parts */ +/* returns the full size of the blob including variable-size parts (including attributes) */ static guint32 g_ir_node_get_full_size_internal (GIrNode *parent, GIrNode *node) @@ -878,6 +878,8 @@ g_ir_node_get_full_size_internal (GIrNode *parent, node->name ? "' " : "", node, g_ir_node_type_to_string (node->type), size); + g_hash_table_foreach (node->attributes, add_attribute_size, &size); + return size; } @@ -887,14 +889,6 @@ g_ir_node_get_full_size (GIrNode *node) return g_ir_node_get_full_size_internal (NULL, node); } -guint32 -g_ir_node_get_attribute_size (GIrNode *node) -{ - guint32 size = 0; - g_hash_table_foreach (node->attributes, add_attribute_size, &size); - return size; -} - int g_ir_node_cmp (GIrNode *node, GIrNode *other) @@ -1438,7 +1432,7 @@ g_ir_node_build_typelib (GIrNode *node, */ g_assert (node->offset == 0); node->offset = *offset; - build->offset_ordered_nodes = g_list_prepend (build->offset_ordered_nodes, node); + build->nodes_with_attributes = g_list_prepend (build->nodes_with_attributes, node); build->n_attributes += g_hash_table_size (node->attributes); diff --git a/girnode.h b/girnode.h index 038a53d78..bd9acd068 100644 --- a/girnode.h +++ b/girnode.h @@ -51,7 +51,7 @@ struct _GIrTypelibBuild { GList *modules; GHashTable *strings; GHashTable *types; - GList *offset_ordered_nodes; + GList *nodes_with_attributes; guint32 n_attributes; guchar *data; }; @@ -362,7 +362,6 @@ GIrNode * g_ir_node_new (GIrNodeTypeId type); void g_ir_node_free (GIrNode *node); guint32 g_ir_node_get_size (GIrNode *node); guint32 g_ir_node_get_full_size (GIrNode *node); -guint32 g_ir_node_get_attribute_size (GIrNode *node); void g_ir_node_build_typelib (GIrNode *node, GIrNode *parent, GIrTypelibBuild *build,