diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 44797143737284..97bc51539e4c90 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -7148,16 +7148,14 @@ VOID MethodTableBuilder::AllocAndInitMethodDescChunk(COUNT_T startIndex, COUNT_T // and should not be used. We should go to the effort of having proper constructors // in the MethodDesc class. - memcpy(pUnboxedMD, pMD, pMD->SizeOf()); - - // Reset the chunk index - pUnboxedMD->SetChunkIndex(pChunk); - - if (bmtGenerics->GetNumGenericArgs() == 0) { - pUnboxedMD->SetHasNonVtableSlot(); + if (bmtGenerics->GetNumGenericArgs() == 0) + { + memcpy(pUnboxedMD, pMD, pMD->GetBaseSize()); // By settings HasNonVTableSlot, the following chunks of data have been shifted around. // This is an example of the fragility noted in the memcpy comment above + pUnboxedMD->SetHasNonVtableSlot(); + if (pUnboxedMD->HasNativeCodeSlot()) { *pUnboxedMD->GetAddrOfNativeCodeSlot() = *pMD->GetAddrOfNativeCodeSlot(); @@ -7171,6 +7169,13 @@ VOID MethodTableBuilder::AllocAndInitMethodDescChunk(COUNT_T startIndex, COUNT_T *pUnboxedMD->GetAddrOfAsyncMethodData() = *pMD->GetAddrOfAsyncMethodData(); } } + else + { + memcpy(pUnboxedMD, pMD, pMD->SizeOf()); + } + + // Reset the chunk index + pUnboxedMD->SetChunkIndex(pChunk); ////////////////////////////////////////////////////////// // Modify the original MethodDesc to be an unboxing stub diff --git a/src/tests/Regressions/coreclr/GitHub_115667/test115667.cs b/src/tests/Regressions/coreclr/GitHub_115667/test115667.cs new file mode 100644 index 00000000000000..1895a8cfeb6b49 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_115667/test115667.cs @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +using System; +using Xunit; +using System.Threading.Tasks; + +public interface I0 +{ + Task M8(); +} + +public struct S1 : I0 +{ +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously + public async Task M8() +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously + { + return false; + } +} + +public class Runtime_115667 +{ + [Fact] + public static void TestEntryPoint() + { + System.Runtime.Loader.AssemblyLoadContext alc = new CollectibleALC(); + System.Reflection.Assembly asm = alc.LoadFromAssemblyPath(System.Reflection.Assembly.GetExecutingAssembly().Location); + System.Reflection.MethodInfo mi = asm.GetType(typeof(Runtime_115667).FullName).GetMethod(nameof(MainInner)); + System.Type runtimeTy = asm.GetType(typeof(Runtime).FullName); + mi.Invoke(null, new object[] { System.Activator.CreateInstance(runtimeTy) }); + } + + public static void MainInner(IRuntime rt) + { + bool vr1 = new S1().M8().GetAwaiter().GetResult(); + } +} + +public interface IRuntime +{ + void WriteLine(string site, T value); +} + +public class Runtime : IRuntime +{ + public void WriteLine(string site, T value) => System.Console.WriteLine(value); +} + +public class CollectibleALC : System.Runtime.Loader.AssemblyLoadContext +{ + public CollectibleALC() : base(true) + { + } +} diff --git a/src/tests/Regressions/coreclr/GitHub_115667/test115667.csproj b/src/tests/Regressions/coreclr/GitHub_115667/test115667.csproj new file mode 100644 index 00000000000000..d98bb6d39b3624 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_115667/test115667.csproj @@ -0,0 +1,12 @@ + + + True + 1 + + + + + + + + diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 54496d68128d8f..efbbf6e0e5cace 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -952,6 +952,9 @@ https://github.com/dotnet/runtimelab/issues/155: Assembly.Load + + https://github.com/dotnet/runtimelab/issues/155: Assembly.Load + https://github.com/dotnet/runtimelab/issues/155: Reflection.Emit @@ -3064,6 +3067,9 @@ Loads an assembly from file + + Loads an assembly from file +