@@ -23,11 +23,11 @@ import csharp
2323private import semmle.code.csharp.commons.Assertions
2424private import semmle.code.csharp.commons.Constants
2525private import semmle.code.csharp.frameworks.System
26+ private import ControlFlowGraphImpl
2627private import NonReturning
2728private import SuccessorType
2829private import SuccessorTypes
2930
30- // Internal representation of completions
3131private newtype TCompletion =
3232 TSimpleCompletion ( ) or
3333 TBooleanCompletion ( boolean b ) { b = true or b = false } or
@@ -40,26 +40,33 @@ private newtype TCompletion =
4040 TGotoCompletion ( string label ) { label = any ( GotoStmt gs ) .getLabel ( ) } or
4141 TThrowCompletion ( ExceptionClass ec ) or
4242 TExitCompletion ( ) or
43- TNestedCompletion ( Completion inner , Completion outer ) {
44- inner instanceof NormalCompletion and
45- (
46- outer = TReturnCompletion ( )
47- or
48- outer = TBreakCompletion ( )
49- or
50- outer = TContinueCompletion ( )
51- or
52- outer = TGotoCompletion ( _)
53- or
54- outer = TThrowCompletion ( _)
55- or
56- outer = TExitCompletion ( )
57- )
58- or
43+ TNestedCompletion ( Completion inner , Completion outer , int nestLevel ) {
5944 inner = TBreakCompletion ( ) and
60- outer instanceof NonNestedNormalCompletion
45+ outer instanceof NonNestedNormalCompletion and
46+ nestLevel = 0
47+ or
48+ inner instanceof NormalCompletion and
49+ nestedFinallyCompletion ( outer , nestLevel )
6150 }
6251
52+ pragma [ noinline]
53+ private predicate nestedFinallyCompletion ( Completion outer , int nestLevel ) {
54+ (
55+ outer = TReturnCompletion ( )
56+ or
57+ outer = TBreakCompletion ( )
58+ or
59+ outer = TContinueCompletion ( )
60+ or
61+ outer = TGotoCompletion ( _)
62+ or
63+ outer = TThrowCompletion ( _)
64+ or
65+ outer = TExitCompletion ( )
66+ ) and
67+ nestLevel = any ( Statements:: TryStmtTree t ) .nestLevel ( )
68+ }
69+
6370pragma [ noinline]
6471private predicate completionIsValidForStmt ( Stmt s , Completion c ) {
6572 s instanceof BreakStmt and
@@ -674,21 +681,25 @@ class EmptinessCompletion extends ConditionalCompletion, TEmptinessCompletion {
674681class NestedCompletion extends Completion , TNestedCompletion {
675682 Completion inner ;
676683 Completion outer ;
684+ int nestLevel ;
677685
678- NestedCompletion ( ) { this = TNestedCompletion ( inner , outer ) }
686+ NestedCompletion ( ) { this = TNestedCompletion ( inner , outer , nestLevel ) }
679687
680688 /** Gets a completion that is compatible with the inner completion. */
681689 Completion getAnInnerCompatibleCompletion ( ) {
682690 result .getOuterCompletion ( ) = this .getInnerCompletion ( )
683691 }
684692
693+ /** Gets the level of this nested completion. */
694+ int getNestLevel ( ) { result = nestLevel }
695+
685696 override Completion getInnerCompletion ( ) { result = inner }
686697
687698 override Completion getOuterCompletion ( ) { result = outer }
688699
689700 override SuccessorType getAMatchingSuccessorType ( ) { none ( ) }
690701
691- override string toString ( ) { result = outer + " [" + inner + "]" }
702+ override string toString ( ) { result = outer + " [" + inner + "] (" + nestLevel + ") " }
692703}
693704
694705/**
@@ -725,13 +736,13 @@ class NestedBreakCompletion extends NormalCompletion, NestedCompletion {
725736
726737 override BreakCompletion getInnerCompletion ( ) { result = inner }
727738
728- override SimpleCompletion getOuterCompletion ( ) { result = outer }
739+ override NonNestedNormalCompletion getOuterCompletion ( ) { result = outer }
729740
730741 override Completion getAnInnerCompatibleCompletion ( ) {
731742 result = inner and
732743 outer = TSimpleCompletion ( )
733744 or
734- result = TNestedCompletion ( outer , inner )
745+ result = TNestedCompletion ( outer , inner , _ )
735746 }
736747
737748 override SuccessorType getAMatchingSuccessorType ( ) {
@@ -749,7 +760,7 @@ class NestedBreakCompletion extends NormalCompletion, NestedCompletion {
749760class ReturnCompletion extends Completion {
750761 ReturnCompletion ( ) {
751762 this = TReturnCompletion ( ) or
752- this = TNestedCompletion ( _, TReturnCompletion ( ) )
763+ this = TNestedCompletion ( _, TReturnCompletion ( ) , _ )
753764 }
754765
755766 override ReturnSuccessor getAMatchingSuccessorType ( ) { any ( ) }
@@ -768,7 +779,7 @@ class ReturnCompletion extends Completion {
768779class BreakCompletion extends Completion {
769780 BreakCompletion ( ) {
770781 this = TBreakCompletion ( ) or
771- this = TNestedCompletion ( _, TBreakCompletion ( ) )
782+ this = TNestedCompletion ( _, TBreakCompletion ( ) , _ )
772783 }
773784
774785 override BreakSuccessor getAMatchingSuccessorType ( ) { any ( ) }
@@ -787,7 +798,7 @@ class BreakCompletion extends Completion {
787798class ContinueCompletion extends Completion {
788799 ContinueCompletion ( ) {
789800 this = TContinueCompletion ( ) or
790- this = TNestedCompletion ( _, TContinueCompletion ( ) )
801+ this = TNestedCompletion ( _, TContinueCompletion ( ) , _ )
791802 }
792803
793804 override ContinueSuccessor getAMatchingSuccessorType ( ) { any ( ) }
@@ -807,7 +818,7 @@ class GotoCompletion extends Completion {
807818
808819 GotoCompletion ( ) {
809820 this = TGotoCompletion ( label ) or
810- this = TNestedCompletion ( _, TGotoCompletion ( label ) )
821+ this = TNestedCompletion ( _, TGotoCompletion ( label ) , _ )
811822 }
812823
813824 /** Gets the label of the `goto` completion. */
@@ -830,7 +841,7 @@ class ThrowCompletion extends Completion {
830841
831842 ThrowCompletion ( ) {
832843 this = TThrowCompletion ( ec ) or
833- this = TNestedCompletion ( _, TThrowCompletion ( ec ) )
844+ this = TNestedCompletion ( _, TThrowCompletion ( ec ) , _ )
834845 }
835846
836847 /** Gets the type of the exception being thrown. */
@@ -856,7 +867,7 @@ class ThrowCompletion extends Completion {
856867class ExitCompletion extends Completion {
857868 ExitCompletion ( ) {
858869 this = TExitCompletion ( ) or
859- this = TNestedCompletion ( _, TExitCompletion ( ) )
870+ this = TNestedCompletion ( _, TExitCompletion ( ) , _ )
860871 }
861872
862873 override ExitSuccessor getAMatchingSuccessorType ( ) { any ( ) }
0 commit comments