Make the thread dump code safe by doing only async safe operations when a thread...
[mono.git] / mono / metadata / verify.c
index d16deef5e6f3ac3a41c6fe4602b1d4bee05e3337..43a938d0fc4a0e09757c04938cbbb2ba5b269639 100644 (file)
@@ -26,6 +26,7 @@
 #include <mono/metadata/tokentype.h>
 #include <mono/metadata/mono-basic-block.h>
 #include <mono/metadata/attrdefs.h>
+#include <mono/metadata/class-internals.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/monobitset.h>
 #include <string.h>
@@ -530,6 +531,8 @@ mono_type_is_valid_type_in_context_full (MonoType *type, MonoGenericContext *con
                        return FALSE;
                break;
        }
+       default:
+               break;
        }
        return TRUE;
 }
@@ -1448,6 +1451,8 @@ is_valid_bool_arg (ILStackDesc *arg)
                         * is it a "class Foo<T>" or a "struct Foo<T>"?
                         */
                        return !arg->type->data.generic_class->container_class->valuetype;
+               default:
+                       return FALSE;
                }
        default:
                return FALSE;
@@ -2510,6 +2515,12 @@ verify_stack_type_compatibility_full (VerifyContext *ctx, MonoType *type, ILStac
        if (drop_byref)
                return verify_type_compatibility_full (ctx, type, mono_type_get_type_byval (candidate), FALSE);
 
+       /* Handle how Roslyn emit fixed statements by encoding it as byref */
+       if (type->byref && candidate->byref && (type->type == MONO_TYPE_I) && !mono_type_is_reference (candidate)) {
+               if (!IS_STRICT_MODE (ctx))
+                       return TRUE;
+       }
+
        return verify_type_compatibility_full (ctx, type, candidate, FALSE);
 }
 
@@ -2984,6 +2995,12 @@ stack_slot_is_complex_type_not_reference_type (ILStackDesc *slot)
        return stack_slot_get_type (slot) == TYPE_COMPLEX && !MONO_TYPE_IS_REFERENCE (slot->type) && !stack_slot_is_boxed_value (slot);
 }
 
+static gboolean
+stack_slot_is_reference_value (ILStackDesc *slot)
+{
+       return stack_slot_get_type (slot) == TYPE_COMPLEX && (MONO_TYPE_IS_REFERENCE (slot->type) || stack_slot_is_boxed_value (slot));
+}
+
 static void
 do_branch_op (VerifyContext *ctx, signed int delta, const unsigned char table [TYPE_MAX][TYPE_MAX])
 {
@@ -3057,7 +3074,8 @@ do_cmp_op (VerifyContext *ctx, const unsigned char table [TYPE_MAX][TYPE_MAX], g
        a = stack_pop (ctx);
 
        if (opcode == CEE_CGT_UN) {
-               if (stack_slot_get_type (a) == TYPE_COMPLEX && stack_slot_get_type (b) == TYPE_COMPLEX) {
+               if ((stack_slot_is_reference_value (a) && stack_slot_is_null_literal (b)) ||
+                       (stack_slot_is_reference_value (b) && stack_slot_is_null_literal (a))) {
                        stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
                        return;
                }
@@ -3080,7 +3098,11 @@ do_cmp_op (VerifyContext *ctx, const unsigned char table [TYPE_MAX][TYPE_MAX], g
        }
 
        if(res == TYPE_INV) {
-               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf("Compare instruction applyed to ill formed stack (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset));
+               char *left_type = stack_slot_full_name (a);
+               char *right_type = stack_slot_full_name (b);
+               CODE_NOT_VERIFIABLE (ctx, g_strdup_printf("Compare instruction applyed to ill formed stack (%s x %s) at 0x%04x", left_type, right_type, ctx->ip_offset));
+               g_free (left_type);
+               g_free (right_type);
        } else if (res & NON_VERIFIABLE_RESULT) {
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Compare instruction is not verifiable (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset)); 
                res = res & ~NON_VERIFIABLE_RESULT;
@@ -3597,6 +3619,7 @@ do_conversion (VerifyContext *ctx, int kind)
 static void
 do_load_token (VerifyContext *ctx, int token) 
 {
+       MonoError error;
        gpointer handle;
        MonoClass *handle_class;
        if (!check_overflow (ctx))
@@ -3626,11 +3649,12 @@ do_load_token (VerifyContext *ctx, int token)
                        return;
                }
 
-               handle = mono_ldtoken (ctx->image, token, &handle_class, ctx->generic_context);
+               handle = mono_ldtoken_checked (ctx->image, token, &handle_class, ctx->generic_context, &error);
        }
 
        if (!handle) {
-               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid token 0x%x for ldtoken at 0x%04x", token, ctx->ip_offset));
+               ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid token 0x%x for ldtoken at 0x%04x due to %s", token, ctx->ip_offset, mono_error_get_message (&error)));
+               mono_error_cleanup (&error);
                return;
        }
        if (handle_class == mono_defaults.typehandle_class) {
@@ -3888,6 +3912,8 @@ do_cast (VerifyContext *ctx, int token, const char *opcode) {
        case MONO_TYPE_PTR:
        case MONO_TYPE_TYPEDBYREF: 
                CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value for %s at 0x%04x", opcode, ctx->ip_offset));
+       default:
+               break;
        }
 
        do_box = is_boxed || mono_type_is_generic_argument(type) || mono_class_from_mono_type (type)->valuetype;
@@ -4403,8 +4429,6 @@ do_sizeof (VerifyContext *ctx, int token)
 static void
 do_localloc (VerifyContext *ctx)
 {
-       ILStackDesc *top;
-       
        if (ctx->eval.size != 1) {
                ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack must have only size item in localloc at 0x%04x", ctx->ip_offset));
                return;         
@@ -4416,7 +4440,7 @@ do_localloc (VerifyContext *ctx)
        }
 
        /*TODO verify top type*/
-       top = stack_pop (ctx);
+       /* top = */ stack_pop (ctx);
 
        set_stack_value (ctx, stack_push (ctx), &mono_defaults.int_class->byval_arg, FALSE);
        CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Instruction localloc in never verifiable at 0x%04x", ctx->ip_offset));
@@ -4808,7 +4832,7 @@ mono_method_verify (MonoMethod *method, int level)
        MonoSimpleBasicBlock *bb = NULL, *original_bb = NULL;
 
        int i, n, need_merge = 0, start = 0;
-       guint token, ip_offset = 0, prefix = 0;
+       guint ip_offset = 0, prefix = 0;
        MonoGenericContext *generic_context = NULL;
        MonoImage *image;
        VerifyContext ctx;
@@ -5353,7 +5377,7 @@ mono_method_verify (MonoMethod *method, int level)
                        code_bounds_check (5);
                        if (ctx.eval.size)
                                ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Eval stack must be empty in jmp at 0x%04x", ip_offset));
-                       token = read32 (ip + 1);
+                       /* token = read32 (ip + 1); */
                        if (in_any_block (ctx.header, ip_offset))
                                ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("jmp cannot escape exception blocks at 0x%04x", ip_offset));
 
@@ -5372,7 +5396,7 @@ mono_method_verify (MonoMethod *method, int level)
 
                case CEE_CALLI:
                        code_bounds_check (5);
-                       token = read32 (ip + 1);
+                       /* token = read32 (ip + 1); */
                        /*
                         * FIXME: check signature, retval, arguments etc.
                         * FIXME: check requirements for tail call