Merge remote-tracking branch 'upstream/master' into typeAheadSink

This commit is contained in:
Erik Krogh Kristensen
2019-11-27 15:19:06 +01:00
65 changed files with 780 additions and 269 deletions

View File

@@ -68,7 +68,7 @@ predicate benignContext(Expr e) {
any(InvokeExpr invoke).getCallee() = e
or
// arguments to Promise.resolve (and promise library variants) are benign.
e = any(ResolvedPromiseDefinition promise).getValue().asExpr()
e = any(PromiseCreationCall promise).getValue().asExpr()
}
predicate oneshotClosure(DataFlow::CallNode call) {
@@ -198,7 +198,7 @@ module Deferred {
/**
* A resolved promise created by a `new Deferred().resolve()` call.
*/
class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition {
class ResolvedDeferredPromiseDefinition extends PromiseCreationCall {
ResolvedDeferredPromiseDefinition() {
this = any(DeferredPromiseDefinition def).ref().getAMethodCall("resolve")
}

View File

@@ -83,9 +83,13 @@ abstract class Module extends TopLevel {
result = c.(Folder).getJavaScriptFile("index")
)
or
// handle the case where the import path is missing an extension
// handle the case where the import path is missing the extension
exists(Folder f | f = path.resolveUpTo(path.getNumComponent() - 1) |
result = f.getJavaScriptFile(path.getBaseName())
or
// If a js file was not found look for a file that compiles to js
not exists(f.getJavaScriptFile(path.getBaseName())) and
result = f.getJavaScriptFile(path.getStem())
)
)
}

View File

@@ -205,6 +205,9 @@ abstract class PathExpr extends PathExprBase {
/** Gets the base name of the folder or file this path refers to. */
string getBaseName() { result = getValue().(PathString).getBaseName() }
/** Gets the stem, that is, base name without extension, of the folder or file this path refers to. */
string getStem() { result = getValue().(PathString).getStem() }
/**
* Gets the file or folder that the first `n` components of this path refer to
* when resolved relative to the root folder of the given `priority`.

View File

@@ -30,6 +30,22 @@ module Bluebird {
override DataFlow::Node getValue() { result = getArgument(0) }
}
/**
* An aggregated promise produced either by `Promise.all`, `Promise.race` or `Promise.map`.
*/
class AggregateBluebirdPromiseDefinition extends PromiseCreationCall {
AggregateBluebirdPromiseDefinition() {
exists(string m | m = "all" or m = "race" or m = "map" |
this = bluebird().getAMemberCall(m)
)
}
override DataFlow::Node getValue() {
result = getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
}
}
}
/**

View File

@@ -152,15 +152,20 @@ private class ES2015PromiseDefinition extends PromiseDefinition, DataFlow::NewNo
}
/**
* A promise that is resolved with the given value.
* A promise that is created and resolved with one or more value.
*/
abstract class ResolvedPromiseDefinition extends DataFlow::CallNode {
abstract class PromiseCreationCall extends DataFlow::CallNode {
/**
* Gets the value this promise is resolved with.
*/
abstract DataFlow::Node getValue();
}
/**
* A promise that is created using a `.resolve()` call.
*/
abstract class ResolvedPromiseDefinition extends PromiseCreationCall {}
/**
* A resolved promise created by the standard ECMAScript 2015 `Promise.resolve` function.
*/
@@ -172,6 +177,21 @@ class ResolvedES2015PromiseDefinition extends ResolvedPromiseDefinition {
override DataFlow::Node getValue() { result = getArgument(0) }
}
/**
* An aggregated promise produced either by `Promise.all` or `Promise.race`.
*/
class AggregateES2015PromiseDefinition extends PromiseCreationCall {
AggregateES2015PromiseDefinition() {
exists(string m | m = "all" or m = "race" |
this = DataFlow::globalVarRef("Promise").getAMemberCall(m)
)
}
override DataFlow::Node getValue() {
result = getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
}
}
/**
* A data flow edge from a promise reaction to the corresponding handler.
*/
@@ -197,7 +217,7 @@ predicate promiseTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
pred = succ.(PromiseDefinition).getResolveParameter().getACall().getArgument(0)
or
// from `x` to `Promise.resolve(x)`
pred = succ.(ResolvedPromiseDefinition).getValue()
pred = succ.(PromiseCreationCall).getValue()
or
exists(DataFlow::MethodCallNode thn, DataFlow::FunctionNode cb |
thn.getMethodName() = "then" and cb = thn.getCallback(0)

View File

@@ -840,16 +840,18 @@ module DataFlow {
* An array element pattern viewed as a property read; for instance, in
* `var [ x, y ] = arr`, `x` is a read of property 0 of `arr` and similar
* for `y`.
*
* Note: We currently do not expose the array index as the property name,
* instead treating it as a read of an unknown property.
*/
private class ElementPatternAsPropRead extends PropRead, ElementPatternNode {
override Node getBase() { result = TDestructuringPatternNode(pattern) }
override Expr getPropertyNameExpr() { none() }
override string getPropertyName() { none() }
override string getPropertyName() {
exists (int i |
elt = pattern.getElement(i) and
result = i.toString()
)
}
}
/**

View File

@@ -211,7 +211,7 @@ private class WindowNameAccess extends RemoteFlowSource {
this = DataFlow::globalObjectRef().getAPropertyRead("name")
or
// Reference to `name` on a container that does not assign to it.
this.accessesGlobal("name") and
this.asExpr().(GlobalVarAccess).getName() = "name" and
not exists(VarDef def |
def.getAVariable().(GlobalVariable).getName() = "name" and
def.getContainer() = this.asExpr().getContainer()