New test.
[mono.git] / mono / metadata / verify.c
index 0d6cc12fea467abd71ce1036e9bf43191b914d90..180c80daa7c5913bca2e0be80e033debe54bd917 100644 (file)
@@ -231,6 +231,9 @@ mono_class_is_valid_generic_instantiation (VerifyContext *ctx, MonoClass *klass)
 
 static gboolean
 mono_method_is_valid_generic_instantiation (VerifyContext *ctx, MonoMethod *method);
+
+static MonoGenericParam*
+verifier_get_generic_param_from_type (VerifyContext *ctx, MonoType *type);
 //////////////////////////////////////////////////////////////////
 
 
@@ -665,6 +668,23 @@ mono_generic_param_is_constraint_compatible (VerifyContext *ctx, MonoGenericPara
 
                                if (mono_class_is_assignable_from (tc, cc))
                                        break;
+
+                               /*
+                                * This happens when we have the following:
+                                *
+                                * Bar<K> where K : IFace
+                                * Foo<T, U> where T : U where U : IFace
+                                *      ...
+                                *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
+                                *
+                                */
+                               if (mono_type_is_generic_argument (&cc->byval_arg)) {
+                                       MonoGenericParam *other_candidate = verifier_get_generic_param_from_type (ctx, &cc->byval_arg);
+
+                                       if (mono_generic_param_is_constraint_compatible (ctx, target, other_candidate, cc, context)) {
+                                               break;
+                                       }
+                               }
                        }
                        if (!*candidate_class)
                                return FALSE;
@@ -694,7 +714,7 @@ verifier_get_generic_param_from_type (VerifyContext *ctx, MonoType *type)
                gc = mono_method_get_generic_container (gmd);
        }
        if (!gc)
-               return FALSE;
+               return NULL;
        return mono_generic_container_get_param (gc, num);
 }
 
@@ -887,6 +907,13 @@ verifier_load_field (VerifyContext *ctx, int token, MonoClass **out_klass, const
        if (!mono_type_is_valid_in_context (ctx, &klass->byval_arg))
                return NULL;
 
+       if (mono_field_get_flags (field) & FIELD_ATTRIBUTE_LITERAL) {
+               char *type_name = mono_type_get_full_name (field->parent);
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot reference literal field %s::%s at 0x%04x", type_name, field->name, ctx->ip_offset));
+               g_free (type_name);
+               return NULL;
+       }
+
        *out_klass = klass;
        return field;
 }
@@ -3615,7 +3642,7 @@ do_cast (VerifyContext *ctx, int token, const char *opcode) {
        if (!check_underflow (ctx, 1))
                return;
 
-       if (!(type = verifier_load_type (ctx, token, opcode)))
+       if (!(type = get_boxable_mono_type (ctx, token, opcode)))
                return;
 
        if (type->byref) {