X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Floader.c;h=56992b3612738bd5ea800a0a50edc2817068c202;hb=56ad8f4e5dfb8198e4671f631a3103b1e8b83dd3;hp=0566fe2d1028268ae0b92dd1531422364d750289;hpb=66e33aa2ee25b9de6ff80e41aa7036b9a8352479;p=mono.git diff --git a/mono/metadata/loader.c b/mono/metadata/loader.c index 0566fe2d102..56992b36127 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; } @@ -562,7 +564,9 @@ mono_field_from_token_checked (MonoImage *image, guint32 token, MonoClass **retk MonoClass *handle_class; *retklass = NULL; - result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context); + MonoError inner_error; + result = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, &inner_error); + mono_error_cleanup (&inner_error); // This checks the memberref type as well if (!result || handle_class != mono_defaults.fieldhandle_class) { mono_error_set_bad_image (error, image, "Bad field token 0x%08x", token); @@ -682,7 +686,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,48 +875,58 @@ 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; - res = (MonoMethodHeader *)g_malloc0 (MONO_SIZEOF_METHOD_HEADER + sizeof (gpointer) * header->num_locals); + size_t locals_size = sizeof (gpointer) * header->num_locals; + size_t clauses_size = header->num_clauses * sizeof (MonoExceptionClause); + size_t header_size = MONO_SIZEOF_METHOD_HEADER + locals_size + clauses_size; + MonoMethodHeader *res = (MonoMethodHeader *)g_malloc0 (header_size); + res->num_locals = header->num_locals; + res->clauses = (MonoExceptionClause *) &res->locals [res->num_locals] ; + memcpy (res->clauses, header->clauses, clauses_size); + res->code = header->code; res->code_size = header->code_size; res->max_stack = header->max_stack; res->num_clauses = header->num_clauses; 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); + + res->is_transient = TRUE; + + mono_error_init (error); + + for (int 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) { + for (int 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 +948,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 +1017,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 +1038,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) @@ -1866,7 +1880,8 @@ mono_get_method_from_token (MonoImage *image, guint32 token, MonoClass *klass, if (image_is_dynamic (image)) { MonoClass *handle_class; - result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context); + result = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, TRUE, &handle_class, context, error); + mono_error_assert_ok (error); mono_loader_assert_no_error (); // This checks the memberref type as well @@ -1980,7 +1995,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 +2007,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 +2150,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,45 +2805,37 @@ 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); - - mono_image_lock (img); - - if (imethod->header) { - mono_metadata_free_mh (iheader); - mono_image_unlock (img); - return imethod->header; + if (!iheader) { + return NULL; } - mono_memory_barrier (); - imethod->header = iheader; - - mono_image_unlock (img); - - return imethod->header; + return iheader; } if (method->wrapper_type != MONO_WRAPPER_NONE || method->sre_method) { @@ -2851,12 +2852,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 +2870,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 +2908,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]) {