Skip to content

Commit 0457567

Browse files
committed
Ruby: generalise summaries for ActiveSupport Hash extensions
1 parent e01cbb2 commit 0457567

File tree

4 files changed

+51
-8
lines changed

4 files changed

+51
-8
lines changed

ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -592,15 +592,12 @@ private module ParamsSummaries {
592592
/**
593593
* `#merge`
594594
* Returns a new ActionController::Parameters with all keys from other_hash merged into current hash.
595-
* `#reverse_merge`
596-
* `#with_defaults`
597-
* Returns a new ActionController::Parameters with all keys from current hash merged into other_hash.
598595
*/
599596
private class MergeSummary extends SummarizedCallable {
600597
MergeSummary() { this = "ActionController::Parameters#merge" }
601598

602599
override MethodCall getACall() {
603-
result.getMethodName() = ["merge", "reverse_merge", "with_defaults"] and
600+
result.getMethodName() = "merge" and
604601
exists(ParamsInstance i |
605602
i.asExpr().getExpr() = [result.getReceiver(), result.getArgument(0)]
606603
)
@@ -616,15 +613,12 @@ private module ParamsSummaries {
616613
/**
617614
* `#merge!`
618615
* Returns current ActionController::Parameters instance with current hash merged into other_hash.
619-
* `#reverse_merge!`
620-
* `#with_defaults!`
621-
* Returns a new ActionController::Parameters with all keys from current hash merged into other_hash.
622616
*/
623617
private class MergeBangSummary extends SummarizedCallable {
624618
MergeBangSummary() { this = "ActionController::Parameters#merge!" }
625619

626620
override MethodCall getACall() {
627-
result.getMethodName() = ["merge!", "reverse_merge!", "with_defaults!"] and
621+
result.getMethodName() = "merge!" and
628622
exists(ParamsInstance i |
629623
i.asExpr().getExpr() = [result.getReceiver(), result.getArgument(0)]
630624
)

ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.qll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,32 @@ module ActiveSupport {
120120
}
121121
}
122122

123+
/**
124+
* Flow summary for `reverse_merge`, and its alias `with_defaults`.
125+
*/
126+
private class ReverseMergeSummary extends SimpleSummarizedCallable {
127+
ReverseMergeSummary() { this = ["reverse_merge", "with_defaults"] }
128+
129+
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
130+
input = ["Argument[self]", "Argument[0]"] and
131+
output = "ReturnValue" and
132+
preservesValue = false
133+
}
134+
}
135+
136+
/**
137+
* Flow summary for `reverse_merge!`, and its aliases `with_defaults!` and `reverse_update`.
138+
*/
139+
private class ReverseMergeBangSummary extends SimpleSummarizedCallable {
140+
ReverseMergeBangSummary() { this = ["reverse_merge!", "with_defaults!", "reverse_update"] }
141+
142+
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
143+
input = ["Argument[self]", "Argument[0]"] and
144+
output = ["ReturnValue", "Argument[self]"] and
145+
preservesValue = false
146+
}
147+
}
148+
123149
private class TransformSummary extends SimpleSummarizedCallable {
124150
TransformSummary() {
125151
this =

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ edges
4444
| params_flow.rb:145:32:145:37 | call to params : | params_flow.rb:145:10:145:38 | call to with_defaults! |
4545
| params_flow.rb:148:5:148:5 | [post] p : | params_flow.rb:149:10:149:10 | p |
4646
| params_flow.rb:148:22:148:27 | call to params : | params_flow.rb:148:5:148:5 | [post] p : |
47+
| params_flow.rb:153:10:153:15 | call to params : | params_flow.rb:153:10:153:44 | call to reverse_update |
48+
| params_flow.rb:154:32:154:37 | call to params : | params_flow.rb:154:10:154:38 | call to reverse_update |
49+
| params_flow.rb:157:5:157:5 | [post] p : | params_flow.rb:158:10:158:10 | p |
50+
| params_flow.rb:157:22:157:27 | call to params : | params_flow.rb:157:5:157:5 | [post] p : |
4751
nodes
4852
| params_flow.rb:3:10:3:15 | call to params : | semmle.label | call to params : |
4953
| params_flow.rb:3:10:3:19 | ...[...] | semmle.label | ...[...] |
@@ -130,6 +134,13 @@ nodes
130134
| params_flow.rb:148:5:148:5 | [post] p : | semmle.label | [post] p : |
131135
| params_flow.rb:148:22:148:27 | call to params : | semmle.label | call to params : |
132136
| params_flow.rb:149:10:149:10 | p | semmle.label | p |
137+
| params_flow.rb:153:10:153:15 | call to params : | semmle.label | call to params : |
138+
| params_flow.rb:153:10:153:44 | call to reverse_update | semmle.label | call to reverse_update |
139+
| params_flow.rb:154:10:154:38 | call to reverse_update | semmle.label | call to reverse_update |
140+
| params_flow.rb:154:32:154:37 | call to params : | semmle.label | call to params : |
141+
| params_flow.rb:157:5:157:5 | [post] p : | semmle.label | [post] p : |
142+
| params_flow.rb:157:22:157:27 | call to params : | semmle.label | call to params : |
143+
| params_flow.rb:158:10:158:10 | p | semmle.label | p |
133144
subpaths
134145
#select
135146
| 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 : |
@@ -173,3 +184,6 @@ subpaths
173184
| params_flow.rb:144:10:144:44 | call to with_defaults! | params_flow.rb:144:10:144:15 | call to params : | params_flow.rb:144:10:144:44 | call to with_defaults! | $@ | params_flow.rb:144:10:144:15 | call to params : | call to params : |
174185
| params_flow.rb:145:10:145:38 | call to with_defaults! | params_flow.rb:145:32:145:37 | call to params : | params_flow.rb:145:10:145:38 | call to with_defaults! | $@ | params_flow.rb:145:32:145:37 | call to params : | call to params : |
175186
| params_flow.rb:149:10:149:10 | p | params_flow.rb:148:22:148:27 | call to params : | params_flow.rb:149:10:149:10 | p | $@ | params_flow.rb:148:22:148:27 | call to params : | call to params : |
187+
| params_flow.rb:153:10:153:44 | call to reverse_update | params_flow.rb:153:10:153:15 | call to params : | params_flow.rb:153:10:153:44 | call to reverse_update | $@ | params_flow.rb:153:10:153:15 | call to params : | call to params : |
188+
| params_flow.rb:154:10:154:38 | call to reverse_update | params_flow.rb:154:32:154:37 | call to params : | params_flow.rb:154:10:154:38 | call to reverse_update | $@ | params_flow.rb:154:32:154:37 | call to params : | call to params : |
189+
| params_flow.rb:158:10:158:10 | p | params_flow.rb:157:22:157:27 | call to params : | params_flow.rb:158:10:158:10 | p | $@ | params_flow.rb:157:22:157:27 | call to params : | call to params : |

ruby/ql/test/library-tests/frameworks/action_controller/params_flow.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,13 @@ def m32
148148
p.with_defaults!(params)
149149
sink p # $hasTaintFlow
150150
end
151+
152+
def m33
153+
sink params.reverse_update({a: 1, b: 2}) # $hasTaintFlow
154+
sink {a: 1}.reverse_update(params) # $hasTaintFlow
155+
156+
p = {a: 1}
157+
p.reverse_update(params)
158+
sink p # $hasTaintFlow
159+
end
151160
end

0 commit comments

Comments
 (0)