43
43
*/
44
44
45
45
import csharp
46
- private import semmle.code.csharp.controlflow.ControlFlowGraph:: ControlFlow
47
46
private import Completion
48
- private import SuccessorType
49
- private import SuccessorTypes
50
47
private import Splitting
51
48
private import semmle.code.csharp.ExprOrStmtParent
52
49
private import semmle.code.csharp.commons.Compilation
50
+ import ControlFlowGraphImplShared
51
+
52
+ /** An element that defines a new CFG scope. */
53
+ class CfgScope extends Element , @top_level_exprorstmt_parent {
54
+ CfgScope ( ) {
55
+ this instanceof Callable
56
+ or
57
+ // For now, static initializer values have their own scope. Eventually, they
58
+ // should be treated like instance initializers.
59
+ this .( Assignable ) .( Modifiable ) .isStatic ( )
60
+ }
61
+ }
53
62
54
63
/**
55
64
* A compilation.
@@ -71,16 +80,11 @@ CompilationExt getCompilation(SourceFile f) {
71
80
result = TBuildless ( )
72
81
}
73
82
74
- /** An element that defines a new CFG scope. */
75
- class CfgScope extends Element , @top_level_exprorstmt_parent {
76
- CfgScope ( ) { not this instanceof Attribute }
77
- }
78
-
79
83
module ControlFlowTree {
80
84
class Range_ = @callable or @control_flow_element;
81
85
82
86
class Range extends Element , Range_ {
83
- Range ( ) { this = getAChild * ( any ( CfgScope scope ) ) }
87
+ Range ( ) { this = getAChild * ( any ( @top_level_exprorstmt_parent p | not p instanceof Attribute ) ) }
84
88
}
85
89
86
90
Element getAChild ( Element p ) {
@@ -93,61 +97,6 @@ module ControlFlowTree {
93
97
predicate idOf ( Range_ x , int y ) = equivalenceRelation( id / 2 ) ( x , y )
94
98
}
95
99
96
- abstract private class ControlFlowTree extends ControlFlowTree:: Range {
97
- /**
98
- * Holds if `first` is the first element executed within this control
99
- * flow element.
100
- */
101
- pragma [ nomagic]
102
- abstract predicate first ( ControlFlowElement first ) ;
103
-
104
- /**
105
- * Holds if `last` with completion `c` is a potential last element executed
106
- * within this control flow element.
107
- */
108
- pragma [ nomagic]
109
- abstract predicate last ( ControlFlowElement last , Completion c ) ;
110
-
111
- /** Holds if abnormal execution of `child` should propagate upwards. */
112
- abstract predicate propagatesAbnormal ( ControlFlowElement child ) ;
113
-
114
- /**
115
- * Holds if `succ` is a control flow successor for `pred`, given that `pred`
116
- * finishes with completion `c`.
117
- */
118
- pragma [ nomagic]
119
- abstract predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) ;
120
- }
121
-
122
- /**
123
- * Holds if `first` is the first element executed within control flow
124
- * element `cft`.
125
- */
126
- predicate first ( ControlFlowTree cft , ControlFlowElement first ) { cft .first ( first ) }
127
-
128
- /**
129
- * Holds if `last` with completion `c` is a potential last element executed
130
- * within control flow element `cft`.
131
- */
132
- predicate last ( ControlFlowTree cft , ControlFlowElement last , Completion c ) {
133
- cft .last ( last , c )
134
- or
135
- exists ( ControlFlowElement cfe |
136
- cft .propagatesAbnormal ( cfe ) and
137
- last ( cfe , last , c ) and
138
- not c instanceof NormalCompletion
139
- )
140
- }
141
-
142
- /**
143
- * Holds if `succ` is a control flow successor for `pred`, given that `pred`
144
- * finishes with completion `c`.
145
- */
146
- pragma [ nomagic]
147
- predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
148
- any ( ControlFlowTree cft ) .succ ( pred , succ , c )
149
- }
150
-
151
100
/** Holds if `first` is first executed when entering `scope`. */
152
101
predicate scopeFirst ( CfgScope scope , ControlFlowElement first ) {
153
102
scope =
@@ -161,8 +110,7 @@ predicate scopeFirst(CfgScope scope, ControlFlowElement first) {
161
110
)
162
111
or
163
112
expr_parent_top_level_adjusted ( any ( Expr e | first ( e , first ) ) , _, scope ) and
164
- not scope instanceof Callable and
165
- not scope instanceof InitializerSplitting:: InitializedInstanceMember
113
+ not scope instanceof Callable
166
114
}
167
115
168
116
/** Holds if `scope` is exited when `last` finishes with completion `c`. */
@@ -204,53 +152,6 @@ private class ConstructorTree extends ControlFlowTree, Constructor {
204
152
}
205
153
}
206
154
207
- /**
208
- * A control flow element where the children are evaluated following a
209
- * standard left-to-right evaluation. The actual evaluation order is
210
- * determined by the predicate `getChildElement()`.
211
- */
212
- abstract private class StandardElement extends ControlFlowTree {
213
- /** Gets the `i`th child element, in order of evaluation, starting from 0. */
214
- abstract ControlFlowElement getChildElement ( int i ) ;
215
-
216
- /** Gets the first child element of this element. */
217
- final ControlFlowElement getFirstChild ( ) { result = this .getChildElement ( 0 ) }
218
-
219
- /** Holds if this element has no children. */
220
- final predicate isLeafElement ( ) { not exists ( this .getFirstChild ( ) ) }
221
-
222
- /** Gets the last child element of this element. */
223
- final ControlFlowTree getLastChild ( ) {
224
- exists ( int last |
225
- result = this .getChildElement ( last ) and
226
- not exists ( this .getChildElement ( last + 1 ) )
227
- )
228
- }
229
-
230
- final override predicate propagatesAbnormal ( ControlFlowElement child ) {
231
- child = this .getChildElement ( _)
232
- }
233
-
234
- override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
235
- exists ( int i |
236
- last ( this .getChildElement ( i ) , pred , c ) and
237
- first ( this .getChildElement ( i + 1 ) , succ ) and
238
- c instanceof NormalCompletion
239
- )
240
- }
241
- }
242
-
243
- abstract private class PreOrderTree extends ControlFlowTree {
244
- final override predicate first ( ControlFlowElement first ) { first = this }
245
- }
246
-
247
- abstract private class PostOrderTree extends ControlFlowTree {
248
- override predicate last ( ControlFlowElement last , Completion c ) {
249
- last = this and
250
- c .isValidFor ( last )
251
- }
252
- }
253
-
254
155
abstract private class SwitchTree extends ControlFlowTree , Switch {
255
156
override predicate propagatesAbnormal ( ControlFlowElement child ) { child = this .getExpr ( ) }
256
157
@@ -368,7 +269,7 @@ module Expressions {
368
269
)
369
270
}
370
271
371
- private class StandardExpr extends StandardElement , PostOrderTree , Expr {
272
+ private class StandardExpr extends StandardPostOrderTree , Expr {
372
273
StandardExpr ( ) {
373
274
// The following expressions need special treatment
374
275
not this instanceof LogicalNotExpr and
@@ -396,21 +297,6 @@ module Expressions {
396
297
}
397
298
398
299
final override ControlFlowElement getChildElement ( int i ) { result = getExprChild ( this , i ) }
399
-
400
- final override predicate first ( ControlFlowElement first ) {
401
- first ( this .getFirstChild ( ) , first )
402
- or
403
- not exists ( this .getFirstChild ( ) ) and
404
- first = this
405
- }
406
-
407
- final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
408
- StandardElement .super .succ ( pred , succ , c )
409
- or
410
- last ( this .getLastChild ( ) , pred , c ) and
411
- succ = this and
412
- c instanceof NormalCompletion
413
- }
414
300
}
415
301
416
302
/**
@@ -1095,7 +981,7 @@ private class PropertyPatternExprExprTree extends PostOrderTree, PropertyPattern
1095
981
}
1096
982
1097
983
module Statements {
1098
- private class StandardStmt extends StandardElement , PreOrderTree , Stmt {
984
+ private class StandardStmt extends StandardPreOrderTree , Stmt {
1099
985
StandardStmt ( ) {
1100
986
// The following statements need special treatment
1101
987
not this instanceof IfStmt and
@@ -1140,22 +1026,6 @@ module Statements {
1140
1026
result =
1141
1027
rank [ i + 1 ] ( ControlFlowElement cfe , int j | cfe = this .getChildElement0 ( j ) | cfe order by j )
1142
1028
}
1143
-
1144
- final override predicate last ( ControlFlowElement last , Completion c ) {
1145
- last ( this .getLastChild ( ) , last , c )
1146
- or
1147
- this .isLeafElement ( ) and
1148
- last = this and
1149
- c .isValidFor ( this )
1150
- }
1151
-
1152
- final override predicate succ ( ControlFlowElement pred , ControlFlowElement succ , Completion c ) {
1153
- StandardElement .super .succ ( pred , succ , c )
1154
- or
1155
- pred = this and
1156
- first ( this .getFirstChild ( ) , succ ) and
1157
- c instanceof SimpleCompletion
1158
- }
1159
1029
}
1160
1030
1161
1031
private class IfStmtTree extends PreOrderTree , IfStmt {
@@ -1779,88 +1649,6 @@ module Statements {
1779
1649
}
1780
1650
}
1781
1651
1782
- cached
1783
- private module Cached {
1784
- private import semmle.code.csharp.Caching
1785
-
1786
- private predicate isAbnormalExitType ( SuccessorType t ) {
1787
- t instanceof ExceptionSuccessor or t instanceof ExitSuccessor
1788
- }
1789
-
1790
- /**
1791
- * Internal representation of control flow nodes in the control flow graph.
1792
- * The control flow graph is pruned for unreachable nodes.
1793
- */
1794
- cached
1795
- newtype TNode =
1796
- TEntryNode ( Callable c ) {
1797
- Stages:: ControlFlowStage:: forceCachingInSameStage ( ) and
1798
- succEntrySplits ( c , _, _, _)
1799
- } or
1800
- TAnnotatedExitNode ( Callable c , boolean normal ) {
1801
- exists ( Reachability:: SameSplitsBlock b , SuccessorType t | b .isReachable ( _) |
1802
- succExitSplits ( b .getAnElement ( ) , _, c , t ) and
1803
- if isAbnormalExitType ( t ) then normal = false else normal = true
1804
- )
1805
- } or
1806
- TExitNode ( Callable c ) {
1807
- exists ( Reachability:: SameSplitsBlock b | b .isReachable ( _) |
1808
- succExitSplits ( b .getAnElement ( ) , _, c , _)
1809
- )
1810
- } or
1811
- TElementNode ( ControlFlowElement cfe , Splits splits ) {
1812
- exists ( Reachability:: SameSplitsBlock b | b .isReachable ( splits ) | cfe = b .getAnElement ( ) )
1813
- }
1814
-
1815
- /** Gets a successor node of a given flow type, if any. */
1816
- cached
1817
- Node getASuccessorByType ( Node pred , SuccessorType t ) {
1818
- // Callable entry node -> callable body
1819
- exists ( ControlFlowElement succElement , Splits succSplits |
1820
- result = TElementNode ( succElement , succSplits )
1821
- |
1822
- succEntrySplits ( pred .( Nodes:: EntryNode ) .getCallable ( ) , succElement , succSplits , t )
1823
- )
1824
- or
1825
- exists ( ControlFlowElement predElement , Splits predSplits |
1826
- pred = TElementNode ( predElement , predSplits )
1827
- |
1828
- // Element node -> callable exit (annotated)
1829
- result =
1830
- any ( Nodes:: AnnotatedExitNode exit |
1831
- succExitSplits ( predElement , predSplits , exit .getCallable ( ) , t ) and
1832
- if isAbnormalExitType ( t ) then not exit .isNormal ( ) else exit .isNormal ( )
1833
- )
1834
- or
1835
- // Element node -> element node
1836
- exists ( ControlFlowElement succElement , Splits succSplits , Completion c |
1837
- result = TElementNode ( succElement , succSplits )
1838
- |
1839
- succSplits ( predElement , predSplits , succElement , succSplits , c ) and
1840
- t = c .getAMatchingSuccessorType ( )
1841
- )
1842
- )
1843
- or
1844
- // Callable exit (annotated) -> callable exit
1845
- pred .( Nodes:: AnnotatedExitNode ) .getCallable ( ) = result .( Nodes:: ExitNode ) .getCallable ( ) and
1846
- t instanceof SuccessorTypes:: NormalSuccessor
1847
- }
1848
-
1849
- /**
1850
- * Gets a first control flow element executed within `cfe`.
1851
- */
1852
- cached
1853
- ControlFlowElement getAControlFlowEntryNode ( ControlFlowElement cfe ) { first ( cfe , result ) }
1854
-
1855
- /**
1856
- * Gets a potential last control flow element executed within `cfe`.
1857
- */
1858
- cached
1859
- ControlFlowElement getAControlFlowExitNode ( ControlFlowElement cfe ) { last ( cfe , result , _) }
1860
- }
1861
-
1862
- import Cached
1863
-
1864
1652
/** A control flow element that is split into multiple control flow nodes. */
1865
1653
class SplitControlFlowElement extends ControlFlowElement {
1866
1654
SplitControlFlowElement ( ) { strictcount ( this .getAControlFlowNode ( ) ) > 1 }
0 commit comments