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