From cb5ef7dbedbdfd16f1d825008affd0012f012cff Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 11 Mar 2020 13:05:41 +0100 Subject: [PATCH] add basic support for jqXHR with ajax calls --- .../semmle/javascript/frameworks/jQuery.qll | 31 ++++++++++++++----- .../ClientRequests/ClientRequests.expected | 6 ++++ .../frameworks/ClientRequests/tst.js | 5 +++ 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll b/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll index d8faa8c2896..2c9dc9292ff 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/jQuery.qll @@ -284,14 +284,26 @@ private class JQueryAjaxCall extends ClientRequest::Range { not exists(getResponseType()) and responseType = "" ) and promise = false and - result = - getOptionArgument([0 .. 1], "success") - .getALocalSource() - .(DataFlow::FunctionNode) - .getParameter(0) + ( + result = + getOptionArgument([0 .. 1], "success") + .getALocalSource() + .(DataFlow::FunctionNode) + .getParameter(0) + or + result = getAnAjaxCallbackDataNode(this) + ) } } +/** + * Gets the response data node from a call to a jqXHR Object. + */ +DataFlow::Node getAnAjaxCallbackDataNode(ClientRequest::Range request) { + result = + request.getAMemberCall(any(string s | s = "done" or s = "then")).getCallback(0).getParameter(0) +} + /** * A model of a URL request made using a `jQuery.ajax` shorthand. * E.g. `jQuery.getJSON`, `jQuery.post` etc. @@ -332,7 +344,8 @@ private class JQueryAjaxShortHand extends ClientRequest::Range { string getResponseType() { (name = "get" or name = "post") and - getLastArgument().mayHaveStringValue(result) + getLastArgument().mayHaveStringValue(result) and + getNumArgument() > 1 or name = "getJSON" and result = "json" or @@ -348,7 +361,11 @@ private class JQueryAjaxShortHand extends ClientRequest::Range { ) and promise = false and // one of the two last arguments - result = getCallback([getNumArgument() - 2 .. getNumArgument() - 1]).getParameter(0) + ( + result = getCallback([getNumArgument() - 2 .. getNumArgument() - 1]).getParameter(0) + or + result = getAnAjaxCallbackDataNode(this) + ) } } diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected index cd7a0619dca..e3992371215 100644 --- a/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/ClientRequests.expected @@ -62,6 +62,8 @@ test_ClientRequest | tst.js:185:2:185:60 | $( "#re ... lt) {}) | | tst.js:187:2:193:3 | $.ajax( ... on"\\n\\t}) | | tst.js:195:2:195:54 | $.get( ... "json") | +| tst.js:197:2:197:45 | $.ajax( ... blob"}) | +| tst.js:200:2:200:21 | $.get("example.php") | test_getADataNode | tst.js:53:5:53:23 | axios({data: data}) | tst.js:53:18:53:21 | data | | tst.js:57:5:57:39 | axios.p ... data2}) | tst.js:57:19:57:23 | data1 | @@ -165,6 +167,8 @@ test_getUrl | tst.js:185:2:185:60 | $( "#re ... lt) {}) | tst.js:185:23:185:38 | "ajax/test.html" | | tst.js:187:2:193:3 | $.ajax( ... on"\\n\\t}) | tst.js:189:8:189:27 | "http://example.org" | | tst.js:195:2:195:54 | $.get( ... "json") | tst.js:195:9:195:24 | "ajax/test.json" | +| tst.js:197:2:197:45 | $.ajax( ... blob"}) | tst.js:197:15:197:25 | "ajax/blob" | +| tst.js:200:2:200:21 | $.get("example.php") | tst.js:200:8:200:20 | "example.php" | test_getAResponseDataNode | tst.js:19:5:19:23 | requestPromise(url) | tst.js:19:5:19:23 | requestPromise(url) | text | true | | tst.js:21:5:21:23 | superagent.get(url) | tst.js:21:5:21:23 | superagent.get(url) | stream | true | @@ -221,3 +225,5 @@ test_getAResponseDataNode | tst.js:185:2:185:60 | $( "#re ... lt) {}) | tst.js:185:50:185:55 | result | text | false | | tst.js:187:2:193:3 | $.ajax( ... on"\\n\\t}) | tst.js:191:15:191:22 | ajaxData | json | false | | tst.js:195:2:195:54 | $.get( ... "json") | tst.js:195:37:195:40 | data | json | false | +| tst.js:197:2:197:45 | $.ajax( ... blob"}) | tst.js:198:23:198:26 | data | blob | false | +| tst.js:200:2:200:21 | $.get("example.php") | tst.js:200:37:200:44 | response | | false | diff --git a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js index d636fba918a..48a7a53fb96 100644 --- a/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js +++ b/javascript/ql/test/library-tests/frameworks/ClientRequests/tst.js @@ -193,4 +193,9 @@ import {ClientRequest, net} from 'electron'; }); $.get( "ajax/test.json", function( data ) {}, "json"); + + $.ajax({url: "ajax/blob", dataType: "blob"}) + .done(function( data ) {}); + + $.get("example.php").done(function(response) {}) });