@@ -71,6 +71,22 @@ CfgNodes::ExprCfgNode getAPostUpdateNodeForArg(Argument arg) {
71
71
not exists ( getALastEvalNode ( result ) )
72
72
}
73
73
74
+ /**
75
+ * Gets the data-flow node referencing SSA definition `def` at index `i` in basic
76
+ * block `bb`. The node is either the definition itself, or a read of the
77
+ * definition.
78
+ */
79
+ Node getSsaRefNode ( Ssa:: Definition def , BasicBlock bb , int i ) {
80
+ def = result .( SsaDefinitionNode ) .getDefinition ( ) and
81
+ def .definesAt ( _, bb , i )
82
+ or
83
+ exists ( CfgNodes:: ExprCfgNode e |
84
+ e = result .asExpr ( ) and
85
+ e = bb .getNode ( i ) and
86
+ e = def .getARead ( )
87
+ )
88
+ }
89
+
74
90
/** Provides predicates related to local data flow. */
75
91
module LocalFlow {
76
92
private import codeql.ruby.dataflow.internal.SsaImpl
@@ -80,15 +96,9 @@ module LocalFlow {
80
96
* can reach `next`.
81
97
*/
82
98
private predicate localFlowSsaInput ( Node nodeFrom , Ssa:: Definition def , Ssa:: Definition next ) {
83
- exists ( BasicBlock bb , int i | lastRefBeforeRedef ( def , bb , i , next ) |
84
- def = nodeFrom .( SsaDefinitionNode ) .getDefinition ( ) and
85
- def .definesAt ( _, bb , i )
86
- or
87
- exists ( CfgNodes:: ExprCfgNode e |
88
- e = nodeFrom .asExpr ( ) and
89
- e = bb .getNode ( i ) and
90
- e .getExpr ( ) instanceof VariableReadAccess
91
- )
99
+ exists ( BasicBlock bb , int i |
100
+ lastRefBeforeRedef ( def , bb , i , next ) and
101
+ nodeFrom = getSsaRefNode ( def , bb , i )
92
102
)
93
103
}
94
104
@@ -142,18 +152,15 @@ module LocalFlow {
142
152
// Flow into phi node
143
153
exists ( Ssa:: PhiNode phi |
144
154
localFlowSsaInput ( nodeFrom , def , phi ) and
145
- phi = nodeTo .( SsaDefinitionNode ) .getDefinition ( ) and
146
- def = phi .getAnInput ( )
155
+ phi = nodeTo .( SsaDefinitionNode ) .getDefinition ( )
147
156
)
157
+ // or
158
+ // // Flow into uncertain SSA definition
159
+ // exists(SsaImpl::UncertainWriteDefinition uncertain |
160
+ // localFlowSsaInput(nodeFrom, def, uncertain) and
161
+ // uncertain = nodeTo.(SsaDefinitionNode).getDefinition()
162
+ // )
148
163
)
149
- // TODO
150
- // or
151
- // // Flow into uncertain SSA definition
152
- // exists(LocalFlow::UncertainExplicitSsaDefinition uncertain |
153
- // localFlowSsaInput(nodeFrom, def, uncertain) and
154
- // uncertain = nodeTo.(SsaDefinitionNode).getDefinition() and
155
- // def = uncertain.getPriorDefinition()
156
- // )
157
164
}
158
165
159
166
predicate localFlowStepCommon ( Node nodeFrom , Node nodeTo ) {
@@ -996,12 +1003,19 @@ private module OutNodes {
996
1003
import OutNodes
997
1004
998
1005
predicate jumpStep ( Node pred , Node succ ) {
999
- SsaImpl:: captureFlowIn ( _, pred .( SsaDefinitionNode ) .getDefinition ( ) ,
1000
- succ .( SsaDefinitionNode ) .getDefinition ( ) )
1006
+ // Flow into a method via a captured variable
1007
+ exists ( Ssa:: Definition def , BasicBlock bb , int i |
1008
+ SsaImpl:: captureFlowIn ( _, def , bb , i , succ .( SsaDefinitionNode ) .getDefinition ( ) ) and
1009
+ [ pred , pred .( PostUpdateNode ) .getPreUpdateNode ( ) ] = getSsaRefNode ( def , bb , i )
1010
+ )
1001
1011
or
1012
+ // Flow out of a method directly via a captured variable
1002
1013
SsaImpl:: captureFlowOut ( _, pred .( SsaDefinitionNode ) .getDefinition ( ) ,
1003
1014
succ .( SsaDefinitionNode ) .getDefinition ( ) )
1004
1015
or
1016
+ // Flow out of a method via content on a captured variable
1017
+ SsaImpl:: captureContentFlowOut ( _, pred .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( ) , succ .asExpr ( ) )
1018
+ or
1005
1019
succ .asExpr ( ) .getExpr ( ) .( ConstantReadAccess ) .getValue ( ) = pred .asExpr ( ) .getExpr ( )
1006
1020
}
1007
1021
0 commit comments