From cb523b639fee3a5ed9363ace14453a506b9c0692 Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Tue, 9 Jul 2024 16:24:33 -0500 Subject: [PATCH 1/3] Throw InvalidOperationException on RuntimeMethodHandle.GetFunctionPointer() for generic methods --- src/coreclr/vm/method.cpp | 3 +-- .../tests/System.Reflection.Tests/MethodInfoTests.cs | 7 +++++++ src/mono/mono/mini/mini-runtime.c | 5 +++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 628b8c6f6e45dc..d2c459c8204873 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -2013,8 +2013,7 @@ PCODE MethodDesc::TryGetMultiCallableAddrOfCode(CORINFO_ACCESS_FLAGS accessFlags if (IsGenericMethodDefinition()) { - _ASSERTE(!"Cannot take the address of an uninstantiated generic method."); - COMPlusThrow(kInvalidProgramException); + COMPlusThrow(kInvalidOperationException, IDS_EE_CODEEXECUTION_CONTAINSGENERICVAR); } if (accessFlags & CORINFO_ACCESS_LDFTN) diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/MethodInfoTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/MethodInfoTests.cs index c0f95b43425565..bd9a872551ffec 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/MethodInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/MethodInfoTests.cs @@ -306,6 +306,13 @@ public void InvokeUninstantiatedGenericMethod() Assert.Throws(() => GetMethod(typeof(MI_SubClass), nameof(MI_SubClass.StaticGenericMethod)).Invoke(null, [null])); } + [Fact] + public void GetFunctionPointerFromUninstantiatedGenericMethod() + { + RuntimeMethodHandle handle = typeof(MI_SubClass).GetMethod(nameof(MI_SubClass.StaticGenericMethod))!.MethodHandle; + Assert.Throws(() => handle.GetFunctionPointer()); + } + [Fact] public void GetHashCodeTest() { diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 240aa1f8a9b8bc..80c884b3476ff8 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -2938,6 +2938,11 @@ mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error) static gpointer get_ftnptr_for_method (MonoMethod *method, gboolean need_unbox, MonoError *error) { + if (method->is_generic) { + mono_error_set_generic_error (error, "System", "InvalidOperationException", ""); + return NULL; + } + if (!mono_llvm_only) { gpointer res = mono_jit_compile_method (method, error); res = mini_add_method_trampoline (method, res, mono_method_needs_static_rgctx_invoke (method, TRUE), need_unbox); From 50098743704f22ad4604d44179af9f1efab2e617 Mon Sep 17 00:00:00 2001 From: Steve Harter Date: Wed, 10 Jul 2024 18:01:06 -0500 Subject: [PATCH 2/3] Also check if owning type is generic; add checks to mono interpreter --- src/coreclr/vm/method.cpp | 2 +- .../MethodInfoTests.cs | 28 +++++++++++++++++++ src/mono/mono/mini/interp/interp.c | 5 ++++ src/mono/mono/mini/mini-runtime.c | 2 +- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index d2c459c8204873..9a177aee77ba1d 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -2011,7 +2011,7 @@ PCODE MethodDesc::TryGetMultiCallableAddrOfCode(CORINFO_ACCESS_FLAGS accessFlags } CONTRACTL_END - if (IsGenericMethodDefinition()) + if (IsGenericMethodDefinition() || ContainsGenericVariables()) { COMPlusThrow(kInvalidOperationException, IDS_EE_CODEEXECUTION_CONTAINSGENERICVAR); } diff --git a/src/libraries/System.Runtime/tests/System.Reflection.Tests/MethodInfoTests.cs b/src/libraries/System.Runtime/tests/System.Reflection.Tests/MethodInfoTests.cs index bd9a872551ffec..5e791cc2d6dd0d 100644 --- a/src/libraries/System.Runtime/tests/System.Reflection.Tests/MethodInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System.Reflection.Tests/MethodInfoTests.cs @@ -306,6 +306,18 @@ public void InvokeUninstantiatedGenericMethod() Assert.Throws(() => GetMethod(typeof(MI_SubClass), nameof(MI_SubClass.StaticGenericMethod)).Invoke(null, [null])); } + [Fact] + public void InvokeUninstantiatedGenericType_GenericMethod() + { + Assert.Throws(() => GetMethod(typeof(MI_GenericClass<>), "GenericMethod4").Invoke(null, [null])); + } + + [Fact] + public void InvokeUninstantiatedGenericType_NonGenericMethod() + { + Assert.Throws(() => GetMethod(typeof(MI_GenericClass<>), "NonGenericMethod").Invoke(null, [null])); + } + [Fact] public void GetFunctionPointerFromUninstantiatedGenericMethod() { @@ -313,6 +325,20 @@ public void GetFunctionPointerFromUninstantiatedGenericMethod() Assert.Throws(() => handle.GetFunctionPointer()); } + [Fact] + public void GetFunctionPointerOnUninstantiatedGenericType_GenericMethod() + { + RuntimeMethodHandle handle = typeof(MI_GenericClass<>).GetMethod("GenericMethod4")!.MethodHandle; + Assert.Throws(() => handle.GetFunctionPointer()); + } + + [Fact] + public void GetFunctionPointerOnUninstantiatedGenericType_NonGenericMethod() + { + RuntimeMethodHandle handle = typeof(MI_GenericClass<>).GetMethod("NonGenericMethod")!.MethodHandle; + Assert.Throws(() => handle.GetFunctionPointer()); + } + [Fact] public void GetHashCodeTest() { @@ -806,6 +832,8 @@ public class MI_GenericClass public T GenericMethod1(T t) => t; public T GenericMethod2(S s1, T t, string s2) => t; public static S GenericMethod3(S s) => s; + public static T GenericMethod4(T s) => s; + public static void NonGenericMethod() { } } public interface MethodInfoBaseDefinitionInterface diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 3728c995e9dd96..ef2d39632b6691 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -7474,6 +7474,11 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MonoMethod *local_cmethod = LOCAL_VAR (ip [2], MonoMethod*); + if (local_cmethod->is_generic || mono_class_is_gtd (local_cmethod->klass)) { + MonoException *ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidOperationException", ""); + THROW_EX (ex, ip); + } + // FIXME push/pop LMF if (G_UNLIKELY (mono_method_has_unmanaged_callers_only_attribute (local_cmethod))) { local_cmethod = mono_marshal_get_managed_wrapper (local_cmethod, NULL, (MonoGCHandle)0, error); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 80c884b3476ff8..7bfa6bb3e69311 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -2938,7 +2938,7 @@ mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error) static gpointer get_ftnptr_for_method (MonoMethod *method, gboolean need_unbox, MonoError *error) { - if (method->is_generic) { + if (method->is_generic || mono_class_is_gtd (method->klass)) { mono_error_set_generic_error (error, "System", "InvalidOperationException", ""); return NULL; } From 6587d99a366ff29d48281712eb7a292ff636b5a9 Mon Sep 17 00:00:00 2001 From: Buyaa Namnan Date: Thu, 11 Jul 2024 13:27:29 -0700 Subject: [PATCH 3/3] Update src/coreclr/vm/method.cpp --- src/coreclr/vm/method.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 9a177aee77ba1d..8fa55e0db9a511 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -2011,7 +2011,7 @@ PCODE MethodDesc::TryGetMultiCallableAddrOfCode(CORINFO_ACCESS_FLAGS accessFlags } CONTRACTL_END - if (IsGenericMethodDefinition() || ContainsGenericVariables()) + if (ContainsGenericVariables()) { COMPlusThrow(kInvalidOperationException, IDS_EE_CODEEXECUTION_CONTAINSGENERICVAR); }