Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / custom-attrs.c
index 864b846303935d16e0f081507b3ab58052e564ec..a7954f721e44d8100a0fbfc3517615dac8a4dd64 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * custom-attrs.c: Custom attributes.
+/**
+ * \file
+ * Custom attributes.
  * 
  * Author:
  *   Paolo Molaro (lupus@ximian.com)
@@ -42,6 +43,15 @@ static gboolean type_is_reference (MonoType *type);
 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, "System.Reflection", "CustomAttributeTypedArgument");
 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, "System.Reflection", "CustomAttributeNamedArgument");
 
+static MonoCustomAttrInfo*
+mono_custom_attrs_from_builders_handle (MonoImage *alloc_img, MonoImage *image, MonoArrayHandle cattrs);
+
+static gboolean
+bcheck_blob (const char *ptr, int bump, const char *endp, MonoError *error);
+
+static gboolean
+decode_blob_value_checked (const char *ptr, const char *endp, guint32 *size_out, const char **retp, MonoError *error);
+
 /*
  * LOCKING: Acquires the loader lock. 
  */
@@ -181,14 +191,18 @@ cattr_type_from_name (char *n, MonoImage *image, gboolean is_enum, MonoError *er
 }
 
 static MonoClass*
-load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
+load_cattr_enum_type (MonoImage *image, const char *p, const char *boundp, const char **end, MonoError *error)
 {
        char *n;
        MonoType *t;
-       int slen = mono_metadata_decode_value (p, &p);
+       guint32 slen;
+       error_init (error);
 
-       mono_error_init (error);
+       if (!decode_blob_value_checked (p, boundp, &slen, &p, error))
+               return NULL;
 
+       if (boundp && slen > 0 && !bcheck_blob (p, slen - 1, boundp, error))
+               return NULL;
        n = (char *)g_memdup (p, slen + 1);
        n [slen] = 0;
        t = cattr_type_from_name (n, image, TRUE, error);
@@ -200,12 +214,14 @@ load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoErr
 }
 
 static void*
-load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
+load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char *boundp, const char **end, MonoError *error)
 {
-       int slen, type = t->type;
+       int type = t->type;
+       guint32 slen;
        MonoClass *tklass = t->data.klass;
 
-       mono_error_init (error);
+       g_assert (boundp);
+       error_init (error);
 
 handle_enum:
        switch (type) {
@@ -213,6 +229,8 @@ handle_enum:
        case MONO_TYPE_I1:
        case MONO_TYPE_BOOLEAN: {
                MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
+               if (!bcheck_blob (p, 0, boundp, error))
+                       return NULL;
                *bval = *p;
                *end = p + 1;
                return bval;
@@ -221,6 +239,8 @@ handle_enum:
        case MONO_TYPE_U2:
        case MONO_TYPE_I2: {
                guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
+               if (!bcheck_blob (p, 1, boundp, error))
+                       return NULL;
                *val = read16 (p);
                *end = p + 2;
                return val;
@@ -233,6 +253,8 @@ handle_enum:
        case MONO_TYPE_U4:
        case MONO_TYPE_I4: {
                guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
+               if (!bcheck_blob (p, 3, boundp, error))
+                       return NULL;
                *val = read32 (p);
                *end = p + 4;
                return val;
@@ -244,12 +266,16 @@ handle_enum:
        case MONO_TYPE_U8:
        case MONO_TYPE_I8: {
                guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
+               if (!bcheck_blob (p, 7, boundp, error))
+                       return NULL;
                *val = read64 (p);
                *end = p + 8;
                return val;
        }
        case MONO_TYPE_R8: {
                double *val = (double *)g_malloc (sizeof (double));
+               if (!bcheck_blob (p, 7, boundp, error))
+                       return NULL;
                readr8 (p, val);
                *end = p + 8;
                return val;
@@ -263,6 +289,8 @@ handle_enum:
                        
                        if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
                                guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
+                               if (!bcheck_blob (p, 7, boundp, error))
+                                       return NULL;
                                *val = read64 (p);
                                *end = p + 8;
                                return val;
@@ -272,23 +300,33 @@ handle_enum:
                break;
                
        case MONO_TYPE_STRING:
+               if (!bcheck_blob (p, 0, boundp, error))
+                       return NULL;
                if (*p == (char)0xFF) {
                        *end = p + 1;
                        return NULL;
                }
-               slen = mono_metadata_decode_value (p, &p);
+               if (!decode_blob_value_checked (p, boundp, &slen, &p, error))
+                       return NULL;
+               if (slen > 0 && !bcheck_blob (p, slen - 1, boundp, error))
+                       return NULL;
                *end = p + slen;
                return mono_string_new_len_checked (mono_domain_get (), p, slen, error);
        case MONO_TYPE_CLASS: {
                MonoReflectionType *rt;
                char *n;
                MonoType *t;
+               if (!bcheck_blob (p, 0, boundp, error))
+                       return NULL;
                if (*p == (char)0xFF) {
                        *end = p + 1;
                        return NULL;
                }
 handle_type:
-               slen = mono_metadata_decode_value (p, &p);
+               if (!decode_blob_value_checked (p, boundp, &slen, &p, error))
+                       return NULL;
+               if (slen > 0 && !bcheck_blob (p, slen - 1, boundp, error))
+                       return NULL;
                n = (char *)g_memdup (p, slen + 1);
                n [slen] = 0;
                t = cattr_type_from_name (n, image, FALSE, error);
@@ -303,6 +341,8 @@ handle_type:
                return rt;
        }
        case MONO_TYPE_OBJECT: {
+               if (!bcheck_blob (p, 0, boundp, error))
+                       return NULL;
                char subt = *p++;
                MonoObject *obj;
                MonoClass *subc = NULL;
@@ -315,6 +355,8 @@ handle_type:
                        goto handle_enum;
                } else if (subt == 0x1D) {
                        MonoType simple_type = {{0}};
+                       if (!bcheck_blob (p, 0, boundp, error))
+                               return NULL;
                        int etype = *p;
                        p ++;
 
@@ -322,8 +364,8 @@ handle_type:
                        if (etype == 0x50) {
                                tklass = mono_defaults.systemtype_class;
                        } else if (etype == 0x55) {
-                               tklass = load_cattr_enum_type (image, p, &p, error);
-                               if (!mono_error_ok (error))
+                               tklass = load_cattr_enum_type (image, p, boundp, &p, error);
+                               if (!is_ok (error))
                                        return NULL;
                        } else {
                                if (etype == 0x51)
@@ -336,7 +378,10 @@ handle_type:
                } else if (subt == 0x55) {
                        char *n;
                        MonoType *t;
-                       slen = mono_metadata_decode_value (p, &p);
+                       if (!decode_blob_value_checked (p, boundp, &slen, &p, error))
+                               return NULL;
+                       if (slen > 0 && !bcheck_blob (p, slen - 1, boundp, error))
+                               return NULL;
                        n = (char *)g_memdup (p, slen + 1);
                        n [slen] = 0;
                        t = cattr_type_from_name (n, image, FALSE, error);
@@ -351,12 +396,12 @@ handle_type:
                } else {
                        g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
                }
-               val = load_cattr_value (image, &subc->byval_arg, p, end, error);
+               val = load_cattr_value (image, &subc->byval_arg, p, boundp, end, error);
                obj = NULL;
-               if (mono_error_ok (error)) {
+               if (is_ok (error)) {
                        obj = mono_object_new_checked (mono_domain_get (), subc, error);
                        g_assert (!subc->has_references);
-                       if (mono_error_ok (error))
+                       if (is_ok (error))
                                mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
                }
 
@@ -366,6 +411,8 @@ handle_type:
        case MONO_TYPE_SZARRAY: {
                MonoArray *arr;
                guint32 i, alen, basetype;
+               if (!bcheck_blob (p, 3, boundp, error))
+                       return NULL;
                alen = read32 (p);
                p += 4;
                if (alen == 0xffffffff) {
@@ -383,6 +430,8 @@ handle_type:
                        case MONO_TYPE_I1:
                        case MONO_TYPE_BOOLEAN:
                                for (i = 0; i < alen; i++) {
+                                       if (!bcheck_blob (p, 0, boundp, error))
+                                               return NULL;
                                        MonoBoolean val = *p++;
                                        mono_array_set (arr, MonoBoolean, i, val);
                                }
@@ -391,6 +440,8 @@ handle_type:
                        case MONO_TYPE_U2:
                        case MONO_TYPE_I2:
                                for (i = 0; i < alen; i++) {
+                                       if (!bcheck_blob (p, 1, boundp, error))
+                                               return NULL;
                                        guint16 val = read16 (p);
                                        mono_array_set (arr, guint16, i, val);
                                        p += 2;
@@ -400,6 +451,8 @@ handle_type:
                        case MONO_TYPE_U4:
                        case MONO_TYPE_I4:
                                for (i = 0; i < alen; i++) {
+                                       if (!bcheck_blob (p, 3, boundp, error))
+                                               return NULL;
                                        guint32 val = read32 (p);
                                        mono_array_set (arr, guint32, i, val);
                                        p += 4;
@@ -407,6 +460,8 @@ handle_type:
                                break;
                        case MONO_TYPE_R8:
                                for (i = 0; i < alen; i++) {
+                                       if (!bcheck_blob (p, 7, boundp, error))
+                                               return NULL;
                                        double val;
                                        readr8 (p, &val);
                                        mono_array_set (arr, double, i, val);
@@ -416,6 +471,8 @@ handle_type:
                        case MONO_TYPE_U8:
                        case MONO_TYPE_I8:
                                for (i = 0; i < alen; i++) {
+                                       if (!bcheck_blob (p, 7, boundp, error))
+                                               return NULL;
                                        guint64 val = read64 (p);
                                        mono_array_set (arr, guint64, i, val);
                                        p += 8;
@@ -426,8 +483,8 @@ handle_type:
                        case MONO_TYPE_STRING:
                        case MONO_TYPE_SZARRAY:
                                for (i = 0; i < alen; i++) {
-                                       MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
-                                       if (!mono_error_ok (error))
+                                       MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, boundp, &p, error);
+                                       if (!is_ok (error))
                                                return NULL;
                                        mono_array_setref (arr, i, item);
                                }
@@ -445,13 +502,13 @@ handle_type:
 }
 
 static MonoObject*
-load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
+load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char *boundp, const char** end, MonoError *error)
 {
-       mono_error_init (error);
+       error_init (error);
 
        gboolean is_ref = type_is_reference (t);
 
-       void *val = load_cattr_value (image, t, p, end, error);
+       void *val = load_cattr_value (image, t, p, boundp, end, error);
        if (!is_ok (error)) {
                if (is_ref)
                        g_free (val);
@@ -473,7 +530,7 @@ create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
        MonoObject *retval;
        void *params [2], *unboxed;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!ctor)
                ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
@@ -499,7 +556,7 @@ create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
        MonoObject *retval;
        void *unboxed, *params [2];
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!ctor)
                ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
@@ -518,6 +575,12 @@ create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
 }
 
 
+static MonoCustomAttrInfo*
+mono_custom_attrs_from_builders_handle (MonoImage *alloc_img, MonoImage *image, MonoArrayHandle cattrs)
+{
+       return mono_custom_attrs_from_builders (alloc_img, image, MONO_HANDLE_RAW (cattrs)); /* FIXME use coop handles for mono_custom_attrs_from_builders */
+}
+
 MonoCustomAttrInfo*
 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
 {
@@ -566,11 +629,100 @@ mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArr
        return ainfo;
 }
 
+static void
+set_custom_attr_fmt_error (MonoError *error)
+{
+       error_init (error);
+       mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
+}
+
+/**
+ * bcheck_blob:
+ * \param ptr a pointer into a blob
+ * \param bump how far we plan on reading past \p ptr.
+ * \param endp upper bound for \p ptr - one past the last valid value for \p ptr.
+ * \param error set on error
+ *
+ * Check that ptr+bump is below endp.  Returns TRUE on success, or FALSE on
+ * failure and sets \p error.
+ */
+static gboolean
+bcheck_blob (const char *ptr, int bump, const char *endp, MonoError *error)
+{
+       error_init (error);
+       if (ADDP_IS_GREATER_OR_OVF (ptr, bump, endp - 1)) {
+               set_custom_attr_fmt_error (error);
+               return FALSE;
+       } else
+               return TRUE;
+}
+
+/**
+ * decode_blob_size_checked:
+ * \param ptr a pointer into a blob
+ * \param endp upper bound for \p ptr - one pas the last valid value for \p ptr
+ * \param size_out on success set to the decoded size
+ * \param retp on success set to the next byte after the encoded size
+ * \param error set on error
+ *
+ * Decode an encoded size value which takes 1, 2, or 4 bytes and set \p
+ * size_out to the decoded size and \p retp to the next byte after the encoded
+ * size.  Returns TRUE on success, or FALASE on failure and sets \p error.
+ */
+static gboolean
+decode_blob_size_checked (const char *ptr, const char *endp, guint32 *size_out, const char **retp, MonoError *error)
+{
+       error_init (error);
+       if (endp && !bcheck_blob (ptr, 0, endp, error))
+               goto leave;
+       if ((*ptr & 0x80) != 0) {
+               if ((*ptr & 0x40) == 0 && !bcheck_blob (ptr, 1, endp, error))
+                       goto leave;
+               else if (!bcheck_blob (ptr, 3, endp, error))
+                       goto leave;
+       }
+       *size_out = mono_metadata_decode_blob_size (ptr, retp);
+leave:
+       return is_ok (error);
+}
+
+/**
+ * decode_blob_value_checked:
+ * \param ptr a pointer into a blob
+ * \param endp upper bound for \p ptr - one pas the last valid value for \p ptr
+ * \param value_out on success set to the decoded value
+ * \param retp on success set to the next byte after the encoded size
+ * \param error set on error
+ *
+ * Decode an encoded uint32 value which takes 1, 2, or 4 bytes and set \p
+ * value_out to the decoded value and \p retp to the next byte after the
+ * encoded value.  Returns TRUE on success, or FALASE on failure and sets \p
+ * error.
+ */
+static gboolean
+decode_blob_value_checked (const char *ptr, const char *endp, guint32 *value_out, const char **retp, MonoError *error)
+{
+       /* This similar to decode_blob_size_checked, above but delegates to
+        * mono_metadata_decode_value which is semantically different. */
+       error_init (error);
+       if (!bcheck_blob (ptr, 0, endp, error))
+               goto leave;
+       if ((*ptr & 0x80) != 0) {
+               if ((*ptr & 0x40) == 0 && !bcheck_blob (ptr, 1, endp, error))
+                       goto leave;
+               else if (!bcheck_blob (ptr, 3, endp, error))
+                       goto leave;
+       }
+       *value_out = mono_metadata_decode_value (ptr, retp);
+leave:
+       return is_ok (error);
+}
 
 static MonoObject*
 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
 {
        const char *p = (const char*)data;
+       const char *data_end = (const char*)data + len;
        const char *named;
        guint32 i, j, num_named;
        MonoObject *attr;
@@ -578,12 +730,12 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
        void **params = NULL;
        MonoMethodSignature *sig;
 
-       mono_error_init (error);
+       error_init (error);
 
        mono_class_init (method->klass);
 
        if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
-               mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
+               set_custom_attr_fmt_error (error);
                return NULL;
        }
 
@@ -615,8 +767,8 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
        /* skip prolog */
        p += 2;
        for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
-               params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
-               if (!mono_error_ok (error))
+               params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, data_end, &p, error);
+               if (!is_ok (error))
                        goto fail;
        }
 
@@ -633,19 +785,37 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
                goto fail;
        }
 
-       num_named = read16 (named);
-       named += 2;
+       if (named + 1 < data_end) {
+               num_named = read16 (named);
+               named += 2;
+       } else {
+               /* CoreCLR allows p == data + len */
+               if (named == data_end)
+                       num_named = 0;
+               else {
+                       set_custom_attr_fmt_error (error);
+                       goto fail;
+               }
+       }
        for (j = 0; j < num_named; j++) {
-               gint name_len;
+               guint32 name_len;
                char *name, named_type, data_type;
+               if (!bcheck_blob (named, 1, data_end, error))
+                       goto fail;
                named_type = *named++;
                data_type = *named++; /* type of data */
-               if (data_type == MONO_TYPE_SZARRAY)
+               if (data_type == MONO_TYPE_SZARRAY) {
+                       if (!bcheck_blob (named, 0, data_end, error))
+                               goto fail;
                        data_type = *named++;
+               }
                if (data_type == MONO_TYPE_ENUM) {
-                       gint type_len;
+                       guint32 type_len;
                        char *type_name;
-                       type_len = mono_metadata_decode_blob_size (named, &named);
+                       if (!decode_blob_size_checked (named, data_end, &type_len, &named, error))
+                               goto fail;
+                       if (type_len > 0 && !bcheck_blob (named, type_len - 1, data_end, error))
+                               goto fail;
                        type_name = (char *)g_malloc (type_len + 1);
                        memcpy (type_name, named, type_len);
                        type_name [type_len] = 0;
@@ -653,7 +823,10 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
                        /* FIXME: lookup the type and check type consistency */
                        g_free (type_name);
                }
-               name_len = mono_metadata_decode_blob_size (named, &named);
+               if (!decode_blob_size_checked (named, data_end, &name_len, &named, error))
+                       goto fail;
+               if (name_len > 0 && !bcheck_blob (named, name_len - 1, data_end, error))
+                       goto fail;
                name = (char *)g_malloc (name_len + 1);
                memcpy (name, named, name_len);
                name [name_len] = 0;
@@ -670,8 +843,8 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
                                goto fail;
                        }
 
-                       val = load_cattr_value (image, field->type, named, &named, error);
-                       if (!mono_error_ok (error)) {
+                       val = load_cattr_value (image, field->type, named, data_end, &named, error);
+                       if (!is_ok (error)) {
                                g_free (name);
                                if (!type_is_reference (field->type))
                                        g_free (val);
@@ -704,8 +877,8 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
                        prop_type = prop->get? mono_method_signature (prop->get)->ret :
                             mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
 
-                       pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
-                       if (!mono_error_ok (error)) {
+                       pparams [0] = load_cattr_value (image, prop_type, named, data_end, &named, error);
+                       if (!is_ok (error)) {
                                g_free (name);
                                if (!type_is_reference (prop_type))
                                        g_free (pparams [0]);
@@ -751,6 +924,7 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
        MonoClass *attrklass;
        MonoDomain *domain;
        const char *p = (const char*)data;
+       const char *data_end = p + len;
        const char *named;
        guint32 i, j, num_named;
        CattrNamedArg *arginfo = NULL;
@@ -759,7 +933,7 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
        *named_args = NULL;
        *named_arg_info = NULL;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
                mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
@@ -772,21 +946,28 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
 
        if (len < 2 || read16 (p) != 0x0001) /* Prolog */
                return;
+       /* skip prolog */
+       p += 2;
 
+       /* Parse each argument corresponding to the signature's parameters from
+        * the blob and store in typedargs.
+        */
        typedargs = mono_array_new_checked (domain, mono_get_object_class (), mono_method_signature (method)->param_count, error);
        return_if_nok (error);
 
-       /* skip prolog */
-       p += 2;
        for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
                MonoObject *obj;
 
-               obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
+               obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, data_end, &p, error);
                return_if_nok (error);
                mono_array_setref (typedargs, i, obj);
        }
 
        named = p;
+
+       /* Parse mandatory count of named arguments (could be zero) */
+       if (!bcheck_blob (named, 1, data_end, error))
+               return;
        num_named = read16 (named);
        namedargs = mono_array_new_checked (domain, mono_get_object_class (), num_named, error);
        return_if_nok (error);
@@ -796,17 +977,25 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
        arginfo = g_new0 (CattrNamedArg, num_named);
        *named_arg_info = arginfo;
 
+       /* Parse each named arg, and add to arginfo.  Each named argument could
+        * be a field name or a property name followed by a value. */
        for (j = 0; j < num_named; j++) {
-               gint name_len;
+               guint32 name_len;
                char *name, named_type, data_type;
-               named_type = *named++;
+               if (!bcheck_blob (named, 1, data_end, error))
+                       return;
+               named_type = *named++; /* field or property? */
                data_type = *named++; /* type of data */
-               if (data_type == MONO_TYPE_SZARRAY)
+               if (data_type == MONO_TYPE_SZARRAY) {
+                       if (!bcheck_blob (named, 0, data_end, error))
+                               return;
                        data_type = *named++;
+               }
                if (data_type == MONO_TYPE_ENUM) {
-                       gint type_len;
+                       guint32 type_len;
                        char *type_name;
-                       type_len = mono_metadata_decode_blob_size (named, &named);
+                       if (!decode_blob_size_checked (named, data_end, &type_len, &named, error))
+                               return;
                        if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
                                goto fail;
 
@@ -817,7 +1006,9 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                        /* FIXME: lookup the type and check type consistency */
                        g_free (type_name);
                }
-               name_len = mono_metadata_decode_blob_size (named, &named);
+               /* named argument name: length, then name */
+               if (!decode_blob_size_checked(named, data_end, &name_len, &named, error))
+                       return;
                if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
                        goto fail;
                name = (char *)g_malloc (name_len + 1);
@@ -825,6 +1016,7 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                name [name_len] = 0;
                named += name_len;
                if (named_type == 0x53) {
+                       /* Named arg is a field. */
                        MonoObject *obj;
                        MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
 
@@ -836,7 +1028,7 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                        arginfo [j].type = field->type;
                        arginfo [j].field = field;
 
-                       obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
+                       obj = load_cattr_value_boxed (domain, image, field->type, named, data_end, &named, error);
                        if (!is_ok (error)) {
                                g_free (name);
                                return;
@@ -844,6 +1036,7 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                        mono_array_setref (namedargs, j, obj);
 
                } else if (named_type == 0x54) {
+                       /* Named arg is a property */
                        MonoObject *obj;
                        MonoType *prop_type;
                        MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
@@ -859,7 +1052,7 @@ mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *meth
                        arginfo [j].type = prop_type;
                        arginfo [j].prop = prop;
 
-                       obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
+                       obj = load_cattr_value_boxed (domain, image, prop_type, named, data_end, &named, error);
                        if (!is_ok (error)) {
                                g_free (name);
                                return;
@@ -888,7 +1081,7 @@ reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, Mono
        CattrNamedArg *arginfo = NULL;
        int i;
 
-       mono_error_init (error);
+       error_init (error);
 
        *ctor_args = NULL;
        *named_args = NULL;
@@ -970,7 +1163,7 @@ create_custom_attr_data_handle (MonoImage *image, MonoCustomAttrEntry *cattr, Mo
        MonoDomain *domain;
        void *params [4];
 
-       mono_error_init (error);
+       error_init (error);
 
        g_assert (image->assembly);
 
@@ -1015,7 +1208,7 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_
        MonoObject *attr;
        int i, n;
 
-       mono_error_init (error);
+       error_init (error);
 
        for (i = 0; i < cinfo->num_attrs; ++i) {
                MonoCustomAttrEntry *centry = &cinfo->attrs[i];
@@ -1055,6 +1248,9 @@ mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_
        return result;
 }
 
+/**
+ * mono_custom_attrs_construct:
+ */
 MonoArray*
 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
 {
@@ -1072,7 +1268,7 @@ mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
        MonoObject *attr;
        int i;
        
-       mono_error_init (error);
+       error_init (error);
        result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs, error);
        return_val_if_nok (error, NULL);
        for (i = 0; i < cinfo->num_attrs; ++i) {
@@ -1098,8 +1294,7 @@ mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
 }
 /**
  * mono_custom_attrs_from_index_checked:
- *
- * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
+ * \returns NULL if no attributes are found.  On error returns NULL and sets \p error.
  */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ignore_missing, MonoError *error)
@@ -1112,7 +1307,7 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig
        const char *data;
        MonoCustomAttrEntry* attr;
 
-       mono_error_init (error);
+       error_init (error);
 
        ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
 
@@ -1152,7 +1347,7 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig
                        g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image->name, mtoken, mono_error_get_message (error));
                        if (ignore_missing) {
                                mono_error_cleanup (error);
-                               mono_error_init (error);
+                               error_init (error);
                        } else {
                                g_list_free (list);
                                g_free (ainfo);
@@ -1176,6 +1371,9 @@ mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, gboolean ig
        return ainfo;
 }
 
+/**
+ * mono_custom_attrs_from_method:
+ */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_method (MonoMethod *method)
 {
@@ -1190,7 +1388,7 @@ mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
 {
        guint32 idx;
 
-       mono_error_init (error);
+       error_init (error);
 
        /*
         * An instantiated method has the same cattrs as the generic method definition.
@@ -1214,6 +1412,9 @@ mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
        return mono_custom_attrs_from_index_checked (method->klass->image, idx, FALSE, error);
 }
 
+/**
+ * mono_custom_attrs_from_class:
+ */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_class (MonoClass *klass)
 {
@@ -1228,7 +1429,7 @@ mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
 {
        guint32 idx;
 
-       mono_error_init (error);
+       error_init (error);
 
        if (mono_class_is_ginst (klass))
                klass = mono_class_get_generic_class (klass)->container_class;
@@ -1248,6 +1449,9 @@ mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
        return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
 }
 
+/**
+ * mono_custom_attrs_from_assembly:
+ */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
 {
@@ -1262,7 +1466,7 @@ mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, gboolean ignore
 {
        guint32 idx;
        
-       mono_error_init (error);
+       error_init (error);
 
        if (image_is_dynamic (assembly->image))
                return lookup_custom_attr (assembly->image, assembly);
@@ -1276,6 +1480,8 @@ static MonoCustomAttrInfo*
 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
 {
        guint32 idx;
+
+       error_init (error);
        
        if (image_is_dynamic (image))
                return lookup_custom_attr (image, image);
@@ -1285,6 +1491,9 @@ mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
        return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
 }
 
+/**
+ * mono_custom_attrs_from_property:
+ */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
 {
@@ -1298,6 +1507,8 @@ MonoCustomAttrInfo*
 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
 {
        guint32 idx;
+
+       error_init (error);
        
        if (image_is_dynamic (klass->image)) {
                property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
@@ -1309,6 +1520,9 @@ mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *propert
        return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
 }
 
+/**
+ * mono_custom_attrs_from_event:
+ */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
 {
@@ -1322,6 +1536,8 @@ MonoCustomAttrInfo*
 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
 {
        guint32 idx;
+
+       error_init (error);
        
        if (image_is_dynamic (klass->image)) {
                event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
@@ -1333,6 +1549,9 @@ mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoEr
        return mono_custom_attrs_from_index_checked (klass->image, idx, FALSE, error);
 }
 
+/**
+ * mono_custom_attrs_from_field:
+ */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
 {
@@ -1346,7 +1565,7 @@ MonoCustomAttrInfo*
 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
 {
        guint32 idx;
-       mono_error_init (error);
+       error_init (error);
 
        if (image_is_dynamic (klass->image)) {
                field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
@@ -1360,12 +1579,12 @@ mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, M
 
 /**
  * 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
+ * \param method handle to the method that we want to retrieve custom parameter information from
+ * \param 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.
+ * \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)
@@ -1378,13 +1597,13 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
 
 /**
  * mono_custom_attrs_from_param_checked:
- * @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
- * @error: set on error
+ * \param method handle to the method that we want to retrieve custom parameter information from
+ * \param param parameter number, where zero represent the return value, and one is the first parameter in the method
+ * \param error set on error
  *
  * 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.  On failure returns NULL and sets @error.
+ * \returns the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets \p error.
  */
 MonoCustomAttrInfo*
 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
@@ -1395,7 +1614,7 @@ mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoErr
        MonoImage *image;
        MonoReflectionMethodAux *aux;
 
-       mono_error_init (error);
+       error_init (error);
 
        /*
         * An instantiated method has the same cattrs as the generic method definition.
@@ -1454,6 +1673,9 @@ mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoErr
        return mono_custom_attrs_from_index_checked (image, idx, FALSE, error);
 }
 
+/**
+ * mono_custom_attrs_has_attr:
+ */
 gboolean
 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
 {
@@ -1469,6 +1691,9 @@ mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
        return FALSE;
 }
 
+/**
+ * mono_custom_attrs_get_attr:
+ */
 MonoObject*
 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
 {
@@ -1486,7 +1711,7 @@ mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_k
 
        g_assert (attr_klass != NULL);
 
-       mono_error_init (error);
+       error_init (error);
 
        for (i = 0; i < ainfo->num_attrs; ++i) {
                centry = &ainfo->attrs[i];
@@ -1502,92 +1727,108 @@ mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_k
        return create_custom_attr (ainfo->image, centry->ctor, centry->data, centry->data_size, error);
 }
 
-/*
+/**
  * mono_reflection_get_custom_attrs_info:
- * @obj: a reflection object handle
+ * \param obj a reflection object handle
  *
- * Return the custom attribute info for attributes defined for the
- * reflection handle @obj. The objects.
+ * \returns the custom attribute info for attributes defined for the
+ * reflection handle \p obj. The objects.
  *
  * FIXME this function leaks like a sieve for SRE objects.
  */
 MonoCustomAttrInfo*
-mono_reflection_get_custom_attrs_info (MonoObject *obj)
+mono_reflection_get_custom_attrs_info (MonoObject *obj_raw)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
+       MONO_HANDLE_DCL (MonoObject, obj);
        MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
        mono_error_assert_ok (&error);
-       return result;
+       HANDLE_FUNCTION_RETURN_VAL (result);
 }
 
 /**
  * mono_reflection_get_custom_attrs_info_checked:
- * @obj: a reflection object handle
- * @error: set on error
- *
- * Return the custom attribute info for attributes defined for the
- * reflection handle @obj. The objects.
+ * \param obj a reflection object handle
+ * \param error set on error
  *
- * On failure returns NULL and sets @error.
+ * \returns the custom attribute info for attributes defined for the
+ * reflection handle \p obj. The objects. On failure returns NULL and sets \p error.
  *
  * FIXME this function leaks like a sieve for SRE objects.
  */
 MonoCustomAttrInfo*
-mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
+mono_reflection_get_custom_attrs_info_checked (MonoObjectHandle obj, MonoError *error)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoClass *klass;
        MonoCustomAttrInfo *cinfo = NULL;
        
-       mono_error_init (error);
+       error_init (error);
 
-       klass = obj->vtable->klass;
+       klass = mono_handle_class (obj);
        if (klass == mono_defaults.runtimetype_class) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
-               return_val_if_nok (error, NULL);
+               MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST(MonoReflectionType, obj), error);
+               if (!is_ok (error))
+                       goto leave;
                klass = mono_class_from_mono_type (type);
                /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
                cinfo = mono_custom_attrs_from_class_checked (klass, error);
-               return_val_if_nok (error, NULL);
+               if (!is_ok (error))
+                       goto leave;
        } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
-               MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
-               cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, FALSE, error);
-               return_val_if_nok (error, NULL);
+               MonoReflectionAssemblyHandle rassembly = MONO_HANDLE_CAST (MonoReflectionAssembly, obj);
+               cinfo = mono_custom_attrs_from_assembly_checked (MONO_HANDLE_GETVAL (rassembly, assembly), FALSE, error);
+               if (!is_ok (error))
+                       goto leave;
        } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
-               MonoReflectionModule *module = (MonoReflectionModule*)obj;
-               cinfo = mono_custom_attrs_from_module (module->image, error);
-               return_val_if_nok (error, NULL);
+               MonoReflectionModuleHandle module = MONO_HANDLE_CAST (MonoReflectionModule, obj);
+               cinfo = mono_custom_attrs_from_module (MONO_HANDLE_GETVAL (module, image), error);
+               if (!is_ok (error))
+                       goto leave;
        } else if (strcmp ("MonoProperty", klass->name) == 0) {
-               MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
-               cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
-               return_val_if_nok (error, NULL);
+               MonoReflectionPropertyHandle rprop = MONO_HANDLE_CAST (MonoReflectionProperty, obj);
+               MonoProperty *property = MONO_HANDLE_GETVAL (rprop, property);
+               cinfo = mono_custom_attrs_from_property_checked (property->parent, property, error);
+               if (!is_ok (error))
+                       goto leave;
        } else if (strcmp ("MonoEvent", klass->name) == 0) {
-               MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
-               cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
-               return_val_if_nok (error, NULL);
+               MonoReflectionMonoEventHandle revent = MONO_HANDLE_CAST (MonoReflectionMonoEvent, obj);
+               MonoEvent *event = MONO_HANDLE_GETVAL (revent, event);
+               cinfo = mono_custom_attrs_from_event_checked (event->parent, event, error);
+               if (!is_ok (error))
+                       goto leave;
        } else if (strcmp ("MonoField", klass->name) == 0) {
-               MonoReflectionField *rfield = (MonoReflectionField*)obj;
-               cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
-               return_val_if_nok (error, NULL);
+               MonoReflectionFieldHandle rfield = MONO_HANDLE_CAST (MonoReflectionField, obj);
+               MonoClassField *field = MONO_HANDLE_GETVAL (rfield, field);
+               cinfo = mono_custom_attrs_from_field_checked (field->parent, field, error);
+               if (!is_ok (error))
+                       goto leave;
        } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
-               MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
-               cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
-               return_val_if_nok (error, NULL);
+               MonoReflectionMethodHandle rmethod = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
+               cinfo = mono_custom_attrs_from_method_checked (MONO_HANDLE_GETVAL (rmethod, method), error);
+               if (!is_ok (error))
+                       goto leave;
        } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
-               MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
-               MonoClass *member_class = mono_object_class (param->MemberImpl);
+               MonoReflectionParameterHandle param = MONO_HANDLE_CAST (MonoReflectionParameter, obj);
+               MonoObjectHandle member_impl = MONO_HANDLE_NEW_GET (MonoObject, param, MemberImpl);
+               MonoClass *member_class = mono_handle_class (member_impl);
                if (mono_class_is_reflection_method_or_constructor (member_class)) {
-                       MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
-                       cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
-                       return_val_if_nok (error, NULL);
+                       MonoReflectionMethodHandle rmethod = MONO_HANDLE_CAST (MonoReflectionMethod, member_impl);
+                       cinfo = mono_custom_attrs_from_param_checked (MONO_HANDLE_GETVAL (rmethod, method), MONO_HANDLE_GETVAL (param, PositionImpl) + 1, error);
+                       if (!is_ok (error))
+                               goto leave;
                } else if (mono_is_sr_mono_property (member_class)) {
-                       MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
+                       MonoReflectionPropertyHandle prop = MONO_HANDLE_CAST (MonoReflectionProperty, member_impl);
+                       MonoProperty *property = MONO_HANDLE_GETVAL (prop, property);
                        MonoMethod *method;
-                       if (!(method = prop->property->get))
-                               method = prop->property->set;
+                       if (!(method = property->get))
+                               method = property->set;
                        g_assert (method);
 
-                       cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
-                       return_val_if_nok (error, NULL);
+                       cinfo = mono_custom_attrs_from_param_checked (method, MONO_HANDLE_GETVAL (param, PositionImpl) + 1, error);
+                       if (!is_ok (error))
+                               goto leave;
                } 
 #ifndef DISABLE_REFLECTION_EMIT
                else if (mono_is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
@@ -1604,101 +1845,133 @@ mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error
                                                      "Custom attributes on a ParamInfo with member %s are not supported",
                                                      type_name);
                        g_free (type_name);
-                       return NULL;
+                       goto leave;
                }
        } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
-               MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
-               cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
+               MonoReflectionAssemblyBuilderHandle assemblyb = MONO_HANDLE_CAST (MonoReflectionAssemblyBuilder, obj);
+               MonoReflectionAssemblyHandle assembly = MONO_HANDLE_CAST (MonoReflectionAssembly, assemblyb);
+               MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, assemblyb, cattrs);
+               MonoImage * image = MONO_HANDLE_GETVAL (assembly, assembly)->image;
+               g_assert (image);
+               cinfo = mono_custom_attrs_from_builders_handle (NULL, image, cattrs);
        } else if (strcmp ("TypeBuilder", klass->name) == 0) {
-               MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
-               cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
+               MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, obj);
+               MonoReflectionModuleBuilderHandle module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, tb, module);
+               MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (module, dynamic_image);
+               MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, tb, cattrs);
+               cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs);
        } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
-               MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
-               cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
+               MonoReflectionModuleBuilderHandle mb = MONO_HANDLE_CAST (MonoReflectionModuleBuilder, obj);
+               MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
+               MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, mb, cattrs);
+               cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs);
        } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
-               MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
-               cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
+               MonoReflectionCtorBuilderHandle cb = MONO_HANDLE_CAST (MonoReflectionCtorBuilder, obj);
+               MonoMethod *mhandle = MONO_HANDLE_GETVAL (cb, mhandle);
+               MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, cb, cattrs);
+               cinfo = mono_custom_attrs_from_builders_handle (NULL, mhandle->klass->image, cattrs);
        } else if (strcmp ("MethodBuilder", klass->name) == 0) {
-               MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
-               cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
+               MonoReflectionMethodBuilderHandle mb = MONO_HANDLE_CAST (MonoReflectionMethodBuilder, obj);
+               MonoMethod *mhandle = MONO_HANDLE_GETVAL (mb, mhandle);
+               MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, mb, cattrs);
+               cinfo = mono_custom_attrs_from_builders_handle (NULL, mhandle->klass->image, cattrs);
        } else if (strcmp ("FieldBuilder", klass->name) == 0) {
-               MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
-               cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
+               MonoReflectionFieldBuilderHandle fb = MONO_HANDLE_CAST (MonoReflectionFieldBuilder, obj);
+               MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_NEW_GET (MonoReflectionTypeBuilder, fb, typeb);
+               MonoReflectionModuleBuilderHandle mb = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, tb, module);
+               MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
+               MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, fb, cattrs);
+               cinfo = mono_custom_attrs_from_builders_handle (NULL, &dynamic_image->image, cattrs);
        } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
-               MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
-               cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
-               return_val_if_nok (error, NULL);
+               MonoReflectionGenericClassHandle gclass = MONO_HANDLE_CAST (MonoReflectionGenericClass, obj);
+               MonoReflectionTypeHandle generic_type = MONO_HANDLE_NEW_GET (MonoReflectionType, gclass, generic_type);
+               cinfo = mono_reflection_get_custom_attrs_info_checked (MONO_HANDLE_CAST (MonoObject, generic_type), error);
+               if (!is_ok (error))
+                       goto leave;
        } else { /* handle other types here... */
                g_error ("get custom attrs not yet supported for %s", klass->name);
        }
 
-       return cinfo;
+leave:
+       HANDLE_FUNCTION_RETURN_VAL (cinfo);
 }
 
-/*
+/**
  * mono_reflection_get_custom_attrs_by_type:
- * @obj: a reflection object handle
- *
- * Return an array with all the custom attributes defined of the
- * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
+ * \param obj a reflection object handle
+ * \returns an array with all the custom attributes defined of the
+ * reflection handle \p obj. If \p attr_klass is non-NULL, only custom attributes 
  * of that type are returned. The objects are fully build. Return NULL if a loading error
  * occurs.
  */
 MonoArray*
-mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
+mono_reflection_get_custom_attrs_by_type (MonoObject *obj_raw, MonoClass *attr_klass, MonoError *error)
 {
-       MonoArray *result;
+       HANDLE_FUNCTION_ENTER ();
+       MONO_HANDLE_DCL (MonoObject, obj);
+       MonoArrayHandle result = mono_reflection_get_custom_attrs_by_type_handle (obj, attr_klass, error);
+       HANDLE_FUNCTION_RETURN_OBJ (result);
+}
+
+MonoArrayHandle
+mono_reflection_get_custom_attrs_by_type_handle (MonoObjectHandle obj, MonoClass *attr_klass, MonoError *error)
+{
+       MonoArrayHandle result = MONO_HANDLE_NEW (MonoArray, NULL);
        MonoCustomAttrInfo *cinfo;
 
-       mono_error_init (error);
+       error_init (error);
 
        cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
-       return_val_if_nok (error, NULL);
+       if (!is_ok (error))
+               goto leave;
        if (cinfo) {
-               result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
+               MONO_HANDLE_ASSIGN (result, MONO_HANDLE_NEW (MonoArray, mono_custom_attrs_construct_by_type (cinfo, attr_klass, error))); /* FIXME use coop handles for mono_custom_attrs_construct_by_type */
                if (!cinfo->cached)
                        mono_custom_attrs_free (cinfo);
                if (!result)
-                       return NULL;
+                       goto leave;
        } else {
-               result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0, error);
+               MONO_HANDLE_ASSIGN (result, mono_array_new_handle (mono_domain_get (), mono_defaults.attribute_class, 0, error));
        }
 
+leave:
        return result;
 }
 
-/*
+/**
  * mono_reflection_get_custom_attrs:
- * @obj: a reflection object handle
- *
- * Return an array with all the custom attributes defined of the
- * reflection handle @obj. The objects are fully build. Return NULL if a loading error
+ * \param obj a reflection object handle
+ * \return an array with all the custom attributes defined of the
+ * reflection handle \p obj. The objects are fully build. Return NULL if a loading error
  * occurs.
  */
 MonoArray*
-mono_reflection_get_custom_attrs (MonoObject *obj)
+mono_reflection_get_custom_attrs (MonoObject *obj_raw)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
-
-       return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
+       MONO_HANDLE_DCL (MonoObject, obj);
+       MonoArrayHandle result = mono_reflection_get_custom_attrs_by_type_handle (obj, NULL, &error);
+       mono_error_cleanup (&error);
+       HANDLE_FUNCTION_RETURN_OBJ (result);
 }
 
-/*
+/**
  * mono_reflection_get_custom_attrs_data:
- * @obj: a reflection obj handle
- *
- * Returns an array of System.Reflection.CustomAttributeData,
+ * \param obj a reflection obj handle
+ * \returns an array of \c System.Reflection.CustomAttributeData,
  * which include information about attributes reflected on
  * types loaded using the Reflection Only methods
  */
 MonoArray*
-mono_reflection_get_custom_attrs_data (MonoObject *obj)
+mono_reflection_get_custom_attrs_data (MonoObject *obj_raw)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
-       MonoArray* result;
-       result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
+       MONO_HANDLE_DCL (MonoObject, obj);
+       MonoArrayHandle result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
        mono_error_cleanup (&error);
-       return result;
+       HANDLE_FUNCTION_RETURN_OBJ (result);
 }
 
 /*
@@ -1710,24 +1983,27 @@ mono_reflection_get_custom_attrs_data (MonoObject *obj)
  * which include information about attributes reflected on
  * types loaded using the Reflection Only methods
  */
-MonoArray*
-mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
+MonoArrayHandle
+mono_reflection_get_custom_attrs_data_checked (MonoObjectHandle obj, MonoError *error)
 {
-       MonoArray *result;
+       MonoArrayHandle result = MONO_HANDLE_NEW (MonoArray, NULL);
        MonoCustomAttrInfo *cinfo;
 
-       mono_error_init (error);
+       error_init (error);
 
        cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
-       return_val_if_nok (error, NULL);
+       if (!is_ok (error))
+               goto leave;
        if (cinfo) {
-               result = mono_custom_attrs_data_construct (cinfo, error);
+               MONO_HANDLE_ASSIGN (result, MONO_HANDLE_NEW (MonoArray, mono_custom_attrs_data_construct (cinfo, error))); /* FIXME use coop handles in mono_custom_attrs_data_construct */
                if (!cinfo->cached)
                        mono_custom_attrs_free (cinfo);
-               return_val_if_nok (error, NULL);
+               if (!is_ok (error))
+                       goto leave;
        } else 
-               result = mono_array_new_checked (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error);
+               MONO_HANDLE_ASSIGN (result, mono_array_new_handle (mono_domain_get (), mono_defaults.customattribute_data_class, 0, error));
 
+leave:
        return result;
 }
 
@@ -1838,13 +2114,11 @@ custom_attr_class_name_from_method_token (MonoImage *image, guint32 method_token
 
 /**
  * mono_assembly_metadata_foreach_custom_attr:
- * @assembly: the assembly to iterate over
- * @func: the function to call for each custom attribute
- * @user_data: passed to @func
- *
- * Calls @func for each custom attribute type on the given assembly until @func returns TRUE.
+ * \param assembly the assembly to iterate over
+ * \param func the function to call for each custom attribute
+ * \param user_data passed to \p func
+ * Calls \p func for each custom attribute type on the given assembly until \p func returns TRUE.
  * Everything is done using low-level metadata APIs, so it is safe to use during assembly loading.
- *
  */
 void
 mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data)
@@ -1861,6 +2135,9 @@ mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssembly
         */
 
        image = assembly->image;
+       /* Dynamic images would need to go through the AssemblyBuilder's
+        * CustomAttributeBuilder array.  Going through the tables below
+        * definitely won't work. */
        g_assert (!image_is_dynamic (image));
        idx = 1; /* there is only one assembly */
        idx <<= MONO_CUSTOM_ATTR_BITS;