Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4fb3fd9

Browse files
committed
JS: Address comments
1 parent 55ab7e6 commit 4fb3fd9

3 files changed

Lines changed: 39 additions & 26 deletions

File tree

javascript/ql/src/semmle/javascript/frameworks/ClientRequests.qll

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,19 @@ class ClientRequest extends DataFlow::InvokeNode {
4343
* wrapped in a promise object.
4444
*
4545
* The `responseType` describes how the response is represented as a JavaScript value
46-
* (after resolving promises).
47-
*
48-
* The response type may be any of the values supported by
49-
* [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType),
50-
* namely `arraybuffer`, `blob`, `document`, `json`, or `text`.
51-
*
52-
* Additionally, the `responseType` may have one of the following values:
53-
* - `fetch.response`: The result is a `Response` object as defined by the [fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Response).
54-
* - `stream`: The result is a Node.js stream
55-
* - `error`: The result is an error in an unspecified format, possibly containing information from the response
56-
*
57-
*
58-
* Custom implementations of `ClientRequest` may use other formats.
59-
* If the responseType is not known the convention is to use an empty string.
46+
* (after resolving promises), and may assume the following values:
47+
* - Any response type defined by [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType):
48+
* - `text`: The result is a string
49+
* - `json`: The result is a deserialized JSON object
50+
* - `arraybuffer`: The result is an `ArrayBuffer` object
51+
* - `blob`: The result is a `Blob` object
52+
* - `document`: The result is a deserialized HTML or XML document
53+
* - Any of the following additional response types defined by this library:
54+
* - `fetch.response`: The result is a `Response` object from [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Response).
55+
* - `stream`: The result is a Node.js stream and `http.IncomingMessage` object
56+
* - `error`: The result is an error in an unspecified format, possibly containing information from the response
57+
* - An empty string, indicating an unknown response type.
58+
* - Any value provided by custom implementations of `ClientRequest::Range`.
6059
*/
6160
DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
6261
result = self.getAResponseDataNode(responseType, promise)
@@ -99,7 +98,7 @@ module ClientRequest {
9998
* Gets a data flow node that refers to some representation of the response, possibly
10099
* wrapped in a promise object.
101100
*
102-
* See the decription of `responseType` in the corresponding predicate in `ClientRequest`.
101+
* See the decription of `responseType` in `ClientRequest::getAResponseDataNode`.
103102
*/
104103
DataFlow::Node getAResponseDataNode(string responseType, boolean promise) { none() }
105104
}
@@ -192,9 +191,19 @@ module ClientRequest {
192191
)
193192
}
194193

194+
private int getOptionsArgIndex() {
195+
method = "request" and
196+
result = 0
197+
or
198+
(method = "get" or method = "delete" or method = "head") and
199+
result = 1
200+
or
201+
(method = "post" or method = "put" or method = "patch") and
202+
result = 2
203+
}
204+
195205
private DataFlow::Node getOptionArgument(string name) {
196-
// depends on the method name and the call arity, over-approximating slightly in the name of simplicity
197-
result = getOptionArgument([0 .. 2], name)
206+
result = getOptionArgument(getOptionsArgIndex(), name)
198207
}
199208

200209
override DataFlow::Node getUrl() {
@@ -218,15 +227,18 @@ module ClientRequest {
218227

219228
/** Gets the response type from the options passed in. */
220229
string getResponseType() {
221-
exists(DataFlow::Node option | option = getOptionArgument([0 .. 2], "responseType") |
222-
result = option.getStringValue()
230+
exists(DataFlow::Node option | option = getOptionArgument("responseType") |
231+
option.mayHaveStringValue(result)
223232
or
224-
not exists(option.getStringValue()) and
233+
option.analyze().getAValue().isIndefinite(_) and
225234
result = ""
226235
)
227236
or
228-
not exists(getOptionArgument([0 .. 2], "responseType")) and
237+
not exists(getOptionArgument("responseType")) and
229238
result = "json"
239+
or
240+
getArgument(getOptionsArgIndex()).analyze().getAValue().isIndefinite(_) and
241+
result = ""
230242
}
231243

232244
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {

javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ test_ClientRequest
4343
| tst.js:123:5:127:6 | request ... \\n }) |
4444
| tst.js:129:5:129:37 | request ... true}) |
4545
| tst.js:133:5:133:18 | axios.get(url) |
46-
| tst.js:134:5:134:48 | axios.g ... json'}) |
46+
| tst.js:134:5:134:44 | axios({ ... json'}) |
4747
| tst.js:139:5:139:14 | fetch(url) |
4848
| tst.js:143:5:143:12 | got(url) |
4949
| tst.js:144:5:144:28 | got(url ... true }) |
@@ -132,8 +132,8 @@ test_getUrl
132132
| tst.js:123:5:127:6 | request ... \\n }) | tst.js:123:13:123:15 | url |
133133
| tst.js:129:5:129:37 | request ... true}) | tst.js:129:20:129:22 | url |
134134
| tst.js:133:5:133:18 | axios.get(url) | tst.js:133:15:133:17 | url |
135-
| tst.js:134:5:134:48 | axios.g ... json'}) | tst.js:134:15:134:47 | { url: ... 'json'} |
136-
| tst.js:134:5:134:48 | axios.g ... json'}) | tst.js:134:22:134:24 | url |
135+
| tst.js:134:5:134:44 | axios({ ... json'}) | tst.js:134:11:134:43 | { url: ... 'json'} |
136+
| tst.js:134:5:134:44 | axios({ ... json'}) | tst.js:134:18:134:20 | url |
137137
| tst.js:139:5:139:14 | fetch(url) | tst.js:139:11:139:13 | url |
138138
| tst.js:143:5:143:12 | got(url) | tst.js:143:9:143:11 | url |
139139
| tst.js:144:5:144:28 | got(url ... true }) | tst.js:144:9:144:11 | url |
@@ -143,6 +143,7 @@ test_getUrl
143143
test_getAResponseDataNode
144144
| tst.js:19:5:19:23 | requestPromise(url) | tst.js:19:5:19:23 | requestPromise(url) | text | true |
145145
| tst.js:21:5:21:23 | superagent.get(url) | tst.js:21:5:21:23 | superagent.get(url) | stream | true |
146+
| tst.js:25:5:25:14 | axios(url) | tst.js:25:5:25:14 | axios(url) | | true |
146147
| tst.js:25:5:25:14 | axios(url) | tst.js:25:5:25:14 | axios(url) | json | true |
147148
| tst.js:27:5:27:18 | axios.get(url) | tst.js:27:5:27:18 | axios.get(url) | json | true |
148149
| tst.js:29:5:29:23 | axios({ url: url }) | tst.js:29:5:29:23 | axios({ url: url }) | json | true |
@@ -175,7 +176,7 @@ test_getAResponseDataNode
175176
| tst.js:123:5:127:6 | request ... \\n }) | tst.js:125:9:125:21 | response.body | json | false |
176177
| tst.js:129:5:129:37 | request ... true}) | tst.js:129:5:129:37 | request ... true}) | json | true |
177178
| tst.js:133:5:133:18 | axios.get(url) | tst.js:133:5:133:18 | axios.get(url) | json | true |
178-
| tst.js:134:5:134:48 | axios.g ... json'}) | tst.js:134:5:134:48 | axios.g ... json'}) | json | true |
179+
| tst.js:134:5:134:44 | axios({ ... json'}) | tst.js:134:5:134:44 | axios({ ... json'}) | json | true |
179180
| tst.js:139:5:139:14 | fetch(url) | tst.js:139:5:139:14 | fetch(url) | fetch.response | true |
180181
| tst.js:143:5:143:12 | got(url) | tst.js:143:5:143:12 | got(url) | text | true |
181182
| tst.js:144:5:144:28 | got(url ... true }) | tst.js:144:5:144:28 | got(url ... true }) | json | true |

javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ import {ClientRequest, net} from 'electron';
131131

132132
(function() {
133133
axios.get(url).then(response => response.data);
134-
axios.get({ url: url, responseType: 'json'}).then(response => response.data);
134+
axios({ url: url, responseType: 'json'}).then(response => response.data);
135135
})
136136

137137

0 commit comments

Comments
 (0)