Skip to content

Commit d392cda

Browse files
authored
Merge pull request #11022 from hmac/try-code-injection
Ruby: try/try! as code execution
2 parents ef967b6 + 0dd63c0 commit d392cda

File tree

5 files changed

+47
-0
lines changed

5 files changed

+47
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The `ActiveSupport` extensions `Object#try` and `Object#try!` are now recognised as code executions.

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

+23
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,29 @@ module ActiveSupport {
8181
preservesValue = true
8282
}
8383
}
84+
85+
/**
86+
* A call to `Object#try`, which may execute its first argument as a Ruby
87+
* method call.
88+
* ```rb
89+
* x = "abc"
90+
* x.try(:upcase) # => "ABC"
91+
* y = nil
92+
* y.try(:upcase) # => nil
93+
* ```
94+
* `Object#try!` behaves similarly but raises `NoMethodError` if the
95+
* receiver is not `nil` and does not respond to the method.
96+
*/
97+
class TryCallCodeExecution extends CodeExecution::Range, DataFlow::CallNode {
98+
TryCallCodeExecution() {
99+
this.asExpr().getExpr() instanceof UnknownMethodCall and
100+
this.getMethodName() = ["try", "try!"]
101+
}
102+
103+
override DataFlow::Node getCode() { result = this.getArgument(0) }
104+
105+
override predicate runsArbitraryCode() { none() }
106+
}
84107
}
85108

86109
/**

ruby/ql/test/library-tests/frameworks/active_support/ActiveSupport.expected

+9
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,12 @@ constantizeCalls
55
loggerInstantiations
66
| active_support.rb:6:1:6:33 | call to new |
77
| active_support.rb:7:1:7:40 | call to new |
8+
codeExecutions
9+
| active_support.rb:1:1:1:22 | call to constantize |
10+
| active_support.rb:3:1:3:13 | call to constantize |
11+
| active_support.rb:4:1:4:18 | call to safe_constantize |
12+
| active_support.rb:296:5:296:18 | call to try |
13+
| active_support.rb:297:5:297:17 | call to try |
14+
| active_support.rb:298:5:298:19 | call to try! |
15+
| active_support.rb:298:5:298:35 | call to try! |
16+
| active_support.rb:299:5:299:18 | call to try! |
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import codeql.ruby.frameworks.ActiveSupport
22
import codeql.ruby.DataFlow
33
import codeql.ruby.frameworks.stdlib.Logger
4+
import codeql.ruby.Concepts
45

56
query DataFlow::Node constantizeCalls(ActiveSupport::CoreExtensions::String::Constantize c) {
67
result = c.getCode()
78
}
89

910
query predicate loggerInstantiations(Logger::LoggerInstantiation l) { any() }
11+
12+
query predicate codeExecutions(CodeExecution c) { any() }

ruby/ql/test/library-tests/frameworks/active_support/active_support.rb

+8
Original file line numberDiff line numberDiff line change
@@ -290,3 +290,11 @@ def m_deep_dup
290290
x = source "a"
291291
sink x.deep_dup # $hasValueFlow=a
292292
end
293+
294+
def m_try(method)
295+
x = "abc"
296+
x.try(:upcase)
297+
x.try(method)
298+
x.try!(:upcase).try!(:downcase)
299+
x.try!(method)
300+
end

0 commit comments

Comments
 (0)