@@ -17,6 +17,7 @@ private import semmle.code.csharp.frameworks.EntityFramework
1717private import semmle.code.csharp.frameworks.NHibernate
1818private import semmle.code.csharp.frameworks.system.Collections
1919private import semmle.code.csharp.frameworks.system.threading.Tasks
20+ private import semmle.code.cil.Ssa:: Ssa as CilSsa
2021
2122/** Gets the callable in which this node occurs. */
2223DataFlowCallable nodeGetEnclosingCallable ( NodeImpl n ) { result = n .getEnclosingCallableImpl ( ) }
@@ -177,6 +178,12 @@ predicate hasNodePath(ControlFlowReachabilityConfiguration conf, ExprNode n1, No
177178 )
178179}
179180
181+ /** Gets the CIL data-flow node for `node`, if any. */
182+ CIL:: DataFlowNode asCilDataFlowNode ( Node node ) {
183+ result = node .asParameter ( ) or
184+ result = node .asExpr ( )
185+ }
186+
180187/** Provides predicates related to local data flow. */
181188module LocalFlow {
182189 private class LocalExprStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -281,15 +288,6 @@ module LocalFlow {
281288 }
282289 }
283290
284- private CIL:: DataFlowNode asCilDataFlowNode ( Node node ) {
285- result = node .asParameter ( ) or
286- result = node .asExpr ( )
287- }
288-
289- private predicate localFlowStepCil ( Node nodeFrom , Node nodeTo ) {
290- asCilDataFlowNode ( nodeFrom ) .getALocalFlowSucc ( asCilDataFlowNode ( nodeTo ) , any ( CIL:: Untainted t ) )
291- }
292-
293291 /**
294292 * An uncertain SSA definition. Either an uncertain explicit definition or an
295293 * uncertain qualifier definition.
@@ -341,7 +339,7 @@ module LocalFlow {
341339
342340 /**
343341 * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
344- * SSA definition `def.
342+ * SSA definition `def` .
345343 */
346344 predicate localSsaFlowStep ( Ssa:: Definition def , Node nodeFrom , Node nodeTo ) {
347345 // Flow from SSA definition/parameter to first read
@@ -386,6 +384,76 @@ module LocalFlow {
386384 )
387385 }
388386
387+ private module CilFlow {
388+ private import semmle.code.cil.internal.SsaImpl as CilSsaImpl
389+
390+ /**
391+ * Holds if `nodeFrom` is a last node referencing SSA definition `def`, which
392+ * can reach `next`.
393+ */
394+ private predicate localFlowCilSsaInput (
395+ Node nodeFrom , CilSsa:: Definition def , CilSsa:: Definition next
396+ ) {
397+ exists ( CIL:: BasicBlock bb , int i | CilSsaImpl:: lastRefBeforeRedef ( def , bb , i , next ) |
398+ def .definesAt ( _, bb , i ) and
399+ def = nodeFrom .( CilSsaDefinitionNode ) .getDefinition ( )
400+ or
401+ nodeFrom = TCilExprNode ( bb .getNode ( i ) .( CIL:: ReadAccess ) )
402+ )
403+ }
404+
405+ /**
406+ * Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
407+ * CIL SSA definition `def`.
408+ */
409+ private predicate localCilSsaFlowStep ( CilSsa:: Definition def , Node nodeFrom , Node nodeTo ) {
410+ // Flow into SSA definition
411+ exists ( CIL:: VariableUpdate vu |
412+ vu = def .getVariableUpdate ( ) and
413+ vu .getSource ( ) = asCilDataFlowNode ( nodeFrom ) and
414+ def = nodeTo .( CilSsaDefinitionNode ) .getDefinition ( )
415+ )
416+ or
417+ // Flow from SSA definition to first read
418+ def = nodeFrom .( CilSsaDefinitionNode ) .getDefinition ( ) and
419+ nodeTo = TCilExprNode ( CilSsaImpl:: getAFirstRead ( def ) )
420+ or
421+ // Flow from read to next read
422+ exists ( CIL:: ReadAccess readFrom , CIL:: ReadAccess readTo |
423+ CilSsaImpl:: hasAdjacentReads ( def , readFrom , readTo ) and
424+ nodeTo = TCilExprNode ( readTo ) and
425+ nodeFrom = TCilExprNode ( readFrom )
426+ )
427+ or
428+ // Flow into phi node
429+ exists ( CilSsa:: PhiNode phi |
430+ localFlowCilSsaInput ( nodeFrom , def , phi ) and
431+ phi = nodeTo .( CilSsaDefinitionNode ) .getDefinition ( ) and
432+ def = CilSsaImpl:: getAPhiInput ( phi )
433+ )
434+ }
435+
436+ private predicate localExactStep ( CIL:: DataFlowNode src , CIL:: DataFlowNode sink ) {
437+ src = sink .( CIL:: Opcodes:: Dup ) .getAnOperand ( )
438+ or
439+ src = sink .( CIL:: Conversion ) .getExpr ( )
440+ or
441+ src = sink .( CIL:: WriteAccess ) .getExpr ( )
442+ or
443+ src = sink .( CIL:: Method ) .getAnImplementation ( ) .getAnInstruction ( ) .( CIL:: Return )
444+ or
445+ src = sink .( CIL:: Return ) .getExpr ( )
446+ or
447+ src = sink .( CIL:: ConditionalBranch ) .getAnOperand ( )
448+ }
449+
450+ predicate localFlowStepCil ( Node nodeFrom , Node nodeTo ) {
451+ localExactStep ( asCilDataFlowNode ( nodeFrom ) , asCilDataFlowNode ( nodeTo ) )
452+ or
453+ localCilSsaFlowStep ( _, nodeFrom , nodeTo )
454+ }
455+ }
456+
389457 predicate localFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
390458 exists ( Ssa:: Definition def |
391459 localSsaFlowStep ( def , nodeFrom , nodeTo ) and
@@ -398,7 +466,7 @@ module LocalFlow {
398466 or
399467 ThisFlow:: adjacentThisRefs ( nodeFrom .( PostUpdateNode ) .getPreUpdateNode ( ) , nodeTo )
400468 or
401- localFlowStepCil ( nodeFrom , nodeTo )
469+ CilFlow :: localFlowStepCil ( nodeFrom , nodeTo )
402470 }
403471
404472 /**
@@ -719,6 +787,7 @@ private module Cached {
719787 cfn .getElement ( ) instanceof Expr
720788 } or
721789 TCilExprNode ( CIL:: Expr e ) { e .getImplementation ( ) instanceof CIL:: BestImplementation } or
790+ TCilSsaDefinitionNode ( CilSsa:: Definition def ) or
722791 TSsaDefinitionNode ( Ssa:: Definition def ) {
723792 // Handled by `TExplicitParameterNode` below
724793 not def .( Ssa:: ExplicitDefinition ) .getADefinition ( ) instanceof
@@ -867,6 +936,28 @@ predicate nodeIsHidden(Node n) {
867936 n .asExpr ( ) = any ( WithExpr we ) .getInitializer ( )
868937}
869938
939+ /** A CIL SSA definition, viewed as a node in a data flow graph. */
940+ class CilSsaDefinitionNode extends NodeImpl , TCilSsaDefinitionNode {
941+ CilSsa:: Definition def ;
942+
943+ CilSsaDefinitionNode ( ) { this = TCilSsaDefinitionNode ( def ) }
944+
945+ /** Gets the underlying SSA definition. */
946+ CilSsa:: Definition getDefinition ( ) { result = def }
947+
948+ override DataFlowCallable getEnclosingCallableImpl ( ) {
949+ result .asCallable ( ) = def .getBasicBlock ( ) .getFirstNode ( ) .getImplementation ( ) .getMethod ( )
950+ }
951+
952+ override CIL:: Type getTypeImpl ( ) { result = def .getSourceVariable ( ) .getType ( ) }
953+
954+ override ControlFlow:: Node getControlFlowNodeImpl ( ) { none ( ) }
955+
956+ override Location getLocationImpl ( ) { result = def .getBasicBlock ( ) .getLocation ( ) }
957+
958+ override string toStringImpl ( ) { result = def .toString ( ) }
959+ }
960+
870961/** An SSA definition, viewed as a node in a data flow graph. */
871962class SsaDefinitionNode extends NodeImpl , TSsaDefinitionNode {
872963 Ssa:: Definition def ;
0 commit comments