Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kliger (λgeek) <akliger@gmail.com>2017-10-18 15:09:39 +0300
committerLudovic Henry <luhenry@microsoft.com>2017-10-18 15:09:39 +0300
commit1f4613aa1acacbea90a8aa82daeea4a449cf4df7 (patch)
tree34da703401ecd871331658f5e5468a8e8156ca65
parentd092ad186ffae768279b092bdab513f65af2f7b2 (diff)
[sre] Register a canonical reflected method for a methodspec token. (Fixes #60233) (#5814)mono-5.4.1.6
* [sre] mono_dynamic_image_register_token: Change asserts to warnings This partly relaxes the changes in 792b5367cd3a6ffa1a192c4d2d7ace3509cbb646 which added the assertions. In practice the assertions introduced a crash in heavy uses of System.Reflection.Emit such as unit testing frameworks and dynamic languages. We still want to know if there are surprising uses of mono_dynamic_image_register_token, but we don't need a crash. SRE used to work before 792b5367cd3a6ffa1a192c4d2d7ace3509cbb646, so no need to break it. * [test] ILGenerator test for duplicate methodspec tokens Regression test for [Bugzilla #60233](https://bugzilla.xamarin.com/show_bug.cgi?id=60233) * [sre] Register a canonical reflected method for a methodspec token (Fixes #60233) This is like the fix for [bugzilla 59364](https://bugzilla.xamarin.com/show_bug.cgi?id=59364) but this time it's a methodspec token, not a memberref token.
-rw-r--r--mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs45
-rw-r--r--mono/metadata/dynamic-image.c7
-rw-r--r--mono/metadata/sre.c12
3 files changed, 56 insertions, 8 deletions
diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs
index c943d6859ca..b31ed2e117e 100644
--- a/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs
+++ b/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs
@@ -524,11 +524,13 @@ namespace MonoTests.System.Reflection.Emit
}
- public class Base {
+ public class Base<T> {
public int x;
+
+ public void M () { }
}
- public class Derived : Base {
+ public class Derived : Base<string> {
}
[Test]
@@ -540,7 +542,7 @@ namespace MonoTests.System.Reflection.Emit
//
// Regression test for bugzilla #59364
- var f1 = typeof (Base).GetField ("x");
+ var f1 = typeof (Base<string>).GetField ("x");
var f2 = typeof (Derived).GetField ("x");
var value_getter = typeof (RuntimeFieldHandle).GetProperty("Value").GetMethod;
@@ -572,5 +574,42 @@ namespace MonoTests.System.Reflection.Emit
Assert.AreEqual ("1", s);
}
+ [Test]
+ public void MethodSpecTokenSame () {
+ DefineBasicMethod ();
+ // Get the same method from a base generic instance and
+ // a type derived from it so that the
+ // MemberInfo:DeclaredType differs but the tokens are
+ // the same.
+ //
+ // Regression test for bugzilla #60233
+
+ var m1 = typeof (Base<string>).GetMethod ("M");
+ var m2 = typeof (Derived).GetMethod ("M");
+
+ var il = il_gen;
+
+ var loc = il.DeclareLocal (typeof (Derived));
+
+ il.Emit (OpCodes.Newobj, typeof (Derived).GetConstructor(new Type[]{}));
+ il.Emit (OpCodes.Stloc, loc);
+ il.Emit (OpCodes.Ldloc, loc);
+ il.Emit (OpCodes.Call, m1);
+ il.Emit (OpCodes.Ldloc, loc);
+ il.Emit (OpCodes.Call, m2);
+ il.Emit (OpCodes.Ldstr, "1");
+ 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);
+
+ }
+
}
}
diff --git a/mono/metadata/dynamic-image.c b/mono/metadata/dynamic-image.c
index 4cfeaa41db8..b8874198b02 100644
--- a/mono/metadata/dynamic-image.c
+++ b/mono/metadata/dynamic-image.c
@@ -204,9 +204,12 @@ mono_dynamic_image_register_token (MonoDynamicImage *assembly, guint32 token, Mo
if (prev) {
switch (how_collide) {
case MONO_DYN_IMAGE_TOK_NEW:
- g_assert_not_reached ();
+ g_warning ("%s: Unexpected previous object when called with MONO_DYN_IMAGE_TOK_NEW", __func__);
+ break;
case MONO_DYN_IMAGE_TOK_SAME_OK:
- g_assert (prev == MONO_HANDLE_RAW (obj));
+ if (prev != MONO_HANDLE_RAW (obj)) {
+ g_warning ("%s: condition `prev == MONO_HANDLE_RAW (obj)' not met", __func__);
+ }
break;
case MONO_DYN_IMAGE_TOK_REPLACE:
break;
diff --git a/mono/metadata/sre.c b/mono/metadata/sre.c
index a009f41ecd8..cf4715e61e5 100644
--- a/mono/metadata/sre.c
+++ b/mono/metadata/sre.c
@@ -1149,9 +1149,15 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
MonoReflectionMethodHandle m = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
if (method->is_inflated) {
- if (create_open_instance)
- token = mono_image_get_methodspec_token (assembly, method);
- else
+ if (create_open_instance) {
+ guint32 methodspec_token = mono_image_get_methodspec_token (assembly, method);
+ MonoReflectionMethodHandle canonical_obj =
+ mono_method_get_object_handle (MONO_HANDLE_DOMAIN (obj), method, NULL, error);
+ if (!is_ok (error))
+ goto leave;
+ MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
+ token = methodspec_token;
+ } else
token = mono_image_get_inflated_method_token (assembly, method);
} else if ((method->klass->image == &assembly->image) &&
!mono_class_is_ginst (method->klass)) {