Skip to content

Commit 4239268

Browse files
committed
Ruby: Prevent some false flow into splat params
In cases where there are positional parameters after a splat parameter, don't attempt to match the splat parameter to a splat argument. We need more sophisticated modelling to handle these cases, which is future work.
1 parent 6f3e2cd commit 4239268

File tree

3 files changed

+50
-23
lines changed

3 files changed

+50
-23
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,9 @@ private module ParameterNodes {
629629
or
630630
exists(int n | n > 0 |
631631
parameter = callable.getParameter(n).(SplatParameter) and
632-
pos.isSplat(n)
632+
pos.isSplat(n) and
633+
// There are no positional parameters after the splat
634+
not exists(SimpleParameter p, int m | m > n | p = callable.getParameter(m))
633635
)
634636
)
635637
}

ruby/ql/test/library-tests/dataflow/params/params-flow.expected

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,8 @@ edges
7272
| params_flow.rb:67:13:67:16 | args | params_flow.rb:67:12:67:16 | * ... [element 0] |
7373
| params_flow.rb:69:14:69:14 | x | params_flow.rb:70:10:70:10 | x |
7474
| params_flow.rb:69:17:69:17 | y | params_flow.rb:71:10:71:10 | y |
75-
| params_flow.rb:69:20:69:21 | *z [element 0] | params_flow.rb:72:10:72:10 | z [element 0] |
76-
| params_flow.rb:69:20:69:21 | *z [element 1] | params_flow.rb:73:10:73:10 | z [element 1] |
7775
| params_flow.rb:69:24:69:24 | w | params_flow.rb:74:10:74:10 | w |
7876
| params_flow.rb:69:27:69:27 | r | params_flow.rb:75:10:75:10 | r |
79-
| params_flow.rb:72:10:72:10 | z [element 0] | params_flow.rb:72:10:72:13 | ...[...] |
80-
| params_flow.rb:73:10:73:10 | z [element 1] | params_flow.rb:73:10:73:13 | ...[...] |
8177
| params_flow.rb:78:10:78:18 | call to taint | params_flow.rb:69:14:69:14 | x |
8278
| params_flow.rb:78:21:78:29 | call to taint | params_flow.rb:69:17:69:17 | y |
8379
| params_flow.rb:78:43:78:51 | call to taint | params_flow.rb:69:24:69:24 | w |
@@ -91,12 +87,17 @@ edges
9187
| params_flow.rb:94:39:94:47 | call to taint | params_flow.rb:83:23:83:23 | w |
9288
| params_flow.rb:96:10:96:18 | call to taint | params_flow.rb:69:14:69:14 | x |
9389
| params_flow.rb:96:21:96:29 | call to taint | params_flow.rb:69:17:69:17 | y |
94-
| params_flow.rb:96:32:96:65 | * ... [element 0] | params_flow.rb:69:20:69:21 | *z [element 0] |
95-
| params_flow.rb:96:32:96:65 | * ... [element 1] | params_flow.rb:69:20:69:21 | *z [element 1] |
96-
| params_flow.rb:96:34:96:42 | call to taint | params_flow.rb:96:32:96:65 | * ... [element 0] |
97-
| params_flow.rb:96:45:96:53 | call to taint | params_flow.rb:96:32:96:65 | * ... [element 1] |
9890
| params_flow.rb:96:68:96:76 | call to taint | params_flow.rb:69:24:69:24 | w |
9991
| params_flow.rb:96:79:96:87 | call to taint | params_flow.rb:69:27:69:27 | r |
92+
| params_flow.rb:98:19:98:19 | a | params_flow.rb:99:10:99:10 | a |
93+
| params_flow.rb:98:31:98:31 | b | params_flow.rb:102:10:102:10 | b |
94+
| params_flow.rb:105:15:105:23 | call to taint | params_flow.rb:98:19:98:19 | a |
95+
| params_flow.rb:106:15:106:23 | call to taint | params_flow.rb:98:19:98:19 | a |
96+
| params_flow.rb:106:37:106:45 | call to taint | params_flow.rb:98:31:98:31 | b |
97+
| params_flow.rb:108:37:108:37 | a | params_flow.rb:109:10:109:10 | a |
98+
| params_flow.rb:108:44:108:44 | c | params_flow.rb:111:10:111:10 | c |
99+
| params_flow.rb:114:33:114:41 | call to taint | params_flow.rb:108:37:108:37 | a |
100+
| params_flow.rb:114:58:114:66 | call to taint | params_flow.rb:108:44:108:44 | c |
100101
nodes
101102
| params_flow.rb:9:16:9:17 | p1 | semmle.label | p1 |
102103
| params_flow.rb:9:20:9:21 | p2 | semmle.label | p2 |
@@ -179,16 +180,10 @@ nodes
179180
| params_flow.rb:67:13:67:16 | args | semmle.label | args |
180181
| params_flow.rb:69:14:69:14 | x | semmle.label | x |
181182
| params_flow.rb:69:17:69:17 | y | semmle.label | y |
182-
| params_flow.rb:69:20:69:21 | *z [element 0] | semmle.label | *z [element 0] |
183-
| params_flow.rb:69:20:69:21 | *z [element 1] | semmle.label | *z [element 1] |
184183
| params_flow.rb:69:24:69:24 | w | semmle.label | w |
185184
| params_flow.rb:69:27:69:27 | r | semmle.label | r |
186185
| params_flow.rb:70:10:70:10 | x | semmle.label | x |
187186
| params_flow.rb:71:10:71:10 | y | semmle.label | y |
188-
| params_flow.rb:72:10:72:10 | z [element 0] | semmle.label | z [element 0] |
189-
| params_flow.rb:72:10:72:13 | ...[...] | semmle.label | ...[...] |
190-
| params_flow.rb:73:10:73:10 | z [element 1] | semmle.label | z [element 1] |
191-
| params_flow.rb:73:10:73:13 | ...[...] | semmle.label | ...[...] |
192187
| params_flow.rb:74:10:74:10 | w | semmle.label | w |
193188
| params_flow.rb:75:10:75:10 | r | semmle.label | r |
194189
| params_flow.rb:78:10:78:18 | call to taint | semmle.label | call to taint |
@@ -207,12 +202,21 @@ nodes
207202
| params_flow.rb:94:39:94:47 | call to taint | semmle.label | call to taint |
208203
| params_flow.rb:96:10:96:18 | call to taint | semmle.label | call to taint |
209204
| params_flow.rb:96:21:96:29 | call to taint | semmle.label | call to taint |
210-
| params_flow.rb:96:32:96:65 | * ... [element 0] | semmle.label | * ... [element 0] |
211-
| params_flow.rb:96:32:96:65 | * ... [element 1] | semmle.label | * ... [element 1] |
212-
| params_flow.rb:96:34:96:42 | call to taint | semmle.label | call to taint |
213-
| params_flow.rb:96:45:96:53 | call to taint | semmle.label | call to taint |
214205
| params_flow.rb:96:68:96:76 | call to taint | semmle.label | call to taint |
215206
| params_flow.rb:96:79:96:87 | call to taint | semmle.label | call to taint |
207+
| params_flow.rb:98:19:98:19 | a | semmle.label | a |
208+
| params_flow.rb:98:31:98:31 | b | semmle.label | b |
209+
| params_flow.rb:99:10:99:10 | a | semmle.label | a |
210+
| params_flow.rb:102:10:102:10 | b | semmle.label | b |
211+
| params_flow.rb:105:15:105:23 | call to taint | semmle.label | call to taint |
212+
| params_flow.rb:106:15:106:23 | call to taint | semmle.label | call to taint |
213+
| params_flow.rb:106:37:106:45 | call to taint | semmle.label | call to taint |
214+
| params_flow.rb:108:37:108:37 | a | semmle.label | a |
215+
| params_flow.rb:108:44:108:44 | c | semmle.label | c |
216+
| params_flow.rb:109:10:109:10 | a | semmle.label | a |
217+
| params_flow.rb:111:10:111:10 | c | semmle.label | c |
218+
| params_flow.rb:114:33:114:41 | call to taint | semmle.label | call to taint |
219+
| params_flow.rb:114:58:114:66 | call to taint | semmle.label | call to taint |
216220
subpaths
217221
#select
218222
| params_flow.rb:10:10:10:11 | p1 | params_flow.rb:14:12:14:19 | call to taint | params_flow.rb:10:10:10:11 | p1 | $@ | params_flow.rb:14:12:14:19 | call to taint | call to taint |
@@ -245,12 +249,15 @@ subpaths
245249
| params_flow.rb:70:10:70:10 | x | params_flow.rb:96:10:96:18 | call to taint | params_flow.rb:70:10:70:10 | x | $@ | params_flow.rb:96:10:96:18 | call to taint | call to taint |
246250
| params_flow.rb:71:10:71:10 | y | params_flow.rb:78:21:78:29 | call to taint | params_flow.rb:71:10:71:10 | y | $@ | params_flow.rb:78:21:78:29 | call to taint | call to taint |
247251
| params_flow.rb:71:10:71:10 | y | params_flow.rb:96:21:96:29 | call to taint | params_flow.rb:71:10:71:10 | y | $@ | params_flow.rb:96:21:96:29 | call to taint | call to taint |
248-
| params_flow.rb:72:10:72:13 | ...[...] | params_flow.rb:96:34:96:42 | call to taint | params_flow.rb:72:10:72:13 | ...[...] | $@ | params_flow.rb:96:34:96:42 | call to taint | call to taint |
249-
| params_flow.rb:73:10:73:13 | ...[...] | params_flow.rb:96:45:96:53 | call to taint | params_flow.rb:73:10:73:13 | ...[...] | $@ | params_flow.rb:96:45:96:53 | call to taint | call to taint |
250252
| params_flow.rb:74:10:74:10 | w | params_flow.rb:78:43:78:51 | call to taint | params_flow.rb:74:10:74:10 | w | $@ | params_flow.rb:78:43:78:51 | call to taint | call to taint |
251253
| params_flow.rb:74:10:74:10 | w | params_flow.rb:96:68:96:76 | call to taint | params_flow.rb:74:10:74:10 | w | $@ | params_flow.rb:96:68:96:76 | call to taint | call to taint |
252254
| params_flow.rb:75:10:75:10 | r | params_flow.rb:78:54:78:62 | call to taint | params_flow.rb:75:10:75:10 | r | $@ | params_flow.rb:78:54:78:62 | call to taint | call to taint |
253255
| params_flow.rb:75:10:75:10 | r | params_flow.rb:96:79:96:87 | call to taint | params_flow.rb:75:10:75:10 | r | $@ | params_flow.rb:96:79:96:87 | call to taint | call to taint |
254256
| params_flow.rb:84:10:84:10 | t | params_flow.rb:94:10:94:18 | call to taint | params_flow.rb:84:10:84:10 | t | $@ | params_flow.rb:94:10:94:18 | call to taint | call to taint |
255257
| params_flow.rb:85:10:85:10 | u | params_flow.rb:94:21:94:29 | call to taint | params_flow.rb:85:10:85:10 | u | $@ | params_flow.rb:94:21:94:29 | call to taint | call to taint |
256258
| params_flow.rb:87:10:87:10 | w | params_flow.rb:94:39:94:47 | call to taint | params_flow.rb:87:10:87:10 | w | $@ | params_flow.rb:94:39:94:47 | call to taint | call to taint |
259+
| params_flow.rb:99:10:99:10 | a | params_flow.rb:105:15:105:23 | call to taint | params_flow.rb:99:10:99:10 | a | $@ | params_flow.rb:105:15:105:23 | call to taint | call to taint |
260+
| params_flow.rb:99:10:99:10 | a | params_flow.rb:106:15:106:23 | call to taint | params_flow.rb:99:10:99:10 | a | $@ | params_flow.rb:106:15:106:23 | call to taint | call to taint |
261+
| params_flow.rb:102:10:102:10 | b | params_flow.rb:106:37:106:45 | call to taint | params_flow.rb:102:10:102:10 | b | $@ | params_flow.rb:106:37:106:45 | call to taint | call to taint |
262+
| params_flow.rb:109:10:109:10 | a | params_flow.rb:114:33:114:41 | call to taint | params_flow.rb:109:10:109:10 | a | $@ | params_flow.rb:114:33:114:41 | call to taint | call to taint |
263+
| params_flow.rb:111:10:111:10 | c | params_flow.rb:114:58:114:66 | call to taint | params_flow.rb:111:10:111:10 | c | $@ | params_flow.rb:114:58:114:66 | call to taint | call to taint |

ruby/ql/test/library-tests/dataflow/params/params_flow.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ def splatstuff(*x)
6969
def splatmid(x, y, *z, w, r)
7070
sink x # $ hasValueFlow=27 $ hasValueFlow=32 $ hasValueFlow=45
7171
sink y # $ hasValueFlow=28 $ hasValueFlow=46 $ MISSING: hasValueFlow=33
72-
sink z[0] # $ hasValueFlow=47 $ MISSING: hasValueFlow=29 $ hasValueFlow=34
73-
sink z[1] # $ hasValueFlow=48 $ MISSING: hasValueFlow=35
72+
sink z[0] # MISSING: $ hasValueFlow=47 $ hasValueFlow=29 $ hasValueFlow=34
73+
sink z[1] # $ MISSING: hasValueFlow=48 $ hasValueFlow=35
7474
sink w # $ hasValueFlow=30 $ hasValueFlow=50 $ MISSING: hasValueFlow=36
7575
sink r # $ hasValueFlow=31 $ hasValueFlow=51 $ MISSING: hasValueFlow=37
7676
end
@@ -94,3 +94,21 @@ def pos_many(t, u, v, w, x, y, z)
9494
pos_many(taint(38), taint(39), *args, taint(44))
9595

9696
splatmid(taint(45), taint(46), *[taint(47), taint(48), taint(49)], taint(50), taint(51))
97+
98+
def splatmidsmall(a, *splats, b)
99+
sink a # $ hasValueFlow=52 $ hasValueFlow=55
100+
sink splats[0] # $ MISSING: hasValueFlow=53
101+
sink splats[1] # $ MISSING: hasValueFlow=54
102+
sink b # $ hasValueFlow=57
103+
end
104+
105+
splatmidsmall(taint(52), *[taint(53), taint(54)])
106+
splatmidsmall(taint(55), taint(56), taint(57))
107+
108+
def splat_followed_by_keyword_param(a, *b, c:)
109+
sink a # $ hasValueFlow=58
110+
sink b[0] # $ MISSING: hasValueFlow=59
111+
sink c # $ hasValueFlow=60
112+
end
113+
114+
splat_followed_by_keyword_param(taint(58), taint(59), c: taint(60))

0 commit comments

Comments
 (0)