mirror of
https://github.com/github/codeql.git
synced 2026-03-17 04:56:58 +01:00
JS: basic model of closure Promises
This commit is contained in:
@@ -45,3 +45,57 @@ module Q {
|
||||
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
|
||||
}
|
||||
}
|
||||
|
||||
private module ClosurePromise {
|
||||
/**
|
||||
* A promise created by a call `new goog.Promise(executor)`.
|
||||
*/
|
||||
private class ClosurePromiseDefinition extends PromiseDefinition, DataFlow::NewNode {
|
||||
ClosurePromiseDefinition() { this = Closure::moduleImport("goog.Promise").getACall() }
|
||||
|
||||
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A promise created by a call `goog.Promise.resolve(value)`.
|
||||
*/
|
||||
private class ResolvedClosurePromiseDefinition extends ResolvedPromiseDefinition {
|
||||
ResolvedClosurePromiseDefinition() {
|
||||
this = Closure::moduleImport("goog.Promise.resolve").getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getValue() { result = getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint steps through closure promise methods.
|
||||
*/
|
||||
private class ClosurePromiseTaintStep extends TaintTracking::AdditionalTaintStep {
|
||||
DataFlow::Node pred;
|
||||
|
||||
ClosurePromiseTaintStep() {
|
||||
// static methods in goog.Promise
|
||||
exists (DataFlow::CallNode call, string name |
|
||||
call = Closure::moduleImport("goog.Promise." + name).getACall() and
|
||||
this = call and
|
||||
pred = call.getAnArgument()
|
||||
|
|
||||
name = "all" or
|
||||
name = "allSettled" or
|
||||
name = "firstFulfilled" or
|
||||
name = "race"
|
||||
)
|
||||
or
|
||||
// promise created through goog.promise.withResolver()
|
||||
exists (DataFlow::CallNode resolver |
|
||||
resolver = Closure::moduleImport("goog.Promise.withResolver").getACall() and
|
||||
this = resolver.getAPropertyRead("promise") and
|
||||
pred = resolver.getAMethodCall("resolve").getArgument(0)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate step(DataFlow::Node src, DataFlow::Node dst) {
|
||||
src = pred and dst = this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,3 +5,5 @@
|
||||
| promises.js:43:19:45:6 | Q.Promi ... \\n }) |
|
||||
| promises.js:53:19:53:41 | Promise ... source) |
|
||||
| promises.js:62:19:62:41 | Promise ... source) |
|
||||
| promises.js:71:5:71:27 | Promise ... source) |
|
||||
| promises.js:72:5:72:41 | new Pro ... ource)) |
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
| promises.js:53:19:53:41 | Promise ... source) | promises.js:53:35:53:40 | source |
|
||||
| promises.js:62:19:62:41 | Promise ... source) | promises.js:62:35:62:40 | source |
|
||||
| promises.js:71:5:71:27 | Promise ... source) | promises.js:71:21:71:26 | source |
|
||||
|
||||
@@ -64,3 +64,13 @@
|
||||
var sink = val;
|
||||
});
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var Promise = goog.require('goog.Promise');
|
||||
var source = "tainted";
|
||||
Promise.resolve(source).then(val => { var sink = val; });
|
||||
new Promise((res,rej) => res(source)).then(val => { var sink = val });
|
||||
let resolver = Promise.withResolver();
|
||||
resolver.resolve(source);
|
||||
resolver.promise.then(val => { var sink = val });
|
||||
})();
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
| partialCalls.js:4:17:4:24 | source() | partialCalls.js:51:14:51:14 | x |
|
||||
| promise.js:4:24:4:31 | source() | promise.js:4:8:4:32 | Promise ... urce()) |
|
||||
| promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) |
|
||||
| promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) |
|
||||
| promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise |
|
||||
| sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x |
|
||||
| sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x |
|
||||
| sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x |
|
||||
|
||||
@@ -4,3 +4,11 @@ function test() {
|
||||
sink(Promise.resolve(source())); // NOT OK
|
||||
sink(bluebird.resolve(source())); // NOT OK
|
||||
}
|
||||
|
||||
function closure() {
|
||||
let Promise = goog.require('goog.Promise');
|
||||
sink(Promise.resolve(source())); // NOT OK
|
||||
let resolver = Promise.withResolver();
|
||||
resolver.resolve(source());
|
||||
sink(resolver.promise); // NOT OK
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user