From 5d9f76f4815f8c2c178b76f1bc6644363d6df2d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Bourbonnais?= Date: Thu, 17 Dec 2020 13:17:17 -0500 Subject: [PATCH 1/2] Fix illegal delegate usage Cache the delegates to native code we've created so that when we need to call that delegate, we don't ask for a delegate from a native pointer (that is a delegate to managed code.) --- src/runtime/interop.cs | 4 ++++ src/runtime/managedtype.cs | 7 ++++--- src/runtime/nativecall.cs | 11 ++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 10b6ee476..ff9a98622 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -491,6 +491,9 @@ internal static Type GetPrototype(string name) return pmap[name] as Type; } + + internal static Dictionary allocatedThunks = new Dictionary(); + internal static ThunkInfo GetThunk(MethodInfo method, string funcType = null) { Type dt; @@ -505,6 +508,7 @@ internal static ThunkInfo GetThunk(MethodInfo method, string funcType = null) } Delegate d = Delegate.CreateDelegate(dt, method); var info = new ThunkInfo(d); + allocatedThunks[info.Address] = d; return info; } diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index 87a89b00a..b4baef835 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -178,7 +178,7 @@ internal static int PyVisit(IntPtr ob, IntPtr visit, IntPtr arg) { return 0; } - var visitFunc = (Interop.ObjObjFunc)Marshal.GetDelegateForFunctionPointer(visit, typeof(Interop.ObjObjFunc)); + var visitFunc = NativeCall.GetDelegate(visit); return visitFunc(ob, arg); } @@ -196,7 +196,7 @@ internal void CallTypeClear() { return; } - var clearFunc = (Interop.InquiryFunc)Marshal.GetDelegateForFunctionPointer(clearPtr, typeof(Interop.InquiryFunc)); + var clearFunc = NativeCall.GetDelegate(clearPtr); clearFunc(pyHandle); } @@ -214,7 +214,8 @@ internal void CallTypeTraverse(Interop.ObjObjFunc visitproc, IntPtr arg) { return; } - var traverseFunc = (Interop.ObjObjArgFunc)Marshal.GetDelegateForFunctionPointer(traversePtr, typeof(Interop.ObjObjArgFunc)); + var traverseFunc = NativeCall.GetDelegate(traversePtr); + var visiPtr = Marshal.GetFunctionPointerForDelegate(visitproc); traverseFunc(pyHandle, visiPtr, arg); } diff --git a/src/runtime/nativecall.cs b/src/runtime/nativecall.cs index e33eb1c81..8bd5a15f2 100644 --- a/src/runtime/nativecall.cs +++ b/src/runtime/nativecall.cs @@ -40,10 +40,15 @@ public static int Int_Call_3(IntPtr fp, IntPtr a1, IntPtr a2, IntPtr a3) return d(a1, a2, a3); } - private static T GetDelegate(IntPtr fp) where T: Delegate + internal static T GetDelegate(IntPtr fp) where T: Delegate { - // Use Marshal.GetDelegateForFunctionPointer<> directly after upgrade the framework - return (T)Marshal.GetDelegateForFunctionPointer(fp, typeof(T)); + Delegate d = null; + if (!Interop.allocatedThunks.TryGetValue(fp, out d)) + { + // Use Marshal.GetDelegateForFunctionPointer<> directly after upgrade the framework + d = Marshal.GetDelegateForFunctionPointer(fp, typeof(T)); + } + return (T)d; } } } From 1325f5929bd84ca5da482cceeabdead351d39157 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Bourbonnais?= Date: Fri, 18 Dec 2020 10:44:39 -0500 Subject: [PATCH 2/2] Use the generic method --- src/runtime/nativecall.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/nativecall.cs b/src/runtime/nativecall.cs index 8bd5a15f2..60259dcd0 100644 --- a/src/runtime/nativecall.cs +++ b/src/runtime/nativecall.cs @@ -45,8 +45,8 @@ internal static T GetDelegate(IntPtr fp) where T: Delegate Delegate d = null; if (!Interop.allocatedThunks.TryGetValue(fp, out d)) { - // Use Marshal.GetDelegateForFunctionPointer<> directly after upgrade the framework - d = Marshal.GetDelegateForFunctionPointer(fp, typeof(T)); + // We don't cache this delegate because this is a pure delegate ot unmanaged. + d = Marshal.GetDelegateForFunctionPointer(fp); } return (T)d; }