@@ -69,13 +69,26 @@ abstract class NodeImpl extends Node {
69
69
abstract string toStringImpl ( ) ;
70
70
}
71
71
72
+ // TODO: Remove once static initializers are folded into the
73
+ // static constructors
74
+ private DataFlowCallable getEnclosingStaticFieldOrProperty ( Expr e ) {
75
+ result .asFieldOrProperty ( ) =
76
+ any ( FieldOrProperty f |
77
+ f .isStatic ( ) and
78
+ e = f .getAChild + ( ) and
79
+ not exists ( e .getEnclosingCallable ( ) )
80
+ )
81
+ }
82
+
72
83
private class ExprNodeImpl extends ExprNode , NodeImpl {
73
84
override DataFlowCallable getEnclosingCallableImpl ( ) {
74
85
result .asCallable ( ) =
75
86
[
76
87
this .getExpr ( ) .( CIL:: Expr ) .getEnclosingCallable ( ) .( DotNet:: Callable ) ,
77
88
this .getControlFlowNodeImpl ( ) .getEnclosingCallable ( )
78
89
]
90
+ or
91
+ result = getEnclosingStaticFieldOrProperty ( this .asExpr ( ) )
79
92
}
80
93
81
94
override DotNet:: Type getTypeImpl ( ) {
@@ -909,7 +922,8 @@ private module Cached {
909
922
TFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn ) or
910
923
TParamsArgumentNode ( ControlFlow:: Node callCfn ) {
911
924
callCfn = any ( Call c | isParamsArg ( c , _, _) ) .getAControlFlowNode ( )
912
- }
925
+ } or
926
+ TFlowInsensitiveFieldNode ( FieldOrProperty f ) { f .isFieldLike ( ) }
913
927
914
928
/**
915
929
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
@@ -1019,6 +1033,8 @@ predicate nodeIsHidden(Node n) {
1019
1033
n instanceof ParamsArgumentNode
1020
1034
or
1021
1035
n .asExpr ( ) = any ( WithExpr we ) .getInitializer ( )
1036
+ or
1037
+ n instanceof FlowInsensitiveFieldNode
1022
1038
}
1023
1039
1024
1040
/** A CIL SSA definition, viewed as a node in a data flow graph. */
@@ -1344,6 +1360,8 @@ private module ArgumentNodes {
1344
1360
1345
1361
override DataFlowCallable getEnclosingCallableImpl ( ) {
1346
1362
result .asCallable ( ) = cfn .getEnclosingCallable ( )
1363
+ or
1364
+ result = getEnclosingStaticFieldOrProperty ( cfn .getAstNode ( ) )
1347
1365
}
1348
1366
1349
1367
override Type getTypeImpl ( ) { result = cfn .getAstNode ( ) .( Expr ) .getType ( ) }
@@ -1383,6 +1401,8 @@ private module ArgumentNodes {
1383
1401
1384
1402
override DataFlowCallable getEnclosingCallableImpl ( ) {
1385
1403
result .asCallable ( ) = callCfn .getEnclosingCallable ( )
1404
+ or
1405
+ result = getEnclosingStaticFieldOrProperty ( callCfn .getAstNode ( ) )
1386
1406
}
1387
1407
1388
1408
override Type getTypeImpl ( ) { result = this .getParameter ( ) .getType ( ) }
@@ -1782,6 +1802,30 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
1782
1802
}
1783
1803
}
1784
1804
1805
+ /**
1806
+ * A data flow node used for control-flow insensitive flow through fields
1807
+ * and properties.
1808
+ *
1809
+ * In global data flow this is used to model flow through static fields and
1810
+ * properties, while for lambda flow we additionally use it to track assignments
1811
+ * in constructors to uses within the same class.
1812
+ */
1813
+ class FlowInsensitiveFieldNode extends NodeImpl , TFlowInsensitiveFieldNode {
1814
+ private FieldOrProperty f ;
1815
+
1816
+ FlowInsensitiveFieldNode ( ) { this = TFlowInsensitiveFieldNode ( f ) }
1817
+
1818
+ override DataFlowCallable getEnclosingCallableImpl ( ) { result .asFieldOrProperty ( ) = f }
1819
+
1820
+ override Type getTypeImpl ( ) { result = f .getType ( ) }
1821
+
1822
+ override ControlFlow:: Node getControlFlowNodeImpl ( ) { none ( ) }
1823
+
1824
+ override Location getLocationImpl ( ) { result = f .getLocation ( ) }
1825
+
1826
+ override string toStringImpl ( ) { result = "[flow-insensitive] " + f }
1827
+ }
1828
+
1785
1829
/**
1786
1830
* Holds if `pred` can flow to `succ`, by jumping from one callable to
1787
1831
* another. Additional steps specified by the configuration are *not*
@@ -1790,13 +1834,16 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
1790
1834
predicate jumpStep ( Node pred , Node succ ) {
1791
1835
pred .( NonLocalJumpNode ) .getAJumpSuccessor ( true ) = succ
1792
1836
or
1793
- exists ( FieldOrProperty fl , FieldOrPropertyRead flr |
1794
- fl .isStatic ( ) and
1795
- fl .isFieldLike ( ) and
1796
- fl .getAnAssignedValue ( ) = pred .asExpr ( ) and
1797
- fl .getAnAccess ( ) = flr and
1798
- flr = succ .asExpr ( ) and
1799
- flr .hasNonlocalValue ( )
1837
+ exists ( FieldOrProperty f | f .isStatic ( ) |
1838
+ f .getAnAssignedValue ( ) = pred .asExpr ( ) and
1839
+ succ = TFlowInsensitiveFieldNode ( f )
1840
+ or
1841
+ exists ( FieldOrPropertyRead fr |
1842
+ pred = TFlowInsensitiveFieldNode ( f ) and
1843
+ f .getAnAccess ( ) = fr and
1844
+ fr = succ .asExpr ( ) and
1845
+ fr .hasNonlocalValue ( )
1846
+ )
1800
1847
)
1801
1848
or
1802
1849
FlowSummaryImpl:: Private:: Steps:: summaryJumpStep ( pred .( FlowSummaryNode ) .getSummaryNode ( ) ,
@@ -2248,6 +2295,8 @@ module PostUpdateNodes {
2248
2295
2249
2296
override DataFlowCallable getEnclosingCallableImpl ( ) {
2250
2297
result .asCallable ( ) = cfn .getEnclosingCallable ( )
2298
+ or
2299
+ result = getEnclosingStaticFieldOrProperty ( oc )
2251
2300
}
2252
2301
2253
2302
override DotNet:: Type getTypeImpl ( ) { result = oc .getType ( ) }
@@ -2279,6 +2328,8 @@ module PostUpdateNodes {
2279
2328
2280
2329
override DataFlowCallable getEnclosingCallableImpl ( ) {
2281
2330
result .asCallable ( ) = cfn .getEnclosingCallable ( )
2331
+ or
2332
+ result = getEnclosingStaticFieldOrProperty ( cfn .getAstNode ( ) )
2282
2333
}
2283
2334
2284
2335
override Type getTypeImpl ( ) { result = cfn .getAstNode ( ) .( Expr ) .getType ( ) }
@@ -2427,6 +2478,24 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
2427
2478
nodeTo .asExpr ( ) .( EventRead ) .getTarget ( ) = aee .getTarget ( ) and
2428
2479
preservesValue = false
2429
2480
)
2481
+ or
2482
+ preservesValue = true and
2483
+ exists ( FieldOrProperty f , FieldOrPropertyAccess fa |
2484
+ fa = f .getAnAccess ( ) and
2485
+ fa .targetIsLocalInstance ( )
2486
+ |
2487
+ exists ( AssignableDefinition def |
2488
+ def .getTargetAccess ( ) = fa and
2489
+ nodeFrom .asExpr ( ) = def .getSource ( ) and
2490
+ nodeTo = TFlowInsensitiveFieldNode ( f ) and
2491
+ nodeFrom .getEnclosingCallable ( ) instanceof Constructor
2492
+ )
2493
+ or
2494
+ nodeFrom = TFlowInsensitiveFieldNode ( f ) and
2495
+ f .getAnAccess ( ) = fa and
2496
+ fa = nodeTo .asExpr ( ) and
2497
+ fa .( FieldOrPropertyRead ) .hasNonlocalValue ( )
2498
+ )
2430
2499
}
2431
2500
2432
2501
/**
0 commit comments