Skip to content

Commit 9b0c24a

Browse files
authored
Merge pull request github#5876 from erik-krogh/moreAxios
Approved by asgerf
2 parents 7974e3a + 34fbafa commit 9b0c24a

File tree

4 files changed

+53
-15
lines changed

4 files changed

+53
-15
lines changed

javascript/ql/src/semmle/javascript/ApiGraphs.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ module API {
183183
*/
184184
Node getPromised() { result = getASuccessor(Label::promised()) }
185185

186+
/**
187+
* Gets a node representing the error wrapped in the `Promise` object represented by this node.
188+
*/
189+
Node getPromisedError() { result = getASuccessor(Label::promisedError()) }
190+
186191
/**
187192
* Gets a string representation of the lexicographically least among all shortest access paths
188193
* from the root to this node.
@@ -468,6 +473,9 @@ module API {
468473
or
469474
lbl = Label::promised() and
470475
PromiseFlow::storeStep(rhs, pred, Promises::valueProp())
476+
or
477+
lbl = Label::promisedError() and
478+
PromiseFlow::storeStep(rhs, pred, Promises::errorProp())
471479
)
472480
or
473481
exists(DataFlow::ClassNode cls, string name |
@@ -482,6 +490,12 @@ module API {
482490
rhs = f.getAReturn()
483491
)
484492
or
493+
exists(DataFlow::FunctionNode f |
494+
base = MkAsyncFuncResult(f) and
495+
lbl = Label::promisedError() and
496+
rhs = f.getExceptionalReturn()
497+
)
498+
or
485499
exists(int i |
486500
lbl = Label::parameter(i) and
487501
argumentPassing(base, i, rhs)
@@ -559,6 +573,9 @@ module API {
559573
or
560574
lbl = Label::promised() and
561575
PromiseFlow::loadStep(pred, ref, Promises::valueProp())
576+
or
577+
lbl = Label::promisedError() and
578+
PromiseFlow::loadStep(pred, ref, Promises::errorProp())
562579
)
563580
or
564581
exists(DataFlow::Node def, DataFlow::FunctionNode fn |
@@ -962,6 +979,9 @@ private module Label {
962979

963980
/** Gets the `promised` edge label connecting a promise to its contained value. */
964981
string promised() { result = "promised" }
982+
983+
/** Gets the `promisedError` edge label connecting a promise to its rejected value. */
984+
string promisedError() { result = "promisedError" }
965985
}
966986

967987
private class NodeModuleSourcesNodes extends DataFlow::SourceNode::Range {

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

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -206,19 +206,14 @@ module ClientRequest {
206206
/**
207207
* A model of a URL request made using the `axios` library.
208208
*/
209-
class AxiosUrlRequest extends ClientRequest::Range {
209+
class AxiosUrlRequest extends ClientRequest::Range, API::CallNode {
210210
string method;
211211

212212
AxiosUrlRequest() {
213-
exists(string moduleName, DataFlow::SourceNode callee | this = callee.getACall() |
214-
moduleName = "axios" and
215-
(
216-
callee = DataFlow::moduleImport(moduleName) and method = "request"
217-
or
218-
callee = DataFlow::moduleMember(moduleName, method) and
219-
(method = httpMethodName() or method = "request")
220-
)
221-
)
213+
this = API::moduleImport("axios").getACall() and method = "request"
214+
or
215+
this = API::moduleImport("axios").getMember(method).getACall() and
216+
method = [httpMethodName(), "request"]
222217
}
223218

224219
private int getOptionsArgIndex() {
@@ -247,12 +242,10 @@ module ClientRequest {
247242
method = "request" and
248243
result = getOptionArgument(0, "data")
249244
or
250-
(method = "post" or method = "put" or method = "put") and
251-
(result = getArgument(1) or result = getOptionArgument(2, "data"))
245+
method = ["post", "put"] and
246+
result = [getArgument(1), getOptionArgument(2, "data")]
252247
or
253-
exists(string name | name = "headers" or name = "params" |
254-
result = getOptionArgument([0 .. 2], name)
255-
)
248+
result = getOptionArgument([0 .. 2], ["headers", "params"])
256249
}
257250

258251
/** Gets the response type from the options passed in. */
@@ -275,6 +268,10 @@ module ClientRequest {
275268
responseType = getResponseType() and
276269
promise = true and
277270
result = this
271+
or
272+
responseType = getResponseType() and
273+
promise = false and
274+
result = getReturn().getPromisedError().getMember("response").getAnImmediateUse()
278275
}
279276
}
280277

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ test_ClientRequest
8787
| tst.js:271:3:271:61 | proxy.w ... 080' }) |
8888
| tst.js:274:1:283:2 | httpPro ... true\\n}) |
8989
| tst.js:286:20:286:55 | new Web ... :8080') |
90+
| tst.js:296:5:299:6 | axios({ ... \\n }) |
9091
test_getADataNode
9192
| tst.js:53:5:53:23 | axios({data: data}) | tst.js:53:18:53:21 | data |
9293
| tst.js:57:5:57:39 | axios.p ... data2}) | tst.js:57:19:57:23 | data1 |
@@ -227,6 +228,8 @@ test_getUrl
227228
| tst.js:271:3:271:61 | proxy.w ... 080' }) | tst.js:271:33:271:58 | 'http:/ ... m:8080' |
228229
| tst.js:274:1:283:2 | httpPro ... true\\n}) | tst.js:275:13:281:5 | {\\n ... ,\\n } |
229230
| tst.js:286:20:286:55 | new Web ... :8080') | tst.js:286:34:286:54 | 'ws://l ... t:8080' |
231+
| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:296:11:299:5 | {\\n ... ,\\n } |
232+
| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:298:14:298:44 | "http:/ ... -axios" |
230233
test_getAResponseDataNode
231234
| tst.js:19:5:19:23 | requestPromise(url) | tst.js:19:5:19:23 | requestPromise(url) | text | true |
232235
| tst.js:21:5:21:23 | superagent.get(url) | tst.js:21:5:21:23 | superagent.get(url) | stream | true |
@@ -294,3 +297,7 @@ test_getAResponseDataNode
294297
| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:67:235:70 | resp | fetch.response | false |
295298
| tst.js:235:5:237:6 | needle. ... \\n }) | tst.js:235:73:235:76 | body | json | false |
296299
| tst.js:286:20:286:55 | new Web ... :8080') | tst.js:291:44:291:53 | event.data | json | false |
300+
| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:296:5:299:6 | axios({ ... \\n }) | json | true |
301+
| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:302:28:302:39 | err.response | json | false |
302+
| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:303:26:303:37 | err.response | json | false |
303+
| tst.js:296:5:299:6 | axios({ ... \\n }) | tst.js:304:27:304:38 | err.response | json | false |

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,18 @@ function webSocket() {
290290
socket.addEventListener('message', function (event) {
291291
console.log("Data from server: " + event.data);
292292
});
293+
}
294+
295+
function moreAxios() {
296+
axios({
297+
method: 'GET',
298+
url: "http://example.org/more-axios",
299+
}).then(
300+
x => res.send(x.data),
301+
(err) => {
302+
const status = err.response.status;
303+
const data = err.response.data;
304+
const agent = err.response.headers.useragent;
305+
}
306+
);
293307
}

0 commit comments

Comments
 (0)