Skip to content

Commit 49c4522

Browse files
committed
Ruby: add taint steps from case value to variables in patterns
1 parent 77a3e4b commit 49c4522

File tree

6 files changed

+102
-2
lines changed

6 files changed

+102
-2
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
3030
*/
3131
cached
3232
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
33+
// value of `case` expression into variables in patterns
34+
exists(VariableWriteAccess varDef, CaseExpr case, InClause clause, CfgNode nodeToCfg |
35+
clause = case.getABranch() and
36+
varDef.getParent*() = clause.getPattern() and
37+
nodeFrom.asExpr().getExpr() = case.getValue() and
38+
nodeToCfg = nodeTo.(SsaDefinitionNode).getDefinition().getControlFlowNode() and
39+
nodeToCfg = nodeFrom.asExpr().getASuccessor+() and
40+
nodeToCfg.getNode() = varDef
41+
)
42+
or
3343
// operation involving `nodeFrom`
3444
exists(CfgNodes::ExprNodes::OperationCfgNode op |
3545
op = nodeTo.asExpr() and

ruby/ql/test/library-tests/dataflow/local/DataflowStep.expected

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@
7070
| local_dataflow.rb:50:18:50:18 | [post] x | local_dataflow.rb:51:20:51:20 | x |
7171
| local_dataflow.rb:50:18:50:18 | x | local_dataflow.rb:51:20:51:20 | x |
7272
| local_dataflow.rb:51:9:51:15 | "break" | local_dataflow.rb:51:3:51:15 | break |
73+
| local_dataflow.rb:60:1:86:3 | self (test_case) | local_dataflow.rb:78:12:78:20 | self |
74+
| local_dataflow.rb:60:1:86:3 | self in test_case | local_dataflow.rb:78:12:78:20 | self |
75+
| local_dataflow.rb:60:1:86:3 | self in test_case | local_dataflow.rb:79:18:79:24 | self |
76+
| local_dataflow.rb:60:1:86:3 | self in test_case | local_dataflow.rb:80:22:80:28 | self |
77+
| local_dataflow.rb:60:1:86:3 | self in test_case | local_dataflow.rb:82:6:82:12 | self |
78+
| local_dataflow.rb:60:1:86:3 | self in test_case | local_dataflow.rb:83:6:83:12 | self |
79+
| local_dataflow.rb:60:1:86:3 | self in test_case | local_dataflow.rb:84:6:84:12 | self |
7380
| local_dataflow.rb:60:15:60:15 | x | local_dataflow.rb:60:15:60:15 | x |
7481
| local_dataflow.rb:60:15:60:15 | x | local_dataflow.rb:61:12:61:12 | x |
7582
| local_dataflow.rb:61:7:68:5 | case ... | local_dataflow.rb:61:3:68:5 | ... = ... |
@@ -100,3 +107,27 @@
100107
| local_dataflow.rb:73:7:73:7 | x | local_dataflow.rb:72:7:73:7 | then ... |
101108
| local_dataflow.rb:74:3:75:6 | else ... | local_dataflow.rb:69:7:76:5 | case ... |
102109
| local_dataflow.rb:75:6:75:6 | x | local_dataflow.rb:74:3:75:6 | else ... |
110+
| local_dataflow.rb:78:7:85:5 | case ... | local_dataflow.rb:78:3:85:5 | ... = ... |
111+
| local_dataflow.rb:78:12:78:20 | [post] self | local_dataflow.rb:79:18:79:24 | self |
112+
| local_dataflow.rb:78:12:78:20 | [post] self | local_dataflow.rb:80:22:80:28 | self |
113+
| local_dataflow.rb:78:12:78:20 | [post] self | local_dataflow.rb:82:6:82:12 | self |
114+
| local_dataflow.rb:78:12:78:20 | self | local_dataflow.rb:79:18:79:24 | self |
115+
| local_dataflow.rb:78:12:78:20 | self | local_dataflow.rb:80:22:80:28 | self |
116+
| local_dataflow.rb:78:12:78:20 | self | local_dataflow.rb:82:6:82:12 | self |
117+
| local_dataflow.rb:79:11:79:11 | b | local_dataflow.rb:79:23:79:23 | b |
118+
| local_dataflow.rb:79:13:79:43 | then ... | local_dataflow.rb:78:7:85:5 | case ... |
119+
| local_dataflow.rb:79:18:79:24 | call to sink | local_dataflow.rb:79:13:79:43 | then ... |
120+
| local_dataflow.rb:80:6:80:6 | a | local_dataflow.rb:80:11:80:11 | a |
121+
| local_dataflow.rb:80:11:80:11 | [post] a | local_dataflow.rb:80:27:80:27 | a |
122+
| local_dataflow.rb:80:11:80:11 | a | local_dataflow.rb:80:27:80:27 | a |
123+
| local_dataflow.rb:80:17:80:47 | then ... | local_dataflow.rb:78:7:85:5 | case ... |
124+
| local_dataflow.rb:80:22:80:28 | call to sink | local_dataflow.rb:80:17:80:47 | then ... |
125+
| local_dataflow.rb:81:7:81:7 | c | local_dataflow.rb:82:11:82:11 | c |
126+
| local_dataflow.rb:81:11:81:11 | d | local_dataflow.rb:83:11:83:11 | d |
127+
| local_dataflow.rb:81:14:81:14 | e | local_dataflow.rb:84:11:84:11 | e |
128+
| local_dataflow.rb:81:18:84:32 | then ... | local_dataflow.rb:78:7:85:5 | case ... |
129+
| local_dataflow.rb:81:23:84:13 | call to [] | local_dataflow.rb:81:18:84:32 | then ... |
130+
| local_dataflow.rb:82:6:82:12 | [post] self | local_dataflow.rb:83:6:83:12 | self |
131+
| local_dataflow.rb:82:6:82:12 | self | local_dataflow.rb:83:6:83:12 | self |
132+
| local_dataflow.rb:83:6:83:12 | [post] self | local_dataflow.rb:84:6:84:12 | self |
133+
| local_dataflow.rb:83:6:83:12 | self | local_dataflow.rb:84:6:84:12 | self |

ruby/ql/test/library-tests/dataflow/local/Nodes.expected

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ ret
1212
| local_dataflow.rb:50:3:50:13 | next |
1313
| local_dataflow.rb:51:3:51:15 | break |
1414
| local_dataflow.rb:52:3:52:10 | "normal" |
15-
| local_dataflow.rb:69:3:76:5 | ... = ... |
15+
| local_dataflow.rb:78:3:85:5 | ... = ... |
1616
arg
1717
| local_dataflow.rb:3:8:3:10 | self | local_dataflow.rb:3:8:3:10 | call to p | self |
1818
| local_dataflow.rb:3:10:3:10 | a | local_dataflow.rb:3:8:3:10 | call to p | position 0 |
@@ -49,3 +49,21 @@ arg
4949
| local_dataflow.rb:55:6:55:6 | 1 | local_dataflow.rb:55:5:55:13 | call to [] | position 0 |
5050
| local_dataflow.rb:55:9:55:9 | 2 | local_dataflow.rb:55:5:55:13 | call to [] | position 1 |
5151
| local_dataflow.rb:55:12:55:12 | 3 | local_dataflow.rb:55:5:55:13 | call to [] | position 2 |
52+
| local_dataflow.rb:78:12:78:20 | self | local_dataflow.rb:78:12:78:20 | call to source | self |
53+
| local_dataflow.rb:78:19:78:19 | 1 | local_dataflow.rb:78:12:78:20 | call to source | position 0 |
54+
| local_dataflow.rb:79:18:79:24 | self | local_dataflow.rb:79:18:79:24 | call to sink | self |
55+
| local_dataflow.rb:79:23:79:23 | b | local_dataflow.rb:79:18:79:24 | call to sink | position 0 |
56+
| local_dataflow.rb:80:11:80:11 | a | local_dataflow.rb:80:11:80:15 | ... > ... | self |
57+
| local_dataflow.rb:80:15:80:15 | 0 | local_dataflow.rb:80:11:80:15 | ... > ... | position 0 |
58+
| local_dataflow.rb:80:22:80:28 | self | local_dataflow.rb:80:22:80:28 | call to sink | self |
59+
| local_dataflow.rb:80:27:80:27 | a | local_dataflow.rb:80:22:80:28 | call to sink | position 0 |
60+
| local_dataflow.rb:81:23:84:13 | Array | local_dataflow.rb:81:23:84:13 | call to [] | self |
61+
| local_dataflow.rb:82:6:82:12 | call to sink | local_dataflow.rb:81:23:84:13 | call to [] | position 0 |
62+
| local_dataflow.rb:82:6:82:12 | self | local_dataflow.rb:82:6:82:12 | call to sink | self |
63+
| local_dataflow.rb:82:11:82:11 | c | local_dataflow.rb:82:6:82:12 | call to sink | position 0 |
64+
| local_dataflow.rb:83:6:83:12 | call to sink | local_dataflow.rb:81:23:84:13 | call to [] | position 1 |
65+
| local_dataflow.rb:83:6:83:12 | self | local_dataflow.rb:83:6:83:12 | call to sink | self |
66+
| local_dataflow.rb:83:11:83:11 | d | local_dataflow.rb:83:6:83:12 | call to sink | position 0 |
67+
| local_dataflow.rb:84:6:84:12 | call to sink | local_dataflow.rb:81:23:84:13 | call to [] | position 2 |
68+
| local_dataflow.rb:84:6:84:12 | self | local_dataflow.rb:84:6:84:12 | call to sink | self |
69+
| local_dataflow.rb:84:11:84:11 | e | local_dataflow.rb:84:6:84:12 | call to sink | position 0 |
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
failures
2+
edges
3+
| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:79:23:79:23 | b |
4+
| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:80:27:80:27 | a |
5+
| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:82:11:82:11 | c |
6+
| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:83:11:83:11 | d |
7+
| local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:84:11:84:11 | e |
8+
nodes
9+
| local_dataflow.rb:78:12:78:20 | call to source : | semmle.label | call to source : |
10+
| local_dataflow.rb:79:23:79:23 | b | semmle.label | b |
11+
| local_dataflow.rb:80:27:80:27 | a | semmle.label | a |
12+
| local_dataflow.rb:82:11:82:11 | c | semmle.label | c |
13+
| local_dataflow.rb:83:11:83:11 | d | semmle.label | d |
14+
| local_dataflow.rb:84:11:84:11 | e | semmle.label | e |
15+
subpaths
16+
#select
17+
| local_dataflow.rb:79:23:79:23 | b | local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:79:23:79:23 | b | $@ | local_dataflow.rb:78:12:78:20 | call to source : | call to source : |
18+
| local_dataflow.rb:80:27:80:27 | a | local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:80:27:80:27 | a | $@ | local_dataflow.rb:78:12:78:20 | call to source : | call to source : |
19+
| local_dataflow.rb:82:11:82:11 | c | local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:82:11:82:11 | c | $@ | local_dataflow.rb:78:12:78:20 | call to source : | call to source : |
20+
| local_dataflow.rb:83:11:83:11 | d | local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:83:11:83:11 | d | $@ | local_dataflow.rb:78:12:78:20 | call to source : | call to source : |
21+
| local_dataflow.rb:84:11:84:11 | e | local_dataflow.rb:78:12:78:20 | call to source : | local_dataflow.rb:84:11:84:11 | e | $@ | local_dataflow.rb:78:12:78:20 | call to source : | call to source : |
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* @kind path-problem
3+
*/
4+
5+
import ruby
6+
import TestUtilities.InlineFlowTest
7+
import PathGraph
8+
9+
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultTaintFlowConf conf
10+
where conf.hasFlowPath(source, sink)
11+
select sink, source, sink, "$@", source, source.toString()

ruby/ql/test/library-tests/dataflow/local/local_dataflow.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,14 @@ def test_case x
7474
else
7575
x
7676
end
77+
78+
z = case source(1)
79+
in 5 => b then sink(b) # $ hasTaintFlow=1
80+
in a if a > 0 then sink(a) # $ hasTaintFlow=1
81+
in [c, *d, e ] then [
82+
sink(c), # $ hasTaintFlow=1
83+
sink(d), # $ hasTaintFlow=1
84+
sink(e)] # $ hasTaintFlow=1
85+
end
7786
end
78-
87+

0 commit comments

Comments
 (0)