From d0ad7e2df9bf67d11cd0164d39916f4659e606f1 Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Thu, 28 Sep 2017 16:24:30 -0400 Subject: [PATCH] [test] SRE ILGenerator test for methodref and fieldref token caching Regression test for https://bugzilla.xamarin.com/show_bug.cgi?id=59364 We need to cause SRE to generate the same methodref/fieldref token from two different reflection objects. That happens if you get the same method or field via a base and a derived class so that the MemberInfo:DeclaredType is different but the underlying MonoMethod* or MonoClassField* is the same. --- .../System.Reflection.Emit/ILGeneratorTest.cs | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs index a31821924c7..c943d6859ca 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs @@ -480,5 +480,97 @@ namespace MonoTests.System.Reflection.Emit Assert.AreEqual (0x02, il [14]); //typedef Assert.AreEqual (0x01, il [19]); //typeref } + + [Test] + public void MethodRefTokenSame () { + // Get the same non-virtual method from a base and a derived type so + // that the MemberInfo:DeclaredType differs but the tokens are the same. + // + // Regression test for bugzilla #59364 + + DefineBasicMethod (); + + var m1 = typeof (object).GetMethod ("GetType"); + var m2 = typeof (string).GetMethod ("GetType"); + + var value_getter = typeof (RuntimeMethodHandle).GetProperty ("Value").GetMethod; + + var il = il_gen; + + var loc = il.DeclareLocal (typeof (RuntimeMethodHandle)); + + // return ((int)(RuntimeMethodHandle (m1).Value == RuntimeMethodHandle (m2).Value)).ToString () + il.Emit (OpCodes.Ldtoken, m1); + il.Emit (OpCodes.Stloc, loc); + il.Emit (OpCodes.Ldloca, loc); + il.Emit (OpCodes.Call, value_getter); + il.Emit (OpCodes.Ldtoken, m2); + il.Emit (OpCodes.Stloc, loc); + il.Emit (OpCodes.Ldloca, loc); + il.Emit (OpCodes.Call, value_getter); + il.Emit (OpCodes.Ceq); + il.Emit (OpCodes.Box, typeof (Int32)); + il.Emit (OpCodes.Callvirt, typeof (object).GetMethod ("ToString")); + il.Emit (OpCodes.Ret); + + var baked = tb.CreateType (); + + var x = Activator.CreateInstance (baked); + var m = baked.GetMethod ("F"); + + var s = m.Invoke (x, null); + + Assert.AreEqual ("1", s); + + } + + public class Base { + public int x; + } + + public class Derived : Base { + } + + [Test] + public void FieldRefTokenSame () { + DefineBasicMethod (); + + // Get the same field from a base and a derived type so hat + // the MemberInfo:DeclaredType differs but the tokens are the same. + // + // Regression test for bugzilla #59364 + + var f1 = typeof (Base).GetField ("x"); + var f2 = typeof (Derived).GetField ("x"); + + var value_getter = typeof (RuntimeFieldHandle).GetProperty("Value").GetMethod; + + var il = il_gen; + + var loc = il.DeclareLocal (typeof (RuntimeFieldHandle)); + + il.Emit (OpCodes.Ldtoken, f1); + il.Emit (OpCodes.Stloc, loc); + il.Emit (OpCodes.Ldloca, loc); + il.Emit (OpCodes.Call, value_getter); + il.Emit (OpCodes.Ldtoken, f2); + il.Emit (OpCodes.Stloc, loc); + il.Emit (OpCodes.Ldloca, loc); + il.Emit (OpCodes.Call, value_getter); + il.Emit (OpCodes.Ceq); + il.Emit (OpCodes.Box, typeof (Int32)); + il.Emit (OpCodes.Callvirt, typeof (object).GetMethod ("ToString")); + il.Emit (OpCodes.Ret); + + var baked = tb.CreateType (); + + var x = Activator.CreateInstance (baked); + var m = baked.GetMethod ("F"); + + var s = m.Invoke (x, null); + + Assert.AreEqual ("1", s); + } + } } -- 2.25.1