Skip to content

Conversation

@lambdageek
Copy link
Member

Fixes #42917

@lambdageek
Copy link
Member Author

lambdageek commented Sep 30, 2020

With this PR the output from Mono is now

typeof(delegate*<int>):				System.MonoFNPtrFakeClass
typeof(delegate*<int>[]:			System.MonoFNPtrFakeClass[]
typeof(delegate*<int>*):			System.MonoFNPtrFakeClass*
typeof(delegate*<int>[]).GetElementType():	System.MonoFNPtrFakeClass

Methods on Foo:
Void Method(System.MonoFNPtrFakeClass)
 System.MonoFNPtrFakeClass
Void Method(System.MonoFNPtrFakeClass)
 System.MonoFNPtrFakeClass

Compare with CoreCLR which outputs System.IntPtr and fnptr in various places (see https://twitter.com/MStrehovsky/status/1311247635756412928/photo/2)


I'm going to take take a look over the rest of our code to see if there's a MONO_TYPE_FNPTR case missing elsewhere.

@ghost
Copy link

ghost commented Sep 30, 2020

Tagging subscribers to this area: @CoffeeFlux
See info in area-owners.md if you want to be subscribed.

@lambdageek
Copy link
Member Author

lambdageek commented Oct 1, 2020

Grepped through the Mono code for MONO_TYPE_PTR and looked to see if there was a MONO_TYPE_FNPTR case nearby.

There are a few places where we could do better, but I don't think we'd crash:

  • in the debugger-agent, buffer_add_value_full and buffer_add_fixed_array and some other places don't handle function pointers and they end up in NOT_IMPLEMENTED which won't crash the runtime.

Some that I'm not sure about:

  • interpreter build_args_from_sig doesn't have a FNPTR case and asserts.
  • dwarfwriter get_type_die returns I4 for a fnptr (for regular pointers it returns I)
  • dwarfwriter emit_type doesn't emit anything for fnptr (but also doesn't emit anythign for ptr)
  • AOT compiler encode_type doesn't have a FNPTR case and asserts
  • mini-runtime create_runtime_invoke_info doesn't have a FNPTR case and asserts
  • object.c invoke_array_extract_argument doesn't have a FNPTR case and asserts
  • SRE encode_type doesn't know how to encode a FNPTR type and will assert

A few that might cause problems:

  • object.c mono_field_get_value_object_checked doesn't have a FNPTR case and asserts
  • marshal-ilgen.c I think struct marshalling probably has missing cases, which will assert
  • RuntimeFieldInfo.SetValueInternal doesn't have a case for FNPTR and will assert
  • inflate_generic_type doesn't have a FNPTR case and so doesn't inflate delegate *<S,T> where S and T are generic parameters. This one seems bad, but creating some generic struct with a fnptr field and using it seems to work:
    public unsafe struct S<T> {
       public delegate *<T,T> fptr;
    }
    static int F (S<int> s, int x) => s.fptr (x);
    ...
    {
       S<int> s;
       s.fptr = &IntHelper.TimesTwo;
       Console.WriteLine (F (s, 42)); // prints 84, as expected
    }

@lambdageek lambdageek merged commit b51aba4 into dotnet:master Oct 2, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 7, 2020
@lambdageek lambdageek deleted the fix-gh-42917 branch March 19, 2022 16:45
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[mono] typeof(delegate*<...>) crashes the runtime

4 participants