@@ -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 ) {
@@ -995,10 +1002,8 @@ private module OutNodes {
995
1002
996
1003
import OutNodes
997
1004
998
- predicate jumpStep ( Node pred , Node succ ) {
999
- SsaImpl:: captureFlowIn ( _, pred .( SsaDefinitionNode ) .getDefinition ( ) ,
1000
- succ .( SsaDefinitionNode ) .getDefinition ( ) )
1001
- or
1005
+ private predicate jumpStepCommon ( Node pred , Node succ ) {
1006
+ // Flow out of a method directly via a captured variable
1002
1007
SsaImpl:: captureFlowOut ( _, pred .( SsaDefinitionNode ) .getDefinition ( ) ,
1003
1008
succ .( SsaDefinitionNode ) .getDefinition ( ) )
1004
1009
or
@@ -1007,6 +1012,33 @@ predicate jumpStep(Node pred, Node succ) {
1007
1012
FlowSummaryImpl:: Private:: Steps:: summaryJumpStep ( pred , succ )
1008
1013
}
1009
1014
1015
+ predicate jumpStep ( Node pred , Node succ ) {
1016
+ jumpStepCommon ( pred , succ )
1017
+ or
1018
+ // Flow into a method via a captured variable
1019
+ exists ( Ssa:: Definition def , BasicBlock bb , int i |
1020
+ SsaImpl:: captureFlowIn ( _, def , bb , i , succ .( SsaDefinitionNode ) .getDefinition ( ) ) and
1021
+ [ pred , pred .( PostUpdateNode ) .getPreUpdateNode ( ) ] = getSsaRefNode ( def , bb , i )
1022
+ )
1023
+ or
1024
+ // Flow out of a method via content on a captured variable
1025
+ exists ( CfgNodes:: ExprNodes:: LocalVariableReadAccessCfgNode inner |
1026
+ inner = pred .( PostUpdateNode ) .getPreUpdateNode ( ) .asExpr ( )
1027
+ |
1028
+ SsaImpl:: captureContentFlowOut ( _, inner , succ .asExpr ( ) )
1029
+ or
1030
+ SsaImpl:: captureContentFlowOutPhi ( _, inner , succ .( SsaDefinitionNode ) .getDefinition ( ) )
1031
+ )
1032
+ }
1033
+
1034
+ predicate jumpStepTypeTracker ( Node nodeFrom , Node nodeTo ) {
1035
+ jumpStepCommon ( nodeFrom , nodeTo )
1036
+ or
1037
+ // Flow into a method via a captured variable
1038
+ SsaImpl:: captureFlowIn ( _, nodeFrom .( SsaDefinitionNode ) .getDefinition ( ) , _, _,
1039
+ nodeTo .( SsaDefinitionNode ) .getDefinition ( ) )
1040
+ }
1041
+
1010
1042
private ContentSet getKeywordContent ( string name ) {
1011
1043
exists ( ConstantValue:: ConstantSymbolValue key |
1012
1044
result .isSingleton ( TKnownElementContent ( key ) ) and
0 commit comments