Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions src/coreclr/tools/ILVerification.Tests/ILMethodTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,32 @@ public static void TestMethodsWithInvalidIL(InvalidILTestCase invalidIL)
}
}

private static IEnumerable<VerificationResult> Verify(TestCase testCase)
[Theory(DisplayName = "")]
[MemberData(nameof(TestDataLoader.GetMethodsForValidationOnlyMode), MemberType = typeof(TestDataLoader))]
[Trait("", "Validation-only IL Tests")]
public static void TestMethodsInValidationOnlyMode(ValidationOnlyTestCase testCase)
{
// Unlike verification, validation must not throw for invalid IL, so exceptions are not caught here.
var results = Verify(testCase, validationOnly: true).ToList();
var actual = string.Join(",", results.Select(e => e.Code.ToString()));

Assert.True(testCase.ExpectedVerifierErrors.Count == results.Count, $"Actual errors were: {actual}");
foreach (var item in testCase.ExpectedVerifierErrors)
{
Assert.True(results.Any(r => r.Code == item), $"Actual errors were: {actual}");
}
}

private static IEnumerable<VerificationResult> Verify(TestCase testCase, bool validationOnly = false)
{
EcmaModule module = TestDataLoader.GetModuleForTestAssembly(testCase.ModuleName, allowIgnoresAccessChecksTo: true);
var methodHandle = (MethodDefinitionHandle) MetadataTokens.EntityHandle(testCase.MetadataToken);
var method = module.GetMethod(methodHandle);
var verifier = new Verifier((ILVerifyTypeSystemContext)method.Context, new VerifierOptions
{
IncludeMetadataTokensInErrorMessages = true,
SanityChecks = true
SanityChecks = true,
ValidationOnly = validationOnly
});

return verifier.Verify(module.PEReader, methodHandle);
Expand Down
111 changes: 108 additions & 3 deletions src/coreclr/tools/ILVerification.Tests/ILTests/BranchingTests.il
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
IL_0014: ret
}

.method static public hidebysig void Branching.NullConditional_Invalid_StackUnexpected() cil managed
.method static public hidebysig void Branching.NullConditional_Invalid_StackUnexpected_Validation_Valid() cil managed
{
//object o = null;
//Type t = o != null ? o.GetType() : o;
Expand Down Expand Up @@ -175,7 +175,7 @@
ret
}

.method static public hidebysig void Branching.UnequalStackMergeArrays_Invalid_StackUnexpected(class CustomComparer[] comparers,
.method static public hidebysig void Branching.UnequalStackMergeArrays_Invalid_StackUnexpected_Validation_Valid(class CustomComparer[] comparers,
class [System.Runtime]System.Collections.IEqualityComparer[] customComparer) cil managed
{
.maxstack 1
Expand Down Expand Up @@ -949,7 +949,7 @@
ret
}

.method static public hidebysig void Branch.BackwardWithoutPredecessor_Invalid_BackwardBranch() cil managed
.method static public hidebysig void Branch.BackwardWithoutPredecessor_Invalid_BackwardBranch_Validation_Valid() cil managed
{
br MethodEnd

Expand Down Expand Up @@ -1078,4 +1078,109 @@
pop
ret
}

// A block whose only errors make the IL unverifiable still passes its stack on, so ret in the next block is checked.

.method static public hidebysig int32 Propagate.AfterLocalloc_Invalid_Unverifiable.ReturnMissing_Validation_ReturnMissing() cil managed
{
ldc.i4.8
localloc
pop
br.s Next

Next:
ret
}

.method static public hidebysig int32 Propagate.AfterCalli_Invalid_Unverifiable.ReturnMissing_Validation_ReturnMissing(method void *() f) cil managed
{
ldarg.0
calli void()
br.s Next

Next:
ret
}

.method static public hidebysig int32 Propagate.AfterInitLocals_Invalid_InitLocals.ReturnMissing_Validation_ReturnMissing() cil managed
{
.locals (int32 V_0)
ldloc.0
pop
br.s Next

Next:
ret
}

.method static public hidebysig int32 Propagate.AfterElementAddressType_Invalid_StackUnexpectedArrayType.ReturnMissing_Validation_ReturnMissing(int32[] a) cil managed
{
ldarg.0
ldc.i4.0
ldelema [System.Runtime]System.Int64
pop
br.s Next

Next:
ret
}

.method static public hidebysig int32 Propagate.AfterPointeeType_Invalid_StackUnexpected.ReturnMissing_Validation_ReturnMissing(int64& p) cil managed
{
ldarg.0
ldind.i4
pop
br.s Next

Next:
ret
}

// ldind.ref and ldelem.ref through a non-reference type push that type, so the next block is not checked.

.method static public hidebysig object Propagate.StopAfterLoadIndirectRef_Invalid_StackUnexpected_Validation_Valid(int32& p) cil managed
{
ldarg.0
ldind.ref
br.s Next

Next:
ret
}

.method static public hidebysig object Propagate.StopAfterLoadElementRef_Invalid_StackUnexpected_Validation_Valid(int32[] a) cil managed
{
ldarg.0
ldc.i4.0
ldelem.ref
br.s Next

Next:
ret
}

.method static public hidebysig int32 Propagate.StopAfterInvalid_Invalid_StackUnexpected() cil managed
{
.locals init (int32 V_0)
ldnull
stloc.0
br.s Next

Next:
ret
}

.method static public hidebysig int32 Propagate.StopAfterUnverifiableAndInvalid_Invalid_Unverifiable.StackUnexpected_Validation_StackUnexpected() cil managed
{
.locals init (int32 V_0)
ldc.i4.8
localloc
pop
ldnull
stloc.0
br.s Next

Next:
ret
}
}
6 changes: 3 additions & 3 deletions src/coreclr/tools/ILVerification.Tests/ILTests/CallTests.il
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
ret
}

.method public hidebysig instance void Call.BaseMethodModThisLdarga_Invalid_ThisMismatch() cil managed
.method public hidebysig instance void Call.BaseMethodModThisLdarga_Invalid_ThisMismatch_Validation_Valid() cil managed
{
ldarg.0
call instance void SimpleClass::VirtualMethod()
Expand All @@ -63,7 +63,7 @@
ret
}

.method public hidebysig instance void Call.BaseMethodModThisStarg_Invalid_ThisMismatch() cil managed
.method public hidebysig instance void Call.BaseMethodModThisStarg_Invalid_ThisMismatch_Validation_Valid() cil managed
{
ldarg.0
call instance void SimpleClass::VirtualMethod()
Expand Down Expand Up @@ -128,7 +128,7 @@
ret
}

.method public hidebysig instance void Call.ExternBaseMethod_Invalid_ThisMismatch(class DerivedClass c) cil managed
.method public hidebysig instance void Call.ExternBaseMethod_Invalid_ThisMismatch_Validation_Valid(class DerivedClass c) cil managed
{
ldarg.1
call instance void SimpleClass::VirtualMethod()
Expand Down
34 changes: 17 additions & 17 deletions src/coreclr/tools/ILVerification.Tests/ILTests/CalliTests.il
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,22 @@
ret
}

.method public hidebysig static void Calli.StaticFromLdftn_Invalid_Unverifiable() cil managed
.method public hidebysig static void Calli.StaticFromLdftn_Invalid_Unverifiable_Validation_Valid() cil managed
{
ldc.i4.1
ldftn void CalliTests::StaticTarget(int32)
calli void(int32)
ret
}

.method public hidebysig static int32 Calli.ReturnValue_Invalid_Unverifiable() cil managed
.method public hidebysig static int32 Calli.ReturnValue_Invalid_Unverifiable_Validation_Valid() cil managed
{
ldftn int32 CalliTests::ReturnsInt32()
calli int32()
ret
}

.method public hidebysig static void Calli.ErrorAfterCalli_Invalid_Unverifiable.StackUnderflow() cil managed
.method public hidebysig static void Calli.ErrorAfterCalli_Invalid_Unverifiable.StackUnderflow_Validation_StackUnderflow() cil managed
{
ldc.i4.1
ldftn void CalliTests::StaticTarget(int32)
Expand All @@ -59,31 +59,31 @@
ret
}

.method public hidebysig static void Calli.FromArgument_Invalid_Unverifiable(method void *(int32) f) cil managed
.method public hidebysig static void Calli.FromArgument_Invalid_Unverifiable_Validation_Valid(method void *(int32) f) cil managed
{
ldc.i4.1
ldarg.0
calli void(int32)
ret
}

.method public hidebysig static void Calli.ArgumentMismatch_Invalid_Unverifiable.StackUnexpected(method void *(int32) f) cil managed
.method public hidebysig static void Calli.ArgumentMismatch_Invalid_Unverifiable.StackUnexpected_Validation_StackUnexpected(method void *(int32) f) cil managed
{
ldnull
ldarg.0
calli void(int32)
ret
}

.method public hidebysig static void Calli.MethodPointerNotNativeInt_Invalid_Unverifiable.StackMethod() cil managed
.method public hidebysig static void Calli.MethodPointerNotNativeInt_Invalid_Unverifiable.StackMethod_Validation_StackMethod() cil managed
{
ldc.i4.1
ldc.i4.0
calli void(int32)
ret
}

.method public hidebysig instance void Calli.ImplicitThis_Invalid_Unverifiable(method instance void *(int32) f) cil managed
.method public hidebysig instance void Calli.ImplicitThis_Invalid_Unverifiable_Validation_Valid(method instance void *(int32) f) cil managed
{
ldarg.0
ldc.i4.1
Expand All @@ -92,7 +92,7 @@
ret
}

.method public hidebysig instance void Calli.ExplicitThis_Invalid_Unverifiable() cil managed
.method public hidebysig instance void Calli.ExplicitThis_Invalid_Unverifiable_Validation_Valid() cil managed
{
ldarg.0
ldc.i4.1
Expand All @@ -102,22 +102,22 @@
}

// A vararg call site with no extra arguments has no sentinel.
.method public hidebysig static void Calli.Vararg_Invalid_Unverifiable(method vararg void *(int32) f) cil managed
.method public hidebysig static void Calli.Vararg_Invalid_Unverifiable_Validation_Valid(method vararg void *(int32) f) cil managed
{
ldc.i4.1
ldarg.0
calli vararg void(int32)
ret
}

.method public hidebysig static void Calli.TailCall_Invalid_Unverifiable() cil managed
.method public hidebysig static void Calli.TailCall_Invalid_Unverifiable_Validation_Valid() cil managed
{
ldftn void CalliTests::ManagedTarget()
tail. calli void()
ret
}

.method public hidebysig static void Calli.TailCallByRefArgument_Invalid_Unverifiable.TailByRef(method void *(int32&) f) cil managed
.method public hidebysig static void Calli.TailCallByRefArgument_Invalid_Unverifiable.TailByRef_Validation_TailByRef(method void *(int32&) f) cil managed
{
.locals init (int32 V_0)
ldloca.s V_0
Expand All @@ -126,7 +126,7 @@
ret
}

.method public hidebysig static void Calli.TailCallByRefThis_Invalid_Unverifiable.TailByRef(method instance void *() f) cil managed
.method public hidebysig static void Calli.TailCallByRefThis_Invalid_Unverifiable.TailByRef_Validation_TailByRef(method instance void *() f) cil managed
{
.locals init (int32 V_0)
ldloca.s V_0
Expand All @@ -135,7 +135,7 @@
ret
}

.method public hidebysig static void Calli.TailCallNotFollowedByRet_Invalid_Unverifiable.TailRet() cil managed
.method public hidebysig static void Calli.TailCallNotFollowedByRet_Invalid_Unverifiable.TailRet_Validation_TailRet() cil managed
{
ldftn void CalliTests::ManagedTarget()
tail. calli void()
Expand All @@ -145,22 +145,22 @@

// The tail call's return checks are shared with call. A void method cannot tail-call a method returning a value;
// the value then left on the stack also makes the ret report ReturnVoid.
.method public hidebysig static void Calli.TailCallReturnsValue_Invalid_Unverifiable.TailRetVoid.ReturnVoid() cil managed
.method public hidebysig static void Calli.TailCallReturnsValue_Invalid_Unverifiable.TailRetVoid.ReturnVoid_Validation_TailRetVoid.ReturnVoid() cil managed
{
ldftn int32 CalliTests::ReturnsInt32()
tail. calli int32()
ret
}

.method public hidebysig static int32& Calli.ByRefReturn_Invalid_Unverifiable(method int32& *() f) cil managed
.method public hidebysig static int32& Calli.ByRefReturn_Invalid_Unverifiable_Validation_Valid(method int32& *() f) cil managed
{
ldarg.0
calli int32&()
ret
}

// The calli operand is the TypeDef token of CalliTests (0x02000002), not a StandAloneSig token.
.method public hidebysig static void Calli.NotSignatureToken_Invalid_Unverifiable.ExpectedSignatureToken() cil managed
.method public hidebysig static void Calli.NotSignatureToken_Invalid_Unverifiable.ExpectedSignatureToken_Validation_ExpectedSignatureToken() cil managed
{
ldftn void CalliTests::ManagedTarget()
.emitbyte 0x29
Expand Down Expand Up @@ -193,7 +193,7 @@
ret
}

.method public hidebysig instance void 'special.CalliUninitThis..ctor_Invalid_Unverifiable.UninitStack'(method void *(object) f) cil managed
.method public hidebysig instance void 'special.CalliUninitThis..ctor_Invalid_Unverifiable.UninitStack_Validation_UninitStack'(method void *(object) f) cil managed
{
ret
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@
ret
}

.method public hidebysig instance void Casting.AssignThisToSameTypeWithOtherGenericArgs_Invalid_StackUnexpected() cil managed
.method public hidebysig instance void Casting.AssignThisToSameTypeWithOtherGenericArgs_Invalid_StackUnexpected_Validation_Valid() cil managed
{
.locals init (
class GenericCastingTestsType`1<int32> V_0
Expand All @@ -257,7 +257,7 @@
ret
}

.method public hidebysig static void Casting.AssignToSameTypeWithOtherGenericArgs_Invalid_StackUnexpected() cil managed
.method public hidebysig static void Casting.AssignToSameTypeWithOtherGenericArgs_Invalid_StackUnexpected_Validation_Valid() cil managed
{
.locals init (
class GenericCastingTestsType`1<int32> V_0,
Expand Down
Loading
Loading