Skip to content

Commit 0a02b45

Browse files
committed
Ruby: More filter flow steps
Add a jump step from the last self post-update node in a method to the self parameter of the next method.
1 parent fae5320 commit 0a02b45

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

ruby/ql/lib/codeql/ruby/frameworks/actioncontroller/Filters.qll

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,32 @@ module Filters {
428428
)
429429
}
430430

431+
/**
432+
* Holds if `n` is a post-update node for `self` in method `m`.
433+
*/
434+
predicate selfPostUpdate(DataFlow::PostUpdateNode n, Method m) {
435+
n.getPreUpdateNode().asExpr() instanceof SelfVariableAccessCfgNode and
436+
m = n.getPreUpdateNode().asExpr().getExpr().getEnclosingCallable()
437+
}
438+
439+
/**
440+
* Holds if `n` is the syntactically last dataflow node in `m` that satisfies `selfPostUpdate`.
441+
* In the example below, `n` is the post-update node for `bar`.
442+
* ```rb
443+
* def m
444+
* foo
445+
* bar
446+
* end
447+
* ```
448+
*/
449+
predicate lastSelfPostUpdate(DataFlow::PostUpdateNode n, Method m) {
450+
selfPostUpdate(n, m) and
451+
not exists(DataFlow::PostUpdateNode n2 |
452+
selfPostUpdate(n2, m) and
453+
n.getPreUpdateNode().asExpr().getASuccessor+() = n2.getPreUpdateNode().asExpr()
454+
)
455+
}
456+
431457
/**
432458
* Holds if `a` is the syntactically last access of the self variable `v` in method `m`.
433459
*/
@@ -468,7 +494,8 @@ module Filters {
468494
exists(Method predMethod, Method succMethod |
469495
next(predMethod, succMethod) and
470496
(
471-
// Flow from an update of self in `pred` to the self parameter of `succ`
497+
// Flow from an update of self (due to an instance variable write) in
498+
// `pred` to the self parameter of `succ`
472499
//
473500
// def a
474501
// @x = 1 ---+
@@ -480,6 +507,18 @@ module Filters {
480507
lastVariableAccessPostUpdate(pred, predMethod) and
481508
selfParameter(succ, succMethod)
482509
or
510+
// Flow from an update of self in `pred` to the self parameter of `succ`
511+
//
512+
// def a
513+
// @x = 1 ---+
514+
// end |
515+
// |
516+
// def b <----+
517+
// ...
518+
//
519+
lastSelfPostUpdate(pred, predMethod) and
520+
selfParameter(succ, succMethod)
521+
or
483522
// When there is no update of self in `pred`, flow from the last access to self to the self parameter of `succ`
484523
//
485524
// def a

ruby/ql/test/library-tests/frameworks/action_controller/Filters.expected

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,38 @@ additionalFlowSteps
55
| controllers/application_controller.rb:7:5:7:9 | [post] self | controllers/posts_controller.rb:12:3:15:5 | self in index |
66
| controllers/application_controller.rb:7:5:7:9 | [post] self | controllers/posts_controller.rb:17:3:18:5 | self in show |
77
| controllers/application_controller.rb:7:5:7:9 | [post] self | controllers/posts_controller.rb:20:3:21:5 | self in upvote |
8+
| controllers/application_controller.rb:7:23:7:29 | [post] self | controllers/comments_controller.rb:74:3:77:5 | self in ensure_user_can_edit_comments |
9+
| controllers/application_controller.rb:7:23:7:29 | [post] self | controllers/comments_controller.rb:79:3:81:5 | self in set_comment |
10+
| controllers/application_controller.rb:7:23:7:29 | [post] self | controllers/comments_controller.rb:99:3:100:5 | self in foo |
11+
| controllers/application_controller.rb:7:23:7:29 | [post] self | controllers/posts_controller.rb:12:3:15:5 | self in index |
12+
| controllers/application_controller.rb:7:23:7:29 | [post] self | controllers/posts_controller.rb:17:3:18:5 | self in show |
13+
| controllers/application_controller.rb:7:23:7:29 | [post] self | controllers/posts_controller.rb:20:3:21:5 | self in upvote |
14+
| controllers/application_controller.rb:11:53:11:59 | [post] self | controllers/application_controller.rb:6:3:8:5 | self in set_user |
15+
| controllers/application_controller.rb:11:53:11:59 | [post] self | controllers/photos_controller.rb:3:3:6:5 | self in show |
16+
| controllers/application_controller.rb:11:53:11:59 | [post] self | controllers/posts_controller.rb:25:3:27:5 | self in set_post |
817
| controllers/application_controller.rb:11:53:11:59 | self | controllers/application_controller.rb:6:3:8:5 | self in set_user |
918
| controllers/application_controller.rb:11:53:11:59 | self | controllers/photos_controller.rb:3:3:6:5 | self in show |
1019
| controllers/application_controller.rb:11:53:11:59 | self | controllers/posts_controller.rb:25:3:27:5 | self in set_post |
20+
| controllers/comments_controller.rb:50:5:50:12 | [post] self | controllers/comments_controller.rb:87:3:89:5 | self in check_feature_flags |
1121
| controllers/comments_controller.rb:50:5:50:12 | self | controllers/comments_controller.rb:87:3:89:5 | self in check_feature_flags |
1222
| controllers/comments_controller.rb:53:3:54:5 | self in create | controllers/comments_controller.rb:83:3:85:5 | self in log_comment_change |
23+
| controllers/comments_controller.rb:57:5:61:7 | [post] self | controllers/comments_controller.rb:87:3:89:5 | self in check_feature_flags |
1324
| controllers/comments_controller.rb:57:5:61:7 | self | controllers/comments_controller.rb:87:3:89:5 | self in check_feature_flags |
1425
| controllers/comments_controller.rb:58:33:58:48 | self | controllers/comments_controller.rb:87:3:89:5 | self in check_feature_flags |
1526
| controllers/comments_controller.rb:60:58:60:63 | self | controllers/comments_controller.rb:87:3:89:5 | self in check_feature_flags |
27+
| controllers/comments_controller.rb:65:15:65:20 | [post] self | controllers/comments_controller.rb:83:3:85:5 | self in log_comment_change |
1628
| controllers/comments_controller.rb:65:15:65:20 | self | controllers/comments_controller.rb:83:3:85:5 | self in log_comment_change |
29+
| controllers/comments_controller.rb:69:12:69:18 | [post] self | controllers/comments_controller.rb:83:3:85:5 | self in log_comment_change |
1730
| controllers/comments_controller.rb:69:12:69:18 | self | controllers/comments_controller.rb:83:3:85:5 | self in log_comment_change |
31+
| controllers/comments_controller.rb:76:5:76:68 | [post] self | controllers/comments_controller.rb:79:3:81:5 | self in set_comment |
32+
| controllers/comments_controller.rb:76:5:76:68 | [post] self | controllers/comments_controller.rb:99:3:100:5 | self in foo |
1833
| controllers/comments_controller.rb:76:5:76:68 | self | controllers/comments_controller.rb:79:3:81:5 | self in set_comment |
1934
| controllers/comments_controller.rb:76:5:76:68 | self | controllers/comments_controller.rb:99:3:100:5 | self in foo |
2035
| controllers/comments_controller.rb:80:5:80:12 | [post] self | controllers/comments_controller.rb:99:3:100:5 | self in foo |
36+
| controllers/comments_controller.rb:80:36:80:41 | [post] self | controllers/comments_controller.rb:99:3:100:5 | self in foo |
37+
| controllers/comments_controller.rb:84:61:84:68 | [post] self | controllers/comments_controller.rb:87:3:89:5 | self in check_feature_flags |
2138
| controllers/comments_controller.rb:84:61:84:68 | self | controllers/comments_controller.rb:87:3:89:5 | self in check_feature_flags |
39+
| controllers/comments_controller.rb:88:5:88:28 | [post] self | controllers/comments_controller.rb:95:3:97:5 | self in this_must_run_last |
2240
| controllers/comments_controller.rb:88:5:88:28 | self | controllers/comments_controller.rb:95:3:97:5 | self in this_must_run_last |
2341
| controllers/comments_controller.rb:91:3:93:5 | self in this_must_run_first | controllers/application_controller.rb:10:3:12:5 | self in log_request |
2442
| controllers/comments_controller.rb:99:3:100:5 | self in foo | controllers/comments_controller.rb:102:3:103:5 | self in bar |
@@ -30,14 +48,19 @@ additionalFlowSteps
3048
| controllers/photos_controller.rb:5:5:5:6 | [post] self | controllers/photos_controller.rb:8:3:9:5 | self in foo |
3149
| controllers/posts_controller.rb:20:3:21:5 | self in upvote | controllers/posts_controller.rb:29:3:31:5 | self in log_upvote |
3250
| controllers/posts_controller.rb:26:5:26:9 | [post] self | controllers/application_controller.rb:6:3:8:5 | self in set_user |
51+
| controllers/posts_controller.rb:26:23:26:28 | [post] self | controllers/application_controller.rb:6:3:8:5 | self in set_user |
3352
| filter_flow.rb:14:5:14:8 | [post] self | filter_flow.rb:17:3:18:5 | self in b |
53+
| filter_flow.rb:14:12:14:17 | [post] self | filter_flow.rb:17:3:18:5 | self in b |
3454
| filter_flow.rb:17:3:18:5 | self in b | filter_flow.rb:20:3:22:5 | self in c |
3555
| filter_flow.rb:30:5:30:8 | [post] self | filter_flow.rb:33:3:35:5 | self in b |
56+
| filter_flow.rb:30:12:30:17 | [post] self | filter_flow.rb:33:3:35:5 | self in b |
3657
| filter_flow.rb:34:5:34:8 | [post] self | filter_flow.rb:37:3:39:5 | self in c |
3758
| filter_flow.rb:48:5:48:8 | [post] self | filter_flow.rb:51:3:52:5 | self in b |
3859
| filter_flow.rb:51:3:52:5 | self in b | filter_flow.rb:54:3:56:5 | self in c |
60+
| filter_flow.rb:64:16:64:21 | [post] self | filter_flow.rb:67:3:68:5 | self in b |
3961
| filter_flow.rb:64:16:64:21 | self | filter_flow.rb:67:3:68:5 | self in b |
4062
| filter_flow.rb:67:3:68:5 | self in b | filter_flow.rb:70:3:72:5 | self in c |
63+
| filter_flow.rb:80:5:80:8 | [post] self | filter_flow.rb:83:3:84:5 | self in b |
4164
| filter_flow.rb:80:5:80:8 | self | filter_flow.rb:83:3:84:5 | self in b |
4265
| filter_flow.rb:83:3:84:5 | self in b | filter_flow.rb:86:3:88:5 | self in c |
4366
filterChain

ruby/ql/test/library-tests/frameworks/action_controller/params-flow.expected

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
failures
22
| filter_flow.rb:21:10:21:13 | @foo | Unexpected result: hasTaintFlow= |
33
| filter_flow.rb:71:10:71:17 | call to bar | Unexpected result: hasTaintFlow= |
4+
| filter_flow.rb:87:10:87:13 | @foo | Unexpected result: hasTaintFlow= |
45
edges
56
| filter_flow.rb:14:5:14:8 | [post] self [@foo] : | filter_flow.rb:17:3:18:5 | self in b [@foo] : |
67
| filter_flow.rb:14:12:14:17 | call to params : | filter_flow.rb:14:12:14:23 | ...[...] : |
@@ -17,6 +18,13 @@ edges
1718
| filter_flow.rb:70:3:72:5 | self in c [@foo, @bar] : | filter_flow.rb:71:10:71:13 | self [@foo, @bar] : |
1819
| filter_flow.rb:71:10:71:13 | @foo [@bar] : | filter_flow.rb:71:10:71:17 | call to bar |
1920
| filter_flow.rb:71:10:71:13 | self [@foo, @bar] : | filter_flow.rb:71:10:71:13 | @foo [@bar] : |
21+
| filter_flow.rb:80:5:80:8 | [post] self [@foo] : | filter_flow.rb:83:3:84:5 | self in b [@foo] : |
22+
| filter_flow.rb:83:3:84:5 | self in b [@foo] : | filter_flow.rb:86:3:88:5 | self in c [@foo] : |
23+
| filter_flow.rb:86:3:88:5 | self in c [@foo] : | filter_flow.rb:87:10:87:13 | self [@foo] : |
24+
| filter_flow.rb:87:10:87:13 | self [@foo] : | filter_flow.rb:87:10:87:13 | @foo |
25+
| filter_flow.rb:91:5:91:8 | [post] self [@foo] : | filter_flow.rb:80:5:80:8 | [post] self [@foo] : |
26+
| filter_flow.rb:91:12:91:17 | call to params : | filter_flow.rb:91:12:91:23 | ...[...] : |
27+
| filter_flow.rb:91:12:91:23 | ...[...] : | filter_flow.rb:91:5:91:8 | [post] self [@foo] : |
2028
| params_flow.rb:3:10:3:15 | call to params : | params_flow.rb:3:10:3:19 | ...[...] |
2129
| params_flow.rb:7:10:7:15 | call to params : | params_flow.rb:7:10:7:23 | call to as_json |
2230
| params_flow.rb:15:10:15:15 | call to params : | params_flow.rb:15:10:15:33 | call to permit |
@@ -86,6 +94,14 @@ nodes
8694
| filter_flow.rb:71:10:71:13 | @foo [@bar] : | semmle.label | @foo [@bar] : |
8795
| filter_flow.rb:71:10:71:13 | self [@foo, @bar] : | semmle.label | self [@foo, @bar] : |
8896
| filter_flow.rb:71:10:71:17 | call to bar | semmle.label | call to bar |
97+
| filter_flow.rb:80:5:80:8 | [post] self [@foo] : | semmle.label | [post] self [@foo] : |
98+
| filter_flow.rb:83:3:84:5 | self in b [@foo] : | semmle.label | self in b [@foo] : |
99+
| filter_flow.rb:86:3:88:5 | self in c [@foo] : | semmle.label | self in c [@foo] : |
100+
| filter_flow.rb:87:10:87:13 | @foo | semmle.label | @foo |
101+
| filter_flow.rb:87:10:87:13 | self [@foo] : | semmle.label | self [@foo] : |
102+
| filter_flow.rb:91:5:91:8 | [post] self [@foo] : | semmle.label | [post] self [@foo] : |
103+
| filter_flow.rb:91:12:91:17 | call to params : | semmle.label | call to params : |
104+
| filter_flow.rb:91:12:91:23 | ...[...] : | semmle.label | ...[...] : |
89105
| params_flow.rb:3:10:3:15 | call to params : | semmle.label | call to params : |
90106
| params_flow.rb:3:10:3:19 | ...[...] | semmle.label | ...[...] |
91107
| params_flow.rb:7:10:7:15 | call to params : | semmle.label | call to params : |
@@ -188,6 +204,7 @@ subpaths
188204
#select
189205
| filter_flow.rb:21:10:21:13 | @foo | filter_flow.rb:14:12:14:17 | call to params : | filter_flow.rb:21:10:21:13 | @foo | $@ | filter_flow.rb:14:12:14:17 | call to params : | call to params : |
190206
| filter_flow.rb:71:10:71:17 | call to bar | filter_flow.rb:64:16:64:21 | call to params : | filter_flow.rb:71:10:71:17 | call to bar | $@ | filter_flow.rb:64:16:64:21 | call to params : | call to params : |
207+
| filter_flow.rb:87:10:87:13 | @foo | filter_flow.rb:91:12:91:17 | call to params : | filter_flow.rb:87:10:87:13 | @foo | $@ | filter_flow.rb:91:12:91:17 | call to params : | call to params : |
191208
| params_flow.rb:3:10:3:19 | ...[...] | params_flow.rb:3:10:3:15 | call to params : | params_flow.rb:3:10:3:19 | ...[...] | $@ | params_flow.rb:3:10:3:15 | call to params : | call to params : |
192209
| params_flow.rb:7:10:7:23 | call to as_json | params_flow.rb:7:10:7:15 | call to params : | params_flow.rb:7:10:7:23 | call to as_json | $@ | params_flow.rb:7:10:7:15 | call to params : | call to params : |
193210
| params_flow.rb:15:10:15:33 | call to permit | params_flow.rb:15:10:15:15 | call to params : | params_flow.rb:15:10:15:33 | call to permit | $@ | params_flow.rb:15:10:15:15 | call to params : | call to params : |

0 commit comments

Comments
 (0)