mirror of
https://github.com/github/codeql.git
synced 2026-05-03 20:58:03 +02:00
add support for the promise polyfill
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
lgtm,codescanning
|
||||
* The security queries now track flow through various `Promise` polyfills.
|
||||
Affected packages are
|
||||
[kew](https://npmjs.com/package/kew)
|
||||
[kew](https://npmjs.com/package/kew),
|
||||
[promise](https://npmjs.com/package/promise)
|
||||
|
||||
@@ -58,6 +58,22 @@ private predicate hasHandler(DataFlow::InvokeNode promise, string m, int i) {
|
||||
exists(promise.getAMethodCall(m).getCallback(i))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the `Promise` object.
|
||||
* Either from the standard library, a polyfill import, or a polyfill that defines the global `Promise` variable.
|
||||
*/
|
||||
private DataFlow::SourceNode getAPromiseObject() {
|
||||
// Standard library, or polyfills like [es6-shim](https://npmjs.org/package/es6-shim).
|
||||
result = DataFlow::globalVarRef("Promise")
|
||||
or
|
||||
// polyfills from the [`promise`](https://npmjs.org/package/promise) library.
|
||||
result =
|
||||
DataFlow::moduleImport([
|
||||
"promise", "promise/domains", "promise/setimmediate", "promise/lib/es6-extensions",
|
||||
"promise/domains/es6-extensions", "promise/setimmediate/es6-extensions"
|
||||
])
|
||||
}
|
||||
|
||||
/**
|
||||
* A call that looks like a Promise.
|
||||
*
|
||||
@@ -75,7 +91,7 @@ class PromiseCandidate extends DataFlow::InvokeNode {
|
||||
* A promise object created by the standard ECMAScript 2015 `Promise` constructor.
|
||||
*/
|
||||
private class ES2015PromiseDefinition extends PromiseDefinition, DataFlow::NewNode {
|
||||
ES2015PromiseDefinition() { this = DataFlow::globalVarRef("Promise").getAnInstantiation() }
|
||||
ES2015PromiseDefinition() { this = getAPromiseObject().getAnInstantiation() }
|
||||
|
||||
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
|
||||
}
|
||||
@@ -109,9 +125,7 @@ abstract class PromiseAllCreation extends PromiseCreationCall {
|
||||
* A resolved promise created by the standard ECMAScript 2015 `Promise.resolve` function.
|
||||
*/
|
||||
class ResolvedES2015PromiseDefinition extends ResolvedPromiseDefinition {
|
||||
ResolvedES2015PromiseDefinition() {
|
||||
this = DataFlow::globalVarRef("Promise").getAMemberCall("resolve")
|
||||
}
|
||||
ResolvedES2015PromiseDefinition() { this = getAPromiseObject().getAMemberCall("resolve") }
|
||||
|
||||
override DataFlow::Node getValue() { result = getArgument(0) }
|
||||
}
|
||||
@@ -121,8 +135,7 @@ class ResolvedES2015PromiseDefinition extends ResolvedPromiseDefinition {
|
||||
*/
|
||||
class AggregateES2015PromiseDefinition extends PromiseCreationCall {
|
||||
AggregateES2015PromiseDefinition() {
|
||||
exists(string m | m = "all" or m = "race" or m = "any" |
|
||||
this = DataFlow::globalVarRef("Promise").getAMemberCall(m)
|
||||
this = getAPromiseObject().getAMemberCall(m)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -92,3 +92,10 @@
|
||||
var sink = val;
|
||||
});
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var PromiseA = require('promise');
|
||||
var PromiseB = require('promise/domains');
|
||||
PromiseA.resolve(source);
|
||||
PromiseB.resolve(source);
|
||||
})();
|
||||
|
||||
@@ -36,6 +36,8 @@ test_ResolvedPromiseDefinition
|
||||
| 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 |
|
||||
| promises.js:79:19:79:41 | Promise ... source) | promises.js:79:35:79:40 | source |
|
||||
| promises.js:99:3:99:26 | Promise ... source) | promises.js:99:20:99:25 | source |
|
||||
| promises.js:100:3:100:26 | Promise ... source) | promises.js:100:20:100:25 | source |
|
||||
test_PromiseDefinition_getARejectHandler
|
||||
| flow.js:26:2:26:49 | new Pro ... ource)) | flow.js:26:69:26:80 | y => sink(y) |
|
||||
| flow.js:32:2:32:49 | new Pro ... ource)) | flow.js:32:57:32:68 | x => sink(x) |
|
||||
@@ -407,3 +409,7 @@ typetrack
|
||||
| promises.js:75:27:75:29 | val | promises.js:75:5:75:20 | resolver.promise | load $PromiseResolveField$ |
|
||||
| promises.js:88:17:90:4 | Q.Promi ... );\\n }) | promises.js:89:15:89:20 | source | copy $PromiseResolveField$ |
|
||||
| promises.js:88:17:90:4 | Q.Promi ... );\\n }) | promises.js:89:15:89:20 | source | store $PromiseResolveField$ |
|
||||
| promises.js:99:3:99:26 | Promise ... source) | promises.js:99:20:99:25 | source | copy $PromiseResolveField$ |
|
||||
| promises.js:99:3:99:26 | Promise ... source) | promises.js:99:20:99:25 | source | store $PromiseResolveField$ |
|
||||
| promises.js:100:3:100:26 | Promise ... source) | promises.js:100:20:100:25 | source | copy $PromiseResolveField$ |
|
||||
| promises.js:100:3:100:26 | Promise ... source) | promises.js:100:20:100:25 | source | store $PromiseResolveField$ |
|
||||
|
||||
Reference in New Issue
Block a user