Skip to content

Commit 253ccd1

Browse files
authored
Merge pull request #14303 from hvitved/ruby/must-flow
Ruby: Implement `localMustFlowStep `
2 parents 87ad09b + de0deab commit 253ccd1

File tree

6 files changed

+80
-7
lines changed

6 files changed

+80
-7
lines changed

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll

+20-1
Original file line numberDiff line numberDiff line change
@@ -1972,7 +1972,26 @@ private predicate mustHaveCollectionType(Node n, DataFlowType t) {
19721972
not n instanceof SynthSplatParameterNode
19731973
}
19741974

1975-
predicate localMustFlowStep(Node node1, Node node2) { none() }
1975+
predicate localMustFlowStep(Node node1, Node node2) {
1976+
node1 = SsaFlow::toParameterNodeImpl(node2)
1977+
or
1978+
exists(SsaImpl::Definition def |
1979+
def.(Ssa::WriteDefinition).assigns(node1.asExpr()) and
1980+
node2.(SsaDefinitionExtNode).getDefinitionExt() = def
1981+
or
1982+
def = node1.(SsaDefinitionExtNode).getDefinitionExt() and
1983+
node2.asExpr() = SsaImpl::getARead(def)
1984+
)
1985+
or
1986+
node1.asExpr() = node2.asExpr().(CfgNodes::ExprNodes::AssignExprCfgNode).getRhs()
1987+
or
1988+
node1.asExpr() = node2.asExpr().(CfgNodes::ExprNodes::BlockArgumentCfgNode).getValue()
1989+
or
1990+
node2.(ImplicitBlockArgumentNode).getParameterNode(_) = node1
1991+
or
1992+
FlowSummaryImpl::Private::Steps::summaryLocalMustFlowStep(node1.(FlowSummaryNode).getSummaryNode(),
1993+
node2.(FlowSummaryNode).getSummaryNode())
1994+
}
19761995

19771996
/** Gets the type of `n` used for type pruning. */
19781997
DataFlowType getNodeType(Node n) {

ruby/ql/test/library-tests/dataflow/call-sensitivity/call-sensitivity.expected

-5
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,9 @@ edges
7474
| call_sensitivity.rb:194:17:194:17 | x | call_sensitivity.rb:189:19:189:19 | x | provenance | |
7575
| call_sensitivity.rb:194:23:194:23 | x | call_sensitivity.rb:195:11:195:11 | x | provenance | |
7676
| call_sensitivity.rb:195:11:195:11 | x | call_sensitivity.rb:199:30:199:30 | x | provenance | |
77-
| call_sensitivity.rb:195:11:195:11 | x | call_sensitivity.rb:203:26:203:26 | x | provenance | |
7877
| call_sensitivity.rb:199:15:199:24 | ( ... ) | call_sensitivity.rb:193:19:193:19 | x | provenance | |
7978
| call_sensitivity.rb:199:16:199:23 | call to taint | call_sensitivity.rb:199:15:199:24 | ( ... ) | provenance | |
8079
| call_sensitivity.rb:199:30:199:30 | x | call_sensitivity.rb:200:8:200:8 | x | provenance | |
81-
| call_sensitivity.rb:203:26:203:26 | x | call_sensitivity.rb:204:8:204:8 | x | provenance | |
8280
| call_sensitivity.rb:207:16:207:16 | y | call_sensitivity.rb:209:9:209:9 | y | provenance | |
8381
| call_sensitivity.rb:209:9:209:9 | y | call_sensitivity.rb:214:9:214:9 | x | provenance | |
8482
| call_sensitivity.rb:214:9:214:9 | x | call_sensitivity.rb:215:10:215:10 | x | provenance | |
@@ -169,8 +167,6 @@ nodes
169167
| call_sensitivity.rb:199:16:199:23 | call to taint | semmle.label | call to taint |
170168
| call_sensitivity.rb:199:30:199:30 | x | semmle.label | x |
171169
| call_sensitivity.rb:200:8:200:8 | x | semmle.label | x |
172-
| call_sensitivity.rb:203:26:203:26 | x | semmle.label | x |
173-
| call_sensitivity.rb:204:8:204:8 | x | semmle.label | x |
174170
| call_sensitivity.rb:207:16:207:16 | y | semmle.label | y |
175171
| call_sensitivity.rb:209:9:209:9 | y | semmle.label | y |
176172
| call_sensitivity.rb:214:9:214:9 | x | semmle.label | x |
@@ -204,7 +200,6 @@ testFailures
204200
| call_sensitivity.rb:105:10:105:10 | x | call_sensitivity.rb:178:11:178:19 | call to taint | call_sensitivity.rb:105:10:105:10 | x | $@ | call_sensitivity.rb:178:11:178:19 | call to taint | call to taint |
205201
| call_sensitivity.rb:105:10:105:10 | x | call_sensitivity.rb:187:12:187:19 | call to taint | call_sensitivity.rb:105:10:105:10 | x | $@ | call_sensitivity.rb:187:12:187:19 | call to taint | call to taint |
206202
| call_sensitivity.rb:200:8:200:8 | x | call_sensitivity.rb:199:16:199:23 | call to taint | call_sensitivity.rb:200:8:200:8 | x | $@ | call_sensitivity.rb:199:16:199:23 | call to taint | call to taint |
207-
| call_sensitivity.rb:204:8:204:8 | x | call_sensitivity.rb:199:16:199:23 | call to taint | call_sensitivity.rb:204:8:204:8 | x | $@ | call_sensitivity.rb:199:16:199:23 | call to taint | call to taint |
208203
| call_sensitivity.rb:215:10:215:10 | x | call_sensitivity.rb:222:16:222:23 | call to taint | call_sensitivity.rb:215:10:215:10 | x | $@ | call_sensitivity.rb:222:16:222:23 | call to taint | call to taint |
209204
mayBenefitFromCallContext
210205
| call_sensitivity.rb:6:5:6:21 | call to puts |

ruby/ql/test/library-tests/dataflow/call-sensitivity/call_sensitivity.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def invoke_block2 x
201201
end
202202

203203
invoke_block2 "safe" do |x|
204-
sink x # $ SPURIOUS hasValueFlow=37
204+
sink x
205205
end
206206

207207
def call_m (x, y)

ruby/ql/test/library-tests/dataflow/global/Flow.expected

+28
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ edges
55
| blocks.rb:18:11:18:11 | x | blocks.rb:24:18:24:18 | x | provenance | |
66
| blocks.rb:24:3:24:11 | call to source | blocks.rb:17:10:17:10 | x | provenance | |
77
| blocks.rb:24:18:24:18 | x | blocks.rb:25:8:25:8 | x | provenance | |
8+
| callbacks.rb:9:15:9:15 | x | callbacks.rb:10:12:10:12 | x | provenance | |
9+
| callbacks.rb:10:12:10:12 | x | callbacks.rb:17:15:17:15 | x | provenance | |
10+
| callbacks.rb:13:20:13:20 | x | callbacks.rb:14:14:14:14 | x | provenance | |
11+
| callbacks.rb:14:14:14:14 | x | callbacks.rb:9:15:9:15 | x | provenance | |
12+
| callbacks.rb:17:15:17:15 | x | callbacks.rb:17:25:17:25 | x | provenance | |
13+
| callbacks.rb:17:31:17:38 | call to taint | callbacks.rb:13:20:13:20 | x | provenance | |
14+
| callbacks.rb:20:17:20:17 | x | callbacks.rb:21:11:21:11 | x | provenance | |
15+
| callbacks.rb:21:11:21:11 | x | callbacks.rb:28:31:28:31 | x | provenance | |
16+
| callbacks.rb:24:23:24:23 | x | callbacks.rb:25:17:25:17 | x | provenance | |
17+
| callbacks.rb:25:17:25:17 | x | callbacks.rb:20:17:20:17 | x | provenance | |
18+
| callbacks.rb:28:18:28:25 | call to taint | callbacks.rb:24:23:24:23 | x | provenance | |
19+
| callbacks.rb:28:31:28:31 | x | callbacks.rb:28:39:28:39 | x | provenance | |
820
| captured_variables.rb:9:24:9:24 | x | captured_variables.rb:11:5:11:6 | fn : [lambda] [captured x] | provenance | |
921
| captured_variables.rb:11:5:11:6 | fn : [lambda] [captured x] | captured_variables.rb:10:20:10:20 | x | provenance | |
1022
| captured_variables.rb:13:20:13:29 | call to taint | captured_variables.rb:9:24:9:24 | x | provenance | |
@@ -272,6 +284,20 @@ nodes
272284
| blocks.rb:24:3:24:11 | call to source | semmle.label | call to source |
273285
| blocks.rb:24:18:24:18 | x | semmle.label | x |
274286
| blocks.rb:25:8:25:8 | x | semmle.label | x |
287+
| callbacks.rb:9:15:9:15 | x | semmle.label | x |
288+
| callbacks.rb:10:12:10:12 | x | semmle.label | x |
289+
| callbacks.rb:13:20:13:20 | x | semmle.label | x |
290+
| callbacks.rb:14:14:14:14 | x | semmle.label | x |
291+
| callbacks.rb:17:15:17:15 | x | semmle.label | x |
292+
| callbacks.rb:17:25:17:25 | x | semmle.label | x |
293+
| callbacks.rb:17:31:17:38 | call to taint | semmle.label | call to taint |
294+
| callbacks.rb:20:17:20:17 | x | semmle.label | x |
295+
| callbacks.rb:21:11:21:11 | x | semmle.label | x |
296+
| callbacks.rb:24:23:24:23 | x | semmle.label | x |
297+
| callbacks.rb:25:17:25:17 | x | semmle.label | x |
298+
| callbacks.rb:28:18:28:25 | call to taint | semmle.label | call to taint |
299+
| callbacks.rb:28:31:28:31 | x | semmle.label | x |
300+
| callbacks.rb:28:39:28:39 | x | semmle.label | x |
275301
| captured_variables.rb:9:24:9:24 | x | semmle.label | x |
276302
| captured_variables.rb:10:20:10:20 | x | semmle.label | x |
277303
| captured_variables.rb:11:5:11:6 | fn : [lambda] [captured x] | semmle.label | fn : [lambda] [captured x] |
@@ -585,6 +611,8 @@ testFailures
585611
#select
586612
| blocks.rb:8:10:8:14 | yield ... | blocks.rb:14:12:14:20 | call to source | blocks.rb:8:10:8:14 | yield ... | $@ | blocks.rb:14:12:14:20 | call to source | call to source |
587613
| blocks.rb:25:8:25:8 | x | blocks.rb:24:3:24:11 | call to source | blocks.rb:25:8:25:8 | x | $@ | blocks.rb:24:3:24:11 | call to source | call to source |
614+
| callbacks.rb:17:25:17:25 | x | callbacks.rb:17:31:17:38 | call to taint | callbacks.rb:17:25:17:25 | x | $@ | callbacks.rb:17:31:17:38 | call to taint | call to taint |
615+
| callbacks.rb:28:39:28:39 | x | callbacks.rb:28:18:28:25 | call to taint | callbacks.rb:28:39:28:39 | x | $@ | callbacks.rb:28:18:28:25 | call to taint | call to taint |
588616
| captured_variables.rb:10:20:10:20 | x | captured_variables.rb:13:20:13:29 | call to taint | captured_variables.rb:10:20:10:20 | x | $@ | captured_variables.rb:13:20:13:29 | call to taint | call to taint |
589617
| captured_variables.rb:17:14:17:14 | x | captured_variables.rb:20:25:20:34 | call to taint | captured_variables.rb:17:14:17:14 | x | $@ | captured_variables.rb:20:25:20:34 | call to taint | call to taint |
590618
| captured_variables.rb:24:14:24:14 | x | captured_variables.rb:27:48:27:57 | call to taint | captured_variables.rb:24:14:24:14 | x | $@ | captured_variables.rb:27:48:27:57 | call to taint | call to taint |

ruby/ql/test/library-tests/dataflow/global/TypeTrackingInlineTest.expected

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
| blocks.rb:4:10:4:10 | r | Fixed missing result: hasValueFlow=1 |
2+
| callbacks.rb:17:41:17:58 | # $ hasValueFlow=1 | Missing result: hasValueFlow=1 |
3+
| callbacks.rb:29:37:29:37 | x | Unexpected result: hasValueFlow=2 |
24
| captured_variables.rb:50:10:50:10 | x | Fixed missing result: hasValueFlow=2 |
35
| captured_variables.rb:68:25:68:68 | # $ hasValueFlow=3 $ MISSING: hasValueFlow=4 | Missing result: hasValueFlow=3 |
46
| captured_variables.rb:72:21:72:66 | # $ hasValueFlow=4 $ SPURIOUS: hasValueFlow=3 | Fixed spurious result: hasValueFlow=3 |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
def taint x
2+
x
3+
end
4+
5+
def sink x
6+
puts "SINK: #{x}"
7+
end
8+
9+
def apply (f, x)
10+
f.call(x)
11+
end
12+
13+
def apply_wrap (f, x)
14+
apply(f, x)
15+
end
16+
17+
apply_wrap(->(x) { sink(x) }, taint(1)) # $ hasValueFlow=1
18+
apply_wrap(->(x) { sink(x) }, "safe")
19+
20+
def apply_block x
21+
yield x
22+
end
23+
24+
def apply_block_wrap (x, &block)
25+
apply_block(x, &block)
26+
end
27+
28+
apply_block_wrap(taint(2)) { |x| sink(x) } # $ hasValueFlow=2
29+
apply_block_wrap("safe") { |x| sink(x) }

0 commit comments

Comments
 (0)