From 8ef84b4844f4fe520de7a8161026c14d633988fe Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:07:42 +0000 Subject: [PATCH 1/5] Initial plan From 2405c11b9b31016ab198ba5da57ab816ae094a73 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Apr 2026 21:31:14 +0000 Subject: [PATCH 2/5] Fix native memory leak in AsAnyMarshaler.ConvertLayoutToNative Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/33ae7353-2afd-4be1-9081-898caba946da Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> --- .../System.Private.CoreLib/src/System/StubHelpers.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 890bff5ec3c7ec..02a05bb98c2b49 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -1265,9 +1265,17 @@ private unsafe IntPtr ConvertLayoutToNative(object pManagedHome, int dwFlags) IntPtr pNativeHome = Marshal.AllocCoTaskMem(allocSize); // marshal the object as class with layout (UnmanagedType.LPStruct) - if (IsIn(dwFlags)) + try + { + if (IsIn(dwFlags)) + { + StubHelpers.LayoutTypeConvertToUnmanaged(pManagedHome, (byte*)pNativeHome, ref cleanupWorkList); + } + } + catch { - StubHelpers.LayoutTypeConvertToUnmanaged(pManagedHome, (byte*)pNativeHome, ref cleanupWorkList); + Marshal.FreeCoTaskMem(pNativeHome); + throw; } if (IsOut(dwFlags)) { From 7e6b02951dede8088a2b29a2780b358bb04d2d56 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 14 Apr 2026 15:57:27 -0700 Subject: [PATCH 3/5] Apply suggestion from @jkoritzinsky --- src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 02a05bb98c2b49..0693991d3cb753 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -1274,6 +1274,7 @@ private unsafe IntPtr ConvertLayoutToNative(object pManagedHome, int dwFlags) } catch { + StubHelpers.DestroyCleanupList(ref cleanupWorkList); Marshal.FreeCoTaskMem(pNativeHome); throw; } From cb757ba5ad3a2c1d90b9f9d11ef17efa00c41b9d Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 20 Jul 2026 14:07:59 -0700 Subject: [PATCH 4/5] Fix names --- src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 3f6fbca79ea830..62f72e328be307 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -977,13 +977,13 @@ public override unsafe IntPtr ConvertToNative(object managed, int dwFlags) { if (IsIn(dwFlags)) { - StubHelpers.LayoutTypeConvertToUnmanaged(pManagedHome, (byte*)pNativeHome, ref _cleanupWorkList); + StubHelpers.LayoutTypeConvertToUnmanaged(managed, (byte*)pNative, ref _cleanupWorkList); } } catch { StubHelpers.DestroyCleanupList(ref _cleanupWorkList); - Marshal.FreeCoTaskMem(pNativeHome); + Marshal.FreeCoTaskMem(pNative); throw; } From 1c62ca34d02a9bb800c0355949fe8ce32d3e7711 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:45:10 +0000 Subject: [PATCH 5/5] Remove redundant comment and add regression test for exception-path cleanup Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com> --- .../System.Private.CoreLib/src/System/StubHelpers.cs | 1 - src/tests/Interop/PInvoke/AsAny/AsAnyTest.cs | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 62f72e328be307..e5545635ba3172 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -972,7 +972,6 @@ public override unsafe IntPtr ConvertToNative(object managed, int dwFlags) int allocSize = Marshal.SizeOfHelper((RuntimeType)_layoutType, false); IntPtr pNative = Marshal.AllocCoTaskMem(allocSize); - // marshal the object as class with layout (UnmanagedType.LPStruct) try { if (IsIn(dwFlags)) diff --git a/src/tests/Interop/PInvoke/AsAny/AsAnyTest.cs b/src/tests/Interop/PInvoke/AsAny/AsAnyTest.cs index f53a66919e1cf1..d8f68093574de8 100644 --- a/src/tests/Interop/PInvoke/AsAny/AsAnyTest.cs +++ b/src/tests/Interop/PInvoke/AsAny/AsAnyTest.cs @@ -318,6 +318,7 @@ public static int TestEntryPoint() TestIntPtrArray(); TestUIntPtrArray(); TestLayout(); + TestLayoutConvertToNativeExceptionPath(); RunAsAnyFieldTests(); TestUnicodeString(); TestUnicodeStringArray(); @@ -654,6 +655,16 @@ public static void TestLayout() { Console.WriteLine("------------------------"); } + private static void TestLayoutConvertToNativeExceptionPath() + { + // AsAnyField contains a field with [MarshalAs(UnmanagedType.AsAny)], which is not + // supported in layout marshaling. When passed via AsAny, LayoutImplementation.ConvertToNative + // allocates a native buffer and then calls LayoutTypeConvertToUnmanaged, which throws + // TypeLoadException. Verify the exception propagates correctly; the fix ensures the + // native buffer is freed on this exception path rather than leaked. + Assert.Throws(() => PassLayout(new AsAnyField())); + } + static void CharArrayInit(char[] unMappableCharArray_In, char[] unMappableCharArray_InOut, char[] unMappableCharArray_Out, char[] mappableCharArray_In, char[] mappableCharArray_InOut, char[] mappableCharArray_Out, string unMappableStr, string mappableStr)