gobject-introspection r482 - in trunk: . girepository



Author: walters
Date: Sun Aug 24 16:51:43 2008
New Revision: 482
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=482&view=rev

Log:
2008-08-24  Colin Walters  <walters verbum org>

	* girepository/gtypelib.c: Add context stack so
	when we get an error we can print out nicely
	where it is.


Modified:
   trunk/ChangeLog
   trunk/girepository/gtypelib.c

Modified: trunk/girepository/gtypelib.c
==============================================================================
--- trunk/girepository/gtypelib.c	(original)
+++ trunk/girepository/gtypelib.c	Sun Aug 24 16:51:43 2008
@@ -26,18 +26,83 @@
 
 #include "gtypelib.h"
 
+typedef struct {
+  GTypelib *typelib;
+  GSList *context_stack;
+} ValidateContext;
 
 #define ALIGN_VALUE(this, boundary) \
   (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
 
+static void
+push_context (ValidateContext *ctx, const char *name)
+{
+  ctx->context_stack = g_slist_prepend (ctx->context_stack, (char*)name);
+}
+
+static void
+pop_context (ValidateContext *ctx)
+{
+  g_assert (ctx->context_stack != NULL);
+  ctx->context_stack = g_slist_delete_link (ctx->context_stack, 
+					    ctx->context_stack);
+}
+
 static gboolean
-validate_interface_blob (GTypelib     *typelib,
+validate_interface_blob (ValidateContext *ctx,
 			 guint32        offset,
 			 GError       **error);
 
+DirEntry *
+get_dir_entry_checked (GTypelib *typelib,
+		       guint16    index,
+		       GError   **error)
+{
+  Header *header = (Header *)typelib->data;
+  guint32 offset;
+
+  if (index == 0 || index > header->n_entries)
+    {
+      g_set_error (error,
+		   G_TYPELIB_ERROR,
+		   G_TYPELIB_ERROR_INVALID_BLOB,
+		   "Invalid directory index %d", index);
+      return FALSE;	        
+    }
+
+  offset = header->directory + (index - 1) * header->entry_blob_size;
+
+  if (typelib->len < offset + sizeof (DirEntry))
+    {
+      g_set_error (error,
+		   G_TYPELIB_ERROR,
+		   G_TYPELIB_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  return (DirEntry *)&typelib->data[offset];
+}
+
+
+static CommonBlob *
+get_blob (GTypelib *typelib,
+	  guint32   offset,
+	  GError  **error)
+{
+  if (typelib->len < offset + sizeof (CommonBlob))
+    {
+      g_set_error (error,
+		   G_TYPELIB_ERROR,
+		   G_TYPELIB_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+  return (CommonBlob *)&typelib->data[offset];
+}
+
 static InterfaceTypeBlob *
 get_type_blob (GTypelib *typelib,
-	       const char *funcname,
 	       SimpleTypeBlob *simple,
 	       GError  **error)
 {
@@ -55,20 +120,12 @@
       g_set_error (error,
 		   G_TYPELIB_ERROR,
 		   G_TYPELIB_ERROR_INVALID,
-		   "Expected non-basic type in function %s, got %d", funcname,
+		   "Expected non-basic type but got %d",
 		   simple->tag);
       return FALSE;
     }
 
-  if (typelib->len < simple->offset + sizeof (CommonBlob))
-    {
-      g_set_error (error,
-		   G_TYPELIB_ERROR,
-		   G_TYPELIB_ERROR_INVALID,
-		   "The buffer is too short");
-      return FALSE;
-    }
-  return (InterfaceTypeBlob*) &typelib->data[simple->offset];
+  return (InterfaceTypeBlob*) get_blob (typelib, simple->offset, error);
 }
 
 DirEntry *
@@ -144,7 +201,7 @@
 }
 
 static gboolean
-validate_name (GTypelib *typelib,
+validate_name (GTypelib   *typelib,
 	       const char *msg,
 	       const guchar *data, guint32 offset,
 	       GError **error)
@@ -179,9 +236,10 @@
 }
 
 static gboolean 
-validate_header (GTypelib  *typelib,
-		 GError    **error)
+validate_header (ValidateContext  *ctx,
+		 GError          **error)
 {
+  GTypelib *typelib = ctx->typelib;
   Header *header;
 
   if (typelib->len < sizeof (Header))
@@ -336,20 +394,16 @@
 			  GError       **error)
 {
   InterfaceTypeBlob *blob;
-  Header *header;
-
-  header = (Header *)typelib->data;
+  InterfaceBlob *target;
 
   blob = (InterfaceTypeBlob*)&typelib->data[offset];
 
-  if (blob->interface == 0 || blob->interface > header->n_entries)
-    {
-      g_set_error (error,
-		   G_TYPELIB_ERROR,
-		   G_TYPELIB_ERROR_INVALID_BLOB,
-		   "Invalid directory index %d", blob->interface);
-      return FALSE;	        
-    }
+  target = (InterfaceBlob*) get_dir_entry_checked (typelib, blob->interface, error);
+
+  if (!target)
+    return FALSE;
+  if (target->blob_type == 0) /* non-local */
+    return TRUE;
 
   return TRUE;
 }
@@ -628,14 +682,14 @@
 }
 
 static gboolean
-validate_function_blob (GTypelib     *typelib,
+validate_function_blob (ValidateContext *ctx,
 			guint32        offset,
 			guint16        container_type,
 			GError       **error)
 {
+  GTypelib *typelib = ctx->typelib;
   FunctionBlob *blob;
   SignatureBlob *sigblob;
-  const char *funcname;
 
   if (typelib->len < offset + sizeof (FunctionBlob))
     {
@@ -660,7 +714,7 @@
   if (!validate_name (typelib, "function", typelib->data, blob->name, error))
     return FALSE; 
 
-  funcname = get_string_nofail (typelib, blob->name);
+  push_context (ctx, get_string_nofail (typelib, blob->name));
   
   if (!validate_name (typelib, "function symbol", typelib->data, blob->symbol, error))
     return FALSE; 
@@ -677,7 +731,7 @@
 	  g_set_error (error,
 		       G_TYPELIB_ERROR,
 		       G_TYPELIB_ERROR_INVALID_BLOB,
-		       "Constructor %s not allowed", funcname);
+		       "Constructor not allowed");
 	  return FALSE;
 	}
     }
@@ -723,31 +777,36 @@
       SimpleTypeBlob *simple = return_type_from_signature (typelib,
 							   blob->signature,
 							   error);
-      InterfaceTypeBlob *iface;
+      InterfaceTypeBlob *iface_type;
+      InterfaceBlob *iface;
+
       if (!simple)
 	return FALSE;
-      iface = get_type_blob (typelib, funcname, simple, error);
-      if (!iface)
+      iface_type = get_type_blob (typelib, simple, error);
+      if (!iface_type)
 	return FALSE;
-      if (!(iface->tag == GI_TYPE_TAG_INTERFACE))
+      if (!(iface_type->tag == GI_TYPE_TAG_INTERFACE))
 	{
 	  g_set_error (error,
 		       G_TYPELIB_ERROR,
 		       G_TYPELIB_ERROR_INVALID,
-		       "Invalid return type %d for constructor %s",
-		       iface->tag, funcname);
+		       "Invalid return type %d for constructor",
+		       iface_type->tag);
 	  return FALSE;
 	}
     }
-	
+
+  pop_context (ctx);
+
   return TRUE;
 }
 
 static gboolean
-validate_callback_blob (GTypelib     *typelib,
+validate_callback_blob (ValidateContext *ctx,
 			guint32        offset,
 			GError       **error)
 {
+  GTypelib *typelib = ctx->typelib;
   CallbackBlob *blob;
 
   if (typelib->len < offset + sizeof (CallbackBlob))
@@ -772,9 +831,13 @@
 
   if (!validate_name (typelib, "callback", typelib->data, blob->name, error))
     return FALSE; 
+
+  push_context (ctx, get_string_nofail (typelib, blob->name));
   
   if (!validate_signature_blob (typelib, blob->signature, error))
     return FALSE;
+
+  pop_context (ctx);
 	
   return TRUE;
 }
@@ -1068,11 +1131,12 @@
 }
 
 static gboolean
-validate_struct_blob (GTypelib     *typelib,
+validate_struct_blob (ValidateContext *ctx,
 		      guint32        offset,
 		      guint16        blob_type,
 		      GError       **error)
 {
+  GTypelib *typelib = ctx->typelib;
   StructBlob *blob;
   gint i;
 
@@ -1108,6 +1172,8 @@
 
   if (!validate_name (typelib, "struct", typelib->data, blob->name, error))
     return FALSE; 
+
+  push_context (ctx, get_string_nofail (typelib, blob->name));
   
   if (blob_type == BLOB_TYPE_BOXED)
     {
@@ -1151,7 +1217,7 @@
 
   for (i = 0; i < blob->n_methods; i++)
     {
-      if (!validate_function_blob (typelib, 
+      if (!validate_function_blob (ctx, 
 				   offset + sizeof (StructBlob) + 
 				   blob->n_fields * sizeof (FieldBlob) + 
 				   i * sizeof (FunctionBlob), 
@@ -1160,6 +1226,8 @@
 	return FALSE;
     }
 
+  pop_context (ctx);
+
   return TRUE;
 }
 
@@ -1260,10 +1328,11 @@
 }
 
 static gboolean
-validate_object_blob (GTypelib     *typelib,
+validate_object_blob (ValidateContext *ctx,
 		      guint32        offset,
 		      GError       **error)
 {
+  GTypelib *typelib = ctx->typelib;
   Header *header;
   ObjectBlob *blob;
   gint i;
@@ -1388,7 +1457,7 @@
 
   for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
     {
-      if (!validate_function_blob (typelib, offset2, BLOB_TYPE_OBJECT, error))
+      if (!validate_function_blob (ctx, offset2, BLOB_TYPE_OBJECT, error))
 	return FALSE;
     }
 
@@ -1414,10 +1483,11 @@
 }
 
 static gboolean
-validate_interface_blob (GTypelib     *typelib,
+validate_interface_blob (ValidateContext *ctx,
 			 guint32        offset,
 			 GError       **error)
 {
+  GTypelib *typelib = ctx->typelib;
   Header *header;
   InterfaceBlob *blob;
   gint i;
@@ -1510,7 +1580,7 @@
 
   for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
     {
-      if (!validate_function_blob (typelib, offset2, BLOB_TYPE_INTERFACE, error))
+      if (!validate_function_blob (ctx, offset2, BLOB_TYPE_INTERFACE, error))
 	return FALSE;
     }
   
@@ -1552,10 +1622,11 @@
 }
 
 static gboolean
-validate_blob (GTypelib     *typelib,
-	       guint32        offset,
-	       GError       **error)
+validate_blob (ValidateContext *ctx,
+	       guint32          offset,
+	       GError         **error)
 {
+  GTypelib *typelib = ctx->typelib;
   CommonBlob *common;
 
   if (typelib->len < offset + sizeof (CommonBlob))
@@ -1572,16 +1643,16 @@
   switch (common->blob_type)
     {
     case BLOB_TYPE_FUNCTION:
-      if (!validate_function_blob (typelib, offset, 0, error))
+      if (!validate_function_blob (ctx, offset, 0, error))
 	return FALSE;
       break;
     case BLOB_TYPE_CALLBACK:
-      if (!validate_callback_blob (typelib, offset, error))
+      if (!validate_callback_blob (ctx, offset, error))
 	return FALSE;
       break;
     case BLOB_TYPE_STRUCT:
     case BLOB_TYPE_BOXED:
-      if (!validate_struct_blob (typelib, offset, common->blob_type, error))
+      if (!validate_struct_blob (ctx, offset, common->blob_type, error))
 	return FALSE;
       break;
     case BLOB_TYPE_ENUM:
@@ -1590,11 +1661,11 @@
 	return FALSE;
       break;
     case BLOB_TYPE_OBJECT:
-      if (!validate_object_blob (typelib, offset, error))
+      if (!validate_object_blob (ctx, offset, error))
 	return FALSE;
       break;
     case BLOB_TYPE_INTERFACE:
-      if (!validate_interface_blob (typelib, offset, error))
+      if (!validate_interface_blob (ctx, offset, error))
 	return FALSE;
       break;
     case BLOB_TYPE_CONSTANT:
@@ -1621,9 +1692,10 @@
 }
 
 static gboolean 
-validate_directory (GTypelib     *typelib,
-		    GError       **error)
+validate_directory (ValidateContext   *ctx,
+		    GError            **error)
 {
+  GTypelib *typelib = ctx->typelib;
   Header *header = (Header *)typelib->data;
   DirEntry *entry;
   gint i;
@@ -1674,7 +1746,7 @@
 	      return FALSE;
 	    }
 
-	  if (!validate_blob (typelib, entry->offset, error))
+	  if (!validate_blob (ctx, entry->offset, error))
 	    return FALSE;
 	}
       else
@@ -1697,9 +1769,10 @@
 }
 
 static gboolean
-validate_annotations (GTypelib     *typelib, 
+validate_annotations (ValidateContext *ctx, 
 		      GError       **error)
 {
+  GTypelib *typelib = ctx->typelib;
   Header *header = (Header *)typelib->data;
 
   if (header->size < header->annotations + header->n_annotations * sizeof (AnnotationBlob))
@@ -1714,18 +1787,59 @@
   return TRUE;
 }
 
+static void
+prefix_with_context (GError **error,
+		     const char *section,
+		     ValidateContext *ctx)
+{
+  GString *str = g_string_new (NULL);
+  GSList *link;
+  char *buf;
+  
+  link = ctx->context_stack;
+  if (!link)
+    {
+      g_prefix_error (error, "In %s:", section);
+      return;
+    }
+
+  for (; link; link = link->next)
+    {
+      g_string_append (str, link->data);
+      if (link->next)
+	g_string_append_c (str, '/');
+    }
+  g_string_append_c (str, ')');
+  buf = g_string_free (str, FALSE);
+  g_prefix_error (error, "In %s (Context: %s): ", section, buf);
+  g_free (buf);
+}
+
 gboolean 
 g_typelib_validate (GTypelib     *typelib,
 		     GError       **error)
 {
-  if (!validate_header (typelib, error))
-    return FALSE;
+  ValidateContext ctx;
+  ctx.typelib = typelib;
+  ctx.context_stack = NULL;
 
-  if (!validate_directory (typelib, error))
-    return FALSE;
+  if (!validate_header (&ctx, error))
+    {
+      prefix_with_context (error, "In header", &ctx);
+      return FALSE;
+    }
 
-  if (!validate_annotations (typelib, error))
-    return FALSE;
+  if (!validate_directory (&ctx, error))
+    {
+      prefix_with_context (error, "directory", &ctx);
+      return FALSE;
+    }
+
+  if (!validate_annotations (&ctx, error))
+    {
+      prefix_with_context (error, "annotations", &ctx);
+      return FALSE;
+    }
 
   return TRUE;
 }



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