@@ -69,13 +69,26 @@ abstract class NodeImpl extends Node {
6969 abstract string toStringImpl ( ) ;
7070}
7171
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+
7283private class ExprNodeImpl extends ExprNode , NodeImpl {
7384 override DataFlowCallable getEnclosingCallableImpl ( ) {
7485 result .asCallable ( ) =
7586 [
7687 this .getExpr ( ) .( CIL:: Expr ) .getEnclosingCallable ( ) .( DotNet:: Callable ) ,
7788 this .getControlFlowNodeImpl ( ) .getEnclosingCallable ( )
7889 ]
90+ or
91+ result = getEnclosingStaticFieldOrProperty ( this .asExpr ( ) )
7992 }
8093
8194 override DotNet:: Type getTypeImpl ( ) {
@@ -909,7 +922,8 @@ private module Cached {
909922 TFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn ) or
910923 TParamsArgumentNode ( ControlFlow:: Node callCfn ) {
911924 callCfn = any ( Call c | isParamsArg ( c , _, _) ) .getAControlFlowNode ( )
912- }
925+ } or
926+ TFlowInsensitiveFieldNode ( FieldOrProperty f ) { f .isFieldLike ( ) }
913927
914928 /**
915929 * Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
@@ -1019,6 +1033,8 @@ predicate nodeIsHidden(Node n) {
10191033 n instanceof ParamsArgumentNode
10201034 or
10211035 n .asExpr ( ) = any ( WithExpr we ) .getInitializer ( )
1036+ or
1037+ n instanceof FlowInsensitiveFieldNode
10221038}
10231039
10241040/** A CIL SSA definition, viewed as a node in a data flow graph. */
@@ -1344,6 +1360,8 @@ private module ArgumentNodes {
13441360
13451361 override DataFlowCallable getEnclosingCallableImpl ( ) {
13461362 result .asCallable ( ) = cfn .getEnclosingCallable ( )
1363+ or
1364+ result = getEnclosingStaticFieldOrProperty ( cfn .getAstNode ( ) )
13471365 }
13481366
13491367 override Type getTypeImpl ( ) { result = cfn .getAstNode ( ) .( Expr ) .getType ( ) }
@@ -1383,6 +1401,8 @@ private module ArgumentNodes {
13831401
13841402 override DataFlowCallable getEnclosingCallableImpl ( ) {
13851403 result .asCallable ( ) = callCfn .getEnclosingCallable ( )
1404+ or
1405+ result = getEnclosingStaticFieldOrProperty ( callCfn .getAstNode ( ) )
13861406 }
13871407
13881408 override Type getTypeImpl ( ) { result = this .getParameter ( ) .getType ( ) }
@@ -1782,6 +1802,30 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
17821802 }
17831803}
17841804
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+
17851829/**
17861830 * Holds if `pred` can flow to `succ`, by jumping from one callable to
17871831 * another. Additional steps specified by the configuration are *not*
@@ -1790,13 +1834,16 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
17901834predicate jumpStep ( Node pred , Node succ ) {
17911835 pred .( NonLocalJumpNode ) .getAJumpSuccessor ( true ) = succ
17921836 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+ )
18001847 )
18011848 or
18021849 FlowSummaryImpl:: Private:: Steps:: summaryJumpStep ( pred .( FlowSummaryNode ) .getSummaryNode ( ) ,
@@ -2248,6 +2295,8 @@ module PostUpdateNodes {
22482295
22492296 override DataFlowCallable getEnclosingCallableImpl ( ) {
22502297 result .asCallable ( ) = cfn .getEnclosingCallable ( )
2298+ or
2299+ result = getEnclosingStaticFieldOrProperty ( oc )
22512300 }
22522301
22532302 override DotNet:: Type getTypeImpl ( ) { result = oc .getType ( ) }
@@ -2279,6 +2328,8 @@ module PostUpdateNodes {
22792328
22802329 override DataFlowCallable getEnclosingCallableImpl ( ) {
22812330 result .asCallable ( ) = cfn .getEnclosingCallable ( )
2331+ or
2332+ result = getEnclosingStaticFieldOrProperty ( cfn .getAstNode ( ) )
22822333 }
22832334
22842335 override Type getTypeImpl ( ) { result = cfn .getAstNode ( ) .( Expr ) .getType ( ) }
@@ -2427,6 +2478,24 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
24272478 nodeTo .asExpr ( ) .( EventRead ) .getTarget ( ) = aee .getTarget ( ) and
24282479 preservesValue = false
24292480 )
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+ )
24302499}
24312500
24322501/**
0 commit comments