@@ -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 ( ) {
@@ -911,7 +924,8 @@ private module Cached {
911924 TFlowSummaryNode ( FlowSummaryImpl:: Private:: SummaryNode sn ) or
912925 TParamsArgumentNode ( ControlFlow:: Node callCfn ) {
913926 callCfn = any ( Call c | isParamsArg ( c , _, _) ) .getAControlFlowNode ( )
914- }
927+ } or
928+ TFlowInsensitiveFieldNode ( FieldOrProperty f ) { f .isFieldLike ( ) }
915929
916930 /**
917931 * Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
@@ -1021,6 +1035,8 @@ predicate nodeIsHidden(Node n) {
10211035 n instanceof ParamsArgumentNode
10221036 or
10231037 n .asExpr ( ) = any ( WithExpr we ) .getInitializer ( )
1038+ or
1039+ n instanceof FlowInsensitiveFieldNode
10241040}
10251041
10261042/** A CIL SSA definition, viewed as a node in a data flow graph. */
@@ -1346,6 +1362,8 @@ private module ArgumentNodes {
13461362
13471363 override DataFlowCallable getEnclosingCallableImpl ( ) {
13481364 result .asCallable ( ) = cfn .getEnclosingCallable ( )
1365+ or
1366+ result = getEnclosingStaticFieldOrProperty ( cfn .getAstNode ( ) )
13491367 }
13501368
13511369 override Type getTypeImpl ( ) { result = cfn .getAstNode ( ) .( Expr ) .getType ( ) }
@@ -1385,6 +1403,8 @@ private module ArgumentNodes {
13851403
13861404 override DataFlowCallable getEnclosingCallableImpl ( ) {
13871405 result .asCallable ( ) = callCfn .getEnclosingCallable ( )
1406+ or
1407+ result = getEnclosingStaticFieldOrProperty ( callCfn .getAstNode ( ) )
13881408 }
13891409
13901410 override Type getTypeImpl ( ) { result = this .getParameter ( ) .getType ( ) }
@@ -1784,6 +1804,30 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
17841804 }
17851805}
17861806
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+
17871831/**
17881832 * Holds if `pred` can flow to `succ`, by jumping from one callable to
17891833 * another. Additional steps specified by the configuration are *not*
@@ -1792,13 +1836,16 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
17921836predicate jumpStep ( Node pred , Node succ ) {
17931837 pred .( NonLocalJumpNode ) .getAJumpSuccessor ( true ) = succ
17941838 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+ )
18021849 )
18031850 or
18041851 FlowSummaryImpl:: Private:: Steps:: summaryJumpStep ( pred .( FlowSummaryNode ) .getSummaryNode ( ) ,
@@ -2258,6 +2305,8 @@ module PostUpdateNodes {
22582305
22592306 override DataFlowCallable getEnclosingCallableImpl ( ) {
22602307 result .asCallable ( ) = cfn .getEnclosingCallable ( )
2308+ or
2309+ result = getEnclosingStaticFieldOrProperty ( oc )
22612310 }
22622311
22632312 override DotNet:: Type getTypeImpl ( ) { result = oc .getType ( ) }
@@ -2289,6 +2338,8 @@ module PostUpdateNodes {
22892338
22902339 override DataFlowCallable getEnclosingCallableImpl ( ) {
22912340 result .asCallable ( ) = cfn .getEnclosingCallable ( )
2341+ or
2342+ result = getEnclosingStaticFieldOrProperty ( cfn .getAstNode ( ) )
22922343 }
22932344
22942345 override Type getTypeImpl ( ) { result = cfn .getAstNode ( ) .( Expr ) .getType ( ) }
@@ -2437,6 +2488,24 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
24372488 nodeTo .asExpr ( ) .( EventRead ) .getTarget ( ) = aee .getTarget ( ) and
24382489 preservesValue = false
24392490 )
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+ )
24402509}
24412510
24422511/**
0 commit comments