diff --git a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs index efa2b1018688ea..aefee9b9f9f732 100644 --- a/src/coreclr/tools/ILVerification/ILImporter.Verify.cs +++ b/src/coreclr/tools/ILVerification/ILImporter.Verify.cs @@ -2582,6 +2582,8 @@ void ImportLocalAlloc() var size = Pop(); + Check(_stackTop == 0, VerifierError.LocallocStackNotEmpty); + CheckIsInteger(size); Push(StackValue.CreatePrimitive(StackValueKind.NativeInt)); diff --git a/src/coreclr/tools/ILVerification/Strings.resx b/src/coreclr/tools/ILVerification/Strings.resx index 726cf6dd46c029..e38b197837b4a4 100644 --- a/src/coreclr/tools/ILVerification/Strings.resx +++ b/src/coreclr/tools/ILVerification/Strings.resx @@ -447,4 +447,7 @@ Class implements interface but not method, Class: '{0}' Interface: '{1}' Missing method: '{2}'. + + Stack must be empty before localloc, except for the size item. + diff --git a/src/coreclr/tools/ILVerification/VerifierError.cs b/src/coreclr/tools/ILVerification/VerifierError.cs index 4be09b1ce0213f..2d237aa9c5b083 100644 --- a/src/coreclr/tools/ILVerification/VerifierError.cs +++ b/src/coreclr/tools/ILVerification/VerifierError.cs @@ -190,6 +190,7 @@ public enum VerifierError //IDS_E_GLOBAL "" //IDS_E_MDTOKEN "[mdToken=0x%x]" InterfaceImplHasDuplicate, // InterfaceImpl has a duplicate - InterfaceMethodNotImplemented // Class implements interface but not method + InterfaceMethodNotImplemented, // Class implements interface but not method + LocallocStackNotEmpty, // localloc requires that stack must be empty, except for 'size' argument } } diff --git a/src/tests/ilverify/ILTests/DefaultInterfaceMethod.il b/src/tests/ilverify/ILTests/DefaultInterfaceMethod.il index a33f5cdddbe7c2..afd4f59d21e866 100644 --- a/src/tests/ilverify/ILTests/DefaultInterfaceMethod.il +++ b/src/tests/ilverify/ILTests/DefaultInterfaceMethod.il @@ -107,7 +107,7 @@ } } -.class public auto ansi beforefieldinit ChildClassInheritsFromInterfaceWithDefaultImplementationWhereChildInterfaceReabstractsInterfaceMethod_InvalidType_InterfaceMethodNotImplemented +.class public auto ansi beforefieldinit ChildClassInheritsFromInterfaceWithDefaultImplementationWhereChildInterfaceReabstractsInterfaceMethod_InvalidType_InterfaceMethodNotImplemented@InterfaceMethodNotImplemented extends [System.Runtime]System.Object implements IReabstractDefaultImplementation, IInheritedDefaultImplInterface, IInterface { diff --git a/src/tests/ilverify/ILTests/LocalAllocTests.il b/src/tests/ilverify/ILTests/LocalAllocTests.il new file mode 100644 index 00000000000000..5789906868b1f8 --- /dev/null +++ b/src/tests/ilverify/ILTests/LocalAllocTests.il @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +.assembly extern System.Runtime +{ +} + +.assembly extern LocalAllocTestsFriend +{ +} + +.assembly LocalAllocTests +{ +} + +.class public auto ansi beforefieldinit LocAllocTests + extends [System.Runtime]System.Object +{ + .method private hidebysig instance void Load.LocAllocShouldFailWhenStackNotEmpty_Invalid_Unverifiable.LocallocStackNotEmpty() cil managed + { + ldnull // pretend there's meaningfull value on stack + ldc.i4.2 // size parameter for localloc + localloc + pop // pop localloc pointer + pop // pop ldnull + ret + } + + .method private hidebysig instance void Load.LocAllocShouldFailWhenSizeIsAbsent_Invalid_Unverifiable.StackUnderflow() cil managed + { + localloc + pop // pop localloc pointer + ret + } + + .method private hidebysig instance void Load.LocAllocShouldSuccesWhenSizeIsPresent_Invalid_Unverifiable() cil managed + { + ldc.i4.2 // size parameter for localloc + localloc + pop // pop localloc pointer + ret + } +} diff --git a/src/tests/ilverify/ILTests/LocalAllocTests.ilproj b/src/tests/ilverify/ILTests/LocalAllocTests.ilproj new file mode 100644 index 00000000000000..8e8765d14a524d --- /dev/null +++ b/src/tests/ilverify/ILTests/LocalAllocTests.ilproj @@ -0,0 +1,3 @@ + + +