diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs index 86c3112a2992ba..8a29c9de0bb128 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs @@ -1073,9 +1073,9 @@ public static bool MethodILIsStripped(string msilFilePath, string declaringType, if (!TryGetMethodIL(msilFilePath, declaringType, methodName, out byte[] il, out diagnostic)) return false; - bool stripped = il.AsSpan().SequenceEqual((ReadOnlySpan)[0x14, 0x7A]); + bool stripped = il.AsSpan().SequenceEqual((ReadOnlySpan)[0xFE, 0x24]); diagnostic = stripped - ? $"IL of '{declaringType}.{methodName}' is stripped (ldnull; throw)." + ? $"IL of '{declaringType}.{methodName}' is stripped (invalid opcode 0xFE 0x24)." : $"Expected IL of '{declaringType}.{methodName}' to be stripped, but it is present ({il.Length} bytes: {BitConverter.ToString(il)})."; return stripped; } @@ -1088,10 +1088,10 @@ public static bool MethodILIsPresent(string msilFilePath, string declaringType, if (!TryGetMethodIL(msilFilePath, declaringType, methodName, out byte[] il, out diagnostic)) return false; - bool present = !il.AsSpan().SequenceEqual((ReadOnlySpan)[0x14, 0x7A]); + bool present = !il.AsSpan().SequenceEqual((ReadOnlySpan)[0xFE, 0x24]); diagnostic = present ? $"IL of '{declaringType}.{methodName}' is present ({il.Length} bytes)." - : $"Expected IL of '{declaringType}.{methodName}' to be present, but it was stripped (ldnull; throw)."; + : $"Expected IL of '{declaringType}.{methodName}' to be present, but it was stripped (invalid opcode 0xFE 0x24)."; return present; } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMethodILNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMethodILNode.cs index ab0d5c17ca6952..787abe81061470 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMethodILNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/CopiedMethodILNode.cs @@ -14,9 +14,9 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun { public class CopiedMethodILNode : ObjectNode, ISymbolDefinitionNode { - // Throws NullReferenceException if the stripped body is encountered. - // Tiny header (0x0A: 2 bytes code size) + ldnull (0x14) + throw (0x7A). - private static readonly byte[] s_minimalILBody = [0x0A, 0x14, 0x7A]; + // Sentinel body for stripped IL methods: tiny header (0x0A) + invalid opcode 0xFE 0x24. + // Invalid IL so it can never collide with a real method body. + private static readonly byte[] s_minimalILBody = [0x0A, 0xFE, 0x24]; EcmaMethod _method; diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 5cbd48e096b05b..0121ec3b946bdd 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -725,6 +725,17 @@ namespace if (status == COR_ILMETHOD_DECODER::FORMAT_ERROR) COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL); + Module* pModule = pMD->GetModule(); + if (pModule->IsReadyToRun() + && pModule->GetReadyToRunInfo()->HasStrippedILBodies() + && pHeader->GetCodeSize() == 2 + && pHeader->Code[0] == 0xFE + && pHeader->Code[1] == 0x24) + { + EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, + W("A method body required at runtime was stripped from the ReadyToRun image.")); + } + return pHeader; }