$NetBSD: patch-ai,v 1.1 2013/06/17 12:43:28 wiz Exp $ --- mono/metadata/object.c.orig 2009-10-26 20:44:10.000000000 +0000 +++ mono/metadata/object.c @@ -3353,6 +3353,135 @@ mono_install_runtime_invoke (MonoInvokeF default_mono_runtime_invoke = func ? func: dummy_mono_runtime_invoke; } +/* + * is_widen_compatible: + * + * Tests if @candidate can be used in place of @type by means of a widening conversion. + * This means, for example, that a byte can be widened to an int and be used as argument in + * a reflection call. + * + * Returns true if @candidate can be widened to @type. + */ +static gboolean +is_widen_compatible (MonoType * type, MonoType *candidate) +{ + if (type->type == candidate->type) + return TRUE; + + switch (candidate->type) { + case MONO_TYPE_U1: + switch (type->type) { + case MONO_TYPE_U2: + case MONO_TYPE_I2: + case MONO_TYPE_CHAR: + case MONO_TYPE_U: + case MONO_TYPE_I: + case MONO_TYPE_U4: + case MONO_TYPE_I4: + case MONO_TYPE_U8: + case MONO_TYPE_I8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return TRUE; + } + return FALSE; + case MONO_TYPE_I1: + switch (type->type) { + case MONO_TYPE_I2: + case MONO_TYPE_I: + case MONO_TYPE_I4: + case MONO_TYPE_I8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return TRUE; + } + case MONO_TYPE_BOOLEAN: + return type->type == MONO_TYPE_BOOLEAN; + case MONO_TYPE_U2: + switch (type->type) { + case MONO_TYPE_U2: + case MONO_TYPE_U: + case MONO_TYPE_I: + case MONO_TYPE_U4: + case MONO_TYPE_I4: + case MONO_TYPE_U8: + case MONO_TYPE_I8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return TRUE; + } + return FALSE; + case MONO_TYPE_I2: + switch (type->type) { + case MONO_TYPE_I: + case MONO_TYPE_I4: + case MONO_TYPE_I8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return TRUE; + } + return FALSE; + case MONO_TYPE_CHAR: + switch (type->type) { + case MONO_TYPE_U2: + case MONO_TYPE_U: + case MONO_TYPE_I: + case MONO_TYPE_U4: + case MONO_TYPE_I4: + case MONO_TYPE_U8: + case MONO_TYPE_I8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return TRUE; + } + return FALSE; + case MONO_TYPE_U: + switch (type->type) { + case MONO_TYPE_U4: + case MONO_TYPE_U8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return TRUE; + } + return FALSE; + case MONO_TYPE_I: + switch (type->type) { + case MONO_TYPE_I: + case MONO_TYPE_I8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return TRUE; + } + return FALSE; + case MONO_TYPE_U4: + switch (type->type) { + case MONO_TYPE_U: + case MONO_TYPE_U8: + case MONO_TYPE_I8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return TRUE; + } + return FALSE; + case MONO_TYPE_I4: + switch (type->type) { + case MONO_TYPE_I: + case MONO_TYPE_I8: + case MONO_TYPE_R4: + case MONO_TYPE_R8: + return TRUE; + } + return FALSE; + case MONO_TYPE_U8: + case MONO_TYPE_I8: + return type->type == MONO_TYPE_R4 || type->type == MONO_TYPE_R8; + case MONO_TYPE_R4: + return type->type == MONO_TYPE_R8; + case MONO_TYPE_R8: + break; + } + return FALSE; +} /** * mono_runtime_invoke_array: @@ -3405,6 +3534,8 @@ mono_runtime_invoke_array (MonoMethod *m pa = alloca (sizeof (gpointer) * mono_array_length (params)); for (i = 0; i < mono_array_length (params); i++) { MonoType *t = sig->params [i]; + MonoClass *par_class = mono_class_from_mono_type (t); + MonoObject *pao; again: switch (t->type) { @@ -3429,9 +3560,16 @@ mono_runtime_invoke_array (MonoMethod *m if (t->byref) has_byref_nullables = TRUE; } else { + pao = mono_array_get (params, MonoObject*, i); /* MS seems to create the objects if a null is passed in */ - if (!mono_array_get (params, MonoObject*, i)) - mono_array_setref (params, i, mono_object_new (mono_domain_get (), mono_class_from_mono_type (sig->params [i]))); + if (pao) { + if ((t->type == MONO_TYPE_VALUETYPE && pao->vtable->klass != par_class) || + (t->type != MONO_TYPE_VALUETYPE && !is_widen_compatible (t, &pao->vtable->klass->byval_arg))) + mono_raise_exception (mono_get_exception_argument ("", "Incompatible type passed")); + } else { + pao = mono_object_new (mono_domain_get (), par_class); + mono_array_setref (params, i, pao); + } if (t->byref) { /* @@ -3441,12 +3579,13 @@ mono_runtime_invoke_array (MonoMethod *m * object, pass that to the callee, and replace the original * boxed object in the arg array with the copy. */ - MonoObject *orig = mono_array_get (params, MonoObject*, i); + MonoObject *orig = pao; MonoObject *copy = mono_value_box (mono_domain_get (), orig->vtable->klass, mono_object_unbox (orig)); mono_array_setref (params, i, copy); + pao = copy; } - pa [i] = mono_object_unbox (mono_array_get (params, MonoObject*, i)); + pa [i] = mono_object_unbox (pao); } break; case MONO_TYPE_STRING: @@ -3454,11 +3593,19 @@ mono_runtime_invoke_array (MonoMethod *m case MONO_TYPE_CLASS: case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: - if (t->byref) + if (t->byref) { pa [i] = mono_array_addr (params, MonoObject*, i); // FIXME: I need to check this code path - else - pa [i] = mono_array_get (params, MonoObject*, i); + } else { + pao = mono_array_get (params, MonoObject*, i); + pa [i] = pao; + + if (pao != NULL && !mono_class_is_assignable_from (par_class, pao->vtable->klass) && + (pao->vtable->klass == mono_defaults.transparent_proxy_class && + !mono_class_is_assignable_from (par_class, ((MonoTransparentProxy*)pao)->remote_class->proxy_class))) { + mono_raise_exception (mono_get_exception_argument ("", "Incompatible type passed")); + } + } break; case MONO_TYPE_GENERICINST: if (t->byref)