From d6c2b4385305c8fda2d8e4290228f9b83005e192 Mon Sep 17 00:00:00 2001 From: Fan Yang <52458914+fanyang-mono@users.noreply.github.com> Date: Mon, 23 Jan 2023 17:14:06 -0500 Subject: [PATCH] [Mono] Fix function pointer check (#80855) * Fix function pointer check * Make is_monomorphic_array return false when the element is function pointer * Move test to a better location --- src/mono/mono/metadata/class.c | 10 ++-- src/mono/mono/metadata/marshal.c | 2 + .../classloader/Casting/Functionpointer.cs | 46 +++++++++++++++++++ .../Casting/Functionpointer.csproj | 9 ++++ 4 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 src/tests/Loader/classloader/Casting/Functionpointer.cs create mode 100644 src/tests/Loader/classloader/Casting/Functionpointer.csproj diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 3a04a9dee77..0491ce5f3a1 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -4242,11 +4242,11 @@ mono_class_is_assignable_from_general (MonoClass *klass, MonoClass *oklass, gboo } if (m_class_get_byval_arg (klass)->type == MONO_TYPE_FNPTR) { - /* - * if both klass and oklass are fnptr, and they're equal, we would have returned at the - * beginning. - */ - /* Is this right? or do we need to look at signature compatibility? */ + if (mono_metadata_signature_equal (klass_byval_arg->data.method, oklass_byval_arg->data.method)) { + *result = TRUE; + return; + } + *result = FALSE; return; } diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index bca051413a6..5ab899e032d 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -4693,6 +4693,8 @@ is_monomorphic_array (MonoClass *klass) return FALSE; element_class = m_class_get_element_class (klass); + if (m_class_get_byval_arg (element_class)->type == MONO_TYPE_FNPTR) + return FALSE; return mono_class_is_sealed (element_class) || m_class_is_valuetype (element_class); } diff --git a/src/tests/Loader/classloader/Casting/Functionpointer.cs b/src/tests/Loader/classloader/Casting/Functionpointer.cs new file mode 100644 index 00000000000..95d7bf33b13 --- /dev/null +++ b/src/tests/Loader/classloader/Casting/Functionpointer.cs @@ -0,0 +1,46 @@ +using System; +using System.Runtime.InteropServices; + +namespace TestFunctionPointer +{ + unsafe class TestThings + { + public static delegate* managed[][] Functions = { + new delegate* managed[] + { + &Function, + }, + }; + + public static int Function() => 100; + + public static delegate* unmanaged[][] Functions1 = { + new delegate* unmanaged[] + { + &Function1, + }, + }; + + [UnmanagedCallersOnly] + public static int Function1() => 100; + + public static delegate* managed[][] Functions2 = { + new delegate* managed[] + { + &Function2, + }, + }; + + public static int Function2(int a) { + return a; + } + } + + unsafe class Program + { + public static int Main() + { + return TestThings.Functions2[0][0](TestThings.Functions[0][0]()); + } + } +} \ No newline at end of file diff --git a/src/tests/Loader/classloader/Casting/Functionpointer.csproj b/src/tests/Loader/classloader/Casting/Functionpointer.csproj new file mode 100644 index 00000000000..51f7075c49c --- /dev/null +++ b/src/tests/Loader/classloader/Casting/Functionpointer.csproj @@ -0,0 +1,9 @@ + + + Exe + true + + + + + \ No newline at end of file -- GitLab