[verifier] Fail to merge stacks with different safe byref'ness.
authorRodrigo Kumpera <kumpera@gmail.com>
Mon, 11 Sep 2017 23:33:52 +0000 (16:33 -0700)
committerRodrigo Kumpera <kumpera@gmail.com>
Mon, 11 Sep 2017 23:35:54 +0000 (16:35 -0700)
mono/metadata/verify.c
mono/tests/verifier/unverifiable_ref_return_stack_merge.il [new file with mode: 0644]
mono/tests/verifier/valid_ref_return_stack_merge.il [new file with mode: 0644]

index 7c9a48a2f1566a91745e2c049606496fab65cde8..e509ed680c13c646aedb4b49a84abf321204d2f3 100644 (file)
@@ -4674,6 +4674,12 @@ merge_stacks (VerifyContext *ctx, ILCodeDesc *from, ILCodeDesc *to, gboolean sta
                MonoClass *new_class = mono_class_from_mono_type (new_type);
                MonoClass *match_class = NULL;
 
+               // check for safe byref before the next steps override new_slot
+               if (stack_slot_is_safe_byref (old_slot) ^ stack_slot_is_safe_byref (new_slot)) {
+                       CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot merge stack at depth %d byref types are safe byref incompatible at %0x04x ", i, ctx->ip_offset));
+                       goto end_verify;
+               }
+
                // S := T then U = S (new value is compatible with current value, keep current)
                if (verify_stack_type_compatibility (ctx, old_type, new_slot)) {
                        copy_stack_value (new_slot, old_slot);
diff --git a/mono/tests/verifier/unverifiable_ref_return_stack_merge.il b/mono/tests/verifier/unverifiable_ref_return_stack_merge.il
new file mode 100644 (file)
index 0000000..f82539b
--- /dev/null
@@ -0,0 +1,59 @@
+.assembly extern mscorlib
+{
+  .ver 4:0:0:0
+  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+}
+.assembly 'ref-return'
+{
+  .hash algorithm 0x00008004
+  .ver  0:0:0:0
+}
+.module 'ref-return.dll' // GUID = {09E5E448-CA90-49A5-AFBA-0AA241F72FBF}
+
+
+.class private auto ansi beforefieldinit Test extends [mscorlib]System.Object
+{
+       .field  private static  int32 X
+       .field  private static  int32 Y
+
+       .method private static hidebysig  default int32& invalid_branch1 (bool b)  cil managed 
+       {
+               .maxstack 1
+               .locals init (int32&, int32)
+               ldarg.0 
+               brtrue.s LABEL_1
+
+               ldsflda int32 Test::Y
+               br.s LABEL_2
+
+LABEL_1:
+               ldloca 1
+
+LABEL_2:
+               stloc.0 
+
+               ldloc.0 
+               ret 
+       }
+
+       .method private static hidebysig  default int32& invalid_branch2 (bool b)  cil managed 
+       {
+               .maxstack 1
+               .locals init (int32&, int32)
+               ldarg.0 
+               brtrue.s LABEL_1
+
+               ldloca 1
+               br.s LABEL_2
+
+LABEL_1:
+               ldsflda int32 Test::X
+
+LABEL_2:
+               stloc.0 
+
+               ldloc.0 
+               ret 
+       }
+}
+
diff --git a/mono/tests/verifier/valid_ref_return_stack_merge.il b/mono/tests/verifier/valid_ref_return_stack_merge.il
new file mode 100644 (file)
index 0000000..a208308
--- /dev/null
@@ -0,0 +1,39 @@
+.assembly extern mscorlib
+{
+  .ver 4:0:0:0
+  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
+}
+.assembly 'ref-return'
+{
+  .hash algorithm 0x00008004
+  .ver  0:0:0:0
+}
+.module 'ref-return.dll' // GUID = {09E5E448-CA90-49A5-AFBA-0AA241F72FBF}
+
+
+.class private auto ansi beforefieldinit Test extends [mscorlib]System.Object
+{
+       .field  private static  int32 X
+       .field  private static  int32 Y
+
+       .method private static hidebysig  default int32& valid_branch (bool b)  cil managed 
+       {
+               .maxstack 1
+               .locals init (int32&    V_0)
+               ldarg.0 
+               brtrue.s LABEL_1
+
+               ldsflda int32 Test::Y
+               br.s LABEL_2
+
+LABEL_1:
+               ldsflda int32 Test::X
+
+LABEL_2:
+               stloc.0 
+
+               ldloc.0 
+               ret 
+       }
+}
+