Author: kumpera
Date: 2007-07-11 18:55:57 -0400 (Wed, 11 Jul 2007)
New Revision: 81834

Modified:
   trunk/mono/mono/metadata/ChangeLog
   trunk/mono/mono/metadata/class-internals.h
   trunk/mono/mono/metadata/class.c
   trunk/mono/mono/metadata/reflection.c
Log:
2007-07-11  Rodrigo Kumpera  <[EMAIL PROTECTED]>
        * class.c, class-internal.h: added mono_type_is_valid_enum_basetype and
        mono_class_is_valid_enum, they are used to valide a enum when loading.
        * reflection.c: used new functions to throw TypeLoadException when and
        invalid enum is build with TypeBuilder. Fixes #82018
  


Modified: trunk/mono/mono/metadata/ChangeLog
===================================================================
--- trunk/mono/mono/metadata/ChangeLog  2007-07-11 21:23:16 UTC (rev 81833)
+++ trunk/mono/mono/metadata/ChangeLog  2007-07-11 22:55:57 UTC (rev 81834)
@@ -1,4 +1,10 @@
+2007-07-11  Rodrigo Kumpera  <[EMAIL PROTECTED]>
 
+       * class.c, class-internal.h: added mono_type_is_valid_enum_basetype and
+       mono_class_is_valid_enum, they are used to valide a enum when loading.
+       * reflection.c: used new functions to throw TypeLoadException when and
+       invalid enum is build with TypeBuilder. Fixes #82018
+  
 Wed Jul 11 14:47:07 CEST 2007 Paolo Molaro <[EMAIL PROTECTED]>
 
        * object.c: forgot commit of mono_class_setup_methods () to access

Modified: trunk/mono/mono/metadata/class-internals.h
===================================================================
--- trunk/mono/mono/metadata/class-internals.h  2007-07-11 21:23:16 UTC (rev 
81833)
+++ trunk/mono/mono/metadata/class-internals.h  2007-07-11 22:55:57 UTC (rev 
81834)
@@ -831,5 +831,12 @@
 void mono_value_describe_fields  (MonoClass* klass, const char* addr);
 void mono_class_describe_statics (MonoClass* klass);
 
+/*Enum validation related functions*/
+gboolean
+mono_type_is_valid_enum_basetype (MonoType * type);
+
+gboolean
+mono_class_is_valid_enum (MonoClass *klass);
+
 #endif /* __MONO_METADATA_CLASS_INTERBALS_H__ */
 

Modified: trunk/mono/mono/metadata/class.c
===================================================================
--- trunk/mono/mono/metadata/class.c    2007-07-11 21:23:16 UTC (rev 81833)
+++ trunk/mono/mono/metadata/class.c    2007-07-11 22:55:57 UTC (rev 81834)
@@ -5604,3 +5604,73 @@
                return TRUE;
        return can;
 }
+
+/**
+ * mono_type_is_valid_enum_basetype:
+ * @type: The MonoType to check
+ *
+ * Returns: TRUE if the type can be used as the basetype of an enum
+ */
+gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
+       switch (type->type) {
+       case MONO_TYPE_I1:
+       case MONO_TYPE_U1:
+       case MONO_TYPE_BOOLEAN:
+       case MONO_TYPE_I2:
+       case MONO_TYPE_U2:
+       case MONO_TYPE_CHAR:
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4:
+       case MONO_TYPE_I8:
+       case MONO_TYPE_U8:
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+               return TRUE;
+       }
+       return FALSE;
+}
+
+/**
+ * mono_class_is_valid_enum:
+ * @klass: An enum class to be validated
+ *
+ * This method verify the required properties an enum should have.
+ *  
+ * Returns: TRUE if the informed enum class is valid 
+ *
+ * FIXME: TypeBuilder enums are allowed to implement interfaces, but since 
they cannot have methods, only empty interfaces are possible
+ * FIXME: enum types are not allowed to have a cctor, but 
mono_reflection_create_runtime_class sets has_cctor to 1 for all types
+ * FIXME: TypeBuilder enums can have any kind of static fields, but the spec 
is very explicit about that (P II 14.3)
+ */
+gboolean mono_class_is_valid_enum (MonoClass *klass) {
+       MonoClassField * field;
+       gpointer iter = NULL;
+       gboolean found_base_field = FALSE;
+
+       g_assert (klass->enumtype);
+       /* we cannot test against mono_defaults.enum_class, or mcs won't be 
able to compile the System namespace*/
+       if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp 
(klass->parent->name_space, "System") ) {
+               return FALSE;
+       }
+
+       if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != 
TYPE_ATTRIBUTE_AUTO_LAYOUT)
+               return FALSE;
+
+       while ((field = mono_class_get_fields (klass, &iter))) {
+               if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
+                       if (found_base_field)
+                               return FALSE;
+                       found_base_field = TRUE;
+                       if (!mono_type_is_valid_enum_basetype (field->type))
+                               return FALSE;
+               }
+       }
+
+       if (!found_base_field)
+               return FALSE;
+
+       if (klass->method.count > 0) 
+               return FALSE;
+
+       return TRUE;
+}

Modified: trunk/mono/mono/metadata/reflection.c
===================================================================
--- trunk/mono/mono/metadata/reflection.c       2007-07-11 21:23:16 UTC (rev 
81833)
+++ trunk/mono/mono/metadata/reflection.c       2007-07-11 22:55:57 UTC (rev 
81834)
@@ -8287,6 +8287,11 @@
 
                fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 
0);
 
+               if (!mono_type_is_valid_enum_basetype (fb->type->type)) {
+                       mono_loader_unlock ();
+                       return;
+               }
+
                klass->enum_basetype = fb->type->type;
                klass->element_class = my_mono_class_from_mono_type 
(klass->enum_basetype);
                if (!klass->element_class)
@@ -9398,11 +9403,16 @@
        typebuilder_setup_properties (klass);
 
        typebuilder_setup_events (klass);
-
+       
        klass->wastypebuilder = TRUE;
        mono_loader_unlock ();
        mono_domain_unlock (domain);
 
+       if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
+               mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
+               mono_raise_exception (mono_get_exception_type_load (tb->name, 
NULL));
+       }
+
        res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
        g_assert (res != (MonoReflectionType*)tb);
 

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to