@@ -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 ( ) {
@@ -911,7 +924,8 @@ private module Cached {
911
924
TFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn ) or
912
925
TParamsArgumentNode ( ControlFlow:: Node callCfn ) {
913
926
callCfn = any ( Call c | isParamsArg ( c , _, _) ) .getAControlFlowNode ( )
914
- }
927
+ } or
928
+ TFlowInsensitiveFieldNode ( FieldOrProperty f ) { f .isFieldLike ( ) }
915
929
916
930
/**
917
931
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
@@ -1021,6 +1035,8 @@ predicate nodeIsHidden(Node n) {
1021
1035
n instanceof ParamsArgumentNode
1022
1036
or
1023
1037
n .asExpr ( ) = any ( WithExpr we ) .getInitializer ( )
1038
+ or
1039
+ n instanceof FlowInsensitiveFieldNode
1024
1040
}
1025
1041
1026
1042
/** A CIL SSA definition, viewed as a node in a data flow graph. */
@@ -1346,6 +1362,8 @@ private module ArgumentNodes {
1346
1362
1347
1363
override DataFlowCallable getEnclosingCallableImpl ( ) {
1348
1364
result .asCallable ( ) = cfn .getEnclosingCallable ( )
1365
+ or
1366
+ result = getEnclosingStaticFieldOrProperty ( cfn .getAstNode ( ) )
1349
1367
}
1350
1368
1351
1369
override Type getTypeImpl ( ) { result = cfn .getAstNode ( ) .( Expr ) .getType ( ) }
@@ -1385,6 +1403,8 @@ private module ArgumentNodes {
1385
1403
1386
1404
override DataFlowCallable getEnclosingCallableImpl ( ) {
1387
1405
result .asCallable ( ) = callCfn .getEnclosingCallable ( )
1406
+ or
1407
+ result = getEnclosingStaticFieldOrProperty ( callCfn .getAstNode ( ) )
1388
1408
}
1389
1409
1390
1410
override Type getTypeImpl ( ) { result = this .getParameter ( ) .getType ( ) }
@@ -1784,6 +1804,30 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
1784
1804
}
1785
1805
}
1786
1806
1807
+ /**
1808
+ * A data flow node used for control-flow insensitive flow through fields
1809
+ * and properties.
1810
+ *
1811
+ * In global data flow this is used to model flow through static fields and
1812
+ * properties, while for lambda flow we additionally use it to track assignments
1813
+ * in constructors to uses within the same class.
1814
+ */
1815
+ class FlowInsensitiveFieldNode extends NodeImpl , TFlowInsensitiveFieldNode {
1816
+ private FieldOrProperty f ;
1817
+
1818
+ FlowInsensitiveFieldNode ( ) { this = TFlowInsensitiveFieldNode ( f ) }
1819
+
1820
+ override DataFlowCallable getEnclosingCallableImpl ( ) { result .asFieldOrProperty ( ) = f }
1821
+
1822
+ override Type getTypeImpl ( ) { result = f .getType ( ) }
1823
+
1824
+ override ControlFlow:: Node getControlFlowNodeImpl ( ) { none ( ) }
1825
+
1826
+ override Location getLocationImpl ( ) { result = f .getLocation ( ) }
1827
+
1828
+ override string toStringImpl ( ) { result = "[flow-insensitive] " + f }
1829
+ }
1830
+
1787
1831
/**
1788
1832
* Holds if `pred` can flow to `succ`, by jumping from one callable to
1789
1833
* another. Additional steps specified by the configuration are *not*
@@ -1792,13 +1836,16 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
1792
1836
predicate jumpStep ( Node pred , Node succ ) {
1793
1837
pred .( NonLocalJumpNode ) .getAJumpSuccessor ( true ) = succ
1794
1838
or
1795
- exists ( FieldOrProperty fl , FieldOrPropertyRead flr |
1796
- fl .isStatic ( ) and
1797
- fl .isFieldLike ( ) and
1798
- fl .getAnAssignedValue ( ) = pred .asExpr ( ) and
1799
- fl .getAnAccess ( ) = flr and
1800
- flr = succ .asExpr ( ) and
1801
- flr .hasNonlocalValue ( )
1839
+ exists ( FieldOrProperty f | f .isStatic ( ) |
1840
+ f .getAnAssignedValue ( ) = pred .asExpr ( ) and
1841
+ succ = TFlowInsensitiveFieldNode ( f )
1842
+ or
1843
+ exists ( FieldOrPropertyRead fr |
1844
+ pred = TFlowInsensitiveFieldNode ( f ) and
1845
+ f .getAnAccess ( ) = fr and
1846
+ fr = succ .asExpr ( ) and
1847
+ fr .hasNonlocalValue ( )
1848
+ )
1802
1849
)
1803
1850
or
1804
1851
FlowSummaryImpl:: Private:: Steps:: summaryJumpStep ( pred .( FlowSummaryNode ) .getSummaryNode ( ) ,
@@ -2258,6 +2305,8 @@ module PostUpdateNodes {
2258
2305
2259
2306
override DataFlowCallable getEnclosingCallableImpl ( ) {
2260
2307
result .asCallable ( ) = cfn .getEnclosingCallable ( )
2308
+ or
2309
+ result = getEnclosingStaticFieldOrProperty ( oc )
2261
2310
}
2262
2311
2263
2312
override DotNet:: Type getTypeImpl ( ) { result = oc .getType ( ) }
@@ -2289,6 +2338,8 @@ module PostUpdateNodes {
2289
2338
2290
2339
override DataFlowCallable getEnclosingCallableImpl ( ) {
2291
2340
result .asCallable ( ) = cfn .getEnclosingCallable ( )
2341
+ or
2342
+ result = getEnclosingStaticFieldOrProperty ( cfn .getAstNode ( ) )
2292
2343
}
2293
2344
2294
2345
override Type getTypeImpl ( ) { result = cfn .getAstNode ( ) .( Expr ) .getType ( ) }
@@ -2437,6 +2488,24 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
2437
2488
nodeTo .asExpr ( ) .( EventRead ) .getTarget ( ) = aee .getTarget ( ) and
2438
2489
preservesValue = false
2439
2490
)
2491
+ or
2492
+ preservesValue = true and
2493
+ exists ( FieldOrProperty f , FieldOrPropertyAccess fa |
2494
+ fa = f .getAnAccess ( ) and
2495
+ fa .targetIsLocalInstance ( )
2496
+ |
2497
+ exists ( AssignableDefinition def |
2498
+ def .getTargetAccess ( ) = fa and
2499
+ nodeFrom .asExpr ( ) = def .getSource ( ) and
2500
+ nodeTo = TFlowInsensitiveFieldNode ( f ) and
2501
+ nodeFrom .getEnclosingCallable ( ) instanceof Constructor
2502
+ )
2503
+ or
2504
+ nodeFrom = TFlowInsensitiveFieldNode ( f ) and
2505
+ f .getAnAccess ( ) = fa and
2506
+ fa = nodeTo .asExpr ( ) and
2507
+ fa .( FieldOrPropertyRead ) .hasNonlocalValue ( )
2508
+ )
2440
2509
}
2441
2510
2442
2511
/**
0 commit comments