2013-09-26 17:14:40 +02:00

208 lines
5.7 KiB
Plaintext

$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)