Skip to content

Commit dcc6f83

Browse files
Merge pull request #15782 from joefarebrother/ruby-typhoeus
Ruby: Model `Typhoeus::Request.new`
2 parents b4fdd4e + 7027b7f commit dcc6f83

File tree

4 files changed

+122
-5
lines changed

4 files changed

+122
-5
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Calls to `Typhoeus::Request.new` are now considered as instances of the `Http::Client::Request` concept, with the response body being treated as a remote flow source.

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

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,30 @@ private import codeql.ruby.DataFlow
1616
*/
1717
class TyphoeusHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode {
1818
API::Node requestNode;
19+
boolean directResponse;
1920

2021
TyphoeusHttpRequest() {
2122
this = requestNode.asSource() and
22-
requestNode =
23-
API::getTopLevelMember("Typhoeus")
24-
.getReturn(["get", "head", "delete", "options", "post", "put", "patch"])
23+
(
24+
directResponse = true and
25+
requestNode =
26+
API::getTopLevelMember("Typhoeus")
27+
.getReturn(["get", "head", "delete", "options", "post", "put", "patch"])
28+
or
29+
directResponse = false and
30+
requestNode = API::getTopLevelMember("Typhoeus").getMember("Request").getInstance()
31+
)
2532
}
2633

2734
override DataFlow::Node getAUrlPart() { result = this.getArgument(0) }
2835

29-
override DataFlow::Node getResponseBody() { result = requestNode.getAMethodCall("body") }
36+
override DataFlow::Node getResponseBody() {
37+
directResponse = true and
38+
result = getBodyFromResponse(requestNode)
39+
or
40+
directResponse = false and
41+
result = getResponseBodyFromRequest(requestNode)
42+
}
3043

3144
/** Gets the value that controls certificate validation, if any. */
3245
DataFlow::Node getCertificateValidationControllingValue() {
@@ -55,3 +68,36 @@ private module TyphoeusDisablesCertificateValidationConfig implements DataFlow::
5568

5669
private module TyphoeusDisablesCertificateValidationFlow =
5770
DataFlow::Global<TyphoeusDisablesCertificateValidationConfig>;
71+
72+
/** Gets the response body from the given `requestNode` representing a Typhoeus request */
73+
bindingset[requestNode]
74+
pragma[inline_late]
75+
private DataFlow::Node getResponseBodyFromRequest(API::Node requestNode) {
76+
result =
77+
[
78+
getBodyFromResponse(getResponseFromRequest(requestNode)),
79+
requestNode.getMethod("on_body").getBlock().getParameter(0).asSource()
80+
]
81+
}
82+
83+
/** Gets the response from the given `requestNode` representing a Typhoeus request */
84+
bindingset[requestNode]
85+
pragma[inline_late]
86+
private API::Node getResponseFromRequest(API::Node requestNode) {
87+
result =
88+
[
89+
requestNode.getReturn(["run", "response"]),
90+
requestNode
91+
// on_headers does not carry a response body
92+
.getMethod(["on_complete", "on_success", "on_failure", "on_progress"])
93+
.getBlock()
94+
.getParameter(0)
95+
]
96+
}
97+
98+
/** Gets the response body from the given `responseNode` representing a Typhoeus response */
99+
bindingset[responseNode]
100+
pragma[inline_late]
101+
private DataFlow::Node getBodyFromResponse(API::Node responseNode) {
102+
result = responseNode.getAMethodCall(["body", "response_body"])
103+
}

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ httpRequests
6767
| Typhoeus.rb:15:9:15:46 | call to delete |
6868
| Typhoeus.rb:18:9:18:44 | call to head |
6969
| Typhoeus.rb:21:9:21:47 | call to options |
70+
| Typhoeus.rb:24:8:24:50 | call to new |
71+
| Typhoeus.rb:27:8:27:50 | call to new |
72+
| Typhoeus.rb:31:9:31:51 | call to new |
73+
| Typhoeus.rb:34:9:34:51 | call to new |
74+
| Typhoeus.rb:39:9:39:51 | call to new |
75+
| Typhoeus.rb:44:9:44:51 | call to new |
76+
| Typhoeus.rb:49:9:49:51 | call to new |
77+
| Typhoeus.rb:54:9:54:51 | call to new |
7078
getFramework
7179
| Excon.rb:3:9:3:40 | call to get | Excon |
7280
| Excon.rb:6:9:6:60 | call to post | Excon |
@@ -136,6 +144,14 @@ getFramework
136144
| Typhoeus.rb:15:9:15:46 | call to delete | Typhoeus |
137145
| Typhoeus.rb:18:9:18:44 | call to head | Typhoeus |
138146
| Typhoeus.rb:21:9:21:47 | call to options | Typhoeus |
147+
| Typhoeus.rb:24:8:24:50 | call to new | Typhoeus |
148+
| Typhoeus.rb:27:8:27:50 | call to new | Typhoeus |
149+
| Typhoeus.rb:31:9:31:51 | call to new | Typhoeus |
150+
| Typhoeus.rb:34:9:34:51 | call to new | Typhoeus |
151+
| Typhoeus.rb:39:9:39:51 | call to new | Typhoeus |
152+
| Typhoeus.rb:44:9:44:51 | call to new | Typhoeus |
153+
| Typhoeus.rb:49:9:49:51 | call to new | Typhoeus |
154+
| Typhoeus.rb:54:9:54:51 | call to new | Typhoeus |
139155
getResponseBody
140156
| Excon.rb:3:9:3:40 | call to get | Excon.rb:4:1:4:10 | call to body |
141157
| Excon.rb:6:9:6:60 | call to post | Excon.rb:7:1:7:10 | call to body |
@@ -205,6 +221,14 @@ getResponseBody
205221
| Typhoeus.rb:15:9:15:46 | call to delete | Typhoeus.rb:16:1:16:10 | call to body |
206222
| Typhoeus.rb:18:9:18:44 | call to head | Typhoeus.rb:19:1:19:10 | call to body |
207223
| Typhoeus.rb:21:9:21:47 | call to options | Typhoeus.rb:22:1:22:10 | call to body |
224+
| Typhoeus.rb:24:8:24:50 | call to new | Typhoeus.rb:25:1:25:13 | call to body |
225+
| Typhoeus.rb:27:8:27:50 | call to new | Typhoeus.rb:29:1:29:18 | call to body |
226+
| Typhoeus.rb:31:9:31:51 | call to new | Typhoeus.rb:32:1:32:23 | call to response_body |
227+
| Typhoeus.rb:34:9:34:51 | call to new | Typhoeus.rb:36:5:36:15 | call to body |
228+
| Typhoeus.rb:39:9:39:51 | call to new | Typhoeus.rb:41:5:41:15 | call to body |
229+
| Typhoeus.rb:44:9:44:51 | call to new | Typhoeus.rb:46:5:46:15 | call to body |
230+
| Typhoeus.rb:49:9:49:51 | call to new | Typhoeus.rb:51:5:51:15 | call to body |
231+
| Typhoeus.rb:54:9:54:51 | call to new | Typhoeus.rb:55:19:55:24 | body15 |
208232
getAUrlPart
209233
| Excon.rb:3:9:3:40 | call to get | Excon.rb:3:19:3:39 | "http://example.com/" |
210234
| Excon.rb:6:9:6:60 | call to post | Excon.rb:6:20:6:40 | "http://example.com/" |
@@ -287,3 +311,11 @@ getAUrlPart
287311
| Typhoeus.rb:15:9:15:46 | call to delete | Typhoeus.rb:15:25:15:45 | "http://example.com/" |
288312
| Typhoeus.rb:18:9:18:44 | call to head | Typhoeus.rb:18:23:18:43 | "http://example.com/" |
289313
| Typhoeus.rb:21:9:21:47 | call to options | Typhoeus.rb:21:26:21:46 | "http://example.com/" |
314+
| Typhoeus.rb:24:8:24:50 | call to new | Typhoeus.rb:24:30:24:49 | "http://example.com" |
315+
| Typhoeus.rb:27:8:27:50 | call to new | Typhoeus.rb:27:30:27:49 | "http://example.com" |
316+
| Typhoeus.rb:31:9:31:51 | call to new | Typhoeus.rb:31:31:31:50 | "http://example.com" |
317+
| Typhoeus.rb:34:9:34:51 | call to new | Typhoeus.rb:34:31:34:50 | "http://example.com" |
318+
| Typhoeus.rb:39:9:39:51 | call to new | Typhoeus.rb:39:31:39:50 | "http://example.com" |
319+
| Typhoeus.rb:44:9:44:51 | call to new | Typhoeus.rb:44:31:44:50 | "http://example.com" |
320+
| Typhoeus.rb:49:9:49:51 | call to new | Typhoeus.rb:49:31:49:50 | "http://example.com" |
321+
| Typhoeus.rb:54:9:54:51 | call to new | Typhoeus.rb:54:31:54:50 | "http://example.com" |

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,39 @@
1919
resp6.body
2020

2121
resp7 = Typhoeus.options("http://example.com/")
22-
resp7.body
22+
resp7.body
23+
24+
req8 = Typhoeus::Request.new("http://example.com")
25+
req8.run.body
26+
27+
req9 = Typhoeus::Request.new("http://example.com")
28+
req9.run
29+
req9.response.body
30+
31+
req10 = Typhoeus::Request.new("http://example.com")
32+
req10.run.response_body
33+
34+
req11 = Typhoeus::Request.new("http://example.com")
35+
req11.on_complete do |resp11|
36+
resp11.body
37+
end
38+
39+
req12 = Typhoeus::Request.new("http://example.com")
40+
req12.on_success do |resp12|
41+
resp12.body
42+
end
43+
44+
req13 = Typhoeus::Request.new("http://example.com")
45+
req13.on_failure do |resp13|
46+
resp13.body
47+
end
48+
49+
req14 = Typhoeus::Request.new("http://example.com")
50+
req14.on_progress do |resp14|
51+
resp14.body
52+
end
53+
54+
req15 = Typhoeus::Request.new("http://example.com")
55+
req15.on_body do |body15|
56+
# ...
57+
end

0 commit comments

Comments
 (0)