Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Arzt <arzt.samuel@live.de>2017-11-10 17:13:06 +0300
committerJan Kotas <jkotas@microsoft.com>2017-11-10 17:13:06 +0300
commitc22aab437100a45a6e721a8e773dc43a6a5b789e (patch)
tree7ced69250b2c60fe17a5e4205fb9d36fa13b6b30 /src/ILVerify
parent743e47e1b0a2b851a5a34f18ab3a2d9f975b57e3 (diff)
[ILVerify] Implement missing cast, box and leave verifications. (#4903)
* Added missing castclass verifications. * Added tests for new castclass verifications. * Added missing box verifications. * Added tests for new box verifications. * Implemented valid leave target verification. * Added tests for leave target verification. * Added Verifier errors for BadBranch, UnknownOpcode and MethodFallthrough. * Changed disjoint try block determination algorithm and added additional test cases.
Diffstat (limited to 'src/ILVerify')
-rw-r--r--src/ILVerify/src/ILImporter.Verify.cs234
-rw-r--r--src/ILVerify/src/Resources/Strings.resx36
-rw-r--r--src/ILVerify/src/VerifierError.cs20
-rw-r--r--src/ILVerify/tests/ILTests/CastingTests.il69
-rw-r--r--src/ILVerify/tests/ILTests/ExceptionRegionTests.il711
5 files changed, 1014 insertions, 56 deletions
diff --git a/src/ILVerify/src/ILImporter.Verify.cs b/src/ILVerify/src/ILImporter.Verify.cs
index 144c767ba..e8819dedd 100644
--- a/src/ILVerify/src/ILImporter.Verify.cs
+++ b/src/ILVerify/src/ILImporter.Verify.cs
@@ -548,6 +548,118 @@ again:
VerificationError(VerifierError.StackUnexpected, src, dst);
}
+ private void CheckIsValidLeaveTarget(BasicBlock src, BasicBlock target)
+ {
+ // If the source is within filter, target shall be within the same
+ if (src.FilterIndex.HasValue && src.FilterIndex != target.FilterIndex)
+ {
+ VerificationError(VerifierError.LeaveOutOfFilter);
+ }
+
+ // If the source is within fault handler or finally handler, target shall be within the same
+ if (src.HandlerIndex.HasValue && src.HandlerIndex != target.HandlerIndex)
+ {
+ var regionKind = _exceptionRegions[src.HandlerIndex.Value].ILRegion.Kind;
+ if (regionKind == ILExceptionRegionKind.Fault)
+ VerificationError(VerifierError.LeaveOutOfFault);
+ else if (regionKind == ILExceptionRegionKind.Finally)
+ VerificationError(VerifierError.LeaveOutOfFinally);
+ }
+
+ // If the source is within a try block, target shall be within the same or an enclosing try block
+ // or the first instruction of a disjoint try block
+ // or not within any try block
+ bool invalidLeaveIntoTry = false;
+ if (src.TryIndex.HasValue && src.TryIndex != target.TryIndex)
+ {
+ if (target.TryIndex.HasValue)
+ {
+ ref var srcRegion = ref _exceptionRegions[src.TryIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.TryIndex.Value].ILRegion;
+
+ // Target is not enclosing source
+ if (targetRegion.TryOffset > srcRegion.TryOffset ||
+ src.StartOffset >= targetRegion.TryOffset + targetRegion.TryLength)
+ {
+ // Target is not first instruction
+ if (target.StartOffset != targetRegion.TryOffset)
+ {
+ VerificationError(VerifierError.LeaveIntoTry);
+ invalidLeaveIntoTry = true;
+ }
+ else if (srcRegion.TryOffset <= targetRegion.TryOffset &&
+ srcRegion.TryOffset + srcRegion.TryLength > targetRegion.TryOffset) // Source is enclosing target
+ {
+ if (!IsDirectChildRegion(src, target))
+ {
+ VerificationError(VerifierError.LeaveIntoTry);
+ invalidLeaveIntoTry = true;
+ }
+ }
+ else if (!IsDisjointTryBlock(ref targetRegion, ref srcRegion))
+ {
+ VerificationError(VerifierError.LeaveIntoTry);
+ invalidLeaveIntoTry = true;
+ }
+ }
+ }
+ }
+
+ // If the source is within a catch or filtered handler, target shall be within same catch or filtered handler
+ // or within the associated try block
+ // or within a try block enclosing the catch / filtered handler
+ // or the first instruction of a disjoint try block
+ // or not within any try block
+ if (src.HandlerIndex.HasValue && src.HandlerIndex != target.HandlerIndex)
+ {
+ if (target.TryIndex.HasValue)
+ {
+ ref var srcRegion = ref _exceptionRegions[target.TryIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.TryIndex.Value].ILRegion;
+
+ // If target is not associated try block, and not enclosing srcRegion
+ if (target.TryIndex != src.HandlerIndex &&
+ (targetRegion.TryOffset > srcRegion.HandlerOffset ||
+ targetRegion.TryOffset + targetRegion.TryLength < srcRegion.HandlerOffset))
+ {
+ // If target is not first instruction of try, or not a direct sibling
+ if (target.StartOffset != targetRegion.TryOffset || !IsDisjointTryBlock(ref targetRegion, ref srcRegion))
+ VerificationError(VerifierError.LeaveIntoTry);
+ }
+ }
+ }
+
+ // If the target is within a filter or handler, source shall be within same
+ if (target.HandlerIndex.HasValue && src.HandlerIndex != target.HandlerIndex)
+ {
+ ref var targetRegion = ref _exceptionRegions[target.HandlerIndex.Value].ILRegion;
+ // If target region is not enclosing source
+ if (targetRegion.HandlerOffset > src.StartOffset || targetRegion.HandlerOffset + targetRegion.HandlerLength < src.StartOffset)
+ VerificationError(VerifierError.LeaveIntoHandler);
+ }
+ if (target.FilterIndex.HasValue && src.FilterIndex != target.FilterIndex)
+ {
+ ref var targetRegion = ref _exceptionRegions[target.FilterIndex.Value].ILRegion;
+ var filterLength = targetRegion.HandlerOffset - targetRegion.FilterOffset;
+
+ // If target region is not enclosing source
+ if (targetRegion.FilterOffset > src.StartOffset || targetRegion.FilterOffset + filterLength < src.StartOffset)
+ VerificationError(VerifierError.LeaveIntoFilter);
+ }
+
+ // If the target is within a try block (except first instruction), source shall be within same
+ // or within associated handler
+ if (!invalidLeaveIntoTry && target.TryIndex.HasValue && src.TryIndex != target.TryIndex)
+ {
+ ref var targetRegion = ref _exceptionRegions[target.TryIndex.Value].ILRegion;
+
+ if (target.StartOffset != targetRegion.TryOffset && // Not first instruction
+ (!src.HandlerIndex.HasValue || src.HandlerIndex != target.TryIndex) && // Not associated handler
+ (targetRegion.TryOffset > src.StartOffset || targetRegion.TryOffset + targetRegion.TryLength < src.StartOffset)) // Target region does not enclose source
+ VerificationError(VerifierError.LeaveIntoTry);
+ }
+ }
+
bool IsValidBranchTarget(BasicBlock src, BasicBlock target, bool reportErrors = true)
{
bool isValid = true;
@@ -557,7 +669,7 @@ again:
if (src.TryIndex == null)
{
// Branching to first instruction of try-block is valid
- if (target.StartOffset != _exceptionRegions[(int)target.TryIndex].ILRegion.TryOffset || !IsDirectChildRegion(src, target))
+ if (target.StartOffset != _exceptionRegions[target.TryIndex.Value].ILRegion.TryOffset || !IsDirectChildRegion(src, target))
{
if (reportErrors)
VerificationError(VerifierError.BranchIntoTry);
@@ -572,8 +684,8 @@ again:
}
else
{
- ref var srcRegion = ref _exceptionRegions[(int)src.TryIndex].ILRegion;
- ref var targetRegion = ref _exceptionRegions[(int)target.TryIndex].ILRegion;
+ ref var srcRegion = ref _exceptionRegions[src.TryIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.TryIndex.Value].ILRegion;
// If target is inside source region
if (srcRegion.TryOffset <= targetRegion.TryOffset &&
target.StartOffset < srcRegion.TryOffset + srcRegion.TryLength)
@@ -611,8 +723,8 @@ again:
}
else
{
- ref var srcRegion = ref _exceptionRegions[(int)src.FilterIndex].ILRegion;
- ref var targetRegion = ref _exceptionRegions[(int)target.FilterIndex].ILRegion;
+ ref var srcRegion = ref _exceptionRegions[src.FilterIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.FilterIndex.Value].ILRegion;
if (srcRegion.FilterOffset <= targetRegion.FilterOffset)
{
if (reportErrors)
@@ -644,8 +756,8 @@ again:
}
else
{
- ref var srcRegion = ref _exceptionRegions[(int)src.HandlerIndex].ILRegion;
- ref var targetRegion = ref _exceptionRegions[(int)target.HandlerIndex].ILRegion;
+ ref var srcRegion = ref _exceptionRegions[src.HandlerIndex.Value].ILRegion;
+ ref var targetRegion = ref _exceptionRegions[target.HandlerIndex.Value].ILRegion;
if (srcRegion.HandlerOffset <= targetRegion.HandlerOffset)
{
if (reportErrors)
@@ -673,7 +785,7 @@ again:
/// <returns>True if <paramref name="enclosedBlock"/> is a direct child try region of <paramref name="enclosingBlock"/>.</returns>
bool IsDirectChildRegion(BasicBlock enclosingBlock, BasicBlock enclosedBlock)
{
- var enclosedRegion = _exceptionRegions[(int)enclosedBlock.TryIndex].ILRegion;
+ ref var enclosedRegion = ref _exceptionRegions[enclosedBlock.TryIndex.Value].ILRegion;
// Walk from enclosed try start backwards and check each BasicBlock whether it is a try-start
for (int i = enclosedRegion.TryOffset - 1; i > enclosingBlock.StartOffset; --i)
@@ -684,7 +796,7 @@ again:
if (block.TryStart && block.TryIndex != enclosingBlock.TryIndex)
{
- var blockRegion = _exceptionRegions[(int)block.TryIndex].ILRegion;
+ ref var blockRegion = ref _exceptionRegions[block.TryIndex.Value].ILRegion;
// blockRegion is actually enclosing enclosedRegion
if (blockRegion.TryOffset + blockRegion.TryLength > enclosedRegion.TryOffset)
return false;
@@ -694,6 +806,57 @@ again:
return true;
}
+ /// <summary>
+ /// Checks whether the try block <paramref name="disjoint"/> is a disjoint try block relative to <paramref name="source"/>.
+ /// </summary>
+ /// <returns>True if <paramref name="disjoint"/> is a disjoint try block relative to <paramref name="source"/>.</returns>
+ bool IsDisjointTryBlock(ref ILExceptionRegion disjoint, ref ILExceptionRegion source)
+ {
+ if (source.TryOffset <= disjoint.TryOffset && source.TryOffset + source.TryLength >= disjoint.TryOffset + disjoint.TryLength)
+ {
+ // source is enclosing disjoint
+ return false;
+ }
+
+ // Walk from disjoint region backwards and check for enclosing exception regions.
+ for (int i = disjoint.TryOffset - 1; i >= 0; --i)
+ {
+ var block = _basicBlocks[i];
+ if (block == null)
+ continue;
+
+ if (block.TryStart)
+ {
+ ref var blockRegion = ref _exceptionRegions[block.TryIndex.Value].ILRegion;
+ // blockRegion is enclosing disjoint, but not source
+ if (blockRegion.TryOffset + blockRegion.TryLength > disjoint.TryOffset &&
+ (blockRegion.TryOffset > source.TryOffset || blockRegion.TryOffset + blockRegion.TryLength <= source.TryOffset))
+ return false;
+ }
+
+ if (block.HandlerStart)
+ {
+ ref var blockRegion = ref _exceptionRegions[block.HandlerIndex.Value].ILRegion;
+ // blockRegion is enclosing secondRegion, but not source
+ if (blockRegion.HandlerOffset + blockRegion.HandlerLength > disjoint.TryOffset &&
+ (blockRegion.HandlerOffset > source.TryOffset || blockRegion.HandlerOffset + blockRegion.HandlerLength <= source.TryOffset))
+ return false;
+ }
+
+ if (block.FilterStart)
+ {
+ ref var blockRegion = ref _exceptionRegions[block.FilterIndex.Value].ILRegion;
+ // blockRegion is enclosing secondRegion, but not source
+ var filterLength = blockRegion.HandlerOffset - blockRegion.FilterOffset;
+ if (blockRegion.FilterOffset + filterLength > disjoint.TryOffset &&
+ (blockRegion.FilterOffset > source.TryOffset || blockRegion.FilterOffset + filterLength <= source.TryOffset))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
// For now, match PEVerify type formating to make it easy to compare with baseline
static string TypeToStringForIsAssignable(TypeDesc type)
{
@@ -1125,11 +1288,9 @@ again:
var value = Pop();
- // TODO
- // VerifyIsObjRef(tiVal);
+ CheckIsObjRef(value);
- // TODO
- // verCheckClassAccess(pResolvedToken);
+ Check(_method.OwningType.CanAccess(type), VerifierError.TypeAccess);
Push(StackValue.CreateObjRef(type));
}
@@ -1885,19 +2046,14 @@ again:
var targetType = StackValue.CreateFromType(type);
- // TODO: Change the error message to say "cannot box byref" instead
- Check(!IsByRefLike(targetType), VerifierError.ExpectedValClassObjRefVariable, targetType);
+ Check(!IsByRefLike(targetType), VerifierError.BoxByRef, targetType);
-#if false
- VerifyIsBoxable(tiBox);
+ Check(type.IsPrimitive || targetType.Kind == StackValueKind.ObjRef ||
+ type.IsGenericParameter || type.IsValueType, VerifierError.ExpectedValClassObjRefVariable);
- VerifyAndReportFound(m_jitInfo->satisfiesClassConstraints(clsHnd),
- tiBox,
- MVER_E_UNSATISFIED_BOX_OPERAND); //"boxed type has unsatisfied class constraints");
+ Check(type.CheckConstraints(), VerifierError.UnsatisfiedBoxOperand);
- //Check for access to the type.
- verCheckClassAccess(pResolvedToken);
-#endif
+ Check(_method.OwningType.CanAccess(type), VerifierError.TypeAccess);
CheckIsAssignable(value, targetType);
@@ -1920,7 +2076,7 @@ again:
PropagateThisState(_currentBasicBlock, target);
MarkBasicBlock(target);
- // TODO
+ CheckIsValidLeaveTarget(_currentBasicBlock, target);
}
void ImportEndFinally()
@@ -2285,6 +2441,21 @@ again:
_pendingPrefix &= ~prefix;
}
+ void ReportInvalidBranchTarget(int targetOffset)
+ {
+ VerificationError(VerifierError.BadBranch);
+ }
+
+ void ReportFallthroughAtEndOfMethod()
+ {
+ VerificationError(VerifierError.MethodFallthrough);
+ }
+
+ void ReportInvalidInstruction(ILOpcode opcode)
+ {
+ VerificationError(VerifierError.UnknownOpcode);
+ }
+
//
// Deprecated
//
@@ -2308,20 +2479,5 @@ again:
{
throw new PlatformNotSupportedException("TypedReference not supported in .NET Core");
}
-
- private void ReportInvalidBranchTarget(int targetOffset)
- {
- throw new NotImplementedException();
- }
-
- private void ReportFallthroughAtEndOfMethod()
- {
- throw new NotImplementedException();
- }
-
- private void ReportInvalidInstruction(ILOpcode opcode)
- {
- throw new NotImplementedException();
- }
}
}
diff --git a/src/ILVerify/src/Resources/Strings.resx b/src/ILVerify/src/Resources/Strings.resx
index 543e9b44f..9e7b84f19 100644
--- a/src/ILVerify/src/Resources/Strings.resx
+++ b/src/ILVerify/src/Resources/Strings.resx
@@ -120,6 +120,12 @@
<data name="ArrayByRef" xml:space="preserve">
<value>Array of ELEMENT_TYPE_BYREF or ELEMENT_TYPE_TYPEDBYREF.</value>
</data>
+ <data name="BadBranch" xml:space="preserve">
+ <value>Branch out of the method.</value>
+ </data>
+ <data name="BoxByRef" xml:space="preserve">
+ <value>Cannot box byref.</value>
+ </data>
<data name="BranchIntoFilter" xml:space="preserve">
<value>Branch into exception filter block.</value>
</data>
@@ -222,9 +228,30 @@
<data name="LdvirtftnOnStatic" xml:space="preserve">
<value>ldvirtftn on static.</value>
</data>
+ <data name="LeaveIntoFilter" xml:space="preserve">
+ <value>Leave into filter block.</value>
+ </data>
+ <data name="LeaveIntoHandler" xml:space="preserve">
+ <value>Leave into exception handler block.</value>
+ </data>
+ <data name="LeaveIntoTry" xml:space="preserve">
+ <value>Leave into try block.</value>
+ </data>
+ <data name="LeaveOutOfFault" xml:space="preserve">
+ <value>Leave out of fault block.</value>
+ </data>
+ <data name="LeaveOutOfFilter" xml:space="preserve">
+ <value>Leave out of filter block.</value>
+ </data>
+ <data name="LeaveOutOfFinally" xml:space="preserve">
+ <value>Leave out of finally block.</value>
+ </data>
<data name="MethodAccess" xml:space="preserve">
<value>Method is not visible.</value>
</data>
+ <data name="MethodFallthrough" xml:space="preserve">
+ <value>Fall through end of the method without returning.</value>
+ </data>
<data name="PathStackDepth" xml:space="preserve">
<value>Stack depth differs depending on path.</value>
</data>
@@ -312,12 +339,18 @@
<data name="TryNonEmptyStack" xml:space="preserve">
<value>Attempt to enter a try block with nonempty stack.</value>
</data>
+ <data name="TypeAccess" xml:space="preserve">
+ <value>Type is not visible.</value>
+ </data>
<data name="Unaligned" xml:space="preserve">
<value>Missing ldind, stind, ldfld, stfld, ldobj, stobj, initblk, cpblk.</value>
</data>
<data name="UninitStack" xml:space="preserve">
<value>Uninitialized item on stack.</value>
</data>
+ <data name="UnknownOpcode" xml:space="preserve">
+ <value>Unknown opcode.</value>
+ </data>
<data name="UnmanagedPointer" xml:space="preserve">
<value>Unmanaged pointers are not a verifiable type.</value>
</data>
@@ -327,6 +360,9 @@
<data name="UnrecognizedLocalNumber" xml:space="preserve">
<value>Unrecognized local variable number.</value>
</data>
+ <data name="UnsatisfiedBoxOperand" xml:space="preserve">
+ <value>Type operand of box instruction has unsatisfied class type parameter constraints.</value>
+ </data>
<data name="UnsatisfiedMethodInst" xml:space="preserve">
<value>Method instantiation has unsatisfied method type parameter constraints.</value>
</data>
diff --git a/src/ILVerify/src/VerifierError.cs b/src/ILVerify/src/VerifierError.cs
index df2f02329..51e4ad689 100644
--- a/src/ILVerify/src/VerifierError.cs
+++ b/src/ILVerify/src/VerifierError.cs
@@ -25,9 +25,9 @@ namespace ILVerify
//E_FOUND "[found %s]"
//E_EXPECTED "[expected %s]"
- //E_UNKNOWN_OPCODE "Unknown opcode [0x%08X]."
- //E_SIG_CALLCONV "Unknown calling convention [0x%08X]."
- //E_SIG_ELEMTYPE "Unknown ELEMENT_TYPE [0x%08x]."
+ UnknownOpcode, // Unknown opcode.
+ //E_SIG_CALLCONV "Unknown calling convention [0x%08X]."
+ //E_SIG_ELEMTYPE "Unknown ELEMENT_TYPE [0x%08x]."
//E_RET_SIG "[return sig]"
//E_FIELD_SIG "[field sig]"
@@ -36,7 +36,7 @@ namespace ILVerify
//E_STACK_TOO_LARGE "Stack is too large."
//E_ARRAY_NAME_LONG "Array name is too long."
- //E_FALLTHRU "fall through end of the method without returning."
+ MethodFallthrough, // Fall through end of the method without returning.
//E_TRY_GTEQ_END "try start >= try end."
//E_TRYEND_GT_CS "try end > code size."
//E_HND_GTEQ_END "handler start >= handler end."
@@ -59,6 +59,12 @@ namespace ILVerify
//E_FALLTHRU_INTO_HND "fallthru into an exception handler."
//E_FALLTHRU_INTO_FIL "fallthru into an exception filter."
//E_LEAVE "Leave from outside a try or catch block."
+ LeaveIntoTry, // Leave into try block.
+ LeaveIntoHandler, // Leave into exception handler block.
+ LeaveIntoFilter, // Leave into filter block.
+ LeaveOutOfFilter, // Leave out of filter block.
+ LeaveOutOfFinally, // Leave out of finally block.
+ LeaveOutOfFault, // Leave out of fault block.
Rethrow, // Rethrow from outside a catch handler.
Endfinally, // Endfinally from outside a finally handler.
Endfilter, // Endfilter from outside an exception filter block.
@@ -131,6 +137,7 @@ namespace ILVerify
//E_ARGLIST "Allowed only in vararg methods."
ValueTypeExpected, // Value type expected.
//E_OPEN_DLGT_PROT_ACC "Protected method access through an open instance delegate is not verifiable."
+ TypeAccess, // Type is not visible.
MethodAccess, // Method is not visible.
FieldAccess, // Field is not visible.
//E_DEAD "Item is unusable at this point."
@@ -166,7 +173,7 @@ namespace ILVerify
//E_TAIL_RET_TYPE "Tail call return type not compatible."
TailStackEmpty, // Stack not empty after tail call.
//E_METHOD_END "Method ends in the middle of an instruction."
- //E_BAD_BRANCH "Branch out of the method."
+ BadBranch, // Branch out of the method.
//E_FIN_OVERLAP "Finally handler blocks overlap."
//E_LEXICAL_NESTING "Lexical nesting."
Volatile, // Missing ldsfld, stsfld, ldind, stind, ldfld, stfld, ldobj, stobj, initblk, or cpblk.
@@ -184,6 +191,7 @@ namespace ILVerify
//E_SIG_C_VC "ELEMENT_TYPE_CLASS ValueClass in signature."
//E_SIG_VC_C "ELEMENT_TYPE_VALUETYPE non-ValueClass in signature."
//E_BOX_PTR_TO_STACK "Box operation on TypedReference, ArgHandle, or ArgIterator."
+ BoxByRef, // Cannot box byref.
//E_SIG_BYREF_TB_AH "ByRef of TypedReference, ArgHandle, or ArgIterator."
//E_SIG_ARRAY_TB_AH "Array of TypedReference, ArgHandle, or ArgIterator."
EndfilterStack, // Stack not empty when leaving an exception filter.
@@ -221,7 +229,7 @@ namespace ILVerify
UnsatisfiedMethodInst, // Method instantiation has unsatisfied method type parameter constraints.
UnsatisfiedMethodParentInst, // Method parent instantiation has unsatisfied class type parameter constraints.
//E_UNSATISFIED_FIELD_PARENT_INST "Field parent instantiation has unsatisfied class type parameter constraints."
- //E_UNSATISFIED_BOX_OPERAND "Type operand of box instruction has unsatisfied class type parameter constraints."
+ UnsatisfiedBoxOperand, // Type operand of box instruction has unsatisfied class type parameter constraints.
ConstrainedCallWithNonByRefThis, // The 'this' argument to a constrained call must have ByRef type.
//E_CONSTRAINED_OF_NON_VARIABLE_TYPE "The operand to a constrained prefix instruction must be a type parameter."
//E_READONLY_UNEXPECTED_CALLEE "The readonly prefix may only be applied to calls to array methods returning ByRefs."
diff --git a/src/ILVerify/tests/ILTests/CastingTests.il b/src/ILVerify/tests/ILTests/CastingTests.il
index 4be6b764e..c4e085927 100644
--- a/src/ILVerify/tests/ILTests/CastingTests.il
+++ b/src/ILVerify/tests/ILTests/CastingTests.il
@@ -284,6 +284,27 @@
}
}
+// Class with private nested class
+.class public auto ansi beforefieldinit ContainingClass
+ extends [System.Runtime]System.Object
+{
+ .class nested private auto ansi beforefieldinit PrivateNestedClass
+ extends [System.Runtime]System.Object
+ {
+ }
+}
+
+
+// Test enum
+.class public auto ansi sealed Enum
+ extends [System.Runtime]System.Enum
+{
+ .field public static literal valuetype Enum EnumValue1 = int32(0)
+ .field public static literal valuetype Enum EnumValue2 = int32(1)
+
+ .field public specialname rtspecialname int32 value__
+}
+
.class public auto ansi beforefieldinit CastingTestsType
extends [System.Runtime]System.Object
{
@@ -298,4 +319,52 @@
stloc.0
ret
}
+
+ .method public static void Casting.CastToInaccessibleType_Invalid_TypeAccess() cil managed
+ {
+ ldnull
+ castclass ContainingClass/PrivateNestedClass
+ pop
+ ret
+ }
+
+ .method public static void Casting.CastClassInt_Invalid_StackObjRef() cil managed
+ {
+ ldc.i4.0
+ castclass CastingTestsType
+ pop
+ ret
+ }
+
+ .method public static void Casting.BoxInaccesibleType_Invalid_TypeAccess(class ContainingClass/PrivateNestedClass c) cil managed
+ {
+ ldarg.0
+ box ContainingClass/PrivateNestedClass
+ pop
+ ret
+ }
+
+ .method public static void Casting.BoxByRefInt_Invalid_BoxByRef.ExpectedValClassObjRefVariable(int32& i) cil managed
+ {
+ ldarg.0
+ box int32&
+ pop
+ ret
+ }
+
+ .method public static void Casting.BoxToUnsatisfiedConstraint_Invalid_UnsatisfiedBoxOperand(class GenericTypeWithConstrained<class [System.Runtime]System.Object> c) cil managed
+ {
+ ldarg.0
+ box class GenericTypeWithConstrained<class [System.Runtime]System.Object>
+ pop
+ ret
+ }
+
+ .method public static void Casting.BoxEnum_Valid(valuetype Enum e) cil managed
+ {
+ ldarg.0
+ box Enum
+ pop
+ ret
+ }
}
diff --git a/src/ILVerify/tests/ILTests/ExceptionRegionTests.il b/src/ILVerify/tests/ILTests/ExceptionRegionTests.il
index 840643c39..8b388044d 100644
--- a/src/ILVerify/tests/ILTests/ExceptionRegionTests.il
+++ b/src/ILVerify/tests/ILTests/ExceptionRegionTests.il
@@ -15,27 +15,716 @@
{
.method public instance void ExceptionRegion.NestedTryFinally_Valid() cil managed
{
- .try
- {
+ .try
+ {
nop
- leave EndTryCatch
- }
+ leave EndTryCatch
+ }
finally
{
- .try
- {
+ .try
+ {
nop
- leave EndFinally
- }
+ leave EndFinally
+ }
catch [System.Runtime]System.Exception
{
nop
- leave EndFinally
+ leave EndFinally
}
-EndFinally:
+ EndFinally:
endfinally
}
-EndTryCatch:
+ EndTryCatch:
+ ret
+ }
+
+ .method public instance void Leave.ToSameFilter_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ filter
+ {
+ pop
+ leave SameFilter
+
+ SameFilter:
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToOtherFilter_Invalid_LeaveOutOfFilter.LeaveIntoFilter() cil managed
+ {
+ .try
+ {
+ leave AfterTry
+ }
+ filter
+ {
+ pop
+ leave OtherFilter
+
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave MethodEnd
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ leave MethodEnd
+ }
+ filter
+ {
+ pop
+
+ OtherFilter:
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.OutOfFilter_Invalid_LeaveOutOfFilter() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ filter
+ {
+ pop
+ leave MethodEnd
+
+ ldc.i4.0
+ endfilter
+ }
+ {
+ pop
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSameFault_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ fault
+ {
+ leave SameFault
+
+ SameFault:
+ endfault
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSameFinally_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ finally
+ {
+ leave SameFinally
+
+ SameFinally:
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToOtherFinally_Invalid_LeaveOutOfFinally.LeaveIntoHandler() cil managed
+ {
+ .try
+ {
+ leave AfterTry
+ }
+ finally
+ {
+ leave OtherFinally
+ endfinally
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ leave MethodEnd
+ }
+ finally
+ {
+ OtherFinally:
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToOtherFault_Invalid_LeaveOutOfFault.LeaveIntoFault.LeaveIntoHandler() cil managed
+ {
+ .try
+ {
+ leave AfterTry
+ }
+ fault
+ {
+ leave OtherFault
+ endfault
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ leave MethodEnd
+ }
+ fault
+ {
+ OtherFault:
+ endfault
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.OutOfFinally_Invalid_LeaveOutOfFinally() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ finally
+ {
+ leave MethodEnd
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.OutOfFault_Invalid_LeaveOutOfFault() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ fault
+ {
+ leave MethodEnd
+ endfault
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSameTry_Valid() cil managed
+ {
+ .try
+ {
+ leave SameTry
+
+ SameTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToEnclosingTry_Valid() cil managed
+ {
+ .try
+ {
+ .try
+ {
+ leave EnclosingTry
+ }
+ finally
+ {
+ endfinally
+ }
+ EnclosingTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToFirstInstrOfDisjointTry_Valid() cil managed
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToFirstInstrOfNestedDisjointTry_Valid() cil managed
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+
+ .try
+ {
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.IntoOtherTry_Invalid_LeaveIntoTry() cil managed
+ {
+ .try
+ {
+ leave OtherTry
+ }
+ finally
+ {
+ endfinally
+ }
+
+ .try
+ {
+ nop
+ OtherTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSecondInstrOfNestedDisjointTry_Invalid_LeaveIntoTry() cil managed
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+
+ .try
+ {
+ nop
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToFirstInstrOfEnclosedTry_Valid() cil managed
+ {
+ .try
+ {
+ leave EnclosedTry
+
+ .try
+ {
+ EnclosedTry:
+ leave TryEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ TryEnd:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromCatchIntoAssociatedTry_Valid() cil managed
+ {
+ .try
+ {
+ TryStart:
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave TryStart
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.ToSameCatch_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave SameCatch
+
+ SameCatch:
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.IntoEnclosingTry_Valid() cil managed
+ {
+ .try
+ {
+ .try
+ {
+ leave EnclosingTry
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave EnclosingTry
+ }
+ EnclosingTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.OutOfCatch_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave MethodEnd
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.CatchToFirstInstrOfDisjointTry_Valid() cil managed
+ {
+ .try
+ {
+ leave AfterTry
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave DisjointTry
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.CatchToFirstInstrOfNestedTry_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave NestedTry
+
+ .try
+ {
+ NestedTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.CatchToSecondInstrOfNestedTry_Invalid_LeaveIntoTry() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ leave NestedTry
+
+ .try
+ {
+ nop
+ NestedTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.CatchToEnclosingTry_Valid() cil managed
+ {
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ .try
+ {
+ leave EnclosingTry
+ }
+ finally
+ {
+ endfinally
+ }
+
+ EnclosingTry:
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromOutsideIntoFilter_Invalid_LeaveIntoFilter() cil managed
+ {
+ leave IntoFilter
+
+ .try
+ {
+ leave MethodEnd
+ }
+ filter
+ {
+ pop
+ IntoFilter:
+ ldc.i4.0
+ endfilter
+ }
+ {
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromOutsideIntoHandler_Invalid_LeaveIntoHandler() cil managed
+ {
+ leave IntoHandler
+
+ .try
+ {
+ leave MethodEnd
+ }
+ catch [System.Runtime]System.Object
+ {
+ pop
+ IntoHandler:
+ leave MethodEnd
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromOutsideIntoTry_Invalid_LeaveIntoTry() cil managed
+ {
+ leave IntoTry
+
+ .try
+ {
+ nop
+ IntoTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromNestedTryToDisjointTry_Valid() cil managed
+ {
+ .try
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+ leave AfterTry
+ }
+ finally
+ {
+ endfinally
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ DisjointTry:
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ MethodEnd:
+ ret
+ }
+
+ .method public instance void Leave.FromNestedTryToDisjointTryBackward_Valid() cil managed
+ {
+ .try
+ {
+ DisjointTry:
+ leave AfterTry
+ }
+ finally
+ {
+ endfinally
+ }
+ AfterTry:
+ nop
+
+ .try
+ {
+ .try
+ {
+ leave DisjointTry
+ }
+ finally
+ {
+ endfinally
+ }
+ leave MethodEnd
+ }
+ finally
+ {
+ endfinally
+ }
+
+ MethodEnd:
ret
}
}