[gobject-introspection] Attribute bug-fixes



commit 751ffa016e410a031028282e63f98a94cc444b7b
Author: David Zeuthen <davidz redhat com>
Date:   Tue Jun 15 10:50:42 2010 -0400

    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 <davidz redhat com>

 girepository/girmodule.c |   31 ++++++++++++++++++++-----------
 girepository/girnode.c   |   14 ++++----------
 girepository/girnode.h   |    3 +--
 3 files changed, 25 insertions(+), 23 deletions(-)
---
diff --git a/girepository/girmodule.c b/girepository/girmodule.c
index b380912..ae40d5f 100644
--- a/girepository/girmodule.c
+++ b/girepository/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/girepository/girnode.c b/girepository/girnode.c
index 0f5223f..fbdcdf9 100644
--- a/girepository/girnode.c
+++ b/girepository/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/girepository/girnode.h b/girepository/girnode.h
index 038a53d..bd9acd0 100644
--- a/girepository/girnode.h
+++ b/girepository/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,



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