Skip to content

Commit c297a68

Browse files
committed
Model more of the RestClient API
We now handle this form: RestClient::Request.execute(url: "http://example.com")
1 parent e2ef780 commit c297a68

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ private import codeql.ruby.ApiGraphs
66
* A call that makes an HTTP request using `RestClient`.
77
* ```ruby
88
* RestClient.get("http://example.com").body
9+
* RestClient::Resource.new("http://example.com").get.body
10+
* RestClient::Request.execute(url: "http://example.com").body
911
* ```
1012
*/
1113
class RestClientHttpRequest extends HTTP::Client::Request::Range {
@@ -14,18 +16,29 @@ class RestClientHttpRequest extends HTTP::Client::Request::Range {
1416
API::Node connectionNode;
1517

1618
RestClientHttpRequest() {
17-
connectionNode =
18-
[
19-
API::getTopLevelMember("RestClient"),
20-
API::getTopLevelMember("RestClient").getMember("Resource").getInstance()
21-
] and
22-
requestNode =
23-
connectionNode.getReturn(["get", "head", "delete", "options", "post", "put", "patch"]) and
2419
requestUse = requestNode.getAnImmediateUse() and
25-
this = requestUse.asExpr().getExpr()
20+
this = requestUse.asExpr().getExpr() and
21+
(
22+
connectionNode =
23+
[
24+
API::getTopLevelMember("RestClient"),
25+
API::getTopLevelMember("RestClient").getMember("Resource").getInstance()
26+
] and
27+
requestNode =
28+
connectionNode.getReturn(["get", "head", "delete", "options", "post", "put", "patch"])
29+
or
30+
connectionNode = API::getTopLevelMember("RestClient").getMember("Request") and
31+
requestNode = connectionNode.getReturn("execute")
32+
)
2633
}
2734

28-
override DataFlow::Node getURL() { result = requestUse.getArgument(0) }
35+
override DataFlow::Node getURL() {
36+
result = requestUse.getKeywordArgument("url")
37+
or
38+
result = requestUse.getArgument(0) and
39+
// this rules out the alternative above
40+
not result.asExpr().getExpr() instanceof Pair
41+
}
2942

3043
override DataFlow::Node getResponseBody() { result = requestNode.getAMethodCall("body") }
3144

ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
| RestClient.rb:15:9:15:47 | call to delete | RestClient | RestClient.rb:15:27:15:46 | "http://example.com" | RestClient.rb:16:1:16:10 | call to body |
6363
| RestClient.rb:18:9:18:45 | call to head | RestClient | RestClient.rb:18:25:18:44 | "http://example.com" | RestClient.rb:19:1:19:10 | call to body |
6464
| RestClient.rb:21:9:21:48 | call to options | RestClient | RestClient.rb:21:28:21:47 | "http://example.com" | RestClient.rb:22:1:22:10 | call to body |
65+
| RestClient.rb:28:9:28:85 | call to execute | RestClient | RestClient.rb:28:56:28:84 | "http://example.com/resource" | RestClient.rb:29:1:29:10 | call to body |
6566
| Typhoeus.rb:3:9:3:43 | call to get | Typhoeus | Typhoeus.rb:3:22:3:42 | "http://example.com/" | Typhoeus.rb:4:1:4:10 | call to body |
6667
| Typhoeus.rb:6:9:6:63 | call to post | Typhoeus | Typhoeus.rb:6:23:6:43 | "http://example.com/" | Typhoeus.rb:7:1:7:10 | call to body |
6768
| Typhoeus.rb:9:9:9:62 | call to put | Typhoeus | Typhoeus.rb:9:22:9:42 | "http://example.com/" | Typhoeus.rb:10:1:10:10 | call to body |

ruby/ql/test/library-tests/frameworks/http_clients/RestClient.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,7 @@
2323

2424
resource8 = RestClient::Resource.new "http://example.com"
2525
resp8 = resource8.get
26-
resp8.body
26+
resp8.body
27+
28+
resp9 = RestClient::Request.execute(method: :get, url: 'http://example.com/resource')
29+
resp9.body

0 commit comments

Comments
 (0)