Handle crash when [out] parameter of type Intptr* is passed to delegate (#79763)
authorGiridhar Trivedi <giritrivedi@gmail.com>
Tue, 10 Jan 2023 03:03:23 +0000 (08:33 +0530)
committerGitHub <noreply@github.com>
Tue, 10 Jan 2023 03:03:23 +0000 (22:03 -0500)
When a delegate is passed an [out] parameter of type "intptr *"
it will crash since this data type is not handled in
emit_managed_wrapper_ilgen. This will lead to a crash.
With this fix [out] parameter of type "Intptr *" is handled
after adding an addition case statement to handle MONO_TYPE_PTR
in emit_managed_wrapper_ilgen.

Co-authored-by: Giridhar Trivedi <giridhar.trivedi@in.ibm.com>
src/mono/mono/metadata/marshal-lightweight.c
src/tests/Interop/MarshalAPI/FunctionPointer/FunctionPointer.cs
src/tests/Interop/MarshalAPI/FunctionPointer/FunctionPointerNative.cpp
src/tests/Interop/MarshalAPI/FunctionPointer/FunctionPtrTest.csproj

index 072ddf5..2b8c321 100644 (file)
@@ -2629,6 +2629,7 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s
                        case MONO_TYPE_SZARRAY:
                        case MONO_TYPE_CLASS:
                        case MONO_TYPE_VALUETYPE:
+                       case MONO_TYPE_PTR:
                                mono_emit_marshal (m, i, invoke_sig->params [i], mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
                                break;
                        default:
index 34e075a..eff4068 100644 (file)
@@ -13,6 +13,9 @@ public partial class FunctionPtr
 
         [DllImport(nameof(FunctionPointerNative))]
         public static extern bool CheckFcnPtr(IntPtr fcnptr);
+
+        [DllImport(nameof(FunctionPointerNative))]
+        static unsafe extern void FillOutPtr(IntPtr* p);
     }
 
     delegate void VoidDelegate();
@@ -56,12 +59,34 @@ public partial class FunctionPtr
         }
     }
 
+
+    [DllImport(nameof(FunctionPointerNative))]
+    static unsafe extern void FillOutPtr(IntPtr* p);
+
+    private unsafe delegate void DelegateToFillOutPtr([Out] IntPtr* p);
+
+    public static void RunGetDelForOutPtrTest()
+    {
+        Console.WriteLine($"Running {nameof(RunGetDelForOutPtrTest)}...");
+        IntPtr outVar = 0;
+        int expectedValue = 60;
+        unsafe
+        {
+            DelegateToFillOutPtr d = new DelegateToFillOutPtr(FillOutPtr);
+            IntPtr ptr = Marshal.GetFunctionPointerForDelegate(d);
+            DelegateToFillOutPtr OutPtrDelegate = Marshal.GetDelegateForFunctionPointer<DelegateToFillOutPtr>(ptr);
+            OutPtrDelegate(&outVar);
+        }
+        Assert.Equal(expectedValue, outVar);
+    }
+
     public static int Main()
     {
         try
         {
             RunGetDelForFcnPtrTest();
             RunGetFcnPtrSingleMulticastTest();
+            RunGetDelForOutPtrTest();
         }
         catch (Exception e)
         {
index 378a418..9056f9a 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <xplatform.h>
 #include <platformdefines.h>
+#include <stdint.h>
 
 namespace
 {
@@ -29,3 +30,8 @@ extern "C" DLL_EXPORT bool CheckFcnPtr(bool(STDMETHODCALLTYPE *fcnptr)(long long
         return fcnptr(999999999999);
     }
 }
+
+extern "C" DLL_EXPORT void FillOutPtr(intptr_t *p)
+{
+    *p = 60;
+}
index 38d1a61..a69510f 100644 (file)
@@ -1,6 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <OutputType>Exe</OutputType>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="*.cs" />