Merge pull request #3041 from erik-krogh/JQueryAjax

Approved by esbena
This commit is contained in:
semmle-qlci 2020-03-14 22:31:59 +00:00 коммит произвёл GitHub
Родитель ff03478ae8 486efbab77
Коммит 7e093a8e5c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 213 добавлений и 22 удалений

Просмотреть файл

@ -32,6 +32,7 @@
- [for-in](https://www.npmjs.com/package/for-in)
- [for-own](https://www.npmjs.com/package/for-own)
- [http2](https://nodejs.org/api/http2.html)
- [jQuery](https://jquery.com/)
- [lazy-cache](https://www.npmjs.com/package/lazy-cache)
- [mongodb](https://www.npmjs.com/package/mongodb)
- [react](https://www.npmjs.com/package/react)

Просмотреть файл

@ -258,26 +258,145 @@ private class JQueryChainedElement extends DOM::Element, InvokeExpr {
}
/**
* A model of a URL request made using the `jQuery.ajax` or `jQuery.getJSON`.
* Classes and predicates for modelling `ClientRequest`s in JQuery.
*/
private class JQueryClientRequest extends ClientRequest::Range {
JQueryClientRequest() {
exists(string name |
name = "ajax" or
name = "getJSON"
|
private module JQueryClientRequest {
/**
* A model of a URL request made using the `jQuery.ajax`.
*/
private class JQueryAjaxCall extends ClientRequest::Range {
JQueryAjaxCall() { this = jquery().getAMemberCall("ajax") }
override DataFlow::Node getUrl() {
result = getArgument(0) and not exists(getOptionArgument(0, _))
or
result = getOptionArgument([0 .. 1], "url")
}
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() { result = getOptionArgument([0 .. 1], "data") }
private string getResponseType() {
getOptionArgument([0 .. 1], "dataType").mayHaveStringValue(result)
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
(
responseType = getResponseType()
or
not exists(getResponseType()) and responseType = ""
) and
promise = false and
(
result =
getOptionArgument([0 .. 1], "success")
.getALocalSource()
.(DataFlow::FunctionNode)
.getParameter(0)
or
result =
getAResponseNodeFromAnXHRObject(getOptionArgument([0 .. 1],
any(string method | method = "error" or method = "complete"))
.getALocalSource()
.(DataFlow::FunctionNode)
.getParameter(0))
or
result = getAnAjaxCallbackDataNode(this)
)
}
}
/**
* Gets a response data node from a call to a method on jqXHR Object `request`.
*/
private DataFlow::Node getAnAjaxCallbackDataNode(ClientRequest::Range request) {
result =
request
.getAMemberCall(any(string s | s = "done" or s = "then"))
.getCallback(0)
.getParameter(0)
or
result =
getAResponseNodeFromAnXHRObject(request.getAMemberCall("fail").getCallback(0).getParameter(0))
}
/**
* Gets a node refering to the response contained in an `jqXHR` object.
*/
private DataFlow::SourceNode getAResponseNodeFromAnXHRObject(DataFlow::SourceNode obj) {
result =
obj
.getAPropertyRead(any(string s |
s = "responseText" or
s = "responseXML"
))
}
/**
* A model of a URL request made using a `jQuery.ajax` shorthand.
* E.g. `jQuery.getJSON`, `jQuery.post` etc.
* See: https://api.jquery.com/category/ajax/shorthand-methods/.
*
* Models the following method signatures:
* - `jQuery.get( url [, data ] [, success ] [, dataType ] )`
* - `jQuery.getJSON( url [, data ] [, success ] )`
* - `jQuery.getScript( url [, success ] )`
* - `jQuery.post( url [, data ] [, success ] [, dataType ] )`
* - `.load( url [, data ] [, complete ] )`
*/
private class JQueryAjaxShortHand extends ClientRequest::Range {
string name;
JQueryAjaxShortHand() {
(
name = "get" or
name = "getJSON" or
name = "getScript" or
name = "post"
) and
this = jquery().getAMemberCall(name)
)
or
name = "load" and
this = JQuery::objectRef().getAMethodCall(name)
}
override DataFlow::Node getUrl() { result = getArgument(0) }
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() {
result = getArgument(1) and
not name = "getScript" and // doesn't have a data-node.
not result.getALocalSource() instanceof DataFlow::FunctionNode // looks like the success callback.
}
private string getResponseType() {
(name = "get" or name = "post") and
getLastArgument().mayHaveStringValue(result) and
getNumArgument() > 1
or
name = "getJSON" and result = "json"
or
(name = "getScript" or name = "load") and
result = "text"
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
(
responseType = getResponseType()
or
not exists(getResponseType()) and responseType = ""
) and
promise = false and
(
// one of the two last arguments
result = getCallback([getNumArgument() - 2 .. getNumArgument() - 1]).getParameter(0)
or
result = getAnAjaxCallbackDataNode(this)
)
}
}
override DataFlow::Node getUrl() {
result = getArgument(0) or
result = getOptionArgument([0 .. 1], "url")
}
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() { result = getOptionArgument([0 .. 1], "data") }
}
module JQuery {

Просмотреть файл

@ -55,6 +55,17 @@ test_ClientRequest
| tst.js:171:2:171:10 | base(url) |
| tst.js:172:2:172:14 | variant1(url) |
| tst.js:173:2:173:14 | variant2(url) |
| tst.js:177:5:177:49 | $.get( ... a ) {}) |
| tst.js:179:2:179:60 | $.getJS ... a ) {}) |
| tst.js:181:2:181:69 | $.getSc ... r ) {}) |
| tst.js:183:2:183:60 | $.post( ... ) { }) |
| 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") |
| tst.js:202:5:208:7 | $.ajax( ... }}) |
| tst.js:210:2:210: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 |
@ -74,13 +85,16 @@ test_getADataNode
| tst.js:68:5:68:23 | superagent.get(url) | tst.js:68:52:68:60 | queryData |
| tst.js:69:5:69:23 | superagent.get(url) | tst.js:69:48:69:56 | queryData |
| tst.js:74:5:74:29 | $.ajax( ... data}) | tst.js:74:24:74:27 | data |
| tst.js:77:5:77:32 | $.getJS ... data}) | tst.js:77:27:77:30 | data |
| tst.js:77:5:77:32 | $.getJS ... data}) | tst.js:77:20:77:31 | {data: data} |
| tst.js:80:15:80:34 | new XMLHttpRequest() | tst.js:82:14:82:17 | data |
| tst.js:98:15:98:34 | new XMLHttpRequest() | tst.js:101:14:101:17 | data |
| tst.js:106:16:106:35 | new XMLHttpRequest() | tst.js:108:15:108:18 | data |
| tst.js:117:5:121:6 | request ... \\n }) | tst.js:117:18:121:5 | functio ... ;\\n } |
| tst.js:123:5:127:6 | request ... \\n }) | tst.js:123:18:123:29 | {json: true} |
| tst.js:129:5:129:37 | request ... true}) | tst.js:129:25:129:36 | {json: true} |
| tst.js:179:2:179:60 | $.getJS ... a ) {}) | tst.js:179:31:179:38 | "MyData" |
| tst.js:183:2:183:60 | $.post( ... ) { }) | tst.js:183:28:183:37 | "PostData" |
| tst.js:187:2:193:3 | $.ajax( ... on"\\n\\t}) | tst.js:190:11:190:20 | "AjaxData" |
test_getHost
| tst.js:87:5:87:39 | http.ge ... host}) | tst.js:87:34:87:37 | host |
| tst.js:89:5:89:23 | axios({host: host}) | tst.js:89:18:89:21 | host |
@ -121,11 +135,9 @@ test_getUrl
| tst.js:68:5:68:23 | superagent.get(url) | tst.js:68:20:68:22 | url |
| tst.js:69:5:69:23 | superagent.get(url) | tst.js:69:20:69:22 | url |
| tst.js:74:5:74:29 | $.ajax( ... data}) | tst.js:74:12:74:14 | url |
| tst.js:75:5:75:35 | $.ajax( ... data}) | tst.js:75:12:75:34 | {url: u ... : data} |
| tst.js:75:5:75:35 | $.ajax( ... data}) | tst.js:75:18:75:20 | url |
| tst.js:77:5:77:32 | $.getJS ... data}) | tst.js:77:15:77:17 | url |
| tst.js:78:5:78:38 | $.getJS ... data}) | tst.js:78:15:78:37 | {url: u ... : data} |
| tst.js:78:5:78:38 | $.getJS ... data}) | tst.js:78:21:78:23 | url |
| tst.js:80:15:80:34 | new XMLHttpRequest() | tst.js:81:17:81:19 | url |
| tst.js:87:5:87:39 | http.ge ... host}) | tst.js:87:14:87:24 | relativeUrl |
| tst.js:89:5:89:23 | axios({host: host}) | tst.js:89:11:89:22 | {host: host} |
@ -150,6 +162,17 @@ test_getUrl
| tst.js:171:2:171:10 | base(url) | tst.js:171:7:171:9 | url |
| tst.js:172:2:172:14 | variant1(url) | tst.js:172:11:172:13 | url |
| tst.js:173:2:173:14 | variant2(url) | tst.js:173:11:173:13 | url |
| tst.js:177:5:177:49 | $.get( ... a ) {}) | tst.js:177:12:177:27 | "ajax/test.html" |
| tst.js:179:2:179:60 | $.getJS ... a ) {}) | tst.js:179:13:179:28 | "ajax/test.json" |
| tst.js:181:2:181:69 | $.getSc ... r ) {}) | tst.js:181:15:181:28 | "ajax/test.js" |
| tst.js:183:2:183:60 | $.post( ... ) { }) | tst.js:183:10:183:25 | "ajax/test.html" |
| 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" |
| tst.js:202:5:208:7 | $.ajax( ... }}) | tst.js:203:10:203:22 | "example.php" |
| tst.js:210:2:210:21 | $.get("example.php") | tst.js:210:8:210: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 |
@ -199,3 +222,14 @@ test_getAResponseDataNode
| tst.js:151:5:151:23 | superagent.get(url) | tst.js:151:35:151:37 | res | stream | false |
| tst.js:160:5:160:17 | xhr.send(url) | tst.js:162:9:162:29 | xhr.get ... eJson() | json | false |
| tst.js:160:5:160:17 | xhr.send(url) | tst.js:163:9:163:32 | xhr.get ... aders() | headers | false |
| tst.js:177:5:177:49 | $.get( ... a ) {}) | tst.js:177:40:177:43 | data | | false |
| tst.js:179:2:179:60 | $.getJS ... a ) {}) | tst.js:179:51:179:54 | data | json | false |
| tst.js:181:2:181:69 | $.getSc ... r ) {}) | tst.js:181:41:181:44 | data | text | false |
| tst.js:183:2:183:60 | $.post( ... ) { }) | tst.js:183:50:183:53 | data | | false |
| 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 |
| tst.js:202:5:208:7 | $.ajax( ... }}) | tst.js:207:21:207:36 | err.responseText | json | false |
| tst.js:210:2:210:21 | $.get("example.php") | tst.js:210:55:210:70 | xhr.responseText | | false |

Просмотреть файл

@ -74,8 +74,8 @@ import {ClientRequest, net} from 'electron';
$.ajax(url, {data: data});
$.ajax({url: url, tdata: data});
$.getJSON(url, {data: data});
$.getJSON({url: url, tdata: data});
$.getJSON(url, {data: data}); // the entire "{data: data}" object is the data.
$.getJSON({url: url, tdata: data}); // not how to use getJSON.
var xhr = new XMLHttpRequest();
xhr.open(_, url);
@ -172,3 +172,40 @@ import {ClientRequest, net} from 'electron';
variant1(url);
variant2(url);
});
(function() {
$.get( "ajax/test.html", function( data ) {});
$.getJSON( "ajax/test.json", "MyData", function( data ) {});
$.getScript( "ajax/test.js", function( data, textStatus, jqxhr ) {});
$.post( "ajax/test.html", "PostData", function( data ) { });
$( "#result" ).load( "ajax/test.html", function(result) {});
$.ajax({
type: "POST",
url: "http://example.org",
data: "AjaxData",
success: (ajaxData) => {},
dataType: "json"
});
$.get( "ajax/test.json", function( data ) {}, "json");
$.ajax({url: "ajax/blob", dataType: "blob"})
.done(function( data ) {});
$.get("example.php").done(function(response) {})
$.ajax({
url: "example.php",
type: 'POST',
dataType: "json",
error: function (err) {
console.log(err.responseText)
}});
$.get("example.php").fail(function(xhr) {console.log(xhr.responseText)});
});