Handle crash when [out] parameter of type int is passed to delegate (#81276)
authorGiridhar Trivedi <giritrivedi@gmail.com>
Wed, 8 Feb 2023 16:45:44 +0000 (22:15 +0530)
committerGitHub <noreply@github.com>
Wed, 8 Feb 2023 16:45:44 +0000 (11:45 -0500)
When a delegate is passed an [out] parameter of type "int" 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 "int"
is handled after adding an addition case statement to handle MONO_TYPE_I
in emit_managed_wrapper_ilgen. Supporting UT is added.

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

index 2b8c321..eff038a 100644 (file)
@@ -2630,6 +2630,7 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s
                        case MONO_TYPE_CLASS:
                        case MONO_TYPE_VALUETYPE:
                        case MONO_TYPE_PTR:
+                       case MONO_TYPE_I:
                                mono_emit_marshal (m, i, invoke_sig->params [i], mspecs [i + 1], tmp_locals [i], NULL, MARSHAL_ACTION_MANAGED_CONV_OUT);
                                break;
                        default:
index b920b91..e8d4e72 100644 (file)
@@ -16,6 +16,9 @@ public partial class FunctionPtr
 
         [DllImport(nameof(FunctionPointerNative))]
         static unsafe extern void FillOutPtr(IntPtr* p);
+
+       [DllImport(nameof(FunctionPointerNative))]
+       static unsafe extern void FillOutIntParameter(out IntPtr p);
     }
 
     delegate void VoidDelegate();
@@ -81,6 +84,27 @@ public partial class FunctionPtr
         Assert.Equal(expectedValue, outVar);
     }
 
+    [DllImport(nameof(FunctionPointerNative))]
+    static unsafe extern void FillOutIntParameter(out IntPtr p);
+
+    private unsafe delegate void DelegateToFillOutIntParameter(out IntPtr p);
+
+    public static void RunGetDelForOutIntTest()
+    {
+        Console.WriteLine($"Running {nameof(RunGetDelForOutIntTest)}...");
+        IntPtr outVar = 0;
+        int expectedValue = 50;
+        unsafe
+        {
+            DelegateToFillOutIntParameter d = new DelegateToFillOutIntParameter(FillOutIntParameter);
+            IntPtr ptr = Marshal.GetFunctionPointerForDelegate(d);
+            DelegateToFillOutIntParameter OutPtrDelegate = Marshal.GetDelegateForFunctionPointer<DelegateToFillOutIntParameter>(ptr);
+            OutPtrDelegate(out outVar);
+            GC.KeepAlive(d);
+        }
+        Assert.Equal(expectedValue, outVar);
+    }
+
     public static int Main()
     {
         try
@@ -88,6 +112,7 @@ public partial class FunctionPtr
             RunGetDelForFcnPtrTest();
             RunGetFcnPtrSingleMulticastTest();
             RunGetDelForOutPtrTest();
+            RunGetDelForOutIntTest();
         }
         catch (Exception e)
         {
index 9056f9a..e19d5f1 100644 (file)
@@ -35,3 +35,9 @@ extern "C" DLL_EXPORT void FillOutPtr(intptr_t *p)
 {
     *p = 60;
 }
+
+extern "C" DLL_EXPORT void FillOutIntParameter(intptr_t *p)
+{
+    *p = 50;
+}
+