Merge branch 'master' into msbuilddll2
[mono.git] / mono / metadata / reflection.c
index 1ddcb7fe33b5703e573f662612b1fca99afa476a..eddd5dc570f8fb0d819d253181d7aabf62d2686c 100644 (file)
@@ -202,6 +202,19 @@ static void init_type_builder_generics (MonoObject *type);
 
 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
 
+#define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
+#define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
+
+#if SIZEOF_VOID_P == 4
+#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
+#else
+#define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
+#endif
+
+#define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
+#define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
+
+
 void
 mono_reflection_init (void)
 {
@@ -4791,7 +4804,7 @@ mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, Mon
        MonoMethodSignature *sig;
 
        klass = obj->vtable->klass;
-       if (strcmp (klass->name, "MonoMethod") == 0) {
+       if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
                MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
                MonoMethodSignature *old;
                guint32 sig_token, parent;
@@ -6769,9 +6782,13 @@ mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoCla
        if (!System_Reflection_ParameterInfo_array) {
                MonoClass *klass;
 
-               klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
+               klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoParameterInfo");
+               if (!klass)
+                       klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
+
                mono_memory_barrier ();
                System_Reflection_ParameterInfo = klass; 
+
        
                klass = mono_array_class_get (klass, 1);
                mono_memory_barrier ();
@@ -7211,9 +7228,9 @@ static int
 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
                             MonoTypeNameParse *info)
 {
-       char *start, *p, *w, *temp, *last_point, *startn;
+       char *start, *p, *w, *last_point, *startn;
        int in_modifiers = 0;
-       int isbyref = 0, rank, arity = 0, i;
+       int isbyref = 0, rank = 0;
 
        start = p = w = name;
 
@@ -7260,14 +7277,6 @@ _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
                case ']':
                        in_modifiers = 1;
                        break;
-               case '`':
-                       ++p;
-                       i = strtol (p, &temp, 10);
-                       arity += i;
-                       if (p == temp)
-                               return 0;
-                       p = temp-1;
-                       break;
                default:
                        break;
                }
@@ -7301,10 +7310,32 @@ _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
                        *p++ = 0;
                        break;
                case '[':
-                       if (arity != 0) {
-                               *p++ = 0;
+                       //Decide if it's an array of a generic argument list
+                       *p++ = 0;
+
+                       if (!*p) //XXX test
+                               return 0;
+                       if (*p  == ',' || *p == '*' || *p == ']') { //array
+                               rank = 1;
+                               while (*p) {
+                                       if (*p == ']')
+                                               break;
+                                       if (*p == ',')
+                                               rank++;
+                                       else if (*p == '*') /* '*' means unknown lower bound */
+                                               info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
+                                       else
+                                               return 0;
+                                       ++p;
+                               }
+                               if (*p++ != ']')
+                                       return 0;
+                               info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
+                       } else {
+                               if (rank) /* generic args after array spec*/ //XXX test
+                                       return 0;
                                info->type_arguments = g_ptr_array_new ();
-                               for (i = 0; i < arity; i++) {
+                               while (*p) {
                                        MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
                                        gboolean fqname = FALSE;
 
@@ -7347,36 +7378,15 @@ _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
                                        } else if (fqname && (*p == ']')) {
                                                *p++ = 0;
                                        }
-
-                                       if (i + 1 < arity) {
-                                               if (*p != ',')
-                                                       return 0;
-                                       } else {
-                                               if (*p != ']')
-                                                       return 0;
+                                       if (*p == ']') {
+                                               *p++ = 0;
+                                               break;
+                                       } else if (!*p) {
+                                               return 0;
                                        }
                                        *p++ = 0;
                                }
-
-                               arity = 0;
-                               break;
                        }
-                       rank = 1;
-                       *p++ = 0;
-                       while (*p) {
-                               if (*p == ']')
-                                       break;
-                               if (*p == ',')
-                                       rank++;
-                               else if (*p == '*') /* '*' means unknown lower bound */
-                                       info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
-                               else
-                                       return 0;
-                               ++p;
-                       }
-                       if (*p++ != ']')
-                               return 0;
-                       info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
                        break;
                case ']':
                        if (is_recursed)
@@ -7752,7 +7762,7 @@ mono_reflection_get_token (MonoObject *obj)
                MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
 
                token = mono_class_get_event_token (p->event);
-       } else if (strcmp (klass->name, "ParameterInfo") == 0) {
+       } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
                MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
                MonoClass *member_class = mono_object_class (p->MemberImpl);
                g_assert (mono_class_is_reflection_method_or_constructor (member_class));
@@ -7774,6 +7784,23 @@ mono_reflection_get_token (MonoObject *obj)
        return token;
 }
 
+static MonoClass*
+load_cattr_enum_type (MonoImage *image, const char *p, const char **end)
+{
+       char *n;
+       MonoType *t;
+       int slen = mono_metadata_decode_value (p, &p);
+       n = g_memdup (p, slen + 1);
+       n [slen] = 0;
+       t = mono_reflection_type_from_name (n, image);
+       if (!t)
+               g_error ("Cannot load type '%s'", n);
+       g_free (n);
+       p += slen;
+       *end = p;
+       return mono_class_from_mono_type (t);
+}
+
 static void*
 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
 {
@@ -7892,6 +7919,8 @@ handle_type:
                        type = MONO_TYPE_SZARRAY;
                        if (etype == 0x50) {
                                tklass = mono_defaults.systemtype_class;
+                       } else if (etype == 0x55) {
+                               tklass = load_cattr_enum_type (image, p, &p);
                        } else {
                                if (etype == 0x51)
                                        /* See Partition II, Appendix B3 */
@@ -8298,6 +8327,9 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                        gint type_len;
                        char *type_name;
                        type_len = mono_metadata_decode_blob_size (named, &named);
+                       if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
+                               goto fail;
+
                        type_name = g_malloc (type_len + 1);
                        memcpy (type_name, named, type_len);
                        type_name [type_len] = 0;
@@ -8306,6 +8338,8 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                        g_free (type_name);
                }
                name_len = mono_metadata_decode_blob_size (named, &named);
+               if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
+                       goto fail;
                name = g_malloc (name_len + 1);
                memcpy (name, named, name_len);
                name [name_len] = 0;
@@ -8346,6 +8380,11 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
 
        *typed_args = typedargs;
        *named_args = namedargs;
+       return;
+fail:
+       mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
+       g_free (arginfo);
+       *named_arg_info = NULL;
 }
 
 void
@@ -8355,7 +8394,7 @@ mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method,
        MonoArray *typedargs, *namedargs;
        MonoImage *image;
        MonoMethod *method;
-       CattrNamedArg *arginfo;
+       CattrNamedArg *arginfo = NULL;
        MonoError error;
        int i;
 
@@ -8378,8 +8417,10 @@ mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method,
        if (mono_loader_get_last_error ())
                mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
 
-       if (!typedargs || !namedargs)
+       if (!typedargs || !namedargs) {
+               g_free (arginfo);
                return;
+       }
 
        for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
                MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
@@ -8406,6 +8447,7 @@ mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method,
 
        *ctor_args = typedargs;
        *named_args = namedargs;
+       g_free (arginfo);
 }
 
 static MonoObject*
@@ -8678,6 +8720,15 @@ mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
        return mono_custom_attrs_from_index (klass->image, idx);
 }
 
+/**
+ * mono_custom_attrs_from_param:
+ * @method: handle to the method that we want to retrieve custom parameter information from
+ * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
+ *
+ * The result must be released with mono_custom_attrs_free().
+ *
+ * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
+ */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
 {
@@ -8824,7 +8875,7 @@ mono_reflection_get_custom_attrs_info (MonoObject *obj)
        } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
                cinfo = mono_custom_attrs_from_method (rmethod->method);
-       } else if (strcmp ("ParameterInfo", klass->name) == 0) {
+       } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
                MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
                MonoClass *member_class = mono_object_class (param->MemberImpl);
                if (mono_class_is_reflection_method_or_constructor (member_class)) {
@@ -9789,12 +9840,16 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 
                /* Put into cache so mono_class_get () will find it.
                Skip nested types as those should not be available on the global scope. */
-               if (!tb->nesting_type) {
+               if (!tb->nesting_type)
                        mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
-               } else {
-                       klass->image->reflection_info_unregister_classes =
-                               g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
-               }
+
+               /*
+               We must register all types as we cannot rely on the name_cache hashtable since we find the class
+               by performing a mono_class_get which does the full resolution.
+
+               Working around this semantics would require us to write a lot of code for no clear advantage.
+               */
+               mono_image_append_class_to_reflection_info_set (klass);
        } else {
                g_assert (mono_class_get_ref_info (klass) == tb);
        }
@@ -10520,9 +10575,9 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
                 * This table maps metadata structures representing inflated methods/fields
                 * to the reflection objects representing their generic definitions.
                 */
-               mono_loader_lock ();
+               mono_image_lock ((MonoImage*)image);
                mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
-               mono_loader_unlock ();
+               mono_image_unlock ((MonoImage*)image);
        }
 
        if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
@@ -10566,9 +10621,9 @@ inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
        if (method->is_generic && method->klass->image->dynamic) {
                MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
 
-               mono_loader_lock ();
+               mono_image_lock ((MonoImage*)image);
                mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
-               mono_loader_unlock ();
+               mono_image_unlock ((MonoImage*)image);
        }
        return (MonoMethod *) imethod;
 }
@@ -11407,9 +11462,7 @@ mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam
        gparam->type.type = &pklass->byval_arg;
 
        mono_class_set_ref_info (pklass, gparam);
-       mono_image_lock (image);
-       image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
-       mono_image_unlock (image);
+       mono_image_append_class_to_reflection_info_set (pklass);
 }
 
 MonoArray *