Merge pull request #3749 from BrzVlad/fix-mips-fix
[mono.git] / mono / metadata / custom-attrs.c
1 /*
2  * custom-attrs.c: Custom attributes.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  * Copyright 2016 Microsoft
11  *
12  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13  */
14 #include <config.h>
15 #include "mono/metadata/gc-internals.h"
16 #include "mono/metadata/mono-endian.h"
17 #include "mono/metadata/object-internals.h"
18 #include "mono/metadata/reflection-cache.h"
19 #include "mono/metadata/custom-attrs-internals.h"
20 #include "mono/metadata/sre-internals.h"
21 #include "mono/metadata/reflection-internals.h"
22 #include "mono/metadata/tabledefs.h"
23 #include "mono/metadata/tokentype.h"
24 #include "mono/metadata/verify-internals.h"
25 #include "mono/utils/checked-build.h"
26
27
28 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
29 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
30
31 #if SIZEOF_VOID_P == 4
32 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
33 #else
34 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
35 #endif
36
37 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
38 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
39
40 static gboolean type_is_reference (MonoType *type);
41
42 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
43 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
44
45 /*
46  * LOCKING: Acquires the loader lock. 
47  */
48 static MonoCustomAttrInfo*
49 lookup_custom_attr (MonoImage *image, gpointer member)
50 {
51         MONO_REQ_GC_NEUTRAL_MODE;
52
53         MonoCustomAttrInfo* res;
54
55         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
56
57         if (!res)
58                 return NULL;
59
60         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
61         res->cached = 0;
62         return res;
63 }
64
65 static gboolean
66 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
67 {
68         MONO_REQ_GC_UNSAFE_MODE;
69
70         /* FIXME: Need to do more checks */
71         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
72                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
73
74                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
75                         return FALSE;
76         }
77
78         return TRUE;
79 }
80
81 static gboolean
82 type_is_reference (MonoType *type)
83 {
84         switch (type->type) {
85         case MONO_TYPE_BOOLEAN:
86         case MONO_TYPE_CHAR:
87         case MONO_TYPE_U:
88         case MONO_TYPE_I:
89         case MONO_TYPE_U1:
90         case MONO_TYPE_I1:
91         case MONO_TYPE_U2:
92         case MONO_TYPE_I2:
93         case MONO_TYPE_U4:
94         case MONO_TYPE_I4:
95         case MONO_TYPE_U8:
96         case MONO_TYPE_I8:
97         case MONO_TYPE_R8:
98         case MONO_TYPE_R4:
99         case MONO_TYPE_VALUETYPE:
100                 return FALSE;
101         default:
102                 return TRUE;
103         }
104 }
105
106 static void
107 free_param_data (MonoMethodSignature *sig, void **params) {
108         int i;
109         for (i = 0; i < sig->param_count; ++i) {
110                 if (!type_is_reference (sig->params [i]))
111                         g_free (params [i]);
112         }
113 }
114
115 /*
116  * Find the field index in the metadata FieldDef table.
117  */
118 static guint32
119 find_field_index (MonoClass *klass, MonoClassField *field) {
120         int i;
121
122         for (i = 0; i < klass->field.count; ++i) {
123                 if (field == &klass->fields [i])
124                         return klass->field.first + 1 + i;
125         }
126         return 0;
127 }
128
129 /*
130  * Find the property index in the metadata Property table.
131  */
132 static guint32
133 find_property_index (MonoClass *klass, MonoProperty *property) {
134         int i;
135
136         for (i = 0; i < klass->ext->property.count; ++i) {
137                 if (property == &klass->ext->properties [i])
138                         return klass->ext->property.first + 1 + i;
139         }
140         return 0;
141 }
142
143 /*
144  * Find the event index in the metadata Event table.
145  */
146 static guint32
147 find_event_index (MonoClass *klass, MonoEvent *event) {
148         int i;
149
150         for (i = 0; i < klass->ext->event.count; ++i) {
151                 if (event == &klass->ext->events [i])
152                         return klass->ext->event.first + 1 + i;
153         }
154         return 0;
155 }
156
157 /*
158  * Load the type with name @n on behalf of image @image.  On failure sets @error and returns NULL.
159  * The @is_enum flag only affects the error message that's displayed on failure.
160  */
161 static MonoType*
162 cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *error)
163 {
164         MonoError inner_error;
165         MonoType *t = mono_reflection_type_from_name_checked (n, image, &inner_error);
166         if (!t) {
167                 mono_error_set_type_load_name (error, g_strdup(n), NULL,
168                                                "Could not load %s %s while decoding custom attribute: %s",
169                                                is_enum ? "enum type": "type",
170                                                n,
171                                                mono_error_get_message (&inner_error));
172                 mono_error_cleanup (&inner_error);
173                 return NULL;
174         }
175         return t;
176 }
177
178 static MonoClass*
179 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
180 {
181         char *n;
182         MonoType *t;
183         int slen = mono_metadata_decode_value (p, &p);
184
185         mono_error_init (error);
186
187         n = (char *)g_memdup (p, slen + 1);
188         n [slen] = 0;
189         t = cattr_type_from_name (n, image, TRUE, error);
190         g_free (n);
191         return_val_if_nok (error, NULL);
192         p += slen;
193         *end = p;
194         return mono_class_from_mono_type (t);
195 }
196
197 static void*
198 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
199 {
200         int slen, type = t->type;
201         MonoClass *tklass = t->data.klass;
202
203         mono_error_init (error);
204
205 handle_enum:
206         switch (type) {
207         case MONO_TYPE_U1:
208         case MONO_TYPE_I1:
209         case MONO_TYPE_BOOLEAN: {
210                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
211                 *bval = *p;
212                 *end = p + 1;
213                 return bval;
214         }
215         case MONO_TYPE_CHAR:
216         case MONO_TYPE_U2:
217         case MONO_TYPE_I2: {
218                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
219                 *val = read16 (p);
220                 *end = p + 2;
221                 return val;
222         }
223 #if SIZEOF_VOID_P == 4
224         case MONO_TYPE_U:
225         case MONO_TYPE_I:
226 #endif
227         case MONO_TYPE_R4:
228         case MONO_TYPE_U4:
229         case MONO_TYPE_I4: {
230                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
231                 *val = read32 (p);
232                 *end = p + 4;
233                 return val;
234         }
235 #if SIZEOF_VOID_P == 8
236         case MONO_TYPE_U: /* error out instead? this should probably not happen */
237         case MONO_TYPE_I:
238 #endif
239         case MONO_TYPE_U8:
240         case MONO_TYPE_I8: {
241                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
242                 *val = read64 (p);
243                 *end = p + 8;
244                 return val;
245         }
246         case MONO_TYPE_R8: {
247                 double *val = (double *)g_malloc (sizeof (double));
248                 readr8 (p, val);
249                 *end = p + 8;
250                 return val;
251         }
252         case MONO_TYPE_VALUETYPE:
253                 if (t->data.klass->enumtype) {
254                         type = mono_class_enum_basetype (t->data.klass)->type;
255                         goto handle_enum;
256                 } else {
257                         MonoClass *k =  t->data.klass;
258                         
259                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
260                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
261                                 *val = read64 (p);
262                                 *end = p + 8;
263                                 return val;
264                         }
265                 }
266                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
267                 break;
268                 
269         case MONO_TYPE_STRING:
270                 if (*p == (char)0xFF) {
271                         *end = p + 1;
272                         return NULL;
273                 }
274                 slen = mono_metadata_decode_value (p, &p);
275                 *end = p + slen;
276                 return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
277         case MONO_TYPE_CLASS: {
278                 MonoReflectionType *rt;
279                 char *n;
280                 MonoType *t;
281                 if (*p == (char)0xFF) {
282                         *end = p + 1;
283                         return NULL;
284                 }
285 handle_type:
286                 slen = mono_metadata_decode_value (p, &p);
287                 n = (char *)g_memdup (p, slen + 1);
288                 n [slen] = 0;
289                 t = cattr_type_from_name (n, image, FALSE, error);
290                 g_free (n);
291                 return_val_if_nok (error, NULL);
292                 *end = p + slen;
293
294                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
295                 if (!mono_error_ok (error))
296                         return NULL;
297
298                 return rt;
299         }
300         case MONO_TYPE_OBJECT: {
301                 char subt = *p++;
302                 MonoObject *obj;
303                 MonoClass *subc = NULL;
304                 void *val;
305
306                 if (subt == 0x50) {
307                         goto handle_type;
308                 } else if (subt == 0x0E) {
309                         type = MONO_TYPE_STRING;
310                         goto handle_enum;
311                 } else if (subt == 0x1D) {
312                         MonoType simple_type = {{0}};
313                         int etype = *p;
314                         p ++;
315
316                         type = MONO_TYPE_SZARRAY;
317                         if (etype == 0x50) {
318                                 tklass = mono_defaults.systemtype_class;
319                         } else if (etype == 0x55) {
320                                 tklass = load_cattr_enum_type (image, p, &p, error);
321                                 if (!mono_error_ok (error))
322                                         return NULL;
323                         } else {
324                                 if (etype == 0x51)
325                                         /* See Partition II, Appendix B3 */
326                                         etype = MONO_TYPE_OBJECT;
327                                 simple_type.type = (MonoTypeEnum)etype;
328                                 tklass = mono_class_from_mono_type (&simple_type);
329                         }
330                         goto handle_enum;
331                 } else if (subt == 0x55) {
332                         char *n;
333                         MonoType *t;
334                         slen = mono_metadata_decode_value (p, &p);
335                         n = (char *)g_memdup (p, slen + 1);
336                         n [slen] = 0;
337                         t = cattr_type_from_name (n, image, FALSE, error);
338                         g_free (n);
339                         return_val_if_nok (error, NULL);
340                         p += slen;
341                         subc = mono_class_from_mono_type (t);
342                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
343                         MonoType simple_type = {{0}};
344                         simple_type.type = (MonoTypeEnum)subt;
345                         subc = mono_class_from_mono_type (&simple_type);
346                 } else {
347                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
348                 }
349                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
350                 obj = NULL;
351                 if (mono_error_ok (error)) {
352                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
353                         g_assert (!subc->has_references);
354                         if (mono_error_ok (error))
355                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
356                 }
357
358                 g_free (val);
359                 return obj;
360         }
361         case MONO_TYPE_SZARRAY: {
362                 MonoArray *arr;
363                 guint32 i, alen, basetype;
364                 alen = read32 (p);
365                 p += 4;
366                 if (alen == 0xffffffff) {
367                         *end = p;
368                         return NULL;
369                 }
370                 arr = mono_array_new_checked (mono_domain_get(), tklass, alen, error);
371                 return_val_if_nok (error, NULL);
372                 basetype = tklass->byval_arg.type;
373                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
374                         basetype = mono_class_enum_basetype (tklass)->type;
375                 switch (basetype)
376                 {
377                         case MONO_TYPE_U1:
378                         case MONO_TYPE_I1:
379                         case MONO_TYPE_BOOLEAN:
380                                 for (i = 0; i < alen; i++) {
381                                         MonoBoolean val = *p++;
382                                         mono_array_set (arr, MonoBoolean, i, val);
383                                 }
384                                 break;
385                         case MONO_TYPE_CHAR:
386                         case MONO_TYPE_U2:
387                         case MONO_TYPE_I2:
388                                 for (i = 0; i < alen; i++) {
389                                         guint16 val = read16 (p);
390                                         mono_array_set (arr, guint16, i, val);
391                                         p += 2;
392                                 }
393                                 break;
394                         case MONO_TYPE_R4:
395                         case MONO_TYPE_U4:
396                         case MONO_TYPE_I4:
397                                 for (i = 0; i < alen; i++) {
398                                         guint32 val = read32 (p);
399                                         mono_array_set (arr, guint32, i, val);
400                                         p += 4;
401                                 }
402                                 break;
403                         case MONO_TYPE_R8:
404                                 for (i = 0; i < alen; i++) {
405                                         double val;
406                                         readr8 (p, &val);
407                                         mono_array_set (arr, double, i, val);
408                                         p += 8;
409                                 }
410                                 break;
411                         case MONO_TYPE_U8:
412                         case MONO_TYPE_I8:
413                                 for (i = 0; i < alen; i++) {
414                                         guint64 val = read64 (p);
415                                         mono_array_set (arr, guint64, i, val);
416                                         p += 8;
417                                 }
418                                 break;
419                         case MONO_TYPE_CLASS:
420                         case MONO_TYPE_OBJECT:
421                         case MONO_TYPE_STRING:
422                         case MONO_TYPE_SZARRAY:
423                                 for (i = 0; i < alen; i++) {
424                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
425                                         if (!mono_error_ok (error))
426                                                 return NULL;
427                                         mono_array_setref (arr, i, item);
428                                 }
429                                 break;
430                         default:
431                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
432                 }
433                 *end=p;
434                 return arr;
435         }
436         default:
437                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
438         }
439         return NULL;
440 }
441
442 static MonoObject*
443 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
444 {
445         mono_error_init (error);
446
447         gboolean is_ref = type_is_reference (t);
448
449         void *val = load_cattr_value (image, t, p, end, error);
450         if (!is_ok (error)) {
451                 if (is_ref)
452                         g_free (val);
453                 return NULL;
454         }
455
456         if (is_ref)
457                 return (MonoObject*)val;
458
459         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
460         g_free (val);
461         return boxed;
462 }
463
464 static MonoObject*
465 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
466 {
467         static MonoMethod *ctor;
468         MonoObject *retval;
469         void *params [2], *unboxed;
470
471         mono_error_init (error);
472
473         if (!ctor)
474                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
475         
476         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
477         return_val_if_nok (error, NULL);
478
479         params [1] = val;
480         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
481         return_val_if_nok (error, NULL);
482         unboxed = mono_object_unbox (retval);
483
484         mono_runtime_invoke_checked (ctor, unboxed, params, error);
485         return_val_if_nok (error, NULL);
486
487         return retval;
488 }
489
490 static MonoObject*
491 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
492 {
493         static MonoMethod *ctor;
494         MonoObject *retval;
495         void *unboxed, *params [2];
496
497         mono_error_init (error);
498
499         if (!ctor)
500                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
501
502         params [0] = minfo;
503         params [1] = typedarg;
504         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
505         return_val_if_nok (error, NULL);
506
507         unboxed = mono_object_unbox (retval);
508
509         mono_runtime_invoke_checked (ctor, unboxed, params, error);
510         return_val_if_nok (error, NULL);
511
512         return retval;
513 }
514
515
516 MonoCustomAttrInfo*
517 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
518 {
519         MONO_REQ_GC_UNSAFE_MODE;
520
521         int i, index, count, not_visible;
522         MonoCustomAttrInfo *ainfo;
523         MonoReflectionCustomAttr *cattr;
524
525         if (!cattrs)
526                 return NULL;
527         /* FIXME: check in assembly the Run flag is set */
528
529         count = mono_array_length (cattrs);
530
531         /* Skip nonpublic attributes since MS.NET seems to do the same */
532         /* FIXME: This needs to be done more globally */
533         not_visible = 0;
534         for (i = 0; i < count; ++i) {
535                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
536                 if (!custom_attr_visible (image, cattr))
537                         not_visible ++;
538         }
539
540         int num_attrs = count - not_visible;
541         ainfo = (MonoCustomAttrInfo *)mono_image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * num_attrs);
542
543         ainfo->image = image;
544         ainfo->num_attrs = num_attrs;
545         ainfo->cached = alloc_img != NULL;
546         index = 0;
547         for (i = 0; i < count; ++i) {
548                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
549                 if (custom_attr_visible (image, cattr)) {
550                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
551                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
552                         ainfo->attrs [index].ctor = cattr->ctor->method;
553                         g_assert (cattr->ctor->method);
554                         ainfo->attrs [index].data = saved;
555                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
556                         index ++;
557                 }
558         }
559         g_assert (index == num_attrs && count == num_attrs + not_visible);
560
561         return ainfo;
562 }
563
564
565 static MonoObject*
566 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
567 {
568         const char *p = (const char*)data;
569         const char *named;
570         guint32 i, j, num_named;
571         MonoObject *attr;
572         void *params_buf [32];
573         void **params = NULL;
574         MonoMethodSignature *sig;
575
576         mono_error_init (error);
577
578         mono_class_init (method->klass);
579
580         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
581                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
582                 return NULL;
583         }
584
585         if (len == 0) {
586                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
587                 if (!mono_error_ok (error)) return NULL;
588
589                 mono_runtime_invoke_checked (method, attr, NULL, error);
590                 if (!mono_error_ok (error))
591                         return NULL;
592
593                 return attr;
594         }
595
596         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
597                 return NULL;
598
599         /*g_print ("got attr %s\n", method->klass->name);*/
600
601         sig = mono_method_signature (method);
602         if (sig->param_count < 32) {
603                 params = params_buf;
604                 memset (params, 0, sizeof (void*) * sig->param_count);
605         } else {
606                 /* Allocate using GC so it gets GC tracking */
607                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
608         }
609
610         /* skip prolog */
611         p += 2;
612         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
613                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
614                 if (!mono_error_ok (error))
615                         goto fail;
616         }
617
618         named = p;
619         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
620         if (!mono_error_ok (error)) goto fail;
621
622         MonoObject *exc = NULL;
623         mono_runtime_try_invoke (method, attr, params, &exc, error);
624         if (!mono_error_ok (error))
625                 goto fail;
626         if (exc) {
627                 mono_error_set_exception_instance (error, (MonoException*)exc);
628                 goto fail;
629         }
630
631         num_named = read16 (named);
632         named += 2;
633         for (j = 0; j < num_named; j++) {
634                 gint name_len;
635                 char *name, named_type, data_type;
636                 named_type = *named++;
637                 data_type = *named++; /* type of data */
638                 if (data_type == MONO_TYPE_SZARRAY)
639                         data_type = *named++;
640                 if (data_type == MONO_TYPE_ENUM) {
641                         gint type_len;
642                         char *type_name;
643                         type_len = mono_metadata_decode_blob_size (named, &named);
644                         type_name = (char *)g_malloc (type_len + 1);
645                         memcpy (type_name, named, type_len);
646                         type_name [type_len] = 0;
647                         named += type_len;
648                         /* FIXME: lookup the type and check type consistency */
649                         g_free (type_name);
650                 }
651                 name_len = mono_metadata_decode_blob_size (named, &named);
652                 name = (char *)g_malloc (name_len + 1);
653                 memcpy (name, named, name_len);
654                 name [name_len] = 0;
655                 named += name_len;
656                 if (named_type == 0x53) {
657                         MonoClassField *field;
658                         void *val;
659
660                         /* how this fail is a blackbox */
661                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
662                         if (!field) {
663                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
664                                 g_free (name);
665                                 goto fail;
666                         }
667
668                         val = load_cattr_value (image, field->type, named, &named, error);
669                         if (!mono_error_ok (error)) {
670                                 g_free (name);
671                                 if (!type_is_reference (field->type))
672                                         g_free (val);
673                                 goto fail;
674                         }
675
676                         mono_field_set_value (attr, field, val);
677                         if (!type_is_reference (field->type))
678                                 g_free (val);
679                 } else if (named_type == 0x54) {
680                         MonoProperty *prop;
681                         void *pparams [1];
682                         MonoType *prop_type;
683
684                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
685
686                         if (!prop) {
687                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
688                                 g_free (name);
689                                 goto fail;
690                         }
691
692                         if (!prop->set) {
693                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
694                                 g_free (name);
695                                 goto fail;
696                         }
697
698                         /* can we have more that 1 arg in a custom attr named property? */
699                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
700                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
701
702                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
703                         if (!mono_error_ok (error)) {
704                                 g_free (name);
705                                 if (!type_is_reference (prop_type))
706                                         g_free (pparams [0]);
707                                 goto fail;
708                         }
709
710
711                         mono_property_set_value_checked (prop, attr, pparams, error);
712                         if (!type_is_reference (prop_type))
713                                 g_free (pparams [0]);
714                         if (!is_ok (error)) {
715                                 g_free (name);
716                                 goto fail;
717                         }
718                 }
719                 g_free (name);
720         }
721
722         free_param_data (method->signature, params);
723         if (params != params_buf)
724                 mono_gc_free_fixed (params);
725
726         return attr;
727
728 fail:
729         free_param_data (method->signature, params);
730         if (params != params_buf)
731                 mono_gc_free_fixed (params);
732         return NULL;
733 }
734         
735 /*
736  * mono_reflection_create_custom_attr_data_args:
737  *
738  *   Create an array of typed and named arguments from the cattr blob given by DATA.
739  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
740  * NAMED_ARG_INFO will contain information about the named arguments.
741  */
742 void
743 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
744 {
745         MonoArray *typedargs, *namedargs;
746         MonoClass *attrklass;
747         MonoDomain *domain;
748         const char *p = (const char*)data;
749         const char *named;
750         guint32 i, j, num_named;
751         CattrNamedArg *arginfo = NULL;
752
753         *typed_args = NULL;
754         *named_args = NULL;
755         *named_arg_info = NULL;
756
757         mono_error_init (error);
758
759         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
760                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
761                 return;
762         }
763
764         mono_class_init (method->klass);
765         
766         domain = mono_domain_get ();
767
768         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
769                 return;
770
771         typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
772         return_if_nok (error);
773
774         /* skip prolog */
775         p += 2;
776         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
777                 MonoObject *obj;
778
779                 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
780                 return_if_nok (error);
781                 mono_array_setref (typedargs, i, obj);
782         }
783
784         named = p;
785         num_named = read16 (named);
786         namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
787         return_if_nok (error);
788         named += 2;
789         attrklass = method->klass;
790
791         arginfo = g_new0 (CattrNamedArg, num_named);
792         *named_arg_info = arginfo;
793
794         for (j = 0; j < num_named; j++) {
795                 gint name_len;
796                 char *name, named_type, data_type;
797                 named_type = *named++;
798                 data_type = *named++; /* type of data */
799                 if (data_type == MONO_TYPE_SZARRAY)
800                         data_type = *named++;
801                 if (data_type == MONO_TYPE_ENUM) {
802                         gint type_len;
803                         char *type_name;
804                         type_len = mono_metadata_decode_blob_size (named, &named);
805                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
806                                 goto fail;
807
808                         type_name = (char *)g_malloc (type_len + 1);
809                         memcpy (type_name, named, type_len);
810                         type_name [type_len] = 0;
811                         named += type_len;
812                         /* FIXME: lookup the type and check type consistency */
813                         g_free (type_name);
814                 }
815                 name_len = mono_metadata_decode_blob_size (named, &named);
816                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
817                         goto fail;
818                 name = (char *)g_malloc (name_len + 1);
819                 memcpy (name, named, name_len);
820                 name [name_len] = 0;
821                 named += name_len;
822                 if (named_type == 0x53) {
823                         MonoObject *obj;
824                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
825
826                         if (!field) {
827                                 g_free (name);
828                                 goto fail;
829                         }
830
831                         arginfo [j].type = field->type;
832                         arginfo [j].field = field;
833
834                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
835                         if (!is_ok (error)) {
836                                 g_free (name);
837                                 return;
838                         }
839                         mono_array_setref (namedargs, j, obj);
840
841                 } else if (named_type == 0x54) {
842                         MonoObject *obj;
843                         MonoType *prop_type;
844                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
845
846                         if (!prop || !prop->set) {
847                                 g_free (name);
848                                 goto fail;
849                         }
850
851                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
852                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
853
854                         arginfo [j].type = prop_type;
855                         arginfo [j].prop = prop;
856
857                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
858                         if (!is_ok (error)) {
859                                 g_free (name);
860                                 return;
861                         }
862                         mono_array_setref (namedargs, j, obj);
863                 }
864                 g_free (name);
865         }
866
867         *typed_args = typedargs;
868         *named_args = namedargs;
869         return;
870 fail:
871         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
872         g_free (arginfo);
873         *named_arg_info = NULL;
874 }
875
876 static gboolean
877 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
878 {
879         MonoDomain *domain;
880         MonoArray *typedargs, *namedargs;
881         MonoImage *image;
882         MonoMethod *method;
883         CattrNamedArg *arginfo = NULL;
884         int i;
885
886         mono_error_init (error);
887
888         *ctor_args = NULL;
889         *named_args = NULL;
890
891         if (len == 0)
892                 return TRUE;
893
894         image = assembly->assembly->image;
895         method = ref_method->method;
896         domain = mono_object_domain (ref_method);
897
898         if (!mono_class_init (method->klass)) {
899                 mono_error_set_for_class_failure (error, method->klass);
900                 goto leave;
901         }
902
903         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
904         if (!is_ok (error))
905                 goto leave;
906
907         if (!typedargs || !namedargs)
908                 goto leave;
909
910         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
911                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
912                 MonoObject *typedarg;
913
914                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
915                 if (!is_ok (error))
916                         goto leave;
917                 mono_array_setref (typedargs, i, typedarg);
918         }
919
920         for (i = 0; i < mono_array_length (namedargs); ++i) {
921                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
922                 MonoObject *typedarg, *namedarg, *minfo;
923
924                 if (arginfo [i].prop) {
925                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
926                         if (!minfo)
927                                 goto leave;
928                 } else {
929                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
930                         if (!is_ok (error))
931                                 goto leave;
932                 }
933
934                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
935                 if (!is_ok (error))
936                         goto leave;
937                 namedarg = create_cattr_named_arg (minfo, typedarg, error);
938                 if (!is_ok (error))
939                         goto leave;
940
941                 mono_array_setref (namedargs, i, namedarg);
942         }
943
944         *ctor_args = typedargs;
945         *named_args = namedargs;
946
947 leave:
948         g_free (arginfo);
949         return mono_error_ok (error);
950 }
951
952 void
953 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
954 {
955         MonoError error;
956         (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
957         mono_error_set_pending_exception (&error);
958 }
959
960 static MonoObject*
961 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
962 {
963         static MonoMethod *ctor;
964
965         MonoDomain *domain;
966         MonoObject *attr;
967         void *params [4];
968
969         mono_error_init (error);
970
971         g_assert (image->assembly);
972
973         if (!ctor)
974                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
975
976         domain = mono_domain_get ();
977         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
978         return_val_if_nok (error, NULL);
979         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
980         return_val_if_nok (error, NULL);
981         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
982         return_val_if_nok (error, NULL);
983         params [2] = (gpointer)&cattr->data;
984         params [3] = &cattr->data_size;
985
986         mono_runtime_invoke_checked (ctor, attr, params, error);
987         return_val_if_nok (error, NULL);
988         return attr;
989 }
990
991 static MonoArray*
992 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
993 {
994         MonoArray *result;
995         MonoObject *attr;
996         int i, n;
997
998         mono_error_init (error);
999
1000         for (i = 0; i < cinfo->num_attrs; ++i) {
1001                 MonoCustomAttrEntry *centry = &cinfo->attrs[i];
1002                 if (!centry->ctor) {
1003                         /* The cattr type is not finished yet */
1004                         /* We should include the type name but cinfo doesn't contain it */
1005                         mono_error_set_type_load_name (error, NULL, NULL, "Custom attribute constructor is null because the custom attribute type is not finished yet.");
1006                         return NULL;
1007                 }
1008         }
1009
1010         n = 0;
1011         if (attr_klass) {
1012                 for (i = 0; i < cinfo->num_attrs; ++i) {
1013                         MonoMethod *ctor = cinfo->attrs[i].ctor;
1014                         g_assert (ctor);
1015                         if (mono_class_is_assignable_from (attr_klass, ctor->klass))
1016                                 n++;
1017                 }
1018         } else {
1019                 n = cinfo->num_attrs;
1020         }
1021
1022         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n, error);
1023         return_val_if_nok (error, NULL);
1024         n = 0;
1025         for (i = 0; i < cinfo->num_attrs; ++i) {
1026                 MonoCustomAttrEntry *centry = &cinfo->attrs [i];
1027                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, centry->ctor->klass)) {
1028                         attr = create_custom_attr (cinfo->image, centry->ctor, centry->data, centry->data_size, error);
1029                         if (!mono_error_ok (error))
1030                                 return result;
1031                         mono_array_setref (result, n, attr);
1032                         n ++;
1033                 }
1034         }
1035         return result;
1036 }
1037
1038 MonoArray*
1039 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
1040 {
1041         MonoError error;
1042         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
1043         mono_error_assert_ok (&error); /*FIXME proper error handling*/
1044
1045         return result;
1046 }
1047
1048 static MonoArray*
1049 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
1050 {
1051         MonoArray *result;
1052         MonoObject *attr;
1053         int i;
1054         
1055         mono_error_init (error);
1056         result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
1057         return_val_if_nok (error, NULL);
1058         for (i = 0; i < cinfo->num_attrs; ++i) {
1059                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
1060                 return_val_if_nok (error, NULL);
1061                 mono_array_setref (result, i, attr);
1062         }
1063         return result;
1064 }
1065
1066 /**
1067  * mono_custom_attrs_from_index:
1068  *
1069  * Returns: NULL if no attributes are found or if a loading error occurs.
1070  */
1071 MonoCustomAttrInfo*
1072 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
1073 {
1074         MonoError error;
1075         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
1076         mono_error_cleanup (&error);
1077         return result;
1078 }
1079 /**
1080  * mono_custom_attrs_from_index_checked:
1081  *
1082  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
1083  */
1084 MonoCustomAttrInfo*
1085 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
1086 {
1087         guint32 mtoken, i, len;
1088         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
1089         MonoTableInfo *ca;
1090         MonoCustomAttrInfo *ainfo;
1091         GList *tmp, *list = NULL;
1092         const char *data;
1093         MonoCustomAttrEntry* attr;
1094
1095         mono_error_init (error);
1096
1097         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1098
1099         i = mono_metadata_custom_attrs_from_index (image, idx);
1100         if (!i)
1101                 return NULL;
1102         i --;
1103         while (i < ca->rows) {
1104                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
1105                         break;
1106                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
1107                 ++i;
1108         }
1109         len = g_list_length (list);
1110         if (!len)
1111                 return NULL;
1112         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
1113         ainfo->num_attrs = len;
1114         ainfo->image = image;
1115         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
1116                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
1117                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
1118                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
1119                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
1120                         mtoken |= MONO_TOKEN_METHOD_DEF;
1121                         break;
1122                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
1123                         mtoken |= MONO_TOKEN_MEMBER_REF;
1124                         break;
1125                 default:
1126                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
1127                         break;
1128                 }
1129                 attr = &ainfo->attrs [i - 1];
1130                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
1131                 if (!attr->ctor) {
1132                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
1133                         g_list_free (list);
1134                         g_free (ainfo);
1135                         return NULL;
1136                 }
1137
1138                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
1139                         /*FIXME raising an exception here doesn't make any sense*/
1140                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
1141                         g_list_free (list);
1142                         g_free (ainfo);
1143                         return NULL;
1144                 }
1145                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
1146                 attr->data_size = mono_metadata_decode_value (data, &data);
1147                 attr->data = (guchar*)data;
1148         }
1149         g_list_free (list);
1150
1151         return ainfo;
1152 }
1153
1154 MonoCustomAttrInfo*
1155 mono_custom_attrs_from_method (MonoMethod *method)
1156 {
1157         MonoError error;
1158         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
1159         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
1160         return result;
1161 }
1162
1163 MonoCustomAttrInfo*
1164 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
1165 {
1166         guint32 idx;
1167
1168         mono_error_init (error);
1169
1170         /*
1171          * An instantiated method has the same cattrs as the generic method definition.
1172          *
1173          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1174          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1175          */
1176         if (method->is_inflated)
1177                 method = ((MonoMethodInflated *) method)->declaring;
1178         
1179         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
1180                 return lookup_custom_attr (method->klass->image, method);
1181
1182         if (!method->token)
1183                 /* Synthetic methods */
1184                 return NULL;
1185
1186         idx = mono_method_get_index (method);
1187         idx <<= MONO_CUSTOM_ATTR_BITS;
1188         idx |= MONO_CUSTOM_ATTR_METHODDEF;
1189         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
1190 }
1191
1192 MonoCustomAttrInfo*
1193 mono_custom_attrs_from_class (MonoClass *klass)
1194 {
1195         MonoError error;
1196         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
1197         mono_error_cleanup (&error);
1198         return result;
1199 }
1200
1201 MonoCustomAttrInfo*
1202 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
1203 {
1204         guint32 idx;
1205
1206         mono_error_init (error);
1207
1208         if (klass->generic_class)
1209                 klass = klass->generic_class->container_class;
1210
1211         if (image_is_dynamic (klass->image))
1212                 return lookup_custom_attr (klass->image, klass);
1213
1214         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
1215                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
1216                 idx <<= MONO_CUSTOM_ATTR_BITS;
1217                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
1218         } else {
1219                 idx = mono_metadata_token_index (klass->type_token);
1220                 idx <<= MONO_CUSTOM_ATTR_BITS;
1221                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
1222         }
1223         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
1224 }
1225
1226 MonoCustomAttrInfo*
1227 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
1228 {
1229         MonoError error;
1230         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
1231         mono_error_cleanup (&error);
1232         return result;
1233 }
1234
1235 MonoCustomAttrInfo*
1236 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
1237 {
1238         guint32 idx;
1239         
1240         mono_error_init (error);
1241
1242         if (image_is_dynamic (assembly->image))
1243                 return lookup_custom_attr (assembly->image, assembly);
1244         idx = 1; /* there is only one assembly */
1245         idx <<= MONO_CUSTOM_ATTR_BITS;
1246         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
1247         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
1248 }
1249
1250 static MonoCustomAttrInfo*
1251 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
1252 {
1253         guint32 idx;
1254         
1255         if (image_is_dynamic (image))
1256                 return lookup_custom_attr (image, image);
1257         idx = 1; /* there is only one module */
1258         idx <<= MONO_CUSTOM_ATTR_BITS;
1259         idx |= MONO_CUSTOM_ATTR_MODULE;
1260         return mono_custom_attrs_from_index_checked (image, idx, error);
1261 }
1262
1263 MonoCustomAttrInfo*
1264 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
1265 {
1266         MonoError error;
1267         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
1268         mono_error_cleanup (&error);
1269         return result;
1270 }
1271
1272 MonoCustomAttrInfo*
1273 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
1274 {
1275         guint32 idx;
1276         
1277         if (image_is_dynamic (klass->image)) {
1278                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
1279                 return lookup_custom_attr (klass->image, property);
1280         }
1281         idx = find_property_index (klass, property);
1282         idx <<= MONO_CUSTOM_ATTR_BITS;
1283         idx |= MONO_CUSTOM_ATTR_PROPERTY;
1284         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
1285 }
1286
1287 MonoCustomAttrInfo*
1288 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
1289 {
1290         MonoError error;
1291         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
1292         mono_error_cleanup (&error);
1293         return result;
1294 }
1295
1296 MonoCustomAttrInfo*
1297 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
1298 {
1299         guint32 idx;
1300         
1301         if (image_is_dynamic (klass->image)) {
1302                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
1303                 return lookup_custom_attr (klass->image, event);
1304         }
1305         idx = find_event_index (klass, event);
1306         idx <<= MONO_CUSTOM_ATTR_BITS;
1307         idx |= MONO_CUSTOM_ATTR_EVENT;
1308         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
1309 }
1310
1311 MonoCustomAttrInfo*
1312 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
1313 {
1314         MonoError error;
1315         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
1316         mono_error_cleanup (&error);
1317         return result;
1318 }
1319
1320 MonoCustomAttrInfo*
1321 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
1322 {
1323         guint32 idx;
1324         mono_error_init (error);
1325
1326         if (image_is_dynamic (klass->image)) {
1327                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
1328                 return lookup_custom_attr (klass->image, field);
1329         }
1330         idx = find_field_index (klass, field);
1331         idx <<= MONO_CUSTOM_ATTR_BITS;
1332         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
1333         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
1334 }
1335
1336 /**
1337  * mono_custom_attrs_from_param:
1338  * @method: handle to the method that we want to retrieve custom parameter information from
1339  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1340  *
1341  * The result must be released with mono_custom_attrs_free().
1342  *
1343  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
1344  */
1345 MonoCustomAttrInfo*
1346 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
1347 {
1348         MonoError error;
1349         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
1350         mono_error_cleanup (&error);
1351         return result;
1352 }
1353
1354 /**
1355  * mono_custom_attrs_from_param_checked:
1356  * @method: handle to the method that we want to retrieve custom parameter information from
1357  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
1358  * @error: set on error
1359  *
1360  * The result must be released with mono_custom_attrs_free().
1361  *
1362  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
1363  */
1364 MonoCustomAttrInfo*
1365 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
1366 {
1367         MonoTableInfo *ca;
1368         guint32 i, idx, method_index;
1369         guint32 param_list, param_last, param_pos, found;
1370         MonoImage *image;
1371         MonoReflectionMethodAux *aux;
1372
1373         mono_error_init (error);
1374
1375         /*
1376          * An instantiated method has the same cattrs as the generic method definition.
1377          *
1378          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
1379          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
1380          */
1381         if (method->is_inflated)
1382                 method = ((MonoMethodInflated *) method)->declaring;
1383
1384         if (image_is_dynamic (method->klass->image)) {
1385                 MonoCustomAttrInfo *res, *ainfo;
1386                 int size;
1387
1388                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
1389                 if (!aux || !aux->param_cattr)
1390                         return NULL;
1391
1392                 /* Need to copy since it will be freed later */
1393                 ainfo = aux->param_cattr [param];
1394                 if (!ainfo)
1395                         return NULL;
1396                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
1397                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
1398                 memcpy (res, ainfo, size);
1399                 return res;
1400         }
1401
1402         image = method->klass->image;
1403         method_index = mono_method_get_index (method);
1404         if (!method_index)
1405                 return NULL;
1406         ca = &image->tables [MONO_TABLE_METHOD];
1407
1408         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
1409         if (method_index == ca->rows) {
1410                 ca = &image->tables [MONO_TABLE_PARAM];
1411                 param_last = ca->rows + 1;
1412         } else {
1413                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
1414                 ca = &image->tables [MONO_TABLE_PARAM];
1415         }
1416         found = FALSE;
1417         for (i = param_list; i < param_last; ++i) {
1418                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
1419                 if (param_pos == param) {
1420                         found = TRUE;
1421                         break;
1422                 }
1423         }
1424         if (!found)
1425                 return NULL;
1426         idx = i;
1427         idx <<= MONO_CUSTOM_ATTR_BITS;
1428         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
1429         return mono_custom_attrs_from_index_checked (image, idx, error);
1430 }
1431
1432 gboolean
1433 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1434 {
1435         int i;
1436         for (i = 0; i < ainfo->num_attrs; ++i) {
1437                 MonoClass *klass = ainfo->attrs [i].ctor->klass;
1438                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
1439                         return TRUE;
1440         }
1441         return FALSE;
1442 }
1443
1444 MonoObject*
1445 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
1446 {
1447         MonoError error;
1448         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
1449         mono_error_assert_ok (&error); /*FIXME proper error handling*/
1450         return res;
1451 }
1452
1453 MonoObject*
1454 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
1455 {
1456         int i, attr_index;
1457         MonoArray *attrs;
1458
1459         mono_error_init (error);
1460
1461         attr_index = -1;
1462         for (i = 0; i < ainfo->num_attrs; ++i) {
1463                 MonoClass *klass = ainfo->attrs [i].ctor->klass;
1464                 if (mono_class_has_parent (klass, attr_klass)) {
1465                         attr_index = i;
1466                         break;
1467                 }
1468         }
1469         if (attr_index == -1)
1470                 return NULL;
1471
1472         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
1473         if (!mono_error_ok (error))
1474                 return NULL;
1475         return mono_array_get (attrs, MonoObject*, attr_index);
1476 }
1477
1478 /*
1479  * mono_reflection_get_custom_attrs_info:
1480  * @obj: a reflection object handle
1481  *
1482  * Return the custom attribute info for attributes defined for the
1483  * reflection handle @obj. The objects.
1484  *
1485  * FIXME this function leaks like a sieve for SRE objects.
1486  */
1487 MonoCustomAttrInfo*
1488 mono_reflection_get_custom_attrs_info (MonoObject *obj)
1489 {
1490         MonoError error;
1491         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
1492         mono_error_assert_ok (&error);
1493         return result;
1494 }
1495
1496 /**
1497  * mono_reflection_get_custom_attrs_info_checked:
1498  * @obj: a reflection object handle
1499  * @error: set on error
1500  *
1501  * Return the custom attribute info for attributes defined for the
1502  * reflection handle @obj. The objects.
1503  *
1504  * On failure returns NULL and sets @error.
1505  *
1506  * FIXME this function leaks like a sieve for SRE objects.
1507  */
1508 MonoCustomAttrInfo*
1509 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
1510 {
1511         MonoClass *klass;
1512         MonoCustomAttrInfo *cinfo = NULL;
1513         
1514         mono_error_init (error);
1515
1516         klass = obj->vtable->klass;
1517         if (klass == mono_defaults.runtimetype_class) {
1518                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
1519                 return_val_if_nok (error, NULL);
1520                 klass = mono_class_from_mono_type (type);
1521                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
1522                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
1523                 return_val_if_nok (error, NULL);
1524         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
1525                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
1526                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
1527                 return_val_if_nok (error, NULL);
1528         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
1529                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
1530                 cinfo = mono_custom_attrs_from_module (module->image, error);
1531                 return_val_if_nok (error, NULL);
1532         } else if (strcmp ("MonoProperty", klass->name) == 0) {
1533                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
1534                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
1535                 return_val_if_nok (error, NULL);
1536         } else if (strcmp ("MonoEvent", klass->name) == 0) {
1537                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
1538                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
1539                 return_val_if_nok (error, NULL);
1540         } else if (strcmp ("MonoField", klass->name) == 0) {
1541                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
1542                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
1543                 return_val_if_nok (error, NULL);
1544         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
1545                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
1546                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
1547                 return_val_if_nok (error, NULL);
1548         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
1549                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
1550                 MonoClass *member_class = mono_object_class (param->MemberImpl);
1551                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
1552                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
1553                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
1554                         return_val_if_nok (error, NULL);
1555                 } else if (mono_is_sr_mono_property (member_class)) {
1556                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
1557                         MonoMethod *method;
1558                         if (!(method = prop->property->get))
1559                                 method = prop->property->set;
1560                         g_assert (method);
1561
1562                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
1563                         return_val_if_nok (error, NULL);
1564                 } 
1565 #ifndef DISABLE_REFLECTION_EMIT
1566                 else if (mono_is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
1567                         // FIXME: Is this still needed ?
1568                         g_assert_not_reached ();
1569                 } else if (mono_is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
1570                         // FIXME: Is this still needed ?
1571                         g_assert_not_reached ();
1572                 } 
1573 #endif
1574                 else {
1575                         char *type_name = mono_type_get_full_name (member_class);
1576                         mono_error_set_not_supported (error,
1577                                                       "Custom attributes on a ParamInfo with member %s are not supported",
1578                                                       type_name);
1579                         g_free (type_name);
1580                         return NULL;
1581                 }
1582         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
1583                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
1584                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
1585         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
1586                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
1587                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
1588         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
1589                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
1590                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
1591         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
1592                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
1593                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
1594         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
1595                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
1596                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
1597         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
1598                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
1599                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
1600         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
1601                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
1602                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
1603                 return_val_if_nok (error, NULL);
1604         } else { /* handle other types here... */
1605                 g_error ("get custom attrs not yet supported for %s", klass->name);
1606         }
1607
1608         return cinfo;
1609 }
1610
1611 /*
1612  * mono_reflection_get_custom_attrs_by_type:
1613  * @obj: a reflection object handle
1614  *
1615  * Return an array with all the custom attributes defined of the
1616  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
1617  * of that type are returned. The objects are fully build. Return NULL if a loading error
1618  * occurs.
1619  */
1620 MonoArray*
1621 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
1622 {
1623         MonoArray *result;
1624         MonoCustomAttrInfo *cinfo;
1625
1626         mono_error_init (error);
1627
1628         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1629         return_val_if_nok (error, NULL);
1630         if (cinfo) {
1631                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
1632                 if (!cinfo->cached)
1633                         mono_custom_attrs_free (cinfo);
1634                 if (!result)
1635                         return NULL;
1636         } else {
1637                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
1638         }
1639
1640         return result;
1641 }
1642
1643 /*
1644  * mono_reflection_get_custom_attrs:
1645  * @obj: a reflection object handle
1646  *
1647  * Return an array with all the custom attributes defined of the
1648  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
1649  * occurs.
1650  */
1651 MonoArray*
1652 mono_reflection_get_custom_attrs (MonoObject *obj)
1653 {
1654         MonoError error;
1655
1656         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
1657 }
1658
1659 /*
1660  * mono_reflection_get_custom_attrs_data:
1661  * @obj: a reflection obj handle
1662  *
1663  * Returns an array of System.Reflection.CustomAttributeData,
1664  * which include information about attributes reflected on
1665  * types loaded using the Reflection Only methods
1666  */
1667 MonoArray*
1668 mono_reflection_get_custom_attrs_data (MonoObject *obj)
1669 {
1670         MonoError error;
1671         MonoArray* result;
1672         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
1673         mono_error_cleanup (&error);
1674         return result;
1675 }
1676
1677 /*
1678  * mono_reflection_get_custom_attrs_data_checked:
1679  * @obj: a reflection obj handle
1680  * @error: set on error
1681  *
1682  * Returns an array of System.Reflection.CustomAttributeData,
1683  * which include information about attributes reflected on
1684  * types loaded using the Reflection Only methods
1685  */
1686 MonoArray*
1687 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
1688 {
1689         MonoArray *result;
1690         MonoCustomAttrInfo *cinfo;
1691
1692         mono_error_init (error);
1693
1694         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
1695         return_val_if_nok (error, NULL);
1696         if (cinfo) {
1697                 result = mono_custom_attrs_data_construct (cinfo, error);
1698                 if (!cinfo->cached)
1699                         mono_custom_attrs_free (cinfo);
1700                 return_val_if_nok (error, NULL);
1701         } else 
1702                 result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
1703
1704         return result;
1705 }