X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Floader.c;h=f9b83480b52262a3647136ce9aeb5ebf96025386;hb=ef0ddf45c3081e799edcb4e95770186514b80cf1;hp=0566fe2d1028268ae0b92dd1531422364d750289;hpb=ac432e4ba2f187bf6606a2a07bb87607306647b4;p=mono.git diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 0566fe2d102..f9b83480b52 100644 --- a/mono/metadata/loader.c +++ b/mono/metadata/loader.c @@ -17,6 +17,7 @@ * TODO: * This should keep track of the assembly versions that we are loading. * + * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ #include #include @@ -506,13 +507,17 @@ field_from_memberref (MonoImage *image, guint32 token, MonoClass **retklass, } /* FIXME: This needs a cache, especially for generic instances, since - * mono_metadata_parse_type () allocates everything from a mempool. + * we ask mono_metadata_parse_type_checked () to allocates everything from a mempool. + * FIXME part2, mono_metadata_parse_type_checked actually allows for a transient type instead. + * FIXME part3, transient types are not 100% transient, so we need to take care of that first. */ sig_type = (MonoType *)find_cached_memberref_sig (image, cols [MONO_MEMBERREF_SIGNATURE]); if (!sig_type) { - sig_type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr); + MonoError inner_error; + sig_type = mono_metadata_parse_type_checked (image, NULL, 0, FALSE, ptr, &ptr, &inner_error); if (sig_type == NULL) { - mono_error_set_field_load (error, klass, fname, "Could not parse field '%s' signature %08x", fname, token); + mono_error_set_field_load (error, klass, fname, "Could not parse field '%s' signature %08x due to: %s", fname, token, mono_error_get_message (&inner_error)); + mono_error_cleanup (&inner_error); return NULL; } sig_type = (MonoType *)cache_memberref_sig (image, cols [MONO_MEMBERREF_SIGNATURE], sig_type); @@ -534,17 +539,14 @@ field_from_memberref (MonoImage *image, guint32 token, MonoClass **retklass, /* * mono_field_from_token: * @deprecated use the _checked variant + * Notes: runtime code MUST not use this function */ MonoClassField* mono_field_from_token (MonoImage *image, guint32 token, MonoClass **retklass, MonoGenericContext *context) { MonoError error; MonoClassField *res = mono_field_from_token_checked (image, token, retklass, context, &error); - mono_loader_assert_no_error (); - if (!mono_error_ok (&error)) { - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); - } + g_assert (mono_error_ok (&error)); return res; } @@ -682,7 +684,7 @@ find_method_in_class (MonoClass *klass, const char *name, const char *qname, con See mono/tests/generic-type-load-exception.2.il FIXME we should better report this error to the caller */ - if (!klass->methods || klass->exception_type) { + if (!klass->methods || mono_class_has_failure (klass)) { mono_error_set_type_load_class (error, klass, "Could not find method due to a type load error"); //FIXME get the error from the class return NULL; @@ -871,7 +873,7 @@ mono_inflate_generic_signature (MonoMethodSignature *sig, MonoGenericContext *co } static MonoMethodHeader* -inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context) +inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context, MonoError *error) { MonoMethodHeader *res; int i; @@ -883,36 +885,42 @@ inflate_generic_header (MonoMethodHeader *header, MonoGenericContext *context) res->init_locals = header->init_locals; res->num_locals = header->num_locals; res->clauses = header->clauses; - for (i = 0; i < header->num_locals; ++i) - res->locals [i] = mono_class_inflate_generic_type (header->locals [i], context); + + mono_error_init (error); + + for (i = 0; i < header->num_locals; ++i) { + res->locals [i] = mono_class_inflate_generic_type_checked (header->locals [i], context, error); + if (!is_ok (error)) + goto fail; + } if (res->num_clauses) { res->clauses = (MonoExceptionClause *)g_memdup (header->clauses, sizeof (MonoExceptionClause) * res->num_clauses); for (i = 0; i < header->num_clauses; ++i) { MonoExceptionClause *clause = &res->clauses [i]; if (clause->flags != MONO_EXCEPTION_CLAUSE_NONE) continue; - clause->data.catch_class = mono_class_inflate_generic_class (clause->data.catch_class, context); + clause->data.catch_class = mono_class_inflate_generic_class_checked (clause->data.catch_class, context, error); + if (!is_ok (error)) + goto fail; } } return res; +fail: + g_free (res); + return NULL; } /* * token is the method_ref/def/spec token used in a call IL instruction. + * @deprecated use the _checked variant + * Notes: runtime code MUST not use this function */ MonoMethodSignature* mono_method_get_signature_full (MonoMethod *method, MonoImage *image, guint32 token, MonoGenericContext *context) { MonoError error; MonoMethodSignature *res = mono_method_get_signature_checked (method, image, token, context, &error); - - mono_loader_assert_no_error (); - - if (!res) { - g_assert (!mono_error_ok (&error)); - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); /* FIXME Don't swallow the error */ - } + mono_error_cleanup (&error); return res; } @@ -934,8 +942,10 @@ mono_method_get_signature_checked (MonoMethod *method, MonoImage *image, guint32 if (table == MONO_TABLE_METHODSPEC) { /* the verifier (do_invoke_method) will turn the NULL into a verifier error */ - if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || !method->is_inflated) + if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || !method->is_inflated) { + mono_error_set_bad_image (error, image, "Method is a pinvoke or open generic"); return NULL; + } return mono_method_signature_checked (method, error); } @@ -1001,19 +1011,17 @@ mono_method_get_signature_checked (MonoMethod *method, MonoImage *image, guint32 return sig; } +/* + * token is the method_ref/def/spec token used in a call IL instruction. + * @deprecated use the _checked variant + * Notes: runtime code MUST not use this function + */ MonoMethodSignature* mono_method_get_signature (MonoMethod *method, MonoImage *image, guint32 token) { MonoError error; MonoMethodSignature *res = mono_method_get_signature_checked (method, image, token, NULL, &error); - - mono_loader_assert_no_error (); - - if (!res) { - g_assert (!mono_error_ok (&error)); - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); /* FIXME Don't swallow the error */ - } + mono_error_cleanup (&error); return res; } @@ -1024,7 +1032,7 @@ mono_method_search_in_array_class (MonoClass *klass, const char *name, MonoMetho int i; mono_class_setup_methods (klass); - g_assert (!klass->exception_type); /*FIXME this should not fail, right?*/ + g_assert (!mono_class_has_failure (klass)); /*FIXME this should not fail, right?*/ for (i = 0; i < klass->method.count; ++i) { MonoMethod *method = klass->methods [i]; if (strcmp (method->name, name) == 0 && sig->param_count == method->signature->param_count) @@ -1980,7 +1988,10 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, MonoMethod * mono_get_method (MonoImage *image, guint32 token, MonoClass *klass) { - return mono_get_method_full (image, token, klass, NULL); + MonoError error; + MonoMethod *result = mono_get_method_checked (image, token, klass, NULL, &error); + mono_error_cleanup (&error); + return result; } MonoMethod * @@ -1989,11 +2000,7 @@ mono_get_method_full (MonoImage *image, guint32 token, MonoClass *klass, { MonoError error; MonoMethod *result = mono_get_method_checked (image, token, klass, context, &error); - mono_loader_assert_no_error (); - if (!mono_error_ok (&error)) { - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); - } + mono_error_cleanup (&error); return result; } @@ -2136,12 +2143,7 @@ mono_get_method_constrained (MonoImage *image, guint32 token, MonoClass *constra { MonoError error; MonoMethod *result = mono_get_method_constrained_checked (image, token, constrained_class, context, cil_method, &error); - - mono_loader_assert_no_error (); - if (!mono_error_ok (&error)) { - mono_loader_set_error_from_mono_error (&error); - mono_error_cleanup (&error); - } + mono_error_cleanup (&error); return result; } @@ -2796,30 +2798,35 @@ mono_method_get_token (MonoMethod *method) } MonoMethodHeader* -mono_method_get_header (MonoMethod *method) +mono_method_get_header_checked (MonoMethod *method, MonoError *error) { int idx; guint32 rva; MonoImage* img; gpointer loc; - MonoMethodHeader *header; MonoGenericContainer *container; - if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) - return NULL; - + mono_error_init (error); img = method->klass->image; + if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) || (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) { + mono_error_set_bad_image (error, img, "Method has no body"); + return NULL; + } + if (method->is_inflated) { MonoMethodInflated *imethod = (MonoMethodInflated *) method; MonoMethodHeader *header, *iheader; - header = mono_method_get_header (imethod->declaring); + header = mono_method_get_header_checked (imethod->declaring, error); if (!header) return NULL; - iheader = inflate_generic_header (header, mono_method_get_context (method)); + iheader = inflate_generic_header (header, mono_method_get_context (method), error); mono_metadata_free_mh (header); + if (!iheader) { + return NULL; + } mono_image_lock (img); @@ -2851,12 +2858,16 @@ mono_method_get_header (MonoMethod *method) idx = mono_metadata_token_index (method->token); rva = mono_metadata_decode_row_col (&img->tables [MONO_TABLE_METHOD], idx - 1, MONO_METHOD_RVA); - if (!mono_verifier_verify_method_header (img, rva, NULL)) + if (!mono_verifier_verify_method_header (img, rva, NULL)) { + mono_error_set_bad_image (error, img, "Invalid method header, failed verification"); return NULL; + } loc = mono_image_rva_map (img, rva); - if (!loc) + if (!loc) { + mono_error_set_bad_image (error, img, "Method has zero rva"); return NULL; + } /* * When parsing the types of local variables, we must pass any container available @@ -2865,11 +2876,19 @@ mono_method_get_header (MonoMethod *method) container = mono_method_get_generic_container (method); if (!container) container = method->klass->generic_container; - header = mono_metadata_parse_mh_full (img, container, (const char *)loc); + return mono_metadata_parse_mh_full (img, container, (const char *)loc, error); +} +MonoMethodHeader* +mono_method_get_header (MonoMethod *method) +{ + MonoError error; + MonoMethodHeader *header = mono_method_get_header_checked (method, &error); + mono_error_cleanup (&error); return header; } + guint32 mono_method_get_flags (MonoMethod *method, guint32 *iflags) { @@ -2895,7 +2914,7 @@ mono_method_get_index (MonoMethod *method) return mono_metadata_token_index (method->token); mono_class_setup_methods (klass); - if (klass->exception_type) + if (mono_class_has_failure (klass)) return 0; for (i = 0; i < klass->method.count; ++i) { if (method == klass->methods [i]) {