From 5095f1f75f86c2aedaedf9e35457cb6635a3c989 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 11 Sep 2020 00:49:34 -0700 Subject: [PATCH] Fix ldtoken for generic RuntimeMethodHandle ldtoken for generic RuntimeMethodHandle in non-generic method triggered generic dictionary lookup due to normalization of MethodDescs for reflection. It lead to InvalidProgramException later. Fixes #41674 --- src/coreclr/src/vm/jitinterface.cpp | 2 +- .../tests/Lambda/LambdaTests.cs | 18 +++++++ .../coreclr/GitHub_41674/genericldtoken.il | 53 +++++++++++++++++++ .../GitHub_41674/genericldtoken.ilproj | 10 ++++ 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/tests/Regressions/coreclr/GitHub_41674/genericldtoken.il create mode 100644 src/tests/Regressions/coreclr/GitHub_41674/genericldtoken.ilproj diff --git a/src/coreclr/src/vm/jitinterface.cpp b/src/coreclr/src/vm/jitinterface.cpp index 37bede3e2dc0d3..8fc0af16a32f51 100644 --- a/src/coreclr/src/vm/jitinterface.cpp +++ b/src/coreclr/src/vm/jitinterface.cpp @@ -2629,7 +2629,7 @@ void CEEInfo::embedGenericHandle( // Runtime lookup is only required for stubs. Regular entrypoints are always the same shared MethodDescs. fRuntimeLookup = pMD->IsWrapperStub() && - (pMD->GetMethodTable()->IsSharedByGenericInstantiations() || TypeHandle::IsCanonicalSubtypeInstantiation(methodInst)); + (th.IsSharedByGenericInstantiations() || TypeHandle::IsCanonicalSubtypeInstantiation(methodInst)); } else if (!fEmbedParent && pResolvedToken->hField != NULL) diff --git a/src/libraries/System.Linq.Expressions/tests/Lambda/LambdaTests.cs b/src/libraries/System.Linq.Expressions/tests/Lambda/LambdaTests.cs index b6f2d0f71902f5..9cd8d5ef12fda2 100644 --- a/src/libraries/System.Linq.Expressions/tests/Lambda/LambdaTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Lambda/LambdaTests.cs @@ -975,5 +975,23 @@ public void ValidateThatInterpreterWithSimpleTypeUsesDynamicThunk() Expression> complexfunc = (object o1, object o2, object o3) => null; Assert.True(complexfunc.Compile(preferInterpretation:true).Method.GetType().Name == "RTDynamicMethod"); } + + private interface IInterface + { + string B(); + } + + private readonly struct GenericStruct : IInterface + { + public string B() => "B"; + } + + [Fact] + public void MethodOnGenericStructImplementingInterface() + { + Expression, string>> funcE = x => x.B(); + Func, string> f = funcE.Compile(); + Assert.Equal("B", f(new GenericStruct())); + } } } diff --git a/src/tests/Regressions/coreclr/GitHub_41674/genericldtoken.il b/src/tests/Regressions/coreclr/GitHub_41674/genericldtoken.il new file mode 100644 index 00000000000000..245d8b3f973821 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_41674/genericldtoken.il @@ -0,0 +1,53 @@ +.assembly extern System.Runtime { } + +.assembly genericldtoken { } + +.class public sequential ansi sealed beforefieldinit GenericStruct`1 + extends [System.Runtime]System.ValueType +{ + .pack 0 + .size 1 + .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = ( 01 00 00 00 ) + .method public hidebysig newslot virtual final + instance string B() cil managed + { + // Code size 6 (0x6) + .maxstack 8 + IL_0000: ldstr "B" + IL_0005: ret + } +} + +.class private auto ansi beforefieldinit Program + extends [System.Runtime]System.Object +{ + .method private hidebysig static int32 + Main(string[] args) cil managed + { + .entrypoint + // Code size 124 (0x7c) + .maxstack 5 + .locals init (valuetype [System.Runtime]System.RuntimeMethodHandle V_0, + valuetype [System.Runtime]System.RuntimeMethodHandle V_1) + IL_0016: ldtoken method instance string valuetype GenericStruct`1::B() + stloc.0 + + IL_0053: ldtoken valuetype GenericStruct`1 + IL_0058: call class [System.Runtime]System.Type [System.Runtime]System.Type::GetTypeFromHandle(valuetype [System.Runtime]System.RuntimeTypeHandle) + IL_005d: ldstr "B" + IL_0062: call instance class [System.Runtime]System.Reflection.MethodInfo [System.Runtime]System.Type::GetMethod(string) + IL_0067: callvirt instance valuetype [System.Runtime]System.RuntimeMethodHandle [System.Runtime]System.Reflection.MethodBase::get_MethodHandle() + IL_006c: stloc.1 + + IL_006d: ldloca.s V_0 + IL_006f: ldloc.1 + IL_0070: call instance bool [System.Runtime]System.RuntimeMethodHandle::Equals(valuetype [System.Runtime]System.RuntimeMethodHandle) + IL_0075: brtrue.s IL_0079 + + IL_0077: ldc.i4.m1 + IL_0078: ret + + IL_0079: ldc.i4.s 100 + IL_007b: ret + } +} diff --git a/src/tests/Regressions/coreclr/GitHub_41674/genericldtoken.ilproj b/src/tests/Regressions/coreclr/GitHub_41674/genericldtoken.ilproj new file mode 100644 index 00000000000000..6bfc8a43251cfc --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_41674/genericldtoken.ilproj @@ -0,0 +1,10 @@ + + + Exe + BuildAndRun + 0 + + + + +