gobject-introspection r477 - trunk/girepository



Author: walters
Date: Sat Aug 23 21:30:09 2008
New Revision: 477
URL: http://svn.gnome.org/viewvc/gobject-introspection?rev=477&view=rev

Log:
Check constructor returns


Modified:
   trunk/girepository/gtypelib.c

Modified: trunk/girepository/gtypelib.c
==============================================================================
--- trunk/girepository/gtypelib.c	(original)
+++ trunk/girepository/gtypelib.c	Sat Aug 23 21:30:09 2008
@@ -30,6 +30,46 @@
 #define ALIGN_VALUE(this, boundary) \
   (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
 
+static gboolean
+validate_interface_blob (GTypelib     *typelib,
+			 guint32        offset,
+			 GError       **error);
+
+static InterfaceTypeBlob *
+get_type_blob (GTypelib *typelib,
+	       const char *funcname,
+	       SimpleTypeBlob *simple,
+	       GError  **error)
+{
+  if (simple->offset == 0)
+    {
+      g_set_error (error,
+		   G_TYPELIB_ERROR,
+		   G_TYPELIB_ERROR_INVALID,
+		   "Expected blob for type");
+      return FALSE;
+    }
+
+  if (simple->reserved == 0 && simple->reserved2 == 0)
+    {
+      g_set_error (error,
+		   G_TYPELIB_ERROR,
+		   G_TYPELIB_ERROR_INVALID,
+		   "Expected non-basic type in function %s, got %d", funcname,
+		   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];
+}
 
 DirEntry *
 g_typelib_get_dir_entry (GTypelib *typelib,
@@ -80,26 +120,41 @@
 
 #define MAX_NAME_LEN 200
 
-static gboolean
-validate_name (GTypelib *typelib,
-	       const char *msg,
-	       const guchar *data, guint32 offset,
-	       GError **error)
+static const char *
+get_string (GTypelib *typelib, guint32 offset, GError **error)
 {
-  gchar *name;
-
   if (typelib->len < offset)
     {
       g_set_error (error,
 		   G_TYPELIB_ERROR,
 		   G_TYPELIB_ERROR_INVALID,
-		   "The buffer is too short for type %s",
-		   msg);
-      return FALSE;
+		   "Buffer is too short while looking up name");
+      return NULL;
     }
 
-  name = (gchar*)&data[offset];
-  
+  return (const char*)&typelib->data[offset];
+}
+
+static const char *
+get_string_nofail (GTypelib *typelib, guint32 offset)
+{
+  const char *ret = get_string (typelib, offset, NULL);
+  g_assert (ret);
+  return ret;
+}
+
+static gboolean
+validate_name (GTypelib *typelib,
+	       const char *msg,
+	       const guchar *data, guint32 offset,
+	       GError **error)
+{
+  const char *name;
+
+  name = get_string (typelib, offset, error);
+  if (!name)
+    return FALSE;
+
   if (!memchr (name, '\0', MAX_NAME_LEN)) 
     {
       g_set_error (error,
@@ -502,6 +557,34 @@
   return TRUE;
 }
 
+static SimpleTypeBlob *
+return_type_from_signature (GTypelib *typelib,
+			    guint32   offset,
+			    GError  **error)
+{
+  SignatureBlob *blob;
+  if (typelib->len < offset + sizeof (SignatureBlob))
+    {
+      g_set_error (error,
+		   G_TYPELIB_ERROR,
+		   G_TYPELIB_ERROR_INVALID,
+		   "The buffer is too short");
+      return NULL;
+    }
+
+  blob = (SignatureBlob*) &typelib->data[offset];
+  if (blob->return_type.offset == 0)
+    {
+      g_set_error (error,
+		   G_TYPELIB_ERROR,
+		   G_TYPELIB_ERROR_INVALID,
+		   "No return type found in signature");
+      return NULL;
+    }
+
+  return (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (SignatureBlob, return_type)];
+}
+
 static gboolean
 validate_signature_blob (GTypelib     *typelib,
 			 guint32        offset,
@@ -551,6 +634,8 @@
 			GError       **error)
 {
   FunctionBlob *blob;
+  SignatureBlob *sigblob;
+  const char *funcname;
 
   if (typelib->len < offset + sizeof (FunctionBlob))
     {
@@ -574,6 +659,8 @@
 
   if (!validate_name (typelib, "function", typelib->data, blob->name, error))
     return FALSE; 
+
+  funcname = get_string_nofail (typelib, blob->name);
   
   if (!validate_name (typelib, "function symbol", typelib->data, blob->symbol, error))
     return FALSE; 
@@ -590,7 +677,7 @@
 	  g_set_error (error,
 		       G_TYPELIB_ERROR,
 		       G_TYPELIB_ERROR_INVALID_BLOB,
-		       "Constructor not allowed");
+		       "Constructor %s not allowed", funcname);
 	  return FALSE;
 	}
     }
@@ -625,10 +712,33 @@
 
   /* FIXME: validate index range */
   /* FIXME: validate "this" argument for methods */
-  /* FIXME: validate return type for constructors */
 
   if (!validate_signature_blob (typelib, blob->signature, error))
     return FALSE;
+
+  sigblob = (SignatureBlob*) &typelib->data[blob->signature];
+
+  if (blob->constructor) 
+    {
+      SimpleTypeBlob *simple = return_type_from_signature (typelib,
+							   blob->signature,
+							   error);
+      InterfaceTypeBlob *iface;
+      if (!simple)
+	return FALSE;
+      iface = get_type_blob (typelib, funcname, simple, error);
+      if (!iface)
+	return FALSE;
+      if (!(iface->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);
+	  return FALSE;
+	}
+    }
 	
   return TRUE;
 }
@@ -1331,7 +1441,7 @@
       g_set_error (error,
 		   G_TYPELIB_ERROR,
 		   G_TYPELIB_ERROR_INVALID_BLOB,
-		   "Wrong blob type");
+		   "Wrong blob type; expected interface, got %d", blob->blob_type);
       return FALSE;
     }
   



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