mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
JS: Make implicit this receivers explicit
This commit is contained in:
@@ -21,8 +21,8 @@ class DecodingCall extends CallNode {
|
|||||||
Node input;
|
Node input;
|
||||||
|
|
||||||
DecodingCall() {
|
DecodingCall() {
|
||||||
getCalleeName().matches("decodeURI%") and
|
this.getCalleeName().matches("decodeURI%") and
|
||||||
input = getArgument(0) and
|
input = this.getArgument(0) and
|
||||||
kind = "URI decoding"
|
kind = "URI decoding"
|
||||||
or
|
or
|
||||||
input = this.(JsonParserCall).getInput() and
|
input = this.(JsonParserCall).getInput() and
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import LanguageFeatures.UnusedIndexVariable
|
|||||||
*/
|
*/
|
||||||
class UnusedLocal extends LocalVariable {
|
class UnusedLocal extends LocalVariable {
|
||||||
UnusedLocal() {
|
UnusedLocal() {
|
||||||
not exists(getAnAccess()) and
|
not exists(this.getAnAccess()) and
|
||||||
not exists(Parameter p | this = p.getAVariable()) and
|
not exists(Parameter p | this = p.getAVariable()) and
|
||||||
not exists(FunctionExpr fe | this = fe.getVariable()) and
|
not exists(FunctionExpr fe | this = fe.getVariable()) and
|
||||||
not exists(ClassExpr ce | this = ce.getVariable()) and
|
not exists(ClassExpr ce | this = ce.getVariable()) and
|
||||||
@@ -20,6 +20,6 @@ class UnusedLocal extends LocalVariable {
|
|||||||
// avoid double reporting
|
// avoid double reporting
|
||||||
not unusedIndexVariable(_, this, _) and
|
not unusedIndexVariable(_, this, _) and
|
||||||
// common convention: variables with leading underscore are intentionally unused
|
// common convention: variables with leading underscore are intentionally unused
|
||||||
getName().charAt(0) != "_"
|
this.getName().charAt(0) != "_"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ predicate isGetterProperty(string name) {
|
|||||||
* A property access that may invoke a getter.
|
* A property access that may invoke a getter.
|
||||||
*/
|
*/
|
||||||
class GetterPropertyAccess extends PropAccess {
|
class GetterPropertyAccess extends PropAccess {
|
||||||
override predicate isImpure() { isGetterProperty(getPropertyName()) }
|
override predicate isImpure() { isGetterProperty(this.getPropertyName()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -28,29 +28,31 @@ private import Expressions.ExprHasNoEffect
|
|||||||
class AmdModuleDefinition extends CallExpr {
|
class AmdModuleDefinition extends CallExpr {
|
||||||
AmdModuleDefinition() {
|
AmdModuleDefinition() {
|
||||||
inVoidContext(this) and
|
inVoidContext(this) and
|
||||||
getCallee().(GlobalVarAccess).getName() = "define" and
|
this.getCallee().(GlobalVarAccess).getName() = "define" and
|
||||||
exists(int n | n = getNumArgument() |
|
exists(int n | n = this.getNumArgument() |
|
||||||
n = 1
|
n = 1
|
||||||
or
|
or
|
||||||
n = 2 and getArgument(0) instanceof ArrayExpr
|
n = 2 and this.getArgument(0) instanceof ArrayExpr
|
||||||
or
|
or
|
||||||
n = 3 and getArgument(0) instanceof ConstantString and getArgument(1) instanceof ArrayExpr
|
n = 3 and
|
||||||
|
this.getArgument(0) instanceof ConstantString and
|
||||||
|
this.getArgument(1) instanceof ArrayExpr
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the array of module dependencies, if any. */
|
/** Gets the array of module dependencies, if any. */
|
||||||
ArrayExpr getDependencies() {
|
ArrayExpr getDependencies() {
|
||||||
result = getArgument(0) or
|
result = this.getArgument(0) or
|
||||||
result = getArgument(1)
|
result = this.getArgument(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the `i`th dependency of this module definition. */
|
/** Gets the `i`th dependency of this module definition. */
|
||||||
PathExpr getDependency(int i) { result = getDependencies().getElement(i) }
|
PathExpr getDependency(int i) { result = this.getDependencies().getElement(i) }
|
||||||
|
|
||||||
/** Gets a dependency of this module definition. */
|
/** Gets a dependency of this module definition. */
|
||||||
PathExpr getADependency() {
|
PathExpr getADependency() {
|
||||||
result = getDependency(_) or
|
result = this.getDependency(_) or
|
||||||
result = getARequireCall().getAnArgument()
|
result = this.getARequireCall().getAnArgument()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,19 +60,19 @@ class AmdModuleDefinition extends CallExpr {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
DataFlow::SourceNode getFactoryNode() {
|
DataFlow::SourceNode getFactoryNode() {
|
||||||
result = getFactoryNodeInternal() and
|
result = this.getFactoryNodeInternal() and
|
||||||
result instanceof DataFlow::ValueNode
|
result instanceof DataFlow::ValueNode
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataFlow::Node getFactoryNodeInternal() {
|
private DataFlow::Node getFactoryNodeInternal() {
|
||||||
// To avoid recursion, this should not depend on `SourceNode`.
|
// To avoid recursion, this should not depend on `SourceNode`.
|
||||||
result = DataFlow::valueNode(getLastArgument()) or
|
result = DataFlow::valueNode(this.getLastArgument()) or
|
||||||
result = getFactoryNodeInternal().getAPredecessor()
|
result = this.getFactoryNodeInternal().getAPredecessor()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the expression defining this module. */
|
/** Gets the expression defining this module. */
|
||||||
Expr getModuleExpr() {
|
Expr getModuleExpr() {
|
||||||
exists(DataFlow::Node f | f = getFactoryNode() |
|
exists(DataFlow::Node f | f = this.getFactoryNode() |
|
||||||
if f instanceof DataFlow::FunctionNode
|
if f instanceof DataFlow::FunctionNode
|
||||||
then
|
then
|
||||||
exists(ReturnStmt ret | ret.getContainer() = f.(DataFlow::FunctionNode).getAstNode() |
|
exists(ReturnStmt ret | ret.getContainer() = f.(DataFlow::FunctionNode).getAstNode() |
|
||||||
@@ -81,15 +83,15 @@ class AmdModuleDefinition extends CallExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a source node whose value becomes the definition of this module. */
|
/** Gets a source node whose value becomes the definition of this module. */
|
||||||
DataFlow::SourceNode getAModuleSource() { result.flowsToExpr(getModuleExpr()) }
|
DataFlow::SourceNode getAModuleSource() { result.flowsToExpr(this.getModuleExpr()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `p` is the parameter corresponding to dependency `dep`.
|
* Holds if `p` is the parameter corresponding to dependency `dep`.
|
||||||
*/
|
*/
|
||||||
predicate dependencyParameter(PathExpr dep, Parameter p) {
|
predicate dependencyParameter(PathExpr dep, Parameter p) {
|
||||||
exists(int i |
|
exists(int i |
|
||||||
dep = getDependency(i) and
|
dep = this.getDependency(i) and
|
||||||
p = getFactoryParameter(i)
|
p = this.getFactoryParameter(i)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +109,7 @@ class AmdModuleDefinition extends CallExpr {
|
|||||||
*/
|
*/
|
||||||
Parameter getDependencyParameter(string name) {
|
Parameter getDependencyParameter(string name) {
|
||||||
exists(PathExpr dep |
|
exists(PathExpr dep |
|
||||||
dependencyParameter(dep, result) and
|
this.dependencyParameter(dep, result) and
|
||||||
dep.getValue() = name
|
dep.getValue() = name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -116,40 +118,40 @@ class AmdModuleDefinition extends CallExpr {
|
|||||||
* Gets the `i`th parameter of the factory function of this module.
|
* Gets the `i`th parameter of the factory function of this module.
|
||||||
*/
|
*/
|
||||||
private Parameter getFactoryParameter(int i) {
|
private Parameter getFactoryParameter(int i) {
|
||||||
getFactoryNodeInternal().asExpr().(Function).getParameter(i) = result
|
this.getFactoryNodeInternal().asExpr().(Function).getParameter(i) = result
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the parameter corresponding to the pseudo-dependency `require`.
|
* Gets the parameter corresponding to the pseudo-dependency `require`.
|
||||||
*/
|
*/
|
||||||
Parameter getRequireParameter() {
|
Parameter getRequireParameter() {
|
||||||
result = getDependencyParameter("require")
|
result = this.getDependencyParameter("require")
|
||||||
or
|
or
|
||||||
// if no dependencies are listed, the first parameter is assumed to be `require`
|
// if no dependencies are listed, the first parameter is assumed to be `require`
|
||||||
not exists(getDependencies()) and result = getFactoryParameter(0)
|
not exists(this.getDependencies()) and result = this.getFactoryParameter(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private Variable getRequireVariable() { result = getRequireParameter().getVariable() }
|
private Variable getRequireVariable() { result = this.getRequireParameter().getVariable() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the parameter corresponding to the pseudo-dependency `exports`.
|
* Gets the parameter corresponding to the pseudo-dependency `exports`.
|
||||||
*/
|
*/
|
||||||
Parameter getExportsParameter() {
|
Parameter getExportsParameter() {
|
||||||
result = getDependencyParameter("exports")
|
result = this.getDependencyParameter("exports")
|
||||||
or
|
or
|
||||||
// if no dependencies are listed, the second parameter is assumed to be `exports`
|
// if no dependencies are listed, the second parameter is assumed to be `exports`
|
||||||
not exists(getDependencies()) and result = getFactoryParameter(1)
|
not exists(this.getDependencies()) and result = this.getFactoryParameter(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the parameter corresponding to the pseudo-dependency `module`.
|
* Gets the parameter corresponding to the pseudo-dependency `module`.
|
||||||
*/
|
*/
|
||||||
Parameter getModuleParameter() {
|
Parameter getModuleParameter() {
|
||||||
result = getDependencyParameter("module")
|
result = this.getDependencyParameter("module")
|
||||||
or
|
or
|
||||||
// if no dependencies are listed, the third parameter is assumed to be `module`
|
// if no dependencies are listed, the third parameter is assumed to be `module`
|
||||||
not exists(getDependencies()) and result = getFactoryParameter(2)
|
not exists(this.getDependencies()) and result = this.getFactoryParameter(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,13 +159,13 @@ class AmdModuleDefinition extends CallExpr {
|
|||||||
* into this module's `module.exports` property.
|
* into this module's `module.exports` property.
|
||||||
*/
|
*/
|
||||||
DefiniteAbstractValue getAModuleExportsValue() {
|
DefiniteAbstractValue getAModuleExportsValue() {
|
||||||
result = [getAnImplicitExportsValue(), getAnExplicitExportsValue()]
|
result = [this.getAnImplicitExportsValue(), this.getAnExplicitExportsValue()]
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[noinline, nomagic]
|
pragma[noinline, nomagic]
|
||||||
private AbstractValue getAnImplicitExportsValue() {
|
private AbstractValue getAnImplicitExportsValue() {
|
||||||
// implicit exports: anything that is returned from the factory function
|
// implicit exports: anything that is returned from the factory function
|
||||||
result = getModuleExpr().analyze().getAValue()
|
result = this.getModuleExpr().analyze().getAValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
@@ -182,7 +184,7 @@ class AmdModuleDefinition extends CallExpr {
|
|||||||
* Gets a call to `require` inside this module.
|
* Gets a call to `require` inside this module.
|
||||||
*/
|
*/
|
||||||
CallExpr getARequireCall() {
|
CallExpr getARequireCall() {
|
||||||
result.getCallee().getUnderlyingValue() = getRequireVariable().getAnAccess()
|
result.getCallee().getUnderlyingValue() = this.getRequireVariable().getAnAccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +202,7 @@ private class AmdDependencyPath extends PathExprCandidate {
|
|||||||
private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString {
|
private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString {
|
||||||
ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() }
|
ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() }
|
||||||
|
|
||||||
override string getValue() { result = getStringValue() }
|
override string getValue() { result = this.getStringValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -239,7 +241,7 @@ private class AmdDependencyImport extends Import {
|
|||||||
*/
|
*/
|
||||||
private File guessTarget() {
|
private File guessTarget() {
|
||||||
exists(PathString imported, string abspath, string dirname, string basename |
|
exists(PathString imported, string abspath, string dirname, string basename |
|
||||||
targetCandidate(result, abspath, imported, dirname, basename)
|
this.targetCandidate(result, abspath, imported, dirname, basename)
|
||||||
|
|
|
|
||||||
abspath.regexpMatch(".*/\\Q" + imported + "\\E")
|
abspath.regexpMatch(".*/\\Q" + imported + "\\E")
|
||||||
or
|
or
|
||||||
@@ -262,7 +264,7 @@ private class AmdDependencyImport extends Import {
|
|||||||
private predicate targetCandidate(
|
private predicate targetCandidate(
|
||||||
File f, string abspath, PathString imported, string dirname, string basename
|
File f, string abspath, PathString imported, string dirname, string basename
|
||||||
) {
|
) {
|
||||||
imported = getImportedPath().getValue() and
|
imported = this.getImportedPath().getValue() and
|
||||||
f.getStem() = imported.getStem() and
|
f.getStem() = imported.getStem() and
|
||||||
f.getAbsolutePath() = abspath and
|
f.getAbsolutePath() = abspath and
|
||||||
dirname = imported.getDirName() and
|
dirname = imported.getDirName() and
|
||||||
@@ -273,14 +275,14 @@ private class AmdDependencyImport extends Import {
|
|||||||
* Gets the module whose absolute path matches this import, if there is only a single such module.
|
* Gets the module whose absolute path matches this import, if there is only a single such module.
|
||||||
*/
|
*/
|
||||||
private Module resolveByAbsolutePath() {
|
private Module resolveByAbsolutePath() {
|
||||||
result.getFile() = unique(File file | file = guessTarget())
|
result.getFile() = unique(File file | file = this.guessTarget())
|
||||||
}
|
}
|
||||||
|
|
||||||
override Module getImportedModule() {
|
override Module getImportedModule() {
|
||||||
result = super.getImportedModule()
|
result = super.getImportedModule()
|
||||||
or
|
or
|
||||||
not exists(super.getImportedModule()) and
|
not exists(super.getImportedModule()) and
|
||||||
result = resolveByAbsolutePath()
|
result = this.resolveByAbsolutePath()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getImportedModuleNode() {
|
override DataFlow::Node getImportedModuleNode() {
|
||||||
@@ -314,7 +316,7 @@ class AmdModule extends Module {
|
|||||||
|
|
||||||
override DataFlow::Node getAnExportedValue(string name) {
|
override DataFlow::Node getAnExportedValue(string name) {
|
||||||
exists(DataFlow::PropWrite pwn | result = pwn.getRhs() |
|
exists(DataFlow::PropWrite pwn | result = pwn.getRhs() |
|
||||||
pwn.getBase().analyze().getAValue() = getDefine().getAModuleExportsValue() and
|
pwn.getBase().analyze().getAValue() = this.getDefine().getAModuleExportsValue() and
|
||||||
name = pwn.getPropertyName()
|
name = pwn.getPropertyName()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -329,6 +331,6 @@ class AmdModule extends Module {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Returned from factory function
|
// Returned from factory function
|
||||||
result = getDefine().getModuleExpr().flow()
|
result = this.getDefine().getModuleExpr().flow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ module Base64 {
|
|||||||
private class Btoa extends Base64::Encode::Range, DataFlow::CallNode {
|
private class Btoa extends Base64::Encode::Range, DataFlow::CallNode {
|
||||||
Btoa() { this = DataFlow::globalVarRef("btoa").getACall() }
|
Btoa() { this = DataFlow::globalVarRef("btoa").getACall() }
|
||||||
|
|
||||||
override DataFlow::Node getInput() { result = getArgument(0) }
|
override DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override DataFlow::Node getOutput() { result = this }
|
override DataFlow::Node getOutput() { result = this }
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ private class Btoa extends Base64::Encode::Range, DataFlow::CallNode {
|
|||||||
private class Atob extends Base64::Decode::Range, DataFlow::CallNode {
|
private class Atob extends Base64::Decode::Range, DataFlow::CallNode {
|
||||||
Atob() { this = DataFlow::globalVarRef("atob").getACall() }
|
Atob() { this = DataFlow::globalVarRef("atob").getACall() }
|
||||||
|
|
||||||
override DataFlow::Node getInput() { result = getArgument(0) }
|
override DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override DataFlow::Node getOutput() { result = this }
|
override DataFlow::Node getOutput() { result = this }
|
||||||
}
|
}
|
||||||
@@ -93,11 +93,11 @@ private class Atob extends Base64::Decode::Range, DataFlow::CallNode {
|
|||||||
*/
|
*/
|
||||||
private class Buffer_toString extends Base64::Encode::Range, DataFlow::MethodCallNode {
|
private class Buffer_toString extends Base64::Encode::Range, DataFlow::MethodCallNode {
|
||||||
Buffer_toString() {
|
Buffer_toString() {
|
||||||
getMethodName() = "toString" and
|
this.getMethodName() = "toString" and
|
||||||
getArgument(0).mayHaveStringValue("base64")
|
this.getArgument(0).mayHaveStringValue("base64")
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getInput() { result = getReceiver() }
|
override DataFlow::Node getInput() { result = this.getReceiver() }
|
||||||
|
|
||||||
override DataFlow::Node getOutput() { result = this }
|
override DataFlow::Node getOutput() { result = this }
|
||||||
}
|
}
|
||||||
@@ -106,10 +106,10 @@ private class Buffer_toString extends Base64::Encode::Range, DataFlow::MethodCal
|
|||||||
private class Buffer_from extends Base64::Decode::Range, DataFlow::CallNode {
|
private class Buffer_from extends Base64::Decode::Range, DataFlow::CallNode {
|
||||||
Buffer_from() {
|
Buffer_from() {
|
||||||
this = DataFlow::globalVarRef("Buffer").getAMemberCall("from") and
|
this = DataFlow::globalVarRef("Buffer").getAMemberCall("from") and
|
||||||
getArgument(1).mayHaveStringValue("base64")
|
this.getArgument(1).mayHaveStringValue("base64")
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getInput() { result = getArgument(0) }
|
override DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override DataFlow::Node getOutput() { result = this }
|
override DataFlow::Node getOutput() { result = this }
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ private class NpmBase64Encode extends Base64::Encode::Range, DataFlow::CallNode
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getInput() { result = getArgument(0) }
|
override DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override DataFlow::Node getOutput() { result = this }
|
override DataFlow::Node getOutput() { result = this }
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ private class NpmBase64Decode extends Base64::Decode::Range, DataFlow::CallNode
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getInput() { result = getArgument(0) }
|
override DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override DataFlow::Node getOutput() { result = this }
|
override DataFlow::Node getOutput() { result = this }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,10 +288,10 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
|
|||||||
ControlFlowNode getAPredecessor() { this = result.getASuccessor() }
|
ControlFlowNode getAPredecessor() { this = result.getASuccessor() }
|
||||||
|
|
||||||
/** Holds if this is a node with more than one successor. */
|
/** Holds if this is a node with more than one successor. */
|
||||||
predicate isBranch() { strictcount(getASuccessor()) > 1 }
|
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
|
||||||
|
|
||||||
/** Holds if this is a node with more than one predecessor. */
|
/** Holds if this is a node with more than one predecessor. */
|
||||||
predicate isJoin() { strictcount(getAPredecessor()) > 1 }
|
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this is a start node, that is, the CFG node where execution of a
|
* Holds if this is a start node, that is, the CFG node where execution of a
|
||||||
@@ -304,14 +304,14 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
|
|||||||
* of that toplevel or function terminates.
|
* of that toplevel or function terminates.
|
||||||
*/
|
*/
|
||||||
predicate isAFinalNodeOfContainer(StmtContainer container) {
|
predicate isAFinalNodeOfContainer(StmtContainer container) {
|
||||||
getASuccessor().(SyntheticControlFlowNode).isAFinalNodeOfContainer(container)
|
this.getASuccessor().(SyntheticControlFlowNode).isAFinalNodeOfContainer(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this is a final node, that is, a CFG node where execution of a
|
* Holds if this is a final node, that is, a CFG node where execution of a
|
||||||
* toplevel or function terminates.
|
* toplevel or function terminates.
|
||||||
*/
|
*/
|
||||||
final predicate isAFinalNode() { isAFinalNodeOfContainer(_) }
|
final predicate isAFinalNode() { this.isAFinalNodeOfContainer(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this node is unreachable, that is, it has no predecessors in the CFG.
|
* Holds if this node is unreachable, that is, it has no predecessors in the CFG.
|
||||||
@@ -327,7 +327,7 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
|
|||||||
* `s1` is unreachable, but `s2` is not.
|
* `s1` is unreachable, but `s2` is not.
|
||||||
*/
|
*/
|
||||||
predicate isUnreachable() {
|
predicate isUnreachable() {
|
||||||
forall(ControlFlowNode pred | pred = getAPredecessor() |
|
forall(ControlFlowNode pred | pred = this.getAPredecessor() |
|
||||||
pred.(SyntheticControlFlowNode).isUnreachable()
|
pred.(SyntheticControlFlowNode).isUnreachable()
|
||||||
)
|
)
|
||||||
// note the override in ControlFlowEntryNode below
|
// note the override in ControlFlowEntryNode below
|
||||||
@@ -348,7 +348,7 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
|
|||||||
else
|
else
|
||||||
if this instanceof @decorator_list
|
if this instanceof @decorator_list
|
||||||
then result = "parameter decorators of " + this.(AstNode).getParent().(Function).describe()
|
then result = "parameter decorators of " + this.(AstNode).getParent().(Function).describe()
|
||||||
else result = toString()
|
else result = this.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +364,7 @@ class SyntheticControlFlowNode extends @synthetic_cfg_node, ControlFlowNode {
|
|||||||
class ControlFlowEntryNode extends SyntheticControlFlowNode, @entry_node {
|
class ControlFlowEntryNode extends SyntheticControlFlowNode, @entry_node {
|
||||||
override predicate isUnreachable() { none() }
|
override predicate isUnreachable() { none() }
|
||||||
|
|
||||||
override string toString() { result = "entry node of " + getContainer().toString() }
|
override string toString() { result = "entry node of " + this.getContainer().toString() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A synthetic CFG node marking the exit of a function or toplevel script. */
|
/** A synthetic CFG node marking the exit of a function or toplevel script. */
|
||||||
@@ -373,7 +373,7 @@ class ControlFlowExitNode extends SyntheticControlFlowNode, @exit_node {
|
|||||||
exit_cfg_node(this, container)
|
exit_cfg_node(this, container)
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = "exit node of " + getContainer().toString() }
|
override string toString() { result = "exit node of " + this.getContainer().toString() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -407,7 +407,7 @@ class ConditionGuardNode extends GuardControlFlowNode, @condition_guard {
|
|||||||
guard_node(this, 1, _) and result = true
|
guard_node(this, 1, _) and result = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = "guard: " + getTest() + " is " + getOutcome() }
|
override string toString() { result = "guard: " + this.getTest() + " is " + this.getOutcome() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class CanonicalName extends @symbol {
|
|||||||
* Gets the child of this canonical name that has the given `name`, if any.
|
* Gets the child of this canonical name that has the given `name`, if any.
|
||||||
*/
|
*/
|
||||||
CanonicalName getChild(string name) {
|
CanonicalName getChild(string name) {
|
||||||
result = getAChild() and
|
result = this.getAChild() and
|
||||||
result.getName() = name
|
result.getName() = name
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ class CanonicalName extends @symbol {
|
|||||||
symbol_module(this, result)
|
symbol_module(this, result)
|
||||||
or
|
or
|
||||||
exists(PackageJson pkg |
|
exists(PackageJson pkg |
|
||||||
getModule() = pkg.getMainModule() and
|
this.getModule() = pkg.getMainModule() and
|
||||||
result = pkg.getPackageName()
|
result = pkg.getPackageName()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -68,19 +68,19 @@ class CanonicalName extends @symbol {
|
|||||||
/**
|
/**
|
||||||
* Holds if this canonical name has a child, i.e. an extension of its qualified name.
|
* Holds if this canonical name has a child, i.e. an extension of its qualified name.
|
||||||
*/
|
*/
|
||||||
predicate hasChild() { exists(getAChild()) }
|
predicate hasChild() { exists(this.getAChild()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if this has no parent.
|
* True if this has no parent.
|
||||||
*/
|
*/
|
||||||
predicate isRoot() { not exists(getParent()) }
|
predicate isRoot() { not exists(this.getParent()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this is the export namespace of a module.
|
* Holds if this is the export namespace of a module.
|
||||||
*/
|
*/
|
||||||
predicate isModuleRoot() {
|
predicate isModuleRoot() {
|
||||||
exists(getModule()) or
|
exists(this.getModule()) or
|
||||||
exists(getExternalModuleName())
|
exists(this.getExternalModuleName())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,22 +98,22 @@ class CanonicalName extends @symbol {
|
|||||||
|
|
||||||
/** Holds if this has the given qualified name, rooted in the global scope. */
|
/** Holds if this has the given qualified name, rooted in the global scope. */
|
||||||
predicate hasQualifiedName(string globalName) {
|
predicate hasQualifiedName(string globalName) {
|
||||||
globalName = getGlobalName()
|
globalName = this.getGlobalName()
|
||||||
or
|
or
|
||||||
exists(string prefix |
|
exists(string prefix |
|
||||||
getParent().hasQualifiedName(prefix) and
|
this.getParent().hasQualifiedName(prefix) and
|
||||||
globalName = prefix + "." + getName()
|
globalName = prefix + "." + this.getName()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if this has the given qualified name, rooted in the given external module. */
|
/** Holds if this has the given qualified name, rooted in the given external module. */
|
||||||
predicate hasQualifiedName(string moduleName, string exportedName) {
|
predicate hasQualifiedName(string moduleName, string exportedName) {
|
||||||
moduleName = getParent().getExternalModuleName() and
|
moduleName = this.getParent().getExternalModuleName() and
|
||||||
exportedName = getName()
|
exportedName = this.getName()
|
||||||
or
|
or
|
||||||
exists(string prefix |
|
exists(string prefix |
|
||||||
getParent().hasQualifiedName(moduleName, prefix) and
|
this.getParent().hasQualifiedName(moduleName, prefix) and
|
||||||
exportedName = prefix + "." + getName()
|
exportedName = prefix + "." + this.getName()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,16 +121,16 @@ class CanonicalName extends @symbol {
|
|||||||
* Gets the qualified name without the root.
|
* Gets the qualified name without the root.
|
||||||
*/
|
*/
|
||||||
string getRelativeName() {
|
string getRelativeName() {
|
||||||
if getParent().isModuleRoot()
|
if this.getParent().isModuleRoot()
|
||||||
then result = getName()
|
then result = this.getName()
|
||||||
else
|
else
|
||||||
if exists(getGlobalName())
|
if exists(this.getGlobalName())
|
||||||
then result = min(getGlobalName())
|
then result = min(this.getGlobalName())
|
||||||
else
|
else
|
||||||
if exists(getParent())
|
if exists(this.getParent())
|
||||||
then result = getParent().getRelativeName() + "." + getName()
|
then result = this.getParent().getRelativeName() + "." + this.getName()
|
||||||
else (
|
else (
|
||||||
not isModuleRoot() and result = getName()
|
not this.isModuleRoot() and result = this.getName()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,20 +141,20 @@ class CanonicalName extends @symbol {
|
|||||||
* this is the container where the type is declared.
|
* this is the container where the type is declared.
|
||||||
*/
|
*/
|
||||||
Scope getRootScope() {
|
Scope getRootScope() {
|
||||||
exists(CanonicalName root | root = getRootName() |
|
exists(CanonicalName root | root = this.getRootName() |
|
||||||
if exists(root.getModule())
|
if exists(root.getModule())
|
||||||
then result = root.getModule().getScope()
|
then result = root.getModule().getScope()
|
||||||
else
|
else
|
||||||
if exists(root.getGlobalName())
|
if exists(root.getGlobalName())
|
||||||
then result instanceof GlobalScope
|
then result instanceof GlobalScope
|
||||||
else result = getADefinition().getContainer().getScope()
|
else result = this.getADefinition().getContainer().getScope()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private CanonicalName getRootName() {
|
private CanonicalName getRootName() {
|
||||||
if exists(getGlobalName()) or isModuleRoot() or not exists(getParent())
|
if exists(this.getGlobalName()) or this.isModuleRoot() or not exists(this.getParent())
|
||||||
then result = this
|
then result = this
|
||||||
else result = getParent().getRootName()
|
else result = this.getParent().getRootName()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,7 +171,7 @@ class CanonicalName extends @symbol {
|
|||||||
* Gets a string describing the root scope of this canonical name.
|
* Gets a string describing the root scope of this canonical name.
|
||||||
*/
|
*/
|
||||||
string describeRoot() {
|
string describeRoot() {
|
||||||
exists(CanonicalName root | root = getRootName() |
|
exists(CanonicalName root | root = this.getRootName() |
|
||||||
if exists(root.getExternalModuleName())
|
if exists(root.getExternalModuleName())
|
||||||
then result = "module '" + min(root.getExternalModuleName()) + "'"
|
then result = "module '" + min(root.getExternalModuleName()) + "'"
|
||||||
else
|
else
|
||||||
@@ -209,9 +209,9 @@ class CanonicalName extends @symbol {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
string toString() {
|
string toString() {
|
||||||
if isModuleRoot()
|
if this.isModuleRoot()
|
||||||
then result = describeRoot()
|
then result = this.describeRoot()
|
||||||
else result = getRelativeName() + " in " + describeRoot()
|
else result = this.getRelativeName() + " in " + this.describeRoot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +263,7 @@ class TypeName extends CanonicalName {
|
|||||||
*/
|
*/
|
||||||
class Namespace extends CanonicalName {
|
class Namespace extends CanonicalName {
|
||||||
Namespace() {
|
Namespace() {
|
||||||
getAChild().isExportedMember() or
|
this.getAChild().isExportedMember() or
|
||||||
exists(NamespaceDefinition def | ast_node_symbol(def, this)) or
|
exists(NamespaceDefinition def | ast_node_symbol(def, this)) or
|
||||||
exists(NamespaceAccess ref | ast_node_symbol(ref, this))
|
exists(NamespaceAccess ref | ast_node_symbol(ref, this))
|
||||||
}
|
}
|
||||||
@@ -334,5 +334,5 @@ class CanonicalFunctionName extends CanonicalName {
|
|||||||
/**
|
/**
|
||||||
* Gets the implementation of this function, if it exists.
|
* Gets the implementation of this function, if it exists.
|
||||||
*/
|
*/
|
||||||
Function getImplementation() { result = getADefinition() and result.hasBody() }
|
Function getImplementation() { result = this.getADefinition() and result.hasBody() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ module Closure {
|
|||||||
{
|
{
|
||||||
DefaultNamespaceRef() { this = DataFlow::globalVarRef("goog").getAMethodCall() }
|
DefaultNamespaceRef() { this = DataFlow::globalVarRef("goog").getAMethodCall() }
|
||||||
|
|
||||||
override string getClosureNamespace() { result = getArgument(0).getStringValue() }
|
override string getClosureNamespace() { result = this.getArgument(0).getStringValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,7 +68,7 @@ module Closure {
|
|||||||
*/
|
*/
|
||||||
private class DefaultClosureProvideCall extends DefaultNamespaceRef {
|
private class DefaultClosureProvideCall extends DefaultNamespaceRef {
|
||||||
DefaultClosureProvideCall() {
|
DefaultClosureProvideCall() {
|
||||||
getMethodName() = "provide" and
|
this.getMethodName() = "provide" and
|
||||||
isTopLevelExpr(this)
|
isTopLevelExpr(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ module Closure {
|
|||||||
*/
|
*/
|
||||||
private class DefaultClosureRequireCall extends DefaultNamespaceRef, ClosureNamespaceAccess::Range
|
private class DefaultClosureRequireCall extends DefaultNamespaceRef, ClosureNamespaceAccess::Range
|
||||||
{
|
{
|
||||||
DefaultClosureRequireCall() { getMethodName() = "require" }
|
DefaultClosureRequireCall() { this.getMethodName() = "require" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,7 +98,7 @@ module Closure {
|
|||||||
*/
|
*/
|
||||||
private class DefaultClosureModuleDeclaration extends DefaultNamespaceRef {
|
private class DefaultClosureModuleDeclaration extends DefaultNamespaceRef {
|
||||||
DefaultClosureModuleDeclaration() {
|
DefaultClosureModuleDeclaration() {
|
||||||
(getMethodName() = "module" or getMethodName() = "declareModuleId") and
|
(this.getMethodName() = "module" or this.getMethodName() = "declareModuleId") and
|
||||||
isTopLevelExpr(this)
|
isTopLevelExpr(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ module Closure {
|
|||||||
/**
|
/**
|
||||||
* Gets the namespace of this module.
|
* Gets the namespace of this module.
|
||||||
*/
|
*/
|
||||||
string getClosureNamespace() { result = getModuleDeclaration().getClosureNamespace() }
|
string getClosureNamespace() { result = this.getModuleDeclaration().getClosureNamespace() }
|
||||||
|
|
||||||
override Module getAnImportedModule() {
|
override Module getAnImportedModule() {
|
||||||
result.(ClosureModule).getClosureNamespace() =
|
result.(ClosureModule).getClosureNamespace() =
|
||||||
@@ -156,8 +156,8 @@ module Closure {
|
|||||||
* Has no result for ES6 modules using `goog.declareModuleId`.
|
* Has no result for ES6 modules using `goog.declareModuleId`.
|
||||||
*/
|
*/
|
||||||
Variable getExportsVariable() {
|
Variable getExportsVariable() {
|
||||||
getModuleDeclaration().getMethodName() = "module" and
|
this.getModuleDeclaration().getMethodName() = "module" and
|
||||||
result = getScope().getVariable("exports")
|
result = this.getScope().getVariable("exports")
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAnExportedValue(string name) {
|
override DataFlow::Node getAnExportedValue(string name) {
|
||||||
@@ -165,15 +165,15 @@ module Closure {
|
|||||||
result = write.getRhs() and
|
result = write.getRhs() and
|
||||||
write.writes(base.flow(), name, _) and
|
write.writes(base.flow(), name, _) and
|
||||||
(
|
(
|
||||||
base = getExportsVariable().getAReference()
|
base = this.getExportsVariable().getAReference()
|
||||||
or
|
or
|
||||||
base = getExportsVariable().getAnAssignedExpr()
|
base = this.getExportsVariable().getAnAssignedExpr()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getABulkExportedNode() {
|
override DataFlow::Node getABulkExportedNode() {
|
||||||
result = getExportsVariable().getAnAssignedExpr().flow()
|
result = this.getExportsVariable().getAnAssignedExpr().flow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,19 +263,19 @@ module Closure {
|
|||||||
|
|
||||||
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
|
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
|
||||||
index >= 0 and
|
index >= 0 and
|
||||||
callback = getArgument(0) and
|
callback = this.getArgument(0) and
|
||||||
argument = getArgument(index + 2)
|
argument = this.getArgument(index + 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
|
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
|
||||||
boundArgs = getNumArgument() - 2 and
|
boundArgs = this.getNumArgument() - 2 and
|
||||||
callback = getArgument(0) and
|
callback = this.getArgument(0) and
|
||||||
result = this
|
result = this
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
||||||
callback = getArgument(0) and
|
callback = this.getArgument(0) and
|
||||||
result = getArgument(1)
|
result = this.getArgument(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,18 +24,18 @@ class Comment extends @comment, Locatable {
|
|||||||
string getText() { comments(this, _, _, result, _) }
|
string getText() { comments(this, _, _, result, _) }
|
||||||
|
|
||||||
/** Gets the `i`th line of comment text. */
|
/** Gets the `i`th line of comment text. */
|
||||||
string getLine(int i) { result = getText().splitAt("\n", i) }
|
string getLine(int i) { result = this.getText().splitAt("\n", i) }
|
||||||
|
|
||||||
/** Gets the next token after this comment. */
|
/** Gets the next token after this comment. */
|
||||||
Token getNextToken() { next_token(this, result) }
|
Token getNextToken() { next_token(this, result) }
|
||||||
|
|
||||||
override int getNumLines() { result = count(getLine(_)) }
|
override int getNumLines() { result = count(this.getLine(_)) }
|
||||||
|
|
||||||
override string toString() { comments(this, _, _, _, result) }
|
override string toString() { comments(this, _, _, _, result) }
|
||||||
|
|
||||||
/** Holds if this comment spans lines `start` to `end` (inclusive) in file `f`. */
|
/** Holds if this comment spans lines `start` to `end` (inclusive) in file `f`. */
|
||||||
predicate onLines(File f, int start, int end) {
|
predicate onLines(File f, int start, int end) {
|
||||||
exists(Location loc | loc = getLocation() |
|
exists(Location loc | loc = this.getLocation() |
|
||||||
f = loc.getFile() and
|
f = loc.getFile() and
|
||||||
start = loc.getStartLine() and
|
start = loc.getStartLine() and
|
||||||
end = loc.getEndLine()
|
end = loc.getEndLine()
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ module SyntacticConstants {
|
|||||||
cached
|
cached
|
||||||
class UnaryConstant extends SyntacticConstant, UnaryExpr {
|
class UnaryConstant extends SyntacticConstant, UnaryExpr {
|
||||||
cached
|
cached
|
||||||
UnaryConstant() { getOperand() instanceof SyntacticConstant }
|
UnaryConstant() { this.getOperand() instanceof SyntacticConstant }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,8 +71,8 @@ module SyntacticConstants {
|
|||||||
class BinaryConstant extends SyntacticConstant, BinaryExpr {
|
class BinaryConstant extends SyntacticConstant, BinaryExpr {
|
||||||
cached
|
cached
|
||||||
BinaryConstant() {
|
BinaryConstant() {
|
||||||
getLeftOperand() instanceof SyntacticConstant and
|
this.getLeftOperand() instanceof SyntacticConstant and
|
||||||
getRightOperand() instanceof SyntacticConstant
|
this.getRightOperand() instanceof SyntacticConstant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,9 +83,9 @@ module SyntacticConstants {
|
|||||||
class ConditionalConstant extends SyntacticConstant, ConditionalExpr {
|
class ConditionalConstant extends SyntacticConstant, ConditionalExpr {
|
||||||
cached
|
cached
|
||||||
ConditionalConstant() {
|
ConditionalConstant() {
|
||||||
getCondition() instanceof SyntacticConstant and
|
this.getCondition() instanceof SyntacticConstant and
|
||||||
getConsequent() instanceof SyntacticConstant and
|
this.getConsequent() instanceof SyntacticConstant and
|
||||||
getAlternate() instanceof SyntacticConstant
|
this.getAlternate() instanceof SyntacticConstant
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +125,7 @@ module SyntacticConstants {
|
|||||||
cached
|
cached
|
||||||
class WrappedConstant extends SyntacticConstant {
|
class WrappedConstant extends SyntacticConstant {
|
||||||
cached
|
cached
|
||||||
WrappedConstant() { getUnderlyingValue() instanceof SyntacticConstant }
|
WrappedConstant() { this.getUnderlyingValue() instanceof SyntacticConstant }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,5 +150,5 @@ module SyntacticConstants {
|
|||||||
cached
|
cached
|
||||||
class ConstantString extends ConstantExpr {
|
class ConstantString extends ConstantExpr {
|
||||||
cached
|
cached
|
||||||
ConstantString() { exists(getStringValue()) }
|
ConstantString() { exists(this.getStringValue()) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ class VarDef extends ControlFlowNode {
|
|||||||
Expr getTarget() { defn(this, result) }
|
Expr getTarget() { defn(this, result) }
|
||||||
|
|
||||||
/** Gets a variable defined by this node, if any. */
|
/** Gets a variable defined by this node, if any. */
|
||||||
Variable getAVariable() { result = getTarget().(BindingPattern).getAVariable() }
|
Variable getAVariable() { result = this.getTarget().(BindingPattern).getAVariable() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the source of this definition, that is, the data flow node representing
|
* Gets the source of this definition, that is, the data flow node representing
|
||||||
@@ -232,8 +232,8 @@ class VarUse extends ControlFlowNode, @varref instanceof RValue {
|
|||||||
* For global variables, each definition is considered to reach each use.
|
* For global variables, each definition is considered to reach each use.
|
||||||
*/
|
*/
|
||||||
VarDef getADef() {
|
VarDef getADef() {
|
||||||
result = getSsaVariable().getDefinition().getAContributingVarDef() or
|
result = this.getSsaVariable().getDefinition().getAContributingVarDef() or
|
||||||
result.getAVariable() = getVariable().(GlobalVariable)
|
result.getAVariable() = this.getVariable().(GlobalVariable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ abstract class EnumeratedPropName extends DataFlow::Node {
|
|||||||
* Gets a source node that refers to the object whose properties are being enumerated.
|
* Gets a source node that refers to the object whose properties are being enumerated.
|
||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getASourceObjectRef() {
|
DataFlow::SourceNode getASourceObjectRef() {
|
||||||
result = AccessPath::getAnAliasedSourceNode(getSourceObject())
|
result = AccessPath::getAnAliasedSourceNode(this.getSourceObject())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,7 +53,7 @@ abstract class EnumeratedPropName extends DataFlow::Node {
|
|||||||
SourceNode getASourceProp() {
|
SourceNode getASourceProp() {
|
||||||
exists(Node base, Node key |
|
exists(Node base, Node key |
|
||||||
dynamicPropReadStep(base, key, result) and
|
dynamicPropReadStep(base, key, result) and
|
||||||
getASourceObjectRef().flowsTo(base) and
|
this.getASourceObjectRef().flowsTo(base) and
|
||||||
key.getImmediatePredecessor*() = this
|
key.getImmediatePredecessor*() = this
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,14 +37,14 @@ module E4X {
|
|||||||
* Gets the left operand of this qualified identifier, which is either
|
* Gets the left operand of this qualified identifier, which is either
|
||||||
* an identifier or a wildcard.
|
* an identifier or a wildcard.
|
||||||
*/
|
*/
|
||||||
Expr getLeft() { result = getChildExpr(0) }
|
Expr getLeft() { result = this.getChildExpr(0) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the right operand of this qualified identifer, which is either
|
* Gets the right operand of this qualified identifer, which is either
|
||||||
* an identifier, or an arbitrary expression for computed qualified
|
* an identifier, or an arbitrary expression for computed qualified
|
||||||
* identifiers.
|
* identifiers.
|
||||||
*/
|
*/
|
||||||
Expr getRight() { result = getChildExpr(1) }
|
Expr getRight() { result = this.getChildExpr(1) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this is a qualified identifier with a computed name, as in
|
* Holds if this is a qualified identifier with a computed name, as in
|
||||||
@@ -53,7 +53,7 @@ module E4X {
|
|||||||
predicate isComputed() { this instanceof @e4x_xml_dynamic_qualident }
|
predicate isComputed() { this instanceof @e4x_xml_dynamic_qualident }
|
||||||
|
|
||||||
override ControlFlowNode getFirstControlFlowNode() {
|
override ControlFlowNode getFirstControlFlowNode() {
|
||||||
result = getLeft().getFirstControlFlowNode()
|
result = this.getLeft().getFirstControlFlowNode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ module E4X {
|
|||||||
* wildcard identifier or a possibly qualified name), or an arbitrary
|
* wildcard identifier or a possibly qualified name), or an arbitrary
|
||||||
* expression for computed attribute selectors.
|
* expression for computed attribute selectors.
|
||||||
*/
|
*/
|
||||||
Expr getAttribute() { result = getChildExpr(0) }
|
Expr getAttribute() { result = this.getChildExpr(0) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this is an attribute selector with a computed name, as in
|
* Holds if this is an attribute selector with a computed name, as in
|
||||||
@@ -85,7 +85,7 @@ module E4X {
|
|||||||
predicate isComputed() { this instanceof @e4x_xml_dynamic_attribute_selector }
|
predicate isComputed() { this instanceof @e4x_xml_dynamic_attribute_selector }
|
||||||
|
|
||||||
override ControlFlowNode getFirstControlFlowNode() {
|
override ControlFlowNode getFirstControlFlowNode() {
|
||||||
result = getAttribute().getFirstControlFlowNode()
|
result = this.getAttribute().getFirstControlFlowNode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,15 +105,15 @@ module E4X {
|
|||||||
/**
|
/**
|
||||||
* Gets the left operand of this filter expression.
|
* Gets the left operand of this filter expression.
|
||||||
*/
|
*/
|
||||||
Expr getLeft() { result = getChildExpr(0) }
|
Expr getLeft() { result = this.getChildExpr(0) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the right operand of this filter expression.
|
* Gets the right operand of this filter expression.
|
||||||
*/
|
*/
|
||||||
Expr getRight() { result = getChildExpr(1) }
|
Expr getRight() { result = this.getChildExpr(1) }
|
||||||
|
|
||||||
override ControlFlowNode getFirstControlFlowNode() {
|
override ControlFlowNode getFirstControlFlowNode() {
|
||||||
result = getLeft().getFirstControlFlowNode()
|
result = this.getLeft().getFirstControlFlowNode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,15 +133,15 @@ module E4X {
|
|||||||
/**
|
/**
|
||||||
* Gets the base expression of this dot-dot expression.
|
* Gets the base expression of this dot-dot expression.
|
||||||
*/
|
*/
|
||||||
Expr getBase() { result = getChildExpr(0) }
|
Expr getBase() { result = this.getChildExpr(0) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the index expression of this dot-dot expression.
|
* Gets the index expression of this dot-dot expression.
|
||||||
*/
|
*/
|
||||||
Expr getIndex() { result = getChildExpr(1) }
|
Expr getIndex() { result = this.getChildExpr(1) }
|
||||||
|
|
||||||
override ControlFlowNode getFirstControlFlowNode() {
|
override ControlFlowNode getFirstControlFlowNode() {
|
||||||
result = getBase().getFirstControlFlowNode()
|
result = this.getBase().getFirstControlFlowNode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ abstract class EmailSender extends DataFlow::SourceNode {
|
|||||||
* Gets a data flow node that refers to the HTML body or plaintext body of the email.
|
* Gets a data flow node that refers to the HTML body or plaintext body of the email.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getABody() {
|
DataFlow::Node getABody() {
|
||||||
result = getPlainTextBody() or
|
result = this.getPlainTextBody() or
|
||||||
result = getHtmlBody()
|
result = this.getHtmlBody()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,13 +47,13 @@ private class NodemailerEmailSender extends EmailSender, DataFlow::MethodCallNod
|
|||||||
DataFlow::moduleMember("nodemailer", "createTransport").getACall().getAMethodCall("sendMail")
|
DataFlow::moduleMember("nodemailer", "createTransport").getACall().getAMethodCall("sendMail")
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getPlainTextBody() { result = getOptionArgument(0, "text") }
|
override DataFlow::Node getPlainTextBody() { result = this.getOptionArgument(0, "text") }
|
||||||
|
|
||||||
override DataFlow::Node getHtmlBody() { result = getOptionArgument(0, "html") }
|
override DataFlow::Node getHtmlBody() { result = this.getOptionArgument(0, "html") }
|
||||||
|
|
||||||
override DataFlow::Node getTo() { result = getOptionArgument(0, "to") }
|
override DataFlow::Node getTo() { result = this.getOptionArgument(0, "to") }
|
||||||
|
|
||||||
override DataFlow::Node getFrom() { result = getOptionArgument(0, "from") }
|
override DataFlow::Node getFrom() { result = this.getOptionArgument(0, "from") }
|
||||||
|
|
||||||
override DataFlow::Node getSubject() { result = getOptionArgument(0, "subject") }
|
override DataFlow::Node getSubject() { result = this.getOptionArgument(0, "subject") }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ abstract class Error extends Locatable {
|
|||||||
/** Gets the message associated with this error. */
|
/** Gets the message associated with this error. */
|
||||||
abstract string getMessage();
|
abstract string getMessage();
|
||||||
|
|
||||||
override string toString() { result = getMessage() }
|
override string toString() { result = this.getMessage() }
|
||||||
|
|
||||||
/** Holds if this error prevented the file from being extracted. */
|
/** Holds if this error prevented the file from being extracted. */
|
||||||
predicate isFatal() { any() }
|
predicate isFatal() { any() }
|
||||||
@@ -25,5 +25,5 @@ class JSParseError extends @js_parse_error, Error {
|
|||||||
/** Gets the source text of the line this error occurs on. */
|
/** Gets the source text of the line this error occurs on. */
|
||||||
string getLine() { js_parse_errors(this, _, _, result) }
|
string getLine() { js_parse_errors(this, _, _, result) }
|
||||||
|
|
||||||
override predicate isFatal() { not getTopLevel() instanceof Angular2::TemplateTopLevel }
|
override predicate isFatal() { not this.getTopLevel() instanceof Angular2::TemplateTopLevel }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ abstract class ExtendCall extends DataFlow::CallNode {
|
|||||||
* Gets an object from which properties are taken or stored.
|
* Gets an object from which properties are taken or stored.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getAnOperand() {
|
DataFlow::Node getAnOperand() {
|
||||||
result = getASourceOperand() or
|
result = this.getASourceOperand() or
|
||||||
result = getDestinationOperand()
|
result = this.getDestinationOperand()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,22 +55,22 @@ private class ExtendCallWithFlag extends ExtendCall {
|
|||||||
/**
|
/**
|
||||||
* Holds if the first argument appears to be a boolean flag.
|
* Holds if the first argument appears to be a boolean flag.
|
||||||
*/
|
*/
|
||||||
predicate hasFlag() { getArgument(0).mayHaveBooleanValue(_) }
|
predicate hasFlag() { this.getArgument(0).mayHaveBooleanValue(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `n`th argument after the optional boolean flag.
|
* Gets the `n`th argument after the optional boolean flag.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getTranslatedArgument(int n) {
|
DataFlow::Node getTranslatedArgument(int n) {
|
||||||
if hasFlag() then result = getArgument(n + 1) else result = getArgument(n)
|
if this.hasFlag() then result = this.getArgument(n + 1) else result = this.getArgument(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getASourceOperand() {
|
override DataFlow::Node getASourceOperand() {
|
||||||
exists(int n | n >= 1 | result = getTranslatedArgument(n))
|
exists(int n | n >= 1 | result = this.getTranslatedArgument(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getDestinationOperand() { result = getTranslatedArgument(0) }
|
override DataFlow::Node getDestinationOperand() { result = this.getTranslatedArgument(0) }
|
||||||
|
|
||||||
override predicate isDeep() { getArgument(0).mayHaveBooleanValue(true) }
|
override predicate isDeep() { this.getArgument(0).mayHaveBooleanValue(true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,9 +100,11 @@ private class ExtendCallDeep extends ExtendCall {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getASourceOperand() { exists(int n | n >= 1 | result = getArgument(n)) }
|
override DataFlow::Node getASourceOperand() {
|
||||||
|
exists(int n | n >= 1 | result = this.getArgument(n))
|
||||||
|
}
|
||||||
|
|
||||||
override DataFlow::Node getDestinationOperand() { result = getArgument(0) }
|
override DataFlow::Node getDestinationOperand() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate isDeep() { any() }
|
override predicate isDeep() { any() }
|
||||||
}
|
}
|
||||||
@@ -130,9 +132,11 @@ private class ExtendCallShallow extends ExtendCall {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getASourceOperand() { exists(int n | n >= 1 | result = getArgument(n)) }
|
override DataFlow::Node getASourceOperand() {
|
||||||
|
exists(int n | n >= 1 | result = this.getArgument(n))
|
||||||
|
}
|
||||||
|
|
||||||
override DataFlow::Node getDestinationOperand() { result = getArgument(0) }
|
override DataFlow::Node getDestinationOperand() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate isDeep() { none() }
|
override predicate isDeep() { none() }
|
||||||
}
|
}
|
||||||
@@ -149,7 +153,7 @@ private class FunctionalExtendCallShallow extends ExtendCall {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getASourceOperand() { result = getAnArgument() }
|
override DataFlow::Node getASourceOperand() { result = this.getAnArgument() }
|
||||||
|
|
||||||
override DataFlow::Node getDestinationOperand() { none() }
|
override DataFlow::Node getDestinationOperand() { none() }
|
||||||
|
|
||||||
@@ -206,7 +210,7 @@ private class WebpackMergeDeep extends ExtendCall, DataFlow::CallNode {
|
|||||||
.getACall()
|
.getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getASourceOperand() { result = getAnArgument() }
|
override DataFlow::Node getASourceOperand() { result = this.getAnArgument() }
|
||||||
|
|
||||||
override DataFlow::Node getDestinationOperand() { none() }
|
override DataFlow::Node getDestinationOperand() { none() }
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ module HTML {
|
|||||||
* An HTML file.
|
* An HTML file.
|
||||||
*/
|
*/
|
||||||
class HtmlFile extends File {
|
class HtmlFile extends File {
|
||||||
HtmlFile() { getFileType().isHtml() }
|
HtmlFile() { this.getFileType().isHtml() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,7 +18,7 @@ module HTML {
|
|||||||
*/
|
*/
|
||||||
private class FileContainingHtml extends File {
|
private class FileContainingHtml extends File {
|
||||||
FileContainingHtml() {
|
FileContainingHtml() {
|
||||||
getFileType().isHtml()
|
this.getFileType().isHtml()
|
||||||
or
|
or
|
||||||
// The file contains an expression containing an HTML element
|
// The file contains an expression containing an HTML element
|
||||||
exists(Expr e |
|
exists(Expr e |
|
||||||
@@ -60,17 +60,19 @@ module HTML {
|
|||||||
/**
|
/**
|
||||||
* Holds if this is a toplevel element, that is, if it does not have a parent element.
|
* Holds if this is a toplevel element, that is, if it does not have a parent element.
|
||||||
*/
|
*/
|
||||||
predicate isTopLevel() { not exists(getParent()) }
|
predicate isTopLevel() { not exists(this.getParent()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the root HTML document element in which this element is contained.
|
* Gets the root HTML document element in which this element is contained.
|
||||||
*/
|
*/
|
||||||
DocumentElement getDocument() { result = getRoot() }
|
DocumentElement getDocument() { result = this.getRoot() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the root element in which this element is contained.
|
* Gets the root element in which this element is contained.
|
||||||
*/
|
*/
|
||||||
Element getRoot() { if isTopLevel() then result = this else result = getParent().getRoot() }
|
Element getRoot() {
|
||||||
|
if this.isTopLevel() then result = this else result = this.getParent().getRoot()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `i`th child element (0-based) of this element.
|
* Gets the `i`th child element (0-based) of this element.
|
||||||
@@ -80,7 +82,7 @@ module HTML {
|
|||||||
/**
|
/**
|
||||||
* Gets a child element of this element.
|
* Gets a child element of this element.
|
||||||
*/
|
*/
|
||||||
Element getChild() { result = getChild(_) }
|
Element getChild() { result = this.getChild(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `i`th attribute (0-based) of this element.
|
* Gets the `i`th attribute (0-based) of this element.
|
||||||
@@ -90,17 +92,17 @@ module HTML {
|
|||||||
/**
|
/**
|
||||||
* Gets an attribute of this element.
|
* Gets an attribute of this element.
|
||||||
*/
|
*/
|
||||||
Attribute getAnAttribute() { result = getAttribute(_) }
|
Attribute getAnAttribute() { result = this.getAttribute(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an attribute of this element that has the given name.
|
* Gets an attribute of this element that has the given name.
|
||||||
*/
|
*/
|
||||||
Attribute getAttributeByName(string name) {
|
Attribute getAttributeByName(string name) {
|
||||||
result = getAnAttribute() and
|
result = this.getAnAttribute() and
|
||||||
result.getName() = name
|
result.getName() = name
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = "<" + getName() + ">...</>" }
|
override string toString() { result = "<" + this.getName() + ">...</>" }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "HTML::Element" }
|
override string getAPrimaryQlClass() { result = "HTML::Element" }
|
||||||
}
|
}
|
||||||
@@ -136,7 +138,7 @@ module HTML {
|
|||||||
* Gets the root element in which the element to which this attribute
|
* Gets the root element in which the element to which this attribute
|
||||||
* belongs is contained.
|
* belongs is contained.
|
||||||
*/
|
*/
|
||||||
Element getRoot() { result = getElement().getRoot() }
|
Element getRoot() { result = this.getElement().getRoot() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name of this attribute.
|
* Gets the name of this attribute.
|
||||||
@@ -151,7 +153,7 @@ module HTML {
|
|||||||
*/
|
*/
|
||||||
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
||||||
|
|
||||||
override string toString() { result = getName() + "=" + getValue() }
|
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "HTML::Attribute" }
|
override string getAPrimaryQlClass() { result = "HTML::Attribute" }
|
||||||
}
|
}
|
||||||
@@ -170,7 +172,7 @@ module HTML {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class DocumentElement extends Element {
|
class DocumentElement extends Element {
|
||||||
DocumentElement() { getName() = "html" }
|
DocumentElement() { this.getName() = "html" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -183,12 +185,12 @@ module HTML {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class IframeElement extends Element {
|
class IframeElement extends Element {
|
||||||
IframeElement() { getName() = "iframe" }
|
IframeElement() { this.getName() = "iframe" }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of the `src` attribute.
|
* Gets the value of the `src` attribute.
|
||||||
*/
|
*/
|
||||||
string getSourcePath() { result = getAttributeByName("src").getValue() }
|
string getSourcePath() { result = this.getAttributeByName("src").getValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -201,7 +203,7 @@ module HTML {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class ScriptElement extends Element {
|
class ScriptElement extends Element {
|
||||||
ScriptElement() { getName() = "script" }
|
ScriptElement() { this.getName() = "script" }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the absolute file system path the value of the `src` attribute
|
* Gets the absolute file system path the value of the `src` attribute
|
||||||
@@ -212,38 +214,38 @@ module HTML {
|
|||||||
* to the enclosing HTML file. Base URLs are not taken into account.
|
* to the enclosing HTML file. Base URLs are not taken into account.
|
||||||
*/
|
*/
|
||||||
string resolveSourcePath() {
|
string resolveSourcePath() {
|
||||||
exists(string path | path = getSourcePath() |
|
exists(string path | path = this.getSourcePath() |
|
||||||
result = path.regexpCapture("file://(/.*)", 1)
|
result = path.regexpCapture("file://(/.*)", 1)
|
||||||
or
|
or
|
||||||
not path.regexpMatch("(\\w+:)?//.*") and
|
not path.regexpMatch("(\\w+:)?//.*") and
|
||||||
result = getSourcePath().(ScriptSrcPath).resolve(getSearchRoot()).toString()
|
result = this.getSourcePath().(ScriptSrcPath).resolve(this.getSearchRoot()).toString()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of the `src` attribute.
|
* Gets the value of the `src` attribute.
|
||||||
*/
|
*/
|
||||||
string getSourcePath() { result = getAttributeByName("src").getValue() }
|
string getSourcePath() { result = this.getAttributeByName("src").getValue() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of the `integrity` attribute.
|
* Gets the value of the `integrity` attribute.
|
||||||
*/
|
*/
|
||||||
string getIntegrityDigest() { result = getAttributeByName("integrity").getValue() }
|
string getIntegrityDigest() { result = this.getAttributeByName("integrity").getValue() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the folder relative to which the `src` attribute is resolved.
|
* Gets the folder relative to which the `src` attribute is resolved.
|
||||||
*/
|
*/
|
||||||
Folder getSearchRoot() {
|
Folder getSearchRoot() {
|
||||||
if getSourcePath().matches("/%")
|
if this.getSourcePath().matches("/%")
|
||||||
then result.getBaseName() = ""
|
then result.getBaseName() = ""
|
||||||
else result = getFile().getParentContainer()
|
else result = this.getFile().getParentContainer()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the script referred to by the `src` attribute,
|
* Gets the script referred to by the `src` attribute,
|
||||||
* if it can be determined.
|
* if it can be determined.
|
||||||
*/
|
*/
|
||||||
Script resolveSource() { result.getFile().getAbsolutePath() = resolveSourcePath() }
|
Script resolveSource() { result.getFile().getAbsolutePath() = this.resolveSourcePath() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the inline script of this script element, if any.
|
* Gets the inline script of this script element, if any.
|
||||||
@@ -251,15 +253,15 @@ module HTML {
|
|||||||
private InlineScript getInlineScript() {
|
private InlineScript getInlineScript() {
|
||||||
toplevel_parent_xml_node(result, this) and
|
toplevel_parent_xml_node(result, this) and
|
||||||
// the src attribute has precedence
|
// the src attribute has precedence
|
||||||
not exists(getSourcePath())
|
not exists(this.getSourcePath())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the script of this element, if it can be determined.
|
* Gets the script of this element, if it can be determined.
|
||||||
*/
|
*/
|
||||||
Script getScript() {
|
Script getScript() {
|
||||||
result = getInlineScript() or
|
result = this.getInlineScript() or
|
||||||
result = resolveSource()
|
result = this.resolveSource()
|
||||||
}
|
}
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "HTML::ScriptElement" }
|
override string getAPrimaryQlClass() { result = "HTML::ScriptElement" }
|
||||||
@@ -301,7 +303,7 @@ module HTML {
|
|||||||
class TextNode extends Locatable, @xmlcharacters {
|
class TextNode extends Locatable, @xmlcharacters {
|
||||||
TextNode() { exists(FileContainingHtml f | xmlChars(this, _, _, _, _, f)) }
|
TextNode() { exists(FileContainingHtml f | xmlChars(this, _, _, _, _, f)) }
|
||||||
|
|
||||||
override string toString() { result = getText() }
|
override string toString() { result = this.getText() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the content of this text node.
|
* Gets the content of this text node.
|
||||||
@@ -344,7 +346,7 @@ module HTML {
|
|||||||
Element getParent() { xmlComments(this, _, result, _) }
|
Element getParent() { xmlComments(this, _, result, _) }
|
||||||
|
|
||||||
/** Gets the text of this comment, not including delimiters. */
|
/** Gets the text of this comment, not including delimiters. */
|
||||||
string getText() { result = toString().regexpCapture("(?s)<!--(.*)-->", 1) }
|
string getText() { result = this.toString().regexpCapture("(?s)<!--(.*)-->", 1) }
|
||||||
|
|
||||||
override string toString() { xmlComments(this, result, _, _) }
|
override string toString() { xmlComments(this, result, _, _) }
|
||||||
|
|
||||||
|
|||||||
@@ -65,11 +65,11 @@ private class DefaultHtmlSanitizerCall extends HtmlSanitizerCall {
|
|||||||
this = htmlSanitizerFunction().getACall()
|
this = htmlSanitizerFunction().getACall()
|
||||||
or
|
or
|
||||||
// Match home-made sanitizers by name.
|
// Match home-made sanitizers by name.
|
||||||
exists(string calleeName | calleeName = getCalleeName() |
|
exists(string calleeName | calleeName = this.getCalleeName() |
|
||||||
calleeName.regexpMatch("(?i).*html.*") and
|
calleeName.regexpMatch("(?i).*html.*") and
|
||||||
calleeName.regexpMatch("(?i).*(?<!un)(saniti[sz]|escape|strip).*")
|
calleeName.regexpMatch("(?i).*(?<!un)(saniti[sz]|escape|strip).*")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getInput() { result = getArgument(0) }
|
override DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,11 +31,11 @@ class JSDoc extends @jsdoc, Locatable {
|
|||||||
|
|
||||||
/** Gets a JSDoc tag within this JSDoc comment with the given title. */
|
/** Gets a JSDoc tag within this JSDoc comment with the given title. */
|
||||||
JSDocTag getATagByTitle(string title) {
|
JSDocTag getATagByTitle(string title) {
|
||||||
result = getATag() and
|
result = this.getATag() and
|
||||||
result.getTitle() = title
|
result.getTitle() = title
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = getComment().toString() }
|
override string toString() { result = this.getComment().toString() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,7 +59,7 @@ abstract class Documentable extends AstNode {
|
|||||||
/** Gets the JSDoc comment for this element, if any. */
|
/** Gets the JSDoc comment for this element, if any. */
|
||||||
cached
|
cached
|
||||||
JSDoc getDocumentation() {
|
JSDoc getDocumentation() {
|
||||||
Stages::Ast::ref() and result.getComment().getNextToken() = getFirstToken()
|
Stages::Ast::ref() and result.getComment().getNextToken() = this.getFirstToken()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,11 +120,11 @@ class JSDocTag extends @jsdoc_tag, JSDocTypeExprParent {
|
|||||||
|
|
||||||
/** Holds if this tag documents a simple name (as opposed to a name path). */
|
/** Holds if this tag documents a simple name (as opposed to a name path). */
|
||||||
predicate documentsSimpleName() {
|
predicate documentsSimpleName() {
|
||||||
exists(string name | name = getName() | not name.matches("%.%"))
|
exists(string name | name = this.getName() | not name.matches("%.%"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the toplevel in which this tag appears. */
|
/** Gets the toplevel in which this tag appears. */
|
||||||
TopLevel getTopLevel() { result = getParent().getComment().getTopLevel() }
|
TopLevel getTopLevel() { result = this.getParent().getComment().getTopLevel() }
|
||||||
|
|
||||||
override JSDoc getJSDocComment() { result.getATag() = this }
|
override JSDoc getJSDocComment() { result.getATag() = this }
|
||||||
}
|
}
|
||||||
@@ -139,12 +139,12 @@ class JSDocTag extends @jsdoc_tag, JSDocTypeExprParent {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class JSDocParamTag extends JSDocTag {
|
class JSDocParamTag extends JSDocTag {
|
||||||
JSDocParamTag() { getTitle().regexpMatch("param|arg(ument)?") }
|
JSDocParamTag() { this.getTitle().regexpMatch("param|arg(ument)?") }
|
||||||
|
|
||||||
/** Gets the parameter this tag refers to, if it can be determined. */
|
/** Gets the parameter this tag refers to, if it can be determined. */
|
||||||
Variable getDocumentedParameter() {
|
Variable getDocumentedParameter() {
|
||||||
exists(Parameterized parm | parm.getDocumentation() = getParent() |
|
exists(Parameterized parm | parm.getDocumentation() = this.getParent() |
|
||||||
result = pragma[only_bind_out](parm).getParameterVariable(getName())
|
result = pragma[only_bind_out](parm).getParameterVariable(this.getName())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,10 +182,10 @@ class JSDocTypeExpr extends @jsdoc_type_expr, JSDocTypeExprParent, TypeAnnotatio
|
|||||||
|
|
||||||
override string toString() { jsdoc_type_exprs(this, _, _, _, result) }
|
override string toString() { jsdoc_type_exprs(this, _, _, _, result) }
|
||||||
|
|
||||||
override JSDoc getJSDocComment() { result = getParent().getJSDocComment() }
|
override JSDoc getJSDocComment() { result = this.getParent().getJSDocComment() }
|
||||||
|
|
||||||
override Stmt getEnclosingStmt() {
|
override Stmt getEnclosingStmt() {
|
||||||
exists(Documentable astNode | astNode.getDocumentation() = getJSDocComment() |
|
exists(Documentable astNode | astNode.getDocumentation() = this.getJSDocComment() |
|
||||||
result = astNode
|
result = astNode
|
||||||
or
|
or
|
||||||
result = astNode.(ExprOrType).getEnclosingStmt()
|
result = astNode.(ExprOrType).getEnclosingStmt()
|
||||||
@@ -194,9 +194,9 @@ class JSDocTypeExpr extends @jsdoc_type_expr, JSDocTypeExprParent, TypeAnnotatio
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override Function getEnclosingFunction() { result = getContainer() }
|
override Function getEnclosingFunction() { result = this.getContainer() }
|
||||||
|
|
||||||
override TopLevel getTopLevel() { result = getEnclosingStmt().getTopLevel() }
|
override TopLevel getTopLevel() { result = this.getEnclosingStmt().getTopLevel() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -276,34 +276,34 @@ class JSDocVoidTypeExpr extends @jsdoc_void_type_expr, JSDocTypeExpr {
|
|||||||
*/
|
*/
|
||||||
class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
||||||
/** Gets the name of the type the expression refers to. */
|
/** Gets the name of the type the expression refers to. */
|
||||||
string getName() { result = toString() }
|
string getName() { result = this.toString() }
|
||||||
|
|
||||||
override predicate isString() { getName() = "string" }
|
override predicate isString() { this.getName() = "string" }
|
||||||
|
|
||||||
override predicate isStringy() {
|
override predicate isStringy() {
|
||||||
exists(string name | name = getName() |
|
exists(string name | name = this.getName() |
|
||||||
name = "string" or
|
name = "string" or
|
||||||
name = "String"
|
name = "String"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isNumber() { getName() = "number" }
|
override predicate isNumber() { this.getName() = "number" }
|
||||||
|
|
||||||
override predicate isNumbery() {
|
override predicate isNumbery() {
|
||||||
exists(string name | name = getName() |
|
exists(string name | name = this.getName() |
|
||||||
name = ["number", "Number", "double", "Double", "int", "integer", "Integer"]
|
name = ["number", "Number", "double", "Double", "int", "integer", "Integer"]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isBoolean() { getName() = "boolean" }
|
override predicate isBoolean() { this.getName() = "boolean" }
|
||||||
|
|
||||||
override predicate isBooleany() {
|
override predicate isBooleany() {
|
||||||
getName() = "boolean" or
|
this.getName() = "boolean" or
|
||||||
getName() = "Boolean" or
|
this.getName() = "Boolean" or
|
||||||
getName() = "bool"
|
this.getName() = "bool"
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isRawFunction() { getName() = "Function" }
|
override predicate isRawFunction() { this.getName() = "Function" }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this name consists of the unqualified name `prefix`
|
* Holds if this name consists of the unqualified name `prefix`
|
||||||
@@ -315,7 +315,7 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
|||||||
*/
|
*/
|
||||||
predicate hasNameParts(string prefix, string suffix) {
|
predicate hasNameParts(string prefix, string suffix) {
|
||||||
exists(string regex, string name | regex = "([^.]+)(.*)" |
|
exists(string regex, string name | regex = "([^.]+)(.*)" |
|
||||||
name = getName() and
|
name = this.getName() and
|
||||||
prefix = name.regexpCapture(regex, 1) and
|
prefix = name.regexpCapture(regex, 1) and
|
||||||
suffix = name.regexpCapture(regex, 2)
|
suffix = name.regexpCapture(regex, 2)
|
||||||
)
|
)
|
||||||
@@ -325,8 +325,8 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
|||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate hasNamePartsAndEnv(string prefix, string suffix, JSDoc::Environment env) {
|
private predicate hasNamePartsAndEnv(string prefix, string suffix, JSDoc::Environment env) {
|
||||||
// Force join ordering
|
// Force join ordering
|
||||||
hasNameParts(prefix, suffix) and
|
this.hasNameParts(prefix, suffix) and
|
||||||
env.isContainerInScope(getContainer())
|
env.isContainerInScope(this.getContainer())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -335,28 +335,28 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
|||||||
cached
|
cached
|
||||||
private string resolvedName() {
|
private string resolvedName() {
|
||||||
exists(string prefix, string suffix, JSDoc::Environment env |
|
exists(string prefix, string suffix, JSDoc::Environment env |
|
||||||
hasNamePartsAndEnv(prefix, suffix, env) and
|
this.hasNamePartsAndEnv(prefix, suffix, env) and
|
||||||
result = env.resolveAlias(prefix) + suffix
|
result = env.resolveAlias(prefix) + suffix
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate hasQualifiedName(string globalName) {
|
override predicate hasQualifiedName(string globalName) {
|
||||||
globalName = resolvedName()
|
globalName = this.resolvedName()
|
||||||
or
|
or
|
||||||
not exists(resolvedName()) and
|
not exists(this.resolvedName()) and
|
||||||
globalName = getName()
|
globalName = this.getName()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::ClassNode getClass() {
|
override DataFlow::ClassNode getClass() {
|
||||||
exists(string name |
|
exists(string name |
|
||||||
hasQualifiedName(name) and
|
this.hasQualifiedName(name) and
|
||||||
result.hasQualifiedName(name)
|
result.hasQualifiedName(name)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Handle case where a local variable has a reference to the class,
|
// Handle case where a local variable has a reference to the class,
|
||||||
// but the class doesn't have a globally qualified name.
|
// but the class doesn't have a globally qualified name.
|
||||||
exists(string alias, JSDoc::Environment env |
|
exists(string alias, JSDoc::Environment env |
|
||||||
hasNamePartsAndEnv(alias, "", env) and
|
this.hasNamePartsAndEnv(alias, "", env) and
|
||||||
result.getAClassReference().flowsTo(env.getNodeFromAlias(alias))
|
result.getAClassReference().flowsTo(env.getNodeFromAlias(alias))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -373,25 +373,27 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
|||||||
*/
|
*/
|
||||||
class JSDocAppliedTypeExpr extends @jsdoc_applied_type_expr, JSDocTypeExpr {
|
class JSDocAppliedTypeExpr extends @jsdoc_applied_type_expr, JSDocTypeExpr {
|
||||||
/** Gets the head type expression, such as `Array` in `Array<string>`. */
|
/** Gets the head type expression, such as `Array` in `Array<string>`. */
|
||||||
JSDocTypeExpr getHead() { result = getChild(-1) }
|
JSDocTypeExpr getHead() { result = this.getChild(-1) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `i`th argument type of the applied type expression.
|
* Gets the `i`th argument type of the applied type expression.
|
||||||
*
|
*
|
||||||
* For example, in `Array<string>`, `string` is the 0th argument type.
|
* For example, in `Array<string>`, `string` is the 0th argument type.
|
||||||
*/
|
*/
|
||||||
JSDocTypeExpr getArgument(int i) { i >= 0 and result = getChild(i) }
|
JSDocTypeExpr getArgument(int i) { i >= 0 and result = this.getChild(i) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an argument type of the applied type expression.
|
* Gets an argument type of the applied type expression.
|
||||||
*
|
*
|
||||||
* For example, in `Array<string>`, `string` is the only argument type.
|
* For example, in `Array<string>`, `string` is the only argument type.
|
||||||
*/
|
*/
|
||||||
JSDocTypeExpr getAnArgument() { result = getArgument(_) }
|
JSDocTypeExpr getAnArgument() { result = this.getArgument(_) }
|
||||||
|
|
||||||
override predicate hasQualifiedName(string globalName) { getHead().hasQualifiedName(globalName) }
|
override predicate hasQualifiedName(string globalName) {
|
||||||
|
this.getHead().hasQualifiedName(globalName)
|
||||||
|
}
|
||||||
|
|
||||||
override DataFlow::ClassNode getClass() { result = getHead().getClass() }
|
override DataFlow::ClassNode getClass() { result = this.getHead().getClass() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -405,14 +407,14 @@ class JSDocAppliedTypeExpr extends @jsdoc_applied_type_expr, JSDocTypeExpr {
|
|||||||
*/
|
*/
|
||||||
class JSDocNullableTypeExpr extends @jsdoc_nullable_type_expr, JSDocTypeExpr {
|
class JSDocNullableTypeExpr extends @jsdoc_nullable_type_expr, JSDocTypeExpr {
|
||||||
/** Gets the argument type expression. */
|
/** Gets the argument type expression. */
|
||||||
JSDocTypeExpr getTypeExpr() { result = getChild(0) }
|
JSDocTypeExpr getTypeExpr() { result = this.getChild(0) }
|
||||||
|
|
||||||
/** Holds if the `?` operator of this type expression is written in prefix notation. */
|
/** Holds if the `?` operator of this type expression is written in prefix notation. */
|
||||||
predicate isPrefix() { jsdoc_prefix_qualifier(this) }
|
predicate isPrefix() { jsdoc_prefix_qualifier(this) }
|
||||||
|
|
||||||
override JSDocTypeExpr getAnUnderlyingType() { result = getTypeExpr().getAnUnderlyingType() }
|
override JSDocTypeExpr getAnUnderlyingType() { result = this.getTypeExpr().getAnUnderlyingType() }
|
||||||
|
|
||||||
override DataFlow::ClassNode getClass() { result = getTypeExpr().getClass() }
|
override DataFlow::ClassNode getClass() { result = this.getTypeExpr().getClass() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -426,14 +428,14 @@ class JSDocNullableTypeExpr extends @jsdoc_nullable_type_expr, JSDocTypeExpr {
|
|||||||
*/
|
*/
|
||||||
class JSDocNonNullableTypeExpr extends @jsdoc_non_nullable_type_expr, JSDocTypeExpr {
|
class JSDocNonNullableTypeExpr extends @jsdoc_non_nullable_type_expr, JSDocTypeExpr {
|
||||||
/** Gets the argument type expression. */
|
/** Gets the argument type expression. */
|
||||||
JSDocTypeExpr getTypeExpr() { result = getChild(0) }
|
JSDocTypeExpr getTypeExpr() { result = this.getChild(0) }
|
||||||
|
|
||||||
/** Holds if the `!` operator of this type expression is written in prefix notation. */
|
/** Holds if the `!` operator of this type expression is written in prefix notation. */
|
||||||
predicate isPrefix() { jsdoc_prefix_qualifier(this) }
|
predicate isPrefix() { jsdoc_prefix_qualifier(this) }
|
||||||
|
|
||||||
override JSDocTypeExpr getAnUnderlyingType() { result = getTypeExpr().getAnUnderlyingType() }
|
override JSDocTypeExpr getAnUnderlyingType() { result = this.getTypeExpr().getAnUnderlyingType() }
|
||||||
|
|
||||||
override DataFlow::ClassNode getClass() { result = getTypeExpr().getClass() }
|
override DataFlow::ClassNode getClass() { result = this.getTypeExpr().getClass() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -450,14 +452,14 @@ class JSDocRecordTypeExpr extends @jsdoc_record_type_expr, JSDocTypeExpr {
|
|||||||
string getFieldName(int i) { jsdoc_record_field_name(this, i, result) }
|
string getFieldName(int i) { jsdoc_record_field_name(this, i, result) }
|
||||||
|
|
||||||
/** Gets the name of some field of the record type. */
|
/** Gets the name of some field of the record type. */
|
||||||
string getAFieldName() { result = getFieldName(_) }
|
string getAFieldName() { result = this.getFieldName(_) }
|
||||||
|
|
||||||
/** Gets the type of the `i`th field of the record type. */
|
/** Gets the type of the `i`th field of the record type. */
|
||||||
JSDocTypeExpr getFieldType(int i) { result = getChild(i) }
|
JSDocTypeExpr getFieldType(int i) { result = this.getChild(i) }
|
||||||
|
|
||||||
/** Gets the type of the field with the given name. */
|
/** Gets the type of the field with the given name. */
|
||||||
JSDocTypeExpr getFieldTypeByName(string fieldname) {
|
JSDocTypeExpr getFieldTypeByName(string fieldname) {
|
||||||
exists(int idx | fieldname = getFieldName(idx) and result = getFieldType(idx))
|
exists(int idx | fieldname = this.getFieldName(idx) and result = this.getFieldType(idx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,10 +474,10 @@ class JSDocRecordTypeExpr extends @jsdoc_record_type_expr, JSDocTypeExpr {
|
|||||||
*/
|
*/
|
||||||
class JSDocArrayTypeExpr extends @jsdoc_array_type_expr, JSDocTypeExpr {
|
class JSDocArrayTypeExpr extends @jsdoc_array_type_expr, JSDocTypeExpr {
|
||||||
/** Gets the type of the `i`th element of this array type. */
|
/** Gets the type of the `i`th element of this array type. */
|
||||||
JSDocTypeExpr getElementType(int i) { result = getChild(i) }
|
JSDocTypeExpr getElementType(int i) { result = this.getChild(i) }
|
||||||
|
|
||||||
/** Gets an element type of this array type. */
|
/** Gets an element type of this array type. */
|
||||||
JSDocTypeExpr getAnElementType() { result = getElementType(_) }
|
JSDocTypeExpr getAnElementType() { result = this.getElementType(_) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -489,9 +491,11 @@ class JSDocArrayTypeExpr extends @jsdoc_array_type_expr, JSDocTypeExpr {
|
|||||||
*/
|
*/
|
||||||
class JSDocUnionTypeExpr extends @jsdoc_union_type_expr, JSDocTypeExpr {
|
class JSDocUnionTypeExpr extends @jsdoc_union_type_expr, JSDocTypeExpr {
|
||||||
/** Gets one of the type alternatives of this union type. */
|
/** Gets one of the type alternatives of this union type. */
|
||||||
JSDocTypeExpr getAnAlternative() { result = getChild(_) }
|
JSDocTypeExpr getAnAlternative() { result = this.getChild(_) }
|
||||||
|
|
||||||
override JSDocTypeExpr getAnUnderlyingType() { result = getAnAlternative().getAnUnderlyingType() }
|
override JSDocTypeExpr getAnUnderlyingType() {
|
||||||
|
result = this.getAnAlternative().getAnUnderlyingType()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -505,16 +509,16 @@ class JSDocUnionTypeExpr extends @jsdoc_union_type_expr, JSDocTypeExpr {
|
|||||||
*/
|
*/
|
||||||
class JSDocFunctionTypeExpr extends @jsdoc_function_type_expr, JSDocTypeExpr {
|
class JSDocFunctionTypeExpr extends @jsdoc_function_type_expr, JSDocTypeExpr {
|
||||||
/** Gets the result type of this function type. */
|
/** Gets the result type of this function type. */
|
||||||
JSDocTypeExpr getResultType() { result = getChild(-1) }
|
JSDocTypeExpr getResultType() { result = this.getChild(-1) }
|
||||||
|
|
||||||
/** Gets the receiver type of this function type. */
|
/** Gets the receiver type of this function type. */
|
||||||
JSDocTypeExpr getReceiverType() { result = getChild(-2) }
|
JSDocTypeExpr getReceiverType() { result = this.getChild(-2) }
|
||||||
|
|
||||||
/** Gets the `i`th parameter type of this function type. */
|
/** Gets the `i`th parameter type of this function type. */
|
||||||
JSDocTypeExpr getParameterType(int i) { i >= 0 and result = getChild(i) }
|
JSDocTypeExpr getParameterType(int i) { i >= 0 and result = this.getChild(i) }
|
||||||
|
|
||||||
/** Gets a parameter type of this function type. */
|
/** Gets a parameter type of this function type. */
|
||||||
JSDocTypeExpr getAParameterType() { result = getParameterType(_) }
|
JSDocTypeExpr getAParameterType() { result = this.getParameterType(_) }
|
||||||
|
|
||||||
/** Holds if this function type is a constructor type. */
|
/** Holds if this function type is a constructor type. */
|
||||||
predicate isConstructorType() { jsdoc_has_new_parameter(this) }
|
predicate isConstructorType() { jsdoc_has_new_parameter(this) }
|
||||||
@@ -531,13 +535,13 @@ class JSDocFunctionTypeExpr extends @jsdoc_function_type_expr, JSDocTypeExpr {
|
|||||||
*/
|
*/
|
||||||
class JSDocOptionalParameterTypeExpr extends @jsdoc_optional_type_expr, JSDocTypeExpr {
|
class JSDocOptionalParameterTypeExpr extends @jsdoc_optional_type_expr, JSDocTypeExpr {
|
||||||
/** Gets the underlying type of this optional type. */
|
/** Gets the underlying type of this optional type. */
|
||||||
JSDocTypeExpr getUnderlyingType() { result = getChild(0) }
|
JSDocTypeExpr getUnderlyingType() { result = this.getChild(0) }
|
||||||
|
|
||||||
override JSDocTypeExpr getAnUnderlyingType() {
|
override JSDocTypeExpr getAnUnderlyingType() {
|
||||||
result = getUnderlyingType().getAnUnderlyingType()
|
result = this.getUnderlyingType().getAnUnderlyingType()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::ClassNode getClass() { result = getUnderlyingType().getClass() }
|
override DataFlow::ClassNode getClass() { result = this.getUnderlyingType().getClass() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -551,7 +555,7 @@ class JSDocOptionalParameterTypeExpr extends @jsdoc_optional_type_expr, JSDocTyp
|
|||||||
*/
|
*/
|
||||||
class JSDocRestParameterTypeExpr extends @jsdoc_rest_type_expr, JSDocTypeExpr {
|
class JSDocRestParameterTypeExpr extends @jsdoc_rest_type_expr, JSDocTypeExpr {
|
||||||
/** Gets the underlying type of this rest parameter type. */
|
/** Gets the underlying type of this rest parameter type. */
|
||||||
JSDocTypeExpr getUnderlyingType() { result = getChild(0) }
|
JSDocTypeExpr getUnderlyingType() { result = this.getChild(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -578,7 +582,7 @@ module JSDoc {
|
|||||||
* within this container.
|
* within this container.
|
||||||
*/
|
*/
|
||||||
string resolveAlias(string alias) {
|
string resolveAlias(string alias) {
|
||||||
getNodeFromAlias(alias) = AccessPath::getAReferenceOrAssignmentTo(result)
|
this.getNodeFromAlias(alias) = AccessPath::getAReferenceOrAssignmentTo(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -614,10 +618,10 @@ module JSDoc {
|
|||||||
* alias and is an ancestor of `container`.
|
* alias and is an ancestor of `container`.
|
||||||
*/
|
*/
|
||||||
final predicate isContainerInScope(StmtContainer container) {
|
final predicate isContainerInScope(StmtContainer container) {
|
||||||
exists(resolveAlias(_)) and // restrict size of predicate
|
exists(this.resolveAlias(_)) and // restrict size of predicate
|
||||||
container = this
|
container = this
|
||||||
or
|
or
|
||||||
isContainerInScope(container.getEnclosingContainer())
|
this.isContainerInScope(container.getEnclosingContainer())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class JsonValue extends @json_value, Locatable {
|
|||||||
JsonValue getChild(int i) { json(result, _, this, i, _) }
|
JsonValue getChild(int i) { json(result, _, this, i, _) }
|
||||||
|
|
||||||
/** Holds if this JSON value is the top level element in its enclosing file. */
|
/** Holds if this JSON value is the top level element in its enclosing file. */
|
||||||
predicate isTopLevel() { not exists(getParent()) }
|
predicate isTopLevel() { not exists(this.getParent()) }
|
||||||
|
|
||||||
override string toString() { json(this, _, _, _, result) }
|
override string toString() { json(this, _, _, _, result) }
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ class JsonArray extends @json_array, JsonValue {
|
|||||||
override string getAPrimaryQlClass() { result = "JsonArray" }
|
override string getAPrimaryQlClass() { result = "JsonArray" }
|
||||||
|
|
||||||
/** Gets the string value of the `i`th element of this array. */
|
/** Gets the string value of the `i`th element of this array. */
|
||||||
string getElementStringValue(int i) { result = getElementValue(i).getStringValue() }
|
string getElementStringValue(int i) { result = this.getElementValue(i).getStringValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for JsonArray */
|
/** DEPRECATED: Alias for JsonArray */
|
||||||
@@ -186,7 +186,7 @@ class JsonObject extends @json_object, JsonValue {
|
|||||||
override string getAPrimaryQlClass() { result = "JsonObject" }
|
override string getAPrimaryQlClass() { result = "JsonObject" }
|
||||||
|
|
||||||
/** Gets the string value of property `name` of this object. */
|
/** Gets the string value of property `name` of this object. */
|
||||||
string getPropStringValue(string name) { result = getPropValue(name).getStringValue() }
|
string getPropStringValue(string name) { result = this.getPropValue(name).getStringValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for JsonObject */
|
/** DEPRECATED: Alias for JsonObject */
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ import javascript
|
|||||||
*/
|
*/
|
||||||
class JsxNode extends Expr, @jsx_element {
|
class JsxNode extends Expr, @jsx_element {
|
||||||
/** Gets the `i`th element in the body of this element or fragment. */
|
/** Gets the `i`th element in the body of this element or fragment. */
|
||||||
Expr getBodyElement(int i) { i >= 0 and result = getChildExpr(-i - 2) }
|
Expr getBodyElement(int i) { i >= 0 and result = this.getChildExpr(-i - 2) }
|
||||||
|
|
||||||
/** Gets an element in the body of this element or fragment. */
|
/** Gets an element in the body of this element or fragment. */
|
||||||
Expr getABodyElement() { result = getBodyElement(_) }
|
Expr getABodyElement() { result = this.getBodyElement(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the parent JSX element or fragment of this element.
|
* Gets the parent JSX element or fragment of this element.
|
||||||
@@ -46,7 +46,7 @@ deprecated class JSXNode = JsxNode;
|
|||||||
class JsxElement extends JsxNode {
|
class JsxElement extends JsxNode {
|
||||||
JsxName name;
|
JsxName name;
|
||||||
|
|
||||||
JsxElement() { name = getChildExpr(-1) }
|
JsxElement() { name = this.getChildExpr(-1) }
|
||||||
|
|
||||||
/** Gets the expression denoting the name of this element. */
|
/** Gets the expression denoting the name of this element. */
|
||||||
JsxName getNameExpr() { result = name }
|
JsxName getNameExpr() { result = name }
|
||||||
@@ -58,13 +58,15 @@ class JsxElement extends JsxNode {
|
|||||||
JsxAttribute getAttribute(int i) { properties(result, this, i, _, _) }
|
JsxAttribute getAttribute(int i) { properties(result, this, i, _, _) }
|
||||||
|
|
||||||
/** Gets an attribute of this element. */
|
/** Gets an attribute of this element. */
|
||||||
JsxAttribute getAnAttribute() { result = getAttribute(_) }
|
JsxAttribute getAnAttribute() { result = this.getAttribute(_) }
|
||||||
|
|
||||||
/** Gets the attribute of this element with the given name, if any. */
|
/** Gets the attribute of this element with the given name, if any. */
|
||||||
JsxAttribute getAttributeByName(string n) { result = getAnAttribute() and result.getName() = n }
|
JsxAttribute getAttributeByName(string n) {
|
||||||
|
result = this.getAnAttribute() and result.getName() = n
|
||||||
|
}
|
||||||
|
|
||||||
override ControlFlowNode getFirstControlFlowNode() {
|
override ControlFlowNode getFirstControlFlowNode() {
|
||||||
result = getNameExpr().getFirstControlFlowNode()
|
result = this.getNameExpr().getFirstControlFlowNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "JsxElement" }
|
override string getAPrimaryQlClass() { result = "JsxElement" }
|
||||||
@@ -73,10 +75,10 @@ class JsxElement extends JsxNode {
|
|||||||
* Holds if this JSX element is an HTML element.
|
* Holds if this JSX element is an HTML element.
|
||||||
* That is, the name starts with a lowercase letter.
|
* That is, the name starts with a lowercase letter.
|
||||||
*/
|
*/
|
||||||
predicate isHtmlElement() { getName().regexpMatch("[a-z].*") }
|
predicate isHtmlElement() { this.getName().regexpMatch("[a-z].*") }
|
||||||
|
|
||||||
/** DEPRECATED: Alias for isHtmlElement */
|
/** DEPRECATED: Alias for isHtmlElement */
|
||||||
deprecated predicate isHTMLElement() { isHtmlElement() }
|
deprecated predicate isHTMLElement() { this.isHtmlElement() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for JsxElement */
|
/** DEPRECATED: Alias for JsxElement */
|
||||||
@@ -92,12 +94,12 @@ deprecated class JSXElement = JsxElement;
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class JsxFragment extends JsxNode {
|
class JsxFragment extends JsxNode {
|
||||||
JsxFragment() { not exists(getChildExpr(-1)) }
|
JsxFragment() { not exists(this.getChildExpr(-1)) }
|
||||||
|
|
||||||
override ControlFlowNode getFirstControlFlowNode() {
|
override ControlFlowNode getFirstControlFlowNode() {
|
||||||
result = getBodyElement(0).getFirstControlFlowNode()
|
result = this.getBodyElement(0).getFirstControlFlowNode()
|
||||||
or
|
or
|
||||||
not exists(getABodyElement()) and result = this
|
not exists(this.getABodyElement()) and result = this
|
||||||
}
|
}
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "JsxFragment" }
|
override string getAPrimaryQlClass() { result = "JsxFragment" }
|
||||||
@@ -123,28 +125,28 @@ class JsxAttribute extends AstNode, @jsx_attribute {
|
|||||||
*
|
*
|
||||||
* This is not defined for spread attributes.
|
* This is not defined for spread attributes.
|
||||||
*/
|
*/
|
||||||
JsxName getNameExpr() { result = getChildExpr(0) }
|
JsxName getNameExpr() { result = this.getChildExpr(0) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name of this attribute.
|
* Gets the name of this attribute.
|
||||||
*
|
*
|
||||||
* This is not defined for spread attributes.
|
* This is not defined for spread attributes.
|
||||||
*/
|
*/
|
||||||
string getName() { result = getNameExpr().getValue() }
|
string getName() { result = this.getNameExpr().getValue() }
|
||||||
|
|
||||||
/** Gets the expression denoting the value of this attribute. */
|
/** Gets the expression denoting the value of this attribute. */
|
||||||
Expr getValue() { result = getChildExpr(1) }
|
Expr getValue() { result = this.getChildExpr(1) }
|
||||||
|
|
||||||
/** Gets the value of this attribute as a constant string, if possible. */
|
/** Gets the value of this attribute as a constant string, if possible. */
|
||||||
string getStringValue() { result = getValue().getStringValue() }
|
string getStringValue() { result = this.getValue().getStringValue() }
|
||||||
|
|
||||||
/** Gets the JSX element to which this attribute belongs. */
|
/** Gets the JSX element to which this attribute belongs. */
|
||||||
JsxElement getElement() { this = result.getAnAttribute() }
|
JsxElement getElement() { this = result.getAnAttribute() }
|
||||||
|
|
||||||
override ControlFlowNode getFirstControlFlowNode() {
|
override ControlFlowNode getFirstControlFlowNode() {
|
||||||
result = getNameExpr().getFirstControlFlowNode()
|
result = this.getNameExpr().getFirstControlFlowNode()
|
||||||
or
|
or
|
||||||
not exists(getNameExpr()) and result = getValue().getFirstControlFlowNode()
|
not exists(this.getNameExpr()) and result = this.getValue().getFirstControlFlowNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { properties(this, _, _, _, result) }
|
override string toString() { properties(this, _, _, _, result) }
|
||||||
@@ -165,7 +167,7 @@ deprecated class JSXAttribute = JsxAttribute;
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class JsxSpreadAttribute extends JsxAttribute {
|
class JsxSpreadAttribute extends JsxAttribute {
|
||||||
JsxSpreadAttribute() { not exists(getNameExpr()) }
|
JsxSpreadAttribute() { not exists(this.getNameExpr()) }
|
||||||
|
|
||||||
override SpreadElement getValue() {
|
override SpreadElement getValue() {
|
||||||
// override for more precise result type
|
// override for more precise result type
|
||||||
@@ -187,13 +189,13 @@ deprecated class JSXSpreadAttribute = JsxSpreadAttribute;
|
|||||||
*/
|
*/
|
||||||
class JsxQualifiedName extends Expr, @jsx_qualified_name {
|
class JsxQualifiedName extends Expr, @jsx_qualified_name {
|
||||||
/** Gets the namespace component of this qualified name. */
|
/** Gets the namespace component of this qualified name. */
|
||||||
Identifier getNamespace() { result = getChildExpr(0) }
|
Identifier getNamespace() { result = this.getChildExpr(0) }
|
||||||
|
|
||||||
/** Gets the name component of this qualified name. */
|
/** Gets the name component of this qualified name. */
|
||||||
Identifier getName() { result = getChildExpr(1) }
|
Identifier getName() { result = this.getChildExpr(1) }
|
||||||
|
|
||||||
override ControlFlowNode getFirstControlFlowNode() {
|
override ControlFlowNode getFirstControlFlowNode() {
|
||||||
result = getNamespace().getFirstControlFlowNode()
|
result = this.getNamespace().getFirstControlFlowNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "JsxQualifiedName" }
|
override string getAPrimaryQlClass() { result = "JsxQualifiedName" }
|
||||||
@@ -271,16 +273,16 @@ deprecated class JSXEmptyExpr = JsxEmptyExpr;
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class JsxPragma extends JSDocTag {
|
class JsxPragma extends JSDocTag {
|
||||||
JsxPragma() { getTitle() = "jsx" }
|
JsxPragma() { this.getTitle() = "jsx" }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the DOM name specified by the pragma; for `@jsx React.DOM`,
|
* Gets the DOM name specified by the pragma; for `@jsx React.DOM`,
|
||||||
* the result is `React.DOM`.
|
* the result is `React.DOM`.
|
||||||
*/
|
*/
|
||||||
string getDomName() { result = getDescription().trim() }
|
string getDomName() { result = this.getDescription().trim() }
|
||||||
|
|
||||||
/** DEPRECATED: Alias for getDomName */
|
/** DEPRECATED: Alias for getDomName */
|
||||||
deprecated string getDOMName() { result = getDomName() }
|
deprecated string getDOMName() { result = this.getDomName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for JsxPragma */
|
/** DEPRECATED: Alias for JsxPragma */
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class JsonStringifyCall extends DataFlow::CallNode {
|
|||||||
/**
|
/**
|
||||||
* Gets the data flow node holding the input object to be stringified.
|
* Gets the data flow node holding the input object to be stringified.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getInput() { result = getArgument(0) }
|
DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the data flow node holding the resulting string.
|
* Gets the data flow node holding the resulting string.
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class Line extends @line, Locatable {
|
|||||||
* If the line does not start with a whitespace character, or with a mixture of
|
* If the line does not start with a whitespace character, or with a mixture of
|
||||||
* different whitespace characters, its indentation character is undefined.
|
* different whitespace characters, its indentation character is undefined.
|
||||||
*/
|
*/
|
||||||
string getIndentChar() { result = getText().regexpCapture("(\\s)\\1*\\S.*", 1) }
|
string getIndentChar() { result = this.getText().regexpCapture("(\\s)\\1*\\S.*", 1) }
|
||||||
|
|
||||||
override string toString() { result = getText() }
|
override string toString() { result = this.getText() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ class MainModulePath extends PathExpr, @json_string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for getPackageJson */
|
/** DEPRECATED: Alias for getPackageJson */
|
||||||
deprecated PackageJSON getPackageJSON() { result = getPackageJson() }
|
deprecated PackageJSON getPackageJSON() { result = this.getPackageJson() }
|
||||||
|
|
||||||
override string getValue() { result = this.(JsonString).getValue() }
|
override string getValue() { result = this.(JsonString).getValue() }
|
||||||
|
|
||||||
@@ -259,7 +259,7 @@ private class FilesPath extends PathExpr, @json_string {
|
|||||||
PackageJson getPackageJson() { result = pkg }
|
PackageJson getPackageJson() { result = pkg }
|
||||||
|
|
||||||
/** DEPRECATED: Alias for getPackageJson */
|
/** DEPRECATED: Alias for getPackageJson */
|
||||||
deprecated PackageJSON getPackageJSON() { result = getPackageJson() }
|
deprecated PackageJSON getPackageJSON() { result = this.getPackageJson() }
|
||||||
|
|
||||||
override string getValue() { result = this.(JsonString).getValue() }
|
override string getValue() { result = this.(JsonString).getValue() }
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class FirstLineOf extends Locatable {
|
|||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
exists(int xl, int xc |
|
exists(int xl, int xc |
|
||||||
getLocation().hasLocationInfo(filepath, startline, startcolumn, xl, xc) and
|
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, xl, xc) and
|
||||||
startline = endline and
|
startline = endline and
|
||||||
if xl = startline
|
if xl = startline
|
||||||
then endcolumn = xc
|
then endcolumn = xc
|
||||||
@@ -49,7 +49,7 @@ class LastLineOf extends Locatable {
|
|||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
exists(int xl, int xc |
|
exists(int xl, int xc |
|
||||||
getLocation().hasLocationInfo(filepath, xl, xc, endline, endcolumn) and
|
this.getLocation().hasLocationInfo(filepath, xl, xc, endline, endcolumn) and
|
||||||
startline = endline and
|
startline = endline and
|
||||||
if xl = endline then startcolumn = xc else startcolumn = 1
|
if xl = endline then startcolumn = xc else startcolumn = 1
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -401,16 +401,16 @@ class SsaVariable extends TSsaDefinition {
|
|||||||
|
|
||||||
/** Gets a use in basic block `bb` that refers to this SSA variable. */
|
/** Gets a use in basic block `bb` that refers to this SSA variable. */
|
||||||
VarUse getAUseIn(ReachableBasicBlock bb) {
|
VarUse getAUseIn(ReachableBasicBlock bb) {
|
||||||
exists(int i, SsaSourceVariable v | v = getSourceVariable() |
|
exists(int i, SsaSourceVariable v | v = this.getSourceVariable() |
|
||||||
bb.useAt(i, v, result) and this = getDefinition(bb, i, v)
|
bb.useAt(i, v, result) and this = getDefinition(bb, i, v)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a use that refers to this SSA variable. */
|
/** Gets a use that refers to this SSA variable. */
|
||||||
VarUse getAUse() { result = getAUseIn(_) }
|
VarUse getAUse() { result = this.getAUseIn(_) }
|
||||||
|
|
||||||
/** Gets a textual representation of this element. */
|
/** Gets a textual representation of this element. */
|
||||||
string toString() { result = getDefinition().prettyPrintRef() }
|
string toString() { result = this.getDefinition().prettyPrintRef() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this element is at the specified location.
|
* Holds if this element is at the specified location.
|
||||||
@@ -422,7 +422,7 @@ class SsaVariable extends TSsaDefinition {
|
|||||||
predicate hasLocationInfo(
|
predicate hasLocationInfo(
|
||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getDefinition().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
this.getDefinition().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,7 +475,7 @@ class SsaDefinition extends TSsaDefinition {
|
|||||||
abstract string prettyPrintRef();
|
abstract string prettyPrintRef();
|
||||||
|
|
||||||
/** Gets a textual representation of this element. */
|
/** Gets a textual representation of this element. */
|
||||||
string toString() { result = prettyPrintDef() }
|
string toString() { result = this.prettyPrintDef() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this element is at the specified location.
|
* Holds if this element is at the specified location.
|
||||||
@@ -489,7 +489,7 @@ class SsaDefinition extends TSsaDefinition {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/** Gets the function or toplevel to which this definition belongs. */
|
/** Gets the function or toplevel to which this definition belongs. */
|
||||||
StmtContainer getContainer() { result = getBasicBlock().getContainer() }
|
StmtContainer getContainer() { result = this.getBasicBlock().getContainer() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -507,23 +507,23 @@ class SsaExplicitDefinition extends SsaDefinition, TExplicitDef {
|
|||||||
VarDef getDef() { this = TExplicitDef(_, _, result, _) }
|
VarDef getDef() { this = TExplicitDef(_, _, result, _) }
|
||||||
|
|
||||||
/** Gets the basic block to which this definition belongs. */
|
/** Gets the basic block to which this definition belongs. */
|
||||||
override ReachableBasicBlock getBasicBlock() { definesAt(result, _, _) }
|
override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
|
||||||
|
|
||||||
override SsaSourceVariable getSourceVariable() { this = TExplicitDef(_, _, _, result) }
|
override SsaSourceVariable getSourceVariable() { this = TExplicitDef(_, _, _, result) }
|
||||||
|
|
||||||
override VarDef getAContributingVarDef() { result = getDef() }
|
override VarDef getAContributingVarDef() { result = this.getDef() }
|
||||||
|
|
||||||
override string prettyPrintRef() {
|
override string prettyPrintRef() {
|
||||||
exists(int l, int c | hasLocationInfo(_, l, c, _, _) | result = "def@" + l + ":" + c)
|
exists(int l, int c | this.hasLocationInfo(_, l, c, _, _) | result = "def@" + l + ":" + c)
|
||||||
}
|
}
|
||||||
|
|
||||||
override string prettyPrintDef() { result = getDef().toString() }
|
override string prettyPrintDef() { result = this.getDef().toString() }
|
||||||
|
|
||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
exists(Location loc |
|
exists(Location loc |
|
||||||
pragma[only_bind_into](loc) = pragma[only_bind_into](getDef()).getLocation() and
|
pragma[only_bind_into](loc) = pragma[only_bind_into](this.getDef()).getLocation() and
|
||||||
loc.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
loc.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -549,7 +549,9 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
|
|||||||
abstract string getKind();
|
abstract string getKind();
|
||||||
|
|
||||||
override string prettyPrintRef() {
|
override string prettyPrintRef() {
|
||||||
exists(int l, int c | hasLocationInfo(_, l, c, _, _) | result = getKind() + "@" + l + ":" + c)
|
exists(int l, int c | this.hasLocationInfo(_, l, c, _, _) |
|
||||||
|
result = this.getKind() + "@" + l + ":" + c
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
@@ -558,7 +560,7 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
|
|||||||
endline = startline and
|
endline = startline and
|
||||||
endcolumn = startcolumn and
|
endcolumn = startcolumn and
|
||||||
exists(Location loc |
|
exists(Location loc |
|
||||||
pragma[only_bind_into](loc) = pragma[only_bind_into](getBasicBlock()).getLocation() and
|
pragma[only_bind_into](loc) = pragma[only_bind_into](this.getBasicBlock()).getLocation() and
|
||||||
loc.hasLocationInfo(filepath, startline, startcolumn, _, _)
|
loc.hasLocationInfo(filepath, startline, startcolumn, _, _)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -570,7 +572,7 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
|
|||||||
*/
|
*/
|
||||||
class SsaImplicitInit extends SsaImplicitDefinition, TImplicitInit {
|
class SsaImplicitInit extends SsaImplicitDefinition, TImplicitInit {
|
||||||
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
|
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
|
||||||
bb = getBasicBlock() and v = getSourceVariable() and i = 0
|
bb = this.getBasicBlock() and v = this.getSourceVariable() and i = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override ReachableBasicBlock getBasicBlock() { this = TImplicitInit(result, _) }
|
override ReachableBasicBlock getBasicBlock() { this = TImplicitInit(result, _) }
|
||||||
@@ -581,7 +583,9 @@ class SsaImplicitInit extends SsaImplicitDefinition, TImplicitInit {
|
|||||||
|
|
||||||
override VarDef getAContributingVarDef() { none() }
|
override VarDef getAContributingVarDef() { none() }
|
||||||
|
|
||||||
override string prettyPrintDef() { result = "implicit initialization of " + getSourceVariable() }
|
override string prettyPrintDef() {
|
||||||
|
result = "implicit initialization of " + this.getSourceVariable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -596,20 +600,20 @@ class SsaVariableCapture extends SsaImplicitDefinition, TCapture {
|
|||||||
this = TCapture(bb, i, v)
|
this = TCapture(bb, i, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
override ReachableBasicBlock getBasicBlock() { definesAt(result, _, _) }
|
override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
|
||||||
|
|
||||||
override SsaSourceVariable getSourceVariable() { definesAt(_, _, result) }
|
override SsaSourceVariable getSourceVariable() { this.definesAt(_, _, result) }
|
||||||
|
|
||||||
override VarDef getAContributingVarDef() { result.getAVariable() = getSourceVariable() }
|
override VarDef getAContributingVarDef() { result.getAVariable() = this.getSourceVariable() }
|
||||||
|
|
||||||
override string getKind() { result = "capture" }
|
override string getKind() { result = "capture" }
|
||||||
|
|
||||||
override string prettyPrintDef() { result = "capture variable " + getSourceVariable() }
|
override string prettyPrintDef() { result = "capture variable " + this.getSourceVariable() }
|
||||||
|
|
||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
exists(ReachableBasicBlock bb, int i | definesAt(bb, i, _) |
|
exists(ReachableBasicBlock bb, int i | this.definesAt(bb, i, _) |
|
||||||
bb.getNode(i)
|
bb.getNode(i)
|
||||||
.getLocation()
|
.getLocation()
|
||||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||||
@@ -631,14 +635,14 @@ abstract class SsaPseudoDefinition extends SsaImplicitDefinition {
|
|||||||
abstract SsaVariable getAnInput();
|
abstract SsaVariable getAnInput();
|
||||||
|
|
||||||
override VarDef getAContributingVarDef() {
|
override VarDef getAContributingVarDef() {
|
||||||
result = getAnInput().getDefinition().getAContributingVarDef()
|
result = this.getAnInput().getDefinition().getAContributingVarDef()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a textual representation of the inputs of this pseudo-definition
|
* Gets a textual representation of the inputs of this pseudo-definition
|
||||||
* in lexicographical order.
|
* in lexicographical order.
|
||||||
*/
|
*/
|
||||||
string ppInputs() { result = concat(getAnInput().getDefinition().prettyPrintRef(), ", ") }
|
string ppInputs() { result = concat(this.getAnInput().getDefinition().prettyPrintRef(), ", ") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -652,14 +656,14 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
|
|||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
SsaVariable getInputFromBlock(BasicBlock bb) {
|
SsaVariable getInputFromBlock(BasicBlock bb) {
|
||||||
bb = getBasicBlock().getAPredecessor() and
|
bb = this.getBasicBlock().getAPredecessor() and
|
||||||
result = getDefReachingEndOf(bb, getSourceVariable())
|
result = getDefReachingEndOf(bb, this.getSourceVariable())
|
||||||
}
|
}
|
||||||
|
|
||||||
override SsaVariable getAnInput() { result = getInputFromBlock(_) }
|
override SsaVariable getAnInput() { result = this.getInputFromBlock(_) }
|
||||||
|
|
||||||
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
|
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
|
||||||
bb = getBasicBlock() and v = getSourceVariable() and i = -1
|
bb = this.getBasicBlock() and v = this.getSourceVariable() and i = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
override ReachableBasicBlock getBasicBlock() { this = TPhi(result, _) }
|
override ReachableBasicBlock getBasicBlock() { this = TPhi(result, _) }
|
||||||
@@ -668,14 +672,16 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
|
|||||||
|
|
||||||
override string getKind() { result = "phi" }
|
override string getKind() { result = "phi" }
|
||||||
|
|
||||||
override string prettyPrintDef() { result = getSourceVariable() + " = phi(" + ppInputs() + ")" }
|
override string prettyPrintDef() {
|
||||||
|
result = this.getSourceVariable() + " = phi(" + this.ppInputs() + ")"
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If all inputs to this phi node are (transitive) refinements of the same variable,
|
* If all inputs to this phi node are (transitive) refinements of the same variable,
|
||||||
* gets that variable.
|
* gets that variable.
|
||||||
*/
|
*/
|
||||||
SsaVariable getRephinedVariable() {
|
SsaVariable getRephinedVariable() {
|
||||||
forex(SsaVariable input | input = getAnInput() | result = getRefinedVariable(input))
|
forex(SsaVariable input | input = this.getAnInput() | result = getRefinedVariable(input))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -706,10 +712,12 @@ class SsaRefinementNode extends SsaPseudoDefinition, TRefinement {
|
|||||||
/**
|
/**
|
||||||
* Gets the refinement associated with this definition.
|
* Gets the refinement associated with this definition.
|
||||||
*/
|
*/
|
||||||
Refinement getRefinement() { result = getGuard().getTest() }
|
Refinement getRefinement() { result = this.getGuard().getTest() }
|
||||||
|
|
||||||
override SsaVariable getAnInput() {
|
override SsaVariable getAnInput() {
|
||||||
exists(SsaSourceVariable v, BasicBlock bb | v = getSourceVariable() and bb = getBasicBlock() |
|
exists(SsaSourceVariable v, BasicBlock bb |
|
||||||
|
v = this.getSourceVariable() and bb = this.getBasicBlock()
|
||||||
|
|
|
||||||
if exists(SsaPhiNode phi | phi.definesAt(bb, _, v))
|
if exists(SsaPhiNode phi | phi.definesAt(bb, _, v))
|
||||||
then result.(SsaPhiNode).definesAt(bb, _, v)
|
then result.(SsaPhiNode).definesAt(bb, _, v)
|
||||||
else result = getDefReachingEndOf(bb.getAPredecessor(), v)
|
else result = getDefReachingEndOf(bb.getAPredecessor(), v)
|
||||||
@@ -724,16 +732,19 @@ class SsaRefinementNode extends SsaPseudoDefinition, TRefinement {
|
|||||||
|
|
||||||
override SsaSourceVariable getSourceVariable() { this = TRefinement(_, _, _, result) }
|
override SsaSourceVariable getSourceVariable() { this = TRefinement(_, _, _, result) }
|
||||||
|
|
||||||
override string getKind() { result = "refine[" + getGuard() + "]" }
|
override string getKind() { result = "refine[" + this.getGuard() + "]" }
|
||||||
|
|
||||||
override string prettyPrintDef() {
|
override string prettyPrintDef() {
|
||||||
result = getSourceVariable() + " = refine[" + getGuard() + "](" + ppInputs() + ")"
|
result =
|
||||||
|
this.getSourceVariable() + " = refine[" + this.getGuard() + "](" + this.ppInputs() + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getGuard().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
this.getGuard()
|
||||||
|
.getLocation()
|
||||||
|
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,5 +25,5 @@ class SourceMappingComment extends Comment {
|
|||||||
string getSourceMappingUrl() { result = url }
|
string getSourceMappingUrl() { result = url }
|
||||||
|
|
||||||
/** DEPRECATED: Alias for getSourceMappingUrl */
|
/** DEPRECATED: Alias for getSourceMappingUrl */
|
||||||
deprecated string getSourceMappingURL() { result = getSourceMappingUrl() }
|
deprecated string getSourceMappingURL() { result = this.getSourceMappingUrl() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,19 +13,19 @@ import javascript
|
|||||||
*/
|
*/
|
||||||
class TaggedTemplateExpr extends Expr, @tagged_template_expr {
|
class TaggedTemplateExpr extends Expr, @tagged_template_expr {
|
||||||
/** Gets the tagging expression of this tagged template. */
|
/** Gets the tagging expression of this tagged template. */
|
||||||
Expr getTag() { result = getChildExpr(0) }
|
Expr getTag() { result = this.getChildExpr(0) }
|
||||||
|
|
||||||
/** Gets the tagged template itself. */
|
/** Gets the tagged template itself. */
|
||||||
TemplateLiteral getTemplate() { result = getChildExpr(1) }
|
TemplateLiteral getTemplate() { result = this.getChildExpr(1) }
|
||||||
|
|
||||||
/** Gets the `i`th type argument to the tag of this template literal. */
|
/** Gets the `i`th type argument to the tag of this template literal. */
|
||||||
TypeExpr getTypeArgument(int i) { i >= 0 and result = getChildTypeExpr(2 + i) }
|
TypeExpr getTypeArgument(int i) { i >= 0 and result = this.getChildTypeExpr(2 + i) }
|
||||||
|
|
||||||
/** Gets a type argument of the tag of this template literal. */
|
/** Gets a type argument of the tag of this template literal. */
|
||||||
TypeExpr getATypeArgument() { result = getTypeArgument(_) }
|
TypeExpr getATypeArgument() { result = this.getTypeArgument(_) }
|
||||||
|
|
||||||
/** Gets the number of type arguments appearing on the tag of this template literal. */
|
/** Gets the number of type arguments appearing on the tag of this template literal. */
|
||||||
int getNumTypeArgument() { result = count(getATypeArgument()) }
|
int getNumTypeArgument() { result = count(this.getATypeArgument()) }
|
||||||
|
|
||||||
override predicate isImpure() { any() }
|
override predicate isImpure() { any() }
|
||||||
|
|
||||||
@@ -46,19 +46,19 @@ class TemplateLiteral extends Expr, @template_literal {
|
|||||||
* Gets the `i`th element of this template literal, which may either
|
* Gets the `i`th element of this template literal, which may either
|
||||||
* be an interpolated expression or a constant template element.
|
* be an interpolated expression or a constant template element.
|
||||||
*/
|
*/
|
||||||
Expr getElement(int i) { result = getChildExpr(i) }
|
Expr getElement(int i) { result = this.getChildExpr(i) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an element of this template literal.
|
* Gets an element of this template literal.
|
||||||
*/
|
*/
|
||||||
Expr getAnElement() { result = getElement(_) }
|
Expr getAnElement() { result = this.getElement(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of elements of this template literal.
|
* Gets the number of elements of this template literal.
|
||||||
*/
|
*/
|
||||||
int getNumElement() { result = count(getAnElement()) }
|
int getNumElement() { result = count(this.getAnElement()) }
|
||||||
|
|
||||||
override predicate isImpure() { getAnElement().isImpure() }
|
override predicate isImpure() { this.getAnElement().isImpure() }
|
||||||
|
|
||||||
override string getAPrimaryQlClass() { result = "TemplateLiteral" }
|
override string getAPrimaryQlClass() { result = "TemplateLiteral" }
|
||||||
}
|
}
|
||||||
@@ -80,7 +80,7 @@ class TemplateElement extends Expr, @template_element {
|
|||||||
* elements with invalid escape sequences, which only have a raw value but
|
* elements with invalid escape sequences, which only have a raw value but
|
||||||
* no cooked value.
|
* no cooked value.
|
||||||
*/
|
*/
|
||||||
predicate hasValue() { exists(getValue()) }
|
predicate hasValue() { exists(this.getValue()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the "cooked" value of this template element, if any.
|
* Gets the "cooked" value of this template element, if any.
|
||||||
|
|||||||
@@ -21,31 +21,31 @@ class AbstractProperty extends TAbstractProperty {
|
|||||||
* Gets an initial value that is implicitly assigned to this property.
|
* Gets an initial value that is implicitly assigned to this property.
|
||||||
*/
|
*/
|
||||||
AbstractValue getAnInitialValue() {
|
AbstractValue getAnInitialValue() {
|
||||||
result = getAnInitialPropertyValue(getBase(), getPropertyName())
|
result = getAnInitialPropertyValue(this.getBase(), this.getPropertyName())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a value of this property for the purposes of `AnalyzedNode.getALocalValue`.
|
* Gets a value of this property for the purposes of `AnalyzedNode.getALocalValue`.
|
||||||
*/
|
*/
|
||||||
AbstractValue getALocalValue() {
|
AbstractValue getALocalValue() {
|
||||||
result = getAnInitialPropertyValue(getBase(), getPropertyName())
|
result = getAnInitialPropertyValue(this.getBase(), this.getPropertyName())
|
||||||
or
|
or
|
||||||
shouldAlwaysTrackProperties(getBase()) and
|
shouldAlwaysTrackProperties(this.getBase()) and
|
||||||
result = getAnAssignedValue(getBase(), getPropertyName())
|
result = getAnAssignedValue(this.getBase(), this.getPropertyName())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a value of this property for the purposes of `AnalyzedNode.getAValue`.
|
* Gets a value of this property for the purposes of `AnalyzedNode.getAValue`.
|
||||||
*/
|
*/
|
||||||
AbstractValue getAValue() {
|
AbstractValue getAValue() {
|
||||||
result = getALocalValue() or
|
result = this.getALocalValue() or
|
||||||
result = getAnAssignedValue(getBase(), getPropertyName())
|
result = getAnAssignedValue(this.getBase(), this.getPropertyName())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a textual representation of this element.
|
* Gets a textual representation of this element.
|
||||||
*/
|
*/
|
||||||
string toString() { result = "property " + getPropertyName() + " of " + getBase() }
|
string toString() { result = "property " + this.getPropertyName() + " of " + this.getBase() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,7 +53,7 @@ class AbstractProperty extends TAbstractProperty {
|
|||||||
* class instance.
|
* class instance.
|
||||||
*/
|
*/
|
||||||
class AbstractProtoProperty extends AbstractProperty {
|
class AbstractProtoProperty extends AbstractProperty {
|
||||||
AbstractProtoProperty() { getPropertyName() = "__proto__" }
|
AbstractProtoProperty() { this.getPropertyName() = "__proto__" }
|
||||||
|
|
||||||
override AbstractValue getAValue() {
|
override AbstractValue getAValue() {
|
||||||
result = super.getAValue() and
|
result = super.getAValue() and
|
||||||
@@ -62,7 +62,7 @@ class AbstractProtoProperty extends AbstractProperty {
|
|||||||
result instanceof AbstractNull
|
result instanceof AbstractNull
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(AbstractCallable ctor | getBase() = TAbstractInstance(ctor) |
|
exists(AbstractCallable ctor | this.getBase() = TAbstractInstance(ctor) |
|
||||||
// the value of `ctor.prototype`
|
// the value of `ctor.prototype`
|
||||||
exists(AbstractProperty prototype |
|
exists(AbstractProperty prototype |
|
||||||
prototype = MkAbstractProperty(ctor.(AbstractFunction), "prototype") and
|
prototype = MkAbstractProperty(ctor.(AbstractFunction), "prototype") and
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ class AbstractBoolean extends PrimitiveAbstractValue, TAbstractBoolean {
|
|||||||
|
|
||||||
override predicate isCoercibleToNumber() { any() }
|
override predicate isCoercibleToNumber() { any() }
|
||||||
|
|
||||||
override string toString() { result = getBooleanValue().toString() }
|
override string toString() { result = this.getBooleanValue().toString() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,7 +280,7 @@ abstract class AbstractCallable extends DefiniteAbstractValue {
|
|||||||
class AbstractFunction extends AbstractCallable, TAbstractFunction {
|
class AbstractFunction extends AbstractCallable, TAbstractFunction {
|
||||||
override Function getFunction() { this = TAbstractFunction(result) }
|
override Function getFunction() { this = TAbstractFunction(result) }
|
||||||
|
|
||||||
override AST::ValueNode getDefinition() { result = getFunction() }
|
override AST::ValueNode getDefinition() { result = this.getFunction() }
|
||||||
|
|
||||||
override boolean getBooleanValue() { result = true }
|
override boolean getBooleanValue() { result = true }
|
||||||
|
|
||||||
@@ -293,10 +293,12 @@ class AbstractFunction extends AbstractCallable, TAbstractFunction {
|
|||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string path, int startline, int startcolumn, int endline, int endcolumn
|
string path, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getFunction().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
this.getFunction()
|
||||||
|
.getLocation()
|
||||||
|
.hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = getFunction().describe() }
|
override string toString() { result = this.getFunction().describe() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -308,9 +310,9 @@ class AbstractClass extends AbstractCallable, TAbstractClass {
|
|||||||
*/
|
*/
|
||||||
ClassDefinition getClass() { this = TAbstractClass(result) }
|
ClassDefinition getClass() { this = TAbstractClass(result) }
|
||||||
|
|
||||||
override Function getFunction() { result = getClass().getConstructor().getBody() }
|
override Function getFunction() { result = this.getClass().getConstructor().getBody() }
|
||||||
|
|
||||||
override AST::ValueNode getDefinition() { result = getClass() }
|
override AST::ValueNode getDefinition() { result = this.getClass() }
|
||||||
|
|
||||||
override boolean getBooleanValue() { result = true }
|
override boolean getBooleanValue() { result = true }
|
||||||
|
|
||||||
@@ -323,10 +325,10 @@ class AbstractClass extends AbstractCallable, TAbstractClass {
|
|||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string path, int startline, int startcolumn, int endline, int endcolumn
|
string path, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getClass().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
this.getClass().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = getClass().describe() }
|
override string toString() { result = this.getClass().describe() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,10 +364,12 @@ class AbstractArguments extends DefiniteAbstractValue, TAbstractArguments {
|
|||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string path, int startline, int startcolumn, int endline, int endcolumn
|
string path, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getFunction().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
this.getFunction()
|
||||||
|
.getLocation()
|
||||||
|
.hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = "arguments object of " + getFunction().describe() }
|
override string toString() { result = "arguments object of " + this.getFunction().describe() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -401,10 +405,10 @@ class AbstractModuleObject extends DefiniteAbstractValue, TAbstractModuleObject
|
|||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string path, int startline, int startcolumn, int endline, int endcolumn
|
string path, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getModule().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
this.getModule().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = "module object of module " + getModule().getName() }
|
override string toString() { result = "module object of module " + this.getModule().getName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -425,10 +429,10 @@ class AbstractExportsObject extends DefiniteAbstractValue, TAbstractExportsObjec
|
|||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string path, int startline, int startcolumn, int endline, int endcolumn
|
string path, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getModule().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
this.getModule().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = "exports object of module " + getModule().getName() }
|
override string toString() { result = "exports object of module " + this.getModule().getName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -450,7 +454,9 @@ class AbstractObjectLiteral extends DefiniteAbstractValue, TAbstractObjectLitera
|
|||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string path, int startline, int startcolumn, int endline, int endcolumn
|
string path, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getObjectExpr().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
this.getObjectExpr()
|
||||||
|
.getLocation()
|
||||||
|
.hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = "object literal" }
|
override string toString() { result = "object literal" }
|
||||||
@@ -476,10 +482,10 @@ class AbstractInstance extends DefiniteAbstractValue, TAbstractInstance {
|
|||||||
override predicate hasLocationInfo(
|
override predicate hasLocationInfo(
|
||||||
string path, int startline, int startcolumn, int endline, int endcolumn
|
string path, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getConstructor().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
this.getConstructor().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = "instance of " + getConstructor() }
|
override string toString() { result = "instance of " + this.getConstructor() }
|
||||||
}
|
}
|
||||||
|
|
||||||
module AbstractInstance {
|
module AbstractInstance {
|
||||||
@@ -526,7 +532,7 @@ class IndefiniteFunctionOrClass extends AbstractValue, TIndefiniteFunctionOrClas
|
|||||||
}
|
}
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(DataFlow::Incompleteness cause | isIndefinite(cause) |
|
exists(DataFlow::Incompleteness cause | this.isIndefinite(cause) |
|
||||||
result = "indefinite function or class (" + cause + ")"
|
result = "indefinite function or class (" + cause + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -553,7 +559,7 @@ class IndefiniteObject extends AbstractValue, TIndefiniteObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(DataFlow::Incompleteness cause | isIndefinite(cause) |
|
exists(DataFlow::Incompleteness cause | this.isIndefinite(cause) |
|
||||||
result = "indefinite object (" + cause + ")"
|
result = "indefinite object (" + cause + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -576,7 +582,7 @@ class IndefiniteAbstractValue extends AbstractValue, TIndefiniteAbstractValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
exists(DataFlow::Incompleteness cause | isIndefinite(cause) |
|
exists(DataFlow::Incompleteness cause | this.isIndefinite(cause) |
|
||||||
result = "indefinite value (" + cause + ")"
|
result = "indefinite value (" + cause + ")"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -589,7 +595,7 @@ class IndefiniteAbstractValue extends AbstractValue, TIndefiniteAbstractValue {
|
|||||||
* set of concrete values represented by this abstract value.
|
* set of concrete values represented by this abstract value.
|
||||||
*/
|
*/
|
||||||
AbstractValue split() {
|
AbstractValue split() {
|
||||||
exists(string cause | isIndefinite(cause) |
|
exists(string cause | this.isIndefinite(cause) |
|
||||||
result = TIndefiniteFunctionOrClass(cause) or
|
result = TIndefiniteFunctionOrClass(cause) or
|
||||||
result = TIndefiniteObject(cause) or
|
result = TIndefiniteObject(cause) or
|
||||||
result = abstractValueOfType(any(PrimitiveType pt))
|
result = abstractValueOfType(any(PrimitiveType pt))
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class LocalObject extends DataFlow::SourceNode {
|
|||||||
LocalObject() {
|
LocalObject() {
|
||||||
// pragmatic limitation: object literals only
|
// pragmatic limitation: object literals only
|
||||||
this instanceof DataFlow::ObjectLiteralNode and
|
this instanceof DataFlow::ObjectLiteralNode and
|
||||||
not flowsTo(getAnEscape()) and
|
not this.flowsTo(getAnEscape()) and
|
||||||
not exposedAsReceiver(this)
|
not exposedAsReceiver(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,16 +72,16 @@ class LocalObject extends DataFlow::SourceNode {
|
|||||||
// the property is defined in the initializer,
|
// the property is defined in the initializer,
|
||||||
any(DataFlow::PropWrite write).writes(this, name, _) and
|
any(DataFlow::PropWrite write).writes(this, name, _) and
|
||||||
// and it is never deleted
|
// and it is never deleted
|
||||||
not hasDeleteWithName(name) and
|
not this.hasDeleteWithName(name) and
|
||||||
// and there is no deleted property with computed name
|
// and there is no deleted property with computed name
|
||||||
not hasDeleteWithComputedProperty()
|
not this.hasDeleteWithComputedProperty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate hasDeleteWithName(string name) {
|
private predicate hasDeleteWithName(string name) {
|
||||||
exists(DeleteExpr del, DataFlow::PropRef ref |
|
exists(DeleteExpr del, DataFlow::PropRef ref |
|
||||||
del.getOperand().flow() = ref and
|
del.getOperand().flow() = ref and
|
||||||
flowsTo(ref.getBase()) and
|
this.flowsTo(ref.getBase()) and
|
||||||
ref.getPropertyName() = name
|
ref.getPropertyName() = name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ class LocalObject extends DataFlow::SourceNode {
|
|||||||
private predicate hasDeleteWithComputedProperty() {
|
private predicate hasDeleteWithComputedProperty() {
|
||||||
exists(DeleteExpr del, DataFlow::PropRef ref |
|
exists(DeleteExpr del, DataFlow::PropRef ref |
|
||||||
del.getOperand().flow() = ref and
|
del.getOperand().flow() = ref and
|
||||||
flowsTo(ref.getBase()) and
|
this.flowsTo(ref.getBase()) and
|
||||||
not exists(ref.getPropertyName())
|
not exists(ref.getPropertyName())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,9 @@ class Refinement extends Expr instanceof RefinementCandidate {
|
|||||||
abstract private class LiteralRefinement extends RefinementCandidate, Literal {
|
abstract private class LiteralRefinement extends RefinementCandidate, Literal {
|
||||||
override SsaSourceVariable getARefinedVar() { none() }
|
override SsaSourceVariable getARefinedVar() { none() }
|
||||||
|
|
||||||
override RefinementValue eval(RefinementContext ctxt) { ctxt.appliesTo(this) and result = eval() }
|
override RefinementValue eval(RefinementContext ctxt) {
|
||||||
|
ctxt.appliesTo(this) and result = this.eval()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the refinement value that represents this literal.
|
* Gets the refinement value that represents this literal.
|
||||||
@@ -87,13 +89,13 @@ private class NullLiteralRefinement extends LiteralRefinement, NullLiteral {
|
|||||||
/** A Boolean literal, viewed as a refinement expression. */
|
/** A Boolean literal, viewed as a refinement expression. */
|
||||||
private class BoolRefinement extends LiteralRefinement, BooleanLiteral {
|
private class BoolRefinement extends LiteralRefinement, BooleanLiteral {
|
||||||
override RefinementValue eval() {
|
override RefinementValue eval() {
|
||||||
exists(boolean b | b.toString() = getValue() | result = TBoolConstant(b))
|
exists(boolean b | b.toString() = this.getValue() | result = TBoolConstant(b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A constant string, viewed as a refinement expression. */
|
/** A constant string, viewed as a refinement expression. */
|
||||||
private class StringRefinement extends LiteralRefinement, ConstantString {
|
private class StringRefinement extends LiteralRefinement, ConstantString {
|
||||||
override RefinementValue eval() { result = TStringConstant(getStringValue()) }
|
override RefinementValue eval() { result = TStringConstant(this.getStringValue()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A numeric literal, viewed as a refinement expression. */
|
/** A numeric literal, viewed as a refinement expression. */
|
||||||
@@ -108,9 +110,9 @@ abstract private class NumberRefinement extends LiteralRefinement, NumberLiteral
|
|||||||
* other integer values.
|
* other integer values.
|
||||||
*/
|
*/
|
||||||
private class IntRefinement extends NumberRefinement, NumberLiteral {
|
private class IntRefinement extends NumberRefinement, NumberLiteral {
|
||||||
IntRefinement() { getValue().toInt() = 0 }
|
IntRefinement() { this.getValue().toInt() = 0 }
|
||||||
|
|
||||||
override RefinementValue eval() { result = TIntConstant(getValue().toInt()) }
|
override RefinementValue eval() { result = TIntConstant(this.getValue().toInt()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -129,9 +131,9 @@ private class UndefinedInRefinement extends RefinementCandidate,
|
|||||||
|
|
||||||
/** A variable use, viewed as a refinement expression. */
|
/** A variable use, viewed as a refinement expression. */
|
||||||
private class VariableRefinement extends RefinementCandidate, VarUse {
|
private class VariableRefinement extends RefinementCandidate, VarUse {
|
||||||
VariableRefinement() { getVariable() instanceof SsaSourceVariable }
|
VariableRefinement() { this.getVariable() instanceof SsaSourceVariable }
|
||||||
|
|
||||||
override SsaSourceVariable getARefinedVar() { result = getVariable() }
|
override SsaSourceVariable getARefinedVar() { result = this.getVariable() }
|
||||||
|
|
||||||
override RefinementValue eval(RefinementContext ctxt) {
|
override RefinementValue eval(RefinementContext ctxt) {
|
||||||
ctxt.appliesTo(this) and
|
ctxt.appliesTo(this) and
|
||||||
@@ -141,28 +143,28 @@ private class VariableRefinement extends RefinementCandidate, VarUse {
|
|||||||
|
|
||||||
/** A parenthesized refinement expression. */
|
/** A parenthesized refinement expression. */
|
||||||
private class ParRefinement extends RefinementCandidate, ParExpr {
|
private class ParRefinement extends RefinementCandidate, ParExpr {
|
||||||
ParRefinement() { getExpression() instanceof RefinementCandidate }
|
ParRefinement() { this.getExpression() instanceof RefinementCandidate }
|
||||||
|
|
||||||
override SsaSourceVariable getARefinedVar() {
|
override SsaSourceVariable getARefinedVar() {
|
||||||
result = getExpression().(RefinementCandidate).getARefinedVar()
|
result = this.getExpression().(RefinementCandidate).getARefinedVar()
|
||||||
}
|
}
|
||||||
|
|
||||||
override RefinementValue eval(RefinementContext ctxt) {
|
override RefinementValue eval(RefinementContext ctxt) {
|
||||||
result = getExpression().(RefinementCandidate).eval(ctxt)
|
result = this.getExpression().(RefinementCandidate).eval(ctxt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A `typeof` refinement expression. */
|
/** A `typeof` refinement expression. */
|
||||||
private class TypeofRefinement extends RefinementCandidate, TypeofExpr {
|
private class TypeofRefinement extends RefinementCandidate, TypeofExpr {
|
||||||
TypeofRefinement() { getOperand() instanceof RefinementCandidate }
|
TypeofRefinement() { this.getOperand() instanceof RefinementCandidate }
|
||||||
|
|
||||||
override SsaSourceVariable getARefinedVar() {
|
override SsaSourceVariable getARefinedVar() {
|
||||||
result = getOperand().(RefinementCandidate).getARefinedVar()
|
result = this.getOperand().(RefinementCandidate).getARefinedVar()
|
||||||
}
|
}
|
||||||
|
|
||||||
override RefinementValue eval(RefinementContext ctxt) {
|
override RefinementValue eval(RefinementContext ctxt) {
|
||||||
exists(RefinementValue opVal |
|
exists(RefinementValue opVal |
|
||||||
opVal = getOperand().(RefinementCandidate).eval(ctxt) and
|
opVal = this.getOperand().(RefinementCandidate).eval(ctxt) and
|
||||||
result = TStringConstant(opVal.typeof())
|
result = TStringConstant(opVal.typeof())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -171,26 +173,26 @@ private class TypeofRefinement extends RefinementCandidate, TypeofExpr {
|
|||||||
/** An equality test that can be used as a refinement expression. */
|
/** An equality test that can be used as a refinement expression. */
|
||||||
private class EqRefinement extends RefinementCandidate, EqualityTest {
|
private class EqRefinement extends RefinementCandidate, EqualityTest {
|
||||||
EqRefinement() {
|
EqRefinement() {
|
||||||
getLeftOperand() instanceof RefinementCandidate and
|
this.getLeftOperand() instanceof RefinementCandidate and
|
||||||
getRightOperand() instanceof RefinementCandidate
|
this.getRightOperand() instanceof RefinementCandidate
|
||||||
}
|
}
|
||||||
|
|
||||||
override SsaSourceVariable getARefinedVar() {
|
override SsaSourceVariable getARefinedVar() {
|
||||||
result = getLeftOperand().(RefinementCandidate).getARefinedVar() or
|
result = this.getLeftOperand().(RefinementCandidate).getARefinedVar() or
|
||||||
result = getRightOperand().(RefinementCandidate).getARefinedVar()
|
result = this.getRightOperand().(RefinementCandidate).getARefinedVar()
|
||||||
}
|
}
|
||||||
|
|
||||||
override RefinementValue eval(RefinementContext ctxt) {
|
override RefinementValue eval(RefinementContext ctxt) {
|
||||||
exists(RefinementCandidate l, RefinementValue lv, RefinementCandidate r, RefinementValue rv |
|
exists(RefinementCandidate l, RefinementValue lv, RefinementCandidate r, RefinementValue rv |
|
||||||
l = getLeftOperand() and
|
l = this.getLeftOperand() and
|
||||||
r = getRightOperand() and
|
r = this.getRightOperand() and
|
||||||
lv = l.eval(ctxt) and
|
lv = l.eval(ctxt) and
|
||||||
rv = r.eval(ctxt)
|
rv = r.eval(ctxt)
|
||||||
|
|
|
|
||||||
// if both sides evaluate to a constant, compare them
|
// if both sides evaluate to a constant, compare them
|
||||||
if lv instanceof SingletonRefinementValue and rv instanceof SingletonRefinementValue
|
if lv instanceof SingletonRefinementValue and rv instanceof SingletonRefinementValue
|
||||||
then
|
then
|
||||||
exists(boolean s, boolean p | s = getStrictness() and p = getPolarity() |
|
exists(boolean s, boolean p | s = this.getStrictness() and p = this.getPolarity() |
|
||||||
if lv.(SingletonRefinementValue).equals(rv, s)
|
if lv.(SingletonRefinementValue).equals(rv, s)
|
||||||
then result = TBoolConstant(p)
|
then result = TBoolConstant(p)
|
||||||
else result = TBoolConstant(p.booleanNot())
|
else result = TBoolConstant(p.booleanNot())
|
||||||
@@ -209,13 +211,13 @@ private class EqRefinement extends RefinementCandidate, EqualityTest {
|
|||||||
/** An index expression that can be used as a refinement expression. */
|
/** An index expression that can be used as a refinement expression. */
|
||||||
private class IndexRefinement extends RefinementCandidate, IndexExpr {
|
private class IndexRefinement extends RefinementCandidate, IndexExpr {
|
||||||
IndexRefinement() {
|
IndexRefinement() {
|
||||||
getBase() instanceof RefinementCandidate and
|
this.getBase() instanceof RefinementCandidate and
|
||||||
getIndex() instanceof RefinementCandidate
|
this.getIndex() instanceof RefinementCandidate
|
||||||
}
|
}
|
||||||
|
|
||||||
override SsaSourceVariable getARefinedVar() {
|
override SsaSourceVariable getARefinedVar() {
|
||||||
result = getBase().(RefinementCandidate).getARefinedVar() or
|
result = this.getBase().(RefinementCandidate).getARefinedVar() or
|
||||||
result = getIndex().(RefinementCandidate).getARefinedVar()
|
result = this.getIndex().(RefinementCandidate).getARefinedVar()
|
||||||
}
|
}
|
||||||
|
|
||||||
override RefinementValue eval(RefinementContext ctxt) {
|
override RefinementValue eval(RefinementContext ctxt) {
|
||||||
@@ -223,8 +225,8 @@ private class IndexRefinement extends RefinementCandidate, IndexExpr {
|
|||||||
RefinementCandidate base, RefinementValue baseVal, RefinementCandidate index,
|
RefinementCandidate base, RefinementValue baseVal, RefinementCandidate index,
|
||||||
RefinementValue indexVal
|
RefinementValue indexVal
|
||||||
|
|
|
|
||||||
base = getBase() and
|
base = this.getBase() and
|
||||||
index = getIndex() and
|
index = this.getIndex() and
|
||||||
baseVal = base.eval(ctxt) and
|
baseVal = base.eval(ctxt) and
|
||||||
indexVal = index.eval(ctxt)
|
indexVal = index.eval(ctxt)
|
||||||
|
|
|
|
||||||
@@ -424,21 +426,21 @@ private class AnyValue extends RefinementValue, TAny {
|
|||||||
private class ValueWithType extends RefinementValue, TValueWithType {
|
private class ValueWithType extends RefinementValue, TValueWithType {
|
||||||
InferredType getType() { this = TValueWithType(result) }
|
InferredType getType() { this = TValueWithType(result) }
|
||||||
|
|
||||||
override string toString() { result = "any " + getType() }
|
override string toString() { result = "any " + this.getType() }
|
||||||
|
|
||||||
override string typeof() { result = getType().getTypeofTag() }
|
override string typeof() { result = this.getType().getTypeofTag() }
|
||||||
|
|
||||||
override boolean getABooleanValue() {
|
override boolean getABooleanValue() {
|
||||||
result = true
|
result = true
|
||||||
or
|
or
|
||||||
// only primitive types can be falsy
|
// only primitive types can be falsy
|
||||||
getType() instanceof PrimitiveType and result = false
|
this.getType() instanceof PrimitiveType and result = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An abstract value representing `null` or `undefined`. */
|
/** An abstract value representing `null` or `undefined`. */
|
||||||
private class NullOrUndefined extends ValueWithType, SingletonRefinementValue {
|
private class NullOrUndefined extends ValueWithType, SingletonRefinementValue {
|
||||||
NullOrUndefined() { getType() instanceof TTNull or getType() instanceof TTUndefined }
|
NullOrUndefined() { this.getType() instanceof TTNull or this.getType() instanceof TTUndefined }
|
||||||
|
|
||||||
override boolean getABooleanValue() { result = false }
|
override boolean getABooleanValue() { result = false }
|
||||||
|
|
||||||
@@ -501,7 +503,7 @@ private class StringConstant extends SingletonRefinementValue, TStringConstant {
|
|||||||
or
|
or
|
||||||
isStrict = false and
|
isStrict = false and
|
||||||
(
|
(
|
||||||
isEmptyOrZero() and that = TBoolConstant(false)
|
this.isEmptyOrZero() and that = TBoolConstant(false)
|
||||||
or
|
or
|
||||||
value = "1" and that = TBoolConstant(true)
|
value = "1" and that = TBoolConstant(true)
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -49,12 +49,12 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
|||||||
* Holds if this node flows into `sink` in zero or more local (that is,
|
* Holds if this node flows into `sink` in zero or more local (that is,
|
||||||
* intra-procedural) steps.
|
* intra-procedural) steps.
|
||||||
*/
|
*/
|
||||||
predicate flowsToExpr(Expr sink) { flowsTo(DataFlow::valueNode(sink)) }
|
predicate flowsToExpr(Expr sink) { this.flowsTo(DataFlow::valueNode(sink)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a node into which data may flow from this node in zero or more local steps.
|
* Gets a node into which data may flow from this node in zero or more local steps.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getALocalUse() { flowsTo(result) }
|
DataFlow::Node getALocalUse() { this.flowsTo(result) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a reference (read or write) of property `propName` on this node.
|
* Gets a reference (read or write) of property `propName` on this node.
|
||||||
@@ -66,13 +66,15 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
|||||||
/**
|
/**
|
||||||
* Gets a read of property `propName` on this node.
|
* Gets a read of property `propName` on this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::PropRead getAPropertyRead(string propName) { result = getAPropertyReference(propName) }
|
DataFlow::PropRead getAPropertyRead(string propName) {
|
||||||
|
result = this.getAPropertyReference(propName)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a write of property `propName` on this node.
|
* Gets a write of property `propName` on this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::PropWrite getAPropertyWrite(string propName) {
|
DataFlow::PropWrite getAPropertyWrite(string propName) {
|
||||||
result = getAPropertyReference(propName)
|
result = this.getAPropertyReference(propName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,7 +83,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate hasPropertyWrite(string propName, DataFlow::Node rhs) {
|
predicate hasPropertyWrite(string propName, DataFlow::Node rhs) {
|
||||||
rhs = getAPropertyWrite(propName).getRhs()
|
rhs = this.getAPropertyWrite(propName).getRhs()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,18 +98,18 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
|||||||
/**
|
/**
|
||||||
* Gets a read of any property on this node.
|
* Gets a read of any property on this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::PropRead getAPropertyRead() { result = getAPropertyReference() }
|
DataFlow::PropRead getAPropertyRead() { result = this.getAPropertyReference() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a write of any property on this node.
|
* Gets a write of any property on this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::PropWrite getAPropertyWrite() { result = getAPropertyReference() }
|
DataFlow::PropWrite getAPropertyWrite() { result = this.getAPropertyReference() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an invocation of the method or constructor named `memberName` on this node.
|
* Gets an invocation of the method or constructor named `memberName` on this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::InvokeNode getAMemberInvocation(string memberName) {
|
DataFlow::InvokeNode getAMemberInvocation(string memberName) {
|
||||||
result = getAPropertyRead(memberName).getAnInvocation()
|
result = this.getAPropertyRead(memberName).getAnInvocation()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,7 +119,9 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
|||||||
* (as in `o.m(...)`), and calls where the callee undergoes some additional
|
* (as in `o.m(...)`), and calls where the callee undergoes some additional
|
||||||
* data flow (as in `tmp = o.m; tmp(...)`).
|
* data flow (as in `tmp = o.m; tmp(...)`).
|
||||||
*/
|
*/
|
||||||
DataFlow::CallNode getAMemberCall(string memberName) { result = getAMemberInvocation(memberName) }
|
DataFlow::CallNode getAMemberCall(string memberName) {
|
||||||
|
result = this.getAMemberInvocation(memberName)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a method call that invokes method `methodName` on this node.
|
* Gets a method call that invokes method `methodName` on this node.
|
||||||
@@ -126,7 +130,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
|||||||
* that is, `o.m(...)` or `o[p](...)`.
|
* that is, `o.m(...)` or `o[p](...)`.
|
||||||
*/
|
*/
|
||||||
DataFlow::CallNode getAMethodCall(string methodName) {
|
DataFlow::CallNode getAMethodCall(string methodName) {
|
||||||
result = getAMemberInvocation(methodName) and
|
result = this.getAMemberInvocation(methodName) and
|
||||||
Cached::isSyntacticMethodCall(result)
|
Cached::isSyntacticMethodCall(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +140,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
|||||||
* This includes only calls that have the syntactic shape of a method call,
|
* This includes only calls that have the syntactic shape of a method call,
|
||||||
* that is, `o.m(...)` or `o[p](...)`.
|
* that is, `o.m(...)` or `o[p](...)`.
|
||||||
*/
|
*/
|
||||||
DataFlow::CallNode getAMethodCall() { result = getAMethodCall(_) }
|
DataFlow::CallNode getAMethodCall() { result = this.getAMethodCall(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a chained method call that invokes `methodName` last.
|
* Gets a chained method call that invokes `methodName` last.
|
||||||
@@ -146,14 +150,14 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
|||||||
*/
|
*/
|
||||||
DataFlow::CallNode getAChainedMethodCall(string methodName) {
|
DataFlow::CallNode getAChainedMethodCall(string methodName) {
|
||||||
// the direct call to `getAMethodCall` is needed in case the base is not a `DataFlow::CallNode`.
|
// the direct call to `getAMethodCall` is needed in case the base is not a `DataFlow::CallNode`.
|
||||||
result = [getAMethodCall+().getAMethodCall(methodName), getAMethodCall(methodName)]
|
result = [this.getAMethodCall+().getAMethodCall(methodName), this.getAMethodCall(methodName)]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a `new` call that invokes constructor `constructorName` on this node.
|
* Gets a `new` call that invokes constructor `constructorName` on this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::NewNode getAConstructorInvocation(string constructorName) {
|
DataFlow::NewNode getAConstructorInvocation(string constructorName) {
|
||||||
result = getAMemberInvocation(constructorName)
|
result = this.getAMemberInvocation(constructorName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -164,24 +168,24 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
|||||||
/**
|
/**
|
||||||
* Gets a function call to this node.
|
* Gets a function call to this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::CallNode getACall() { result = getAnInvocation() }
|
DataFlow::CallNode getACall() { result = this.getAnInvocation() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a `new` call to this node.
|
* Gets a `new` call to this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::NewNode getAnInstantiation() { result = getAnInvocation() }
|
DataFlow::NewNode getAnInstantiation() { result = this.getAnInvocation() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a source node whose value is stored in property `prop` of this node.
|
* Gets a source node whose value is stored in property `prop` of this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getAPropertySource(string prop) {
|
DataFlow::SourceNode getAPropertySource(string prop) {
|
||||||
result.flowsTo(getAPropertyWrite(prop).getRhs())
|
result.flowsTo(this.getAPropertyWrite(prop).getRhs())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a source node whose value is stored in a property of this node.
|
* Gets a source node whose value is stored in a property of this node.
|
||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getAPropertySource() { result.flowsTo(getAPropertyWrite().getRhs()) }
|
DataFlow::SourceNode getAPropertySource() { result.flowsTo(this.getAPropertyWrite().getRhs()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a node that this node may flow to using one heap and/or interprocedural step.
|
* Gets a node that this node may flow to using one heap and/or interprocedural step.
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class AnalyzedNode extends DataFlow::Node {
|
|||||||
* Gets another data flow node whose value flows into this node in one local step
|
* Gets another data flow node whose value flows into this node in one local step
|
||||||
* (that is, not involving global variables).
|
* (that is, not involving global variables).
|
||||||
*/
|
*/
|
||||||
AnalyzedNode localFlowPred() { result = getAPredecessor() }
|
AnalyzedNode localFlowPred() { result = this.getAPredecessor() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an abstract value that this node may evaluate to at runtime.
|
* Gets an abstract value that this node may evaluate to at runtime.
|
||||||
@@ -57,7 +57,7 @@ class AnalyzedNode extends DataFlow::Node {
|
|||||||
* instances is also performed.
|
* instances is also performed.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
AbstractValue getAValue() { result = getALocalValue() }
|
AbstractValue getAValue() { result = this.getALocalValue() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INTERNAL: Do not use.
|
* INTERNAL: Do not use.
|
||||||
@@ -76,31 +76,31 @@ class AnalyzedNode extends DataFlow::Node {
|
|||||||
// feed back the results from the (value) flow analysis into
|
// feed back the results from the (value) flow analysis into
|
||||||
// the control flow analysis, so all flow predecessors are
|
// the control flow analysis, so all flow predecessors are
|
||||||
// considered as sources
|
// considered as sources
|
||||||
result = localFlowPred().getALocalValue()
|
result = this.localFlowPred().getALocalValue()
|
||||||
or
|
or
|
||||||
// model flow that isn't captured by the data flow graph
|
// model flow that isn't captured by the data flow graph
|
||||||
exists(DataFlow::Incompleteness cause |
|
exists(DataFlow::Incompleteness cause |
|
||||||
isIncomplete(cause) and result = TIndefiniteAbstractValue(cause)
|
this.isIncomplete(cause) and result = TIndefiniteAbstractValue(cause)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a type inferred for this node. */
|
/** Gets a type inferred for this node. */
|
||||||
cached
|
cached
|
||||||
InferredType getAType() { result = getAValue().getType() }
|
InferredType getAType() { result = this.getAValue().getType() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a primitive type to which the value of this node can be coerced.
|
* Gets a primitive type to which the value of this node can be coerced.
|
||||||
*/
|
*/
|
||||||
PrimitiveType getAPrimitiveType() { result = getAValue().toPrimitive().getType() }
|
PrimitiveType getAPrimitiveType() { result = this.getAValue().toPrimitive().getType() }
|
||||||
|
|
||||||
/** Gets a Boolean value that this node evaluates to. */
|
/** Gets a Boolean value that this node evaluates to. */
|
||||||
boolean getABooleanValue() { result = getAValue().getBooleanValue() }
|
boolean getABooleanValue() { result = this.getAValue().getBooleanValue() }
|
||||||
|
|
||||||
/** Gets the unique Boolean value that this node evaluates to, if any. */
|
/** Gets the unique Boolean value that this node evaluates to, if any. */
|
||||||
boolean getTheBooleanValue() { forex(boolean bv | bv = getABooleanValue() | result = bv) }
|
boolean getTheBooleanValue() { forex(boolean bv | bv = this.getABooleanValue() | result = bv) }
|
||||||
|
|
||||||
/** Gets the unique type inferred for this node, if any. */
|
/** Gets the unique type inferred for this node, if any. */
|
||||||
InferredType getTheType() { result = unique(InferredType t | t = getAType()) }
|
InferredType getTheType() { result = unique(InferredType t | t = this.getAType()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a pretty-printed representation of all types inferred for this node
|
* Gets a pretty-printed representation of all types inferred for this node
|
||||||
@@ -110,19 +110,19 @@ class AnalyzedNode extends DataFlow::Node {
|
|||||||
* particular addition) may have more than one inferred type.
|
* particular addition) may have more than one inferred type.
|
||||||
*/
|
*/
|
||||||
string ppTypes() {
|
string ppTypes() {
|
||||||
exists(int n | n = getNumTypes() |
|
exists(int n | n = this.getNumTypes() |
|
||||||
// inferred no types
|
// inferred no types
|
||||||
n = 0 and result = ""
|
n = 0 and result = ""
|
||||||
or
|
or
|
||||||
// inferred a single type
|
// inferred a single type
|
||||||
n = 1 and result = getAType().toString()
|
n = 1 and result = this.getAType().toString()
|
||||||
or
|
or
|
||||||
// inferred all types
|
// inferred all types
|
||||||
n = count(InferredType it) and result = ppAllTypeTags()
|
n = count(InferredType it) and result = ppAllTypeTags()
|
||||||
or
|
or
|
||||||
// the general case: more than one type, but not all types
|
// the general case: more than one type, but not all types
|
||||||
// first pretty-print as a comma separated list, then replace last comma by "or"
|
// first pretty-print as a comma separated list, then replace last comma by "or"
|
||||||
result = (getType(1) + ", " + ppTypes(2)).regexpReplaceAll(", ([^,]++)$", " or $1")
|
result = (this.getType(1) + ", " + this.ppTypes(2)).regexpReplaceAll(", ([^,]++)$", " or $1")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,12 +133,12 @@ class AnalyzedNode extends DataFlow::Node {
|
|||||||
* and one less than the total number of types.
|
* and one less than the total number of types.
|
||||||
*/
|
*/
|
||||||
private string getType(int i) {
|
private string getType(int i) {
|
||||||
getNumTypes() in [2 .. count(InferredType it) - 1] and
|
this.getNumTypes() in [2 .. count(InferredType it) - 1] and
|
||||||
result = rank[i](InferredType tp | tp = getAType() | tp.toString())
|
result = rank[i](InferredType tp | tp = this.getAType() | tp.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the number of types inferred for this node. */
|
/** Gets the number of types inferred for this node. */
|
||||||
private int getNumTypes() { result = count(getAType()) }
|
private int getNumTypes() { result = count(this.getAType()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a pretty-printed comma-separated list of all types inferred for this node,
|
* Gets a pretty-printed comma-separated list of all types inferred for this node,
|
||||||
@@ -147,15 +147,15 @@ class AnalyzedNode extends DataFlow::Node {
|
|||||||
* the all-types case are handled specially above.
|
* the all-types case are handled specially above.
|
||||||
*/
|
*/
|
||||||
private string ppTypes(int i) {
|
private string ppTypes(int i) {
|
||||||
exists(int n | n = getNumTypes() and n in [2 .. count(InferredType it) - 1] |
|
exists(int n | n = this.getNumTypes() and n in [2 .. count(InferredType it) - 1] |
|
||||||
i = n and result = getType(i)
|
i = n and result = this.getType(i)
|
||||||
or
|
or
|
||||||
i in [2 .. n - 1] and result = getType(i) + ", " + ppTypes(i + 1)
|
i in [2 .. n - 1] and result = this.getType(i) + ", " + this.ppTypes(i + 1)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if the flow analysis can infer at least one abstract value for this node. */
|
/** Holds if the flow analysis can infer at least one abstract value for this node. */
|
||||||
predicate hasFlow() { exists(getAValue()) }
|
predicate hasFlow() { exists(this.getAValue()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INTERNAL. Use `isIncomplete()` instead.
|
* INTERNAL. Use `isIncomplete()` instead.
|
||||||
@@ -194,7 +194,7 @@ class AnalyzedModule extends TopLevel instanceof Module {
|
|||||||
* property.
|
* property.
|
||||||
*/
|
*/
|
||||||
AbstractProperty getExportsProperty() {
|
AbstractProperty getExportsProperty() {
|
||||||
result.getBase() = getModuleObject() and
|
result.getBase() = this.getModuleObject() and
|
||||||
result.getPropertyName() = "exports"
|
result.getPropertyName() = "exports"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,14 +202,14 @@ class AnalyzedModule extends TopLevel instanceof Module {
|
|||||||
* Gets an abstract value inferred for this module's `module.exports`
|
* Gets an abstract value inferred for this module's `module.exports`
|
||||||
* property.
|
* property.
|
||||||
*/
|
*/
|
||||||
AbstractValue getAnExportsValue() { result = getExportsProperty().getAValue() }
|
AbstractValue getAnExportsValue() { result = this.getExportsProperty().getAValue() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an abstract value representing a value exported by this module
|
* Gets an abstract value representing a value exported by this module
|
||||||
* under the given `name`.
|
* under the given `name`.
|
||||||
*/
|
*/
|
||||||
AbstractValue getAnExportedValue(string name) {
|
AbstractValue getAnExportedValue(string name) {
|
||||||
exists(AbstractValue exports | exports = getAnExportsValue() |
|
exists(AbstractValue exports | exports = this.getAnExportsValue() |
|
||||||
// CommonJS modules export `module.exports` as their `default`
|
// CommonJS modules export `module.exports` as their `default`
|
||||||
// export in an ES2015 setting
|
// export in an ES2015 setting
|
||||||
not this instanceof ES2015Module and
|
not this instanceof ES2015Module and
|
||||||
@@ -243,7 +243,7 @@ class AnalyzedFunction extends DataFlow::AnalyzedValueNode {
|
|||||||
// implicit return value
|
// implicit return value
|
||||||
(
|
(
|
||||||
// either because execution of the function may terminate normally
|
// either because execution of the function may terminate normally
|
||||||
mayReturnImplicitly()
|
this.mayReturnImplicitly()
|
||||||
or
|
or
|
||||||
// or because there is a bare `return;` statement
|
// or because there is a bare `return;` statement
|
||||||
exists(ReturnStmt ret | ret = astNode.getAReturnStmt() | not exists(ret.getExpr()))
|
exists(ReturnStmt ret | ret = astNode.getAReturnStmt() | not exists(ret.getExpr()))
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class AccessPath extends TAccessPath {
|
|||||||
/**
|
/**
|
||||||
* Gets an expression represented by this access path.
|
* Gets an expression represented by this access path.
|
||||||
*/
|
*/
|
||||||
Expr getAnInstance() { result = getAnInstanceIn(_) }
|
Expr getAnInstance() { result = this.getAnInstanceIn(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a textual representation of this access path.
|
* Gets a textual representation of this access path.
|
||||||
|
|||||||
@@ -24,21 +24,21 @@ class AnalyzedParameter extends AnalyzedValueNode {
|
|||||||
|
|
||||||
override AbstractValue getALocalValue() {
|
override AbstractValue getALocalValue() {
|
||||||
exists(DataFlow::AnalyzedNode pred |
|
exists(DataFlow::AnalyzedNode pred |
|
||||||
getFunction().argumentPassing(astNode, pred.asExpr()) and
|
this.getFunction().argumentPassing(astNode, pred.asExpr()) and
|
||||||
result = pred.getALocalValue()
|
result = pred.getALocalValue()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
not getFunction().mayReceiveArgument(astNode) and
|
not this.getFunction().mayReceiveArgument(astNode) and
|
||||||
result = TAbstractUndefined()
|
result = TAbstractUndefined()
|
||||||
or
|
or
|
||||||
result = astNode.getDefault().analyze().getALocalValue()
|
result = astNode.getDefault().analyze().getALocalValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate hasAdditionalIncompleteness(DataFlow::Incompleteness cause) {
|
override predicate hasAdditionalIncompleteness(DataFlow::Incompleteness cause) {
|
||||||
getFunction().isIncomplete(cause)
|
this.getFunction().isIncomplete(cause)
|
||||||
or
|
or
|
||||||
not getFunction().argumentPassing(astNode, _) and
|
not this.getFunction().argumentPassing(astNode, _) and
|
||||||
getFunction().mayReceiveArgument(astNode) and
|
this.getFunction().mayReceiveArgument(astNode) and
|
||||||
cause = "call"
|
cause = "call"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,9 +104,9 @@ private class AnalyzedNamespaceDeclaration extends DataFlow::AnalyzedValueNode {
|
|||||||
override NamespaceDeclaration astNode;
|
override NamespaceDeclaration astNode;
|
||||||
|
|
||||||
override AbstractValue getALocalValue() {
|
override AbstractValue getALocalValue() {
|
||||||
result = TAbstractOtherObject() and getPreviousValue().getBooleanValue() = false
|
result = TAbstractOtherObject() and this.getPreviousValue().getBooleanValue() = false
|
||||||
or
|
or
|
||||||
result = getPreviousValue() and result.getBooleanValue() = true
|
result = this.getPreviousValue() and result.getBooleanValue() = true
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractValue getPreviousValue() {
|
AbstractValue getPreviousValue() {
|
||||||
@@ -161,7 +161,7 @@ private class AnalyzedSuperCall extends DataFlow::AnalyzedValueNode {
|
|||||||
|
|
||||||
override AbstractValue getALocalValue() {
|
override AbstractValue getALocalValue() {
|
||||||
exists(MethodDefinition md, DataFlow::AnalyzedNode sup, AbstractValue supVal |
|
exists(MethodDefinition md, DataFlow::AnalyzedNode sup, AbstractValue supVal |
|
||||||
md.getBody() = asExpr().getEnclosingFunction() and
|
md.getBody() = this.asExpr().getEnclosingFunction() and
|
||||||
sup = md.getDeclaringClass().getSuperClass().analyze() and
|
sup = md.getDeclaringClass().getSuperClass().analyze() and
|
||||||
supVal = sup.getALocalValue()
|
supVal = sup.getALocalValue()
|
||||||
|
|
|
|
||||||
@@ -183,7 +183,7 @@ private class AnalyzedNewExpr extends DataFlow::AnalyzedValueNode {
|
|||||||
override NewExpr astNode;
|
override NewExpr astNode;
|
||||||
|
|
||||||
override AbstractValue getALocalValue() {
|
override AbstractValue getALocalValue() {
|
||||||
isIndefinite() and
|
this.isIndefinite() and
|
||||||
(
|
(
|
||||||
result = TIndefiniteFunctionOrClass("call") or
|
result = TIndefiniteFunctionOrClass("call") or
|
||||||
result = TIndefiniteObject("call")
|
result = TIndefiniteObject("call")
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ private class AnalyzedExportNamespaceSpecifier extends AnalyzedPropertyWrite, Da
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate writesValue(AbstractValue baseVal, string propName, AbstractValue value) {
|
override predicate writesValue(AbstractValue baseVal, string propName, AbstractValue value) {
|
||||||
baseVal = TAbstractExportsObject(getTopLevel()) and
|
baseVal = TAbstractExportsObject(this.getTopLevel()) and
|
||||||
propName = astNode.getExportedName() and
|
propName = astNode.getExportedName() and
|
||||||
value = TAbstractExportsObject(decl.getReExportedModule())
|
value = TAbstractExportsObject(decl.getReExportedModule())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ private import semmle.javascript.dataflow.LocalObjects
|
|||||||
abstract private class AnalyzedThisExpr extends DataFlow::AnalyzedNode, DataFlow::ThisNode {
|
abstract private class AnalyzedThisExpr extends DataFlow::AnalyzedNode, DataFlow::ThisNode {
|
||||||
DataFlow::FunctionNode binder;
|
DataFlow::FunctionNode binder;
|
||||||
|
|
||||||
AnalyzedThisExpr() { binder = getBinder() }
|
AnalyzedThisExpr() { binder = this.getBinder() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,7 +53,7 @@ private class AnalyzedThisInBoundFunction extends AnalyzedThisExpr {
|
|||||||
private class AnalyzedThisAsModuleExports extends DataFlow::AnalyzedNode, DataFlow::ThisNode {
|
private class AnalyzedThisAsModuleExports extends DataFlow::AnalyzedNode, DataFlow::ThisNode {
|
||||||
NodeModule m;
|
NodeModule m;
|
||||||
|
|
||||||
AnalyzedThisAsModuleExports() { m = getBindingContainer() }
|
AnalyzedThisAsModuleExports() { m = this.getBindingContainer() }
|
||||||
|
|
||||||
override AbstractValue getALocalValue() { result = TAbstractExportsObject(m) }
|
override AbstractValue getALocalValue() { result = TAbstractExportsObject(m) }
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ abstract class CallWithAnalyzedReturnFlow extends DataFlow::AnalyzedValueNode {
|
|||||||
abstract AnalyzedFunction getACallee();
|
abstract AnalyzedFunction getACallee();
|
||||||
|
|
||||||
override AbstractValue getALocalValue() {
|
override AbstractValue getALocalValue() {
|
||||||
result = getACallee().getAReturnValue() and
|
result = this.getACallee().getAReturnValue() and
|
||||||
not this instanceof DataFlow::NewNode
|
not this instanceof DataFlow::NewNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ abstract class CallWithNonLocalAnalyzedReturnFlow extends DataFlow::AnalyzedValu
|
|||||||
abstract AnalyzedFunction getACallee();
|
abstract AnalyzedFunction getACallee();
|
||||||
|
|
||||||
override AbstractValue getAValue() {
|
override AbstractValue getAValue() {
|
||||||
result = getACallee().getAReturnValue()
|
result = this.getACallee().getAReturnValue()
|
||||||
or
|
or
|
||||||
// special case from the local layer (could be more precise if it is inferred that the callee is not `null`/`undefined`)
|
// special case from the local layer (could be more precise if it is inferred that the callee is not `null`/`undefined`)
|
||||||
astNode instanceof OptionalChainRoot and
|
astNode instanceof OptionalChainRoot and
|
||||||
@@ -213,7 +213,7 @@ class LocalFunction extends Function {
|
|||||||
) and
|
) and
|
||||||
// if the function is non-strict and its `arguments` object is accessed, we
|
// if the function is non-strict and its `arguments` object is accessed, we
|
||||||
// also assume that there may be other calls (through `arguments.callee`)
|
// also assume that there may be other calls (through `arguments.callee`)
|
||||||
(isStrict() or not usesArgumentsObject())
|
(this.isStrict() or not this.usesArgumentsObject())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets an invocation of this function. */
|
/** Gets an invocation of this function. */
|
||||||
@@ -307,7 +307,7 @@ private class AnalyzedThisInPartialInvokeCallback extends AnalyzedNode, DataFlow
|
|||||||
AnalyzedThisInPartialInvokeCallback() {
|
AnalyzedThisInPartialInvokeCallback() {
|
||||||
exists(DataFlow::Node callbackArg |
|
exists(DataFlow::Node callbackArg |
|
||||||
receiver = any(DataFlow::PartialInvokeNode call).getBoundReceiver(callbackArg) and
|
receiver = any(DataFlow::PartialInvokeNode call).getBoundReceiver(callbackArg) and
|
||||||
getBinder().flowsTo(callbackArg)
|
this.getBinder().flowsTo(callbackArg)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ abstract class AnalyzedPropertyRead extends DataFlow::AnalyzedNode {
|
|||||||
abstract predicate reads(AbstractValue base, string propName);
|
abstract predicate reads(AbstractValue base, string propName);
|
||||||
|
|
||||||
override AbstractValue getAValue() {
|
override AbstractValue getAValue() {
|
||||||
result = getASourceProperty().getAValue() or
|
result = this.getASourceProperty().getAValue() or
|
||||||
result = DataFlow::AnalyzedNode.super.getAValue()
|
result = DataFlow::AnalyzedNode.super.getAValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
override AbstractValue getALocalValue() {
|
override AbstractValue getALocalValue() {
|
||||||
result = getASourceProperty().getALocalValue() or
|
result = this.getASourceProperty().getALocalValue() or
|
||||||
result = DataFlow::AnalyzedNode.super.getALocalValue()
|
result = DataFlow::AnalyzedNode.super.getALocalValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ abstract class AnalyzedPropertyRead extends DataFlow::AnalyzedNode {
|
|||||||
*/
|
*/
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private AbstractProperty getASourceProperty() {
|
private AbstractProperty getASourceProperty() {
|
||||||
exists(AbstractValue base, string prop | reads(base, prop) |
|
exists(AbstractValue base, string prop | this.reads(base, prop) |
|
||||||
result = MkAbstractProperty(base, prop)
|
result = MkAbstractProperty(base, prop)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ abstract class AnalyzedPropertyRead extends DataFlow::AnalyzedNode {
|
|||||||
override predicate isIncomplete(DataFlow::Incompleteness cause) {
|
override predicate isIncomplete(DataFlow::Incompleteness cause) {
|
||||||
super.isIncomplete(cause)
|
super.isIncomplete(cause)
|
||||||
or
|
or
|
||||||
exists(AbstractValue base | reads(base, _) | base.isIndefinite(cause))
|
exists(AbstractValue base | this.reads(base, _) | base.isIndefinite(cause))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ abstract class AnalyzedPropertyWrite extends DataFlow::Node {
|
|||||||
*/
|
*/
|
||||||
predicate writesValue(AbstractValue baseVal, string propName, AbstractValue val) {
|
predicate writesValue(AbstractValue baseVal, string propName, AbstractValue val) {
|
||||||
exists(AnalyzedNode source |
|
exists(AnalyzedNode source |
|
||||||
writes(baseVal, propName, source) and
|
this.writes(baseVal, propName, source) and
|
||||||
val = source.getALocalValue()
|
val = source.getALocalValue()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ private class AnalyzedArgumentsCallee extends AnalyzedNonNumericPropertyRead {
|
|||||||
AnalyzedArgumentsCallee() { propName = "callee" }
|
AnalyzedArgumentsCallee() { propName = "callee" }
|
||||||
|
|
||||||
override AbstractValue getALocalValue() {
|
override AbstractValue getALocalValue() {
|
||||||
exists(AbstractArguments baseVal | reads(baseVal, _) |
|
exists(AbstractArguments baseVal | this.reads(baseVal, _) |
|
||||||
result = TAbstractFunction(baseVal.getFunction())
|
result = TAbstractFunction(baseVal.getFunction())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ private class AnalyzedCapturedVariable extends @variable {
|
|||||||
* Gets an abstract value that may be assigned to this variable.
|
* Gets an abstract value that may be assigned to this variable.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
AbstractValue getALocalValue() { result = getADef().getAnAssignedValue() }
|
AbstractValue getALocalValue() { result = this.getADef().getAnAssignedValue() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a definition of this variable.
|
* Gets a definition of this variable.
|
||||||
@@ -44,7 +44,7 @@ private class AnalyzedSsaDefinitionNode extends AnalyzedNode, DataFlow::SsaDefin
|
|||||||
private class SsaDefinitionWithNonLocalFlow extends SsaExplicitDefinition {
|
private class SsaDefinitionWithNonLocalFlow extends SsaExplicitDefinition {
|
||||||
CallWithNonLocalAnalyzedReturnFlow source;
|
CallWithNonLocalAnalyzedReturnFlow source;
|
||||||
|
|
||||||
SsaDefinitionWithNonLocalFlow() { source = getDef().getSource().flow() }
|
SsaDefinitionWithNonLocalFlow() { source = this.getDef().getSource().flow() }
|
||||||
|
|
||||||
CallWithNonLocalAnalyzedReturnFlow getSource() { result = source }
|
CallWithNonLocalAnalyzedReturnFlow getSource() { result = source }
|
||||||
}
|
}
|
||||||
@@ -84,10 +84,10 @@ class AnalyzedVarDef extends VarDef {
|
|||||||
* cannot be analyzed completely.
|
* cannot be analyzed completely.
|
||||||
*/
|
*/
|
||||||
AbstractValue getAnAssignedValue() {
|
AbstractValue getAnAssignedValue() {
|
||||||
result = getAnRhsValue()
|
result = this.getAnRhsValue()
|
||||||
or
|
or
|
||||||
exists(DataFlow::Incompleteness cause |
|
exists(DataFlow::Incompleteness cause |
|
||||||
isIncomplete(cause) and result = TIndefiniteAbstractValue(cause)
|
this.isIncomplete(cause) and result = TIndefiniteAbstractValue(cause)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ class AnalyzedVarDef extends VarDef {
|
|||||||
* may evaluate to.
|
* may evaluate to.
|
||||||
*/
|
*/
|
||||||
AbstractValue getAnRhsValue() {
|
AbstractValue getAnRhsValue() {
|
||||||
result = getRhs().getALocalValue()
|
result = this.getRhs().getALocalValue()
|
||||||
or
|
or
|
||||||
this = any(ForInStmt fis).getIteratorExpr() and result = abstractValueOfType(TTString())
|
this = any(ForInStmt fis).getIteratorExpr() and result = abstractValueOfType(TTString())
|
||||||
or
|
or
|
||||||
@@ -109,7 +109,7 @@ class AnalyzedVarDef extends VarDef {
|
|||||||
* this `VarDef`.
|
* this `VarDef`.
|
||||||
*/
|
*/
|
||||||
DataFlow::AnalyzedNode getRhs() {
|
DataFlow::AnalyzedNode getRhs() {
|
||||||
result = getSource().analyze() and getTarget() instanceof VarRef
|
result = this.getSource().analyze() and this.getTarget() instanceof VarRef
|
||||||
or
|
or
|
||||||
result.asExpr() = this.(CompoundAssignExpr)
|
result.asExpr() = this.(CompoundAssignExpr)
|
||||||
or
|
or
|
||||||
@@ -132,7 +132,7 @@ class AnalyzedVarDef extends VarDef {
|
|||||||
or
|
or
|
||||||
exists(ComprehensionBlock cb | this = cb.getIterator()) and cause = "yield"
|
exists(ComprehensionBlock cb | this = cb.getIterator()) and cause = "yield"
|
||||||
or
|
or
|
||||||
getTarget() instanceof DestructuringPattern and cause = "heap"
|
this.getTarget() instanceof DestructuringPattern and cause = "heap"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -197,9 +197,9 @@ abstract class AnalyzedSsaDefinition extends SsaDefinition {
|
|||||||
*/
|
*/
|
||||||
private class AnalyzedExplicitDefinition extends AnalyzedSsaDefinition, SsaExplicitDefinition {
|
private class AnalyzedExplicitDefinition extends AnalyzedSsaDefinition, SsaExplicitDefinition {
|
||||||
override AbstractValue getAnRhsValue() {
|
override AbstractValue getAnRhsValue() {
|
||||||
result = getDef().(AnalyzedVarDef).getAnAssignedValue()
|
result = this.getDef().(AnalyzedVarDef).getAnAssignedValue()
|
||||||
or
|
or
|
||||||
result = getRhsNode().analyze().getALocalValue()
|
result = this.getRhsNode().analyze().getALocalValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ private class AnalyzedExplicitDefinition extends AnalyzedSsaDefinition, SsaExpli
|
|||||||
* Flow analysis for SSA definitions corresponding to implicit variable initialization.
|
* Flow analysis for SSA definitions corresponding to implicit variable initialization.
|
||||||
*/
|
*/
|
||||||
private class AnalyzedImplicitInit extends AnalyzedSsaDefinition, SsaImplicitInit {
|
private class AnalyzedImplicitInit extends AnalyzedSsaDefinition, SsaImplicitInit {
|
||||||
override AbstractValue getAnRhsValue() { result = getImplicitInitValue(getSourceVariable()) }
|
override AbstractValue getAnRhsValue() { result = getImplicitInitValue(this.getSourceVariable()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -215,7 +215,7 @@ private class AnalyzedImplicitInit extends AnalyzedSsaDefinition, SsaImplicitIni
|
|||||||
*/
|
*/
|
||||||
private class AnalyzedVariableCapture extends AnalyzedSsaDefinition, SsaVariableCapture {
|
private class AnalyzedVariableCapture extends AnalyzedSsaDefinition, SsaVariableCapture {
|
||||||
override AbstractValue getAnRhsValue() {
|
override AbstractValue getAnRhsValue() {
|
||||||
exists(LocalVariable v | v = getSourceVariable() |
|
exists(LocalVariable v | v = this.getSourceVariable() |
|
||||||
result = v.(AnalyzedCapturedVariable).getALocalValue()
|
result = v.(AnalyzedCapturedVariable).getALocalValue()
|
||||||
or
|
or
|
||||||
result = any(AnalyzedExplicitDefinition def | def.getSourceVariable() = v).getAnRhsValue()
|
result = any(AnalyzedExplicitDefinition def | def.getSourceVariable() = v).getAnRhsValue()
|
||||||
@@ -230,7 +230,7 @@ private class AnalyzedVariableCapture extends AnalyzedSsaDefinition, SsaVariable
|
|||||||
*/
|
*/
|
||||||
private class AnalyzedPhiNode extends AnalyzedSsaDefinition, SsaPhiNode {
|
private class AnalyzedPhiNode extends AnalyzedSsaDefinition, SsaPhiNode {
|
||||||
override AbstractValue getAnRhsValue() {
|
override AbstractValue getAnRhsValue() {
|
||||||
result = getAnInput().(AnalyzedSsaDefinition).getAnRhsValue()
|
result = this.getAnInput().(AnalyzedSsaDefinition).getAnRhsValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,14 +240,14 @@ private class AnalyzedPhiNode extends AnalyzedSsaDefinition, SsaPhiNode {
|
|||||||
class AnalyzedRefinement extends AnalyzedSsaDefinition, SsaRefinementNode {
|
class AnalyzedRefinement extends AnalyzedSsaDefinition, SsaRefinementNode {
|
||||||
override AbstractValue getAnRhsValue() {
|
override AbstractValue getAnRhsValue() {
|
||||||
// default implementation: don't refine
|
// default implementation: don't refine
|
||||||
result = getAnInputRhsValue()
|
result = this.getAnInputRhsValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an abstract value that one of the inputs of this refinement may evaluate to.
|
* Gets an abstract value that one of the inputs of this refinement may evaluate to.
|
||||||
*/
|
*/
|
||||||
AbstractValue getAnInputRhsValue() {
|
AbstractValue getAnInputRhsValue() {
|
||||||
result = getAnInput().(AnalyzedSsaDefinition).getAnRhsValue()
|
result = this.getAnInput().(AnalyzedSsaDefinition).getAnRhsValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,7 +258,7 @@ class AnalyzedRefinement extends AnalyzedSsaDefinition, SsaRefinementNode {
|
|||||||
* into sets of more precise abstract values to enable them to be refined.
|
* into sets of more precise abstract values to enable them to be refined.
|
||||||
*/
|
*/
|
||||||
class AnalyzedConditionGuard extends AnalyzedRefinement {
|
class AnalyzedConditionGuard extends AnalyzedRefinement {
|
||||||
AnalyzedConditionGuard() { getGuard() instanceof ConditionGuardNode }
|
AnalyzedConditionGuard() { this.getGuard() instanceof ConditionGuardNode }
|
||||||
|
|
||||||
override AbstractValue getAnInputRhsValue() {
|
override AbstractValue getAnInputRhsValue() {
|
||||||
exists(AbstractValue input | input = super.getAnInputRhsValue() |
|
exists(AbstractValue input | input = super.getAnInputRhsValue() |
|
||||||
@@ -276,13 +276,13 @@ class AnalyzedConditionGuard extends AnalyzedRefinement {
|
|||||||
* the beginning of `s` to those that are truthy.
|
* the beginning of `s` to those that are truthy.
|
||||||
*/
|
*/
|
||||||
class AnalyzedPositiveConditionGuard extends AnalyzedRefinement {
|
class AnalyzedPositiveConditionGuard extends AnalyzedRefinement {
|
||||||
AnalyzedPositiveConditionGuard() { getGuard().(ConditionGuardNode).getOutcome() = true }
|
AnalyzedPositiveConditionGuard() { this.getGuard().(ConditionGuardNode).getOutcome() = true }
|
||||||
|
|
||||||
override AbstractValue getAnRhsValue() {
|
override AbstractValue getAnRhsValue() {
|
||||||
result = getAnInputRhsValue() and
|
result = this.getAnInputRhsValue() and
|
||||||
exists(RefinementContext ctxt |
|
exists(RefinementContext ctxt |
|
||||||
ctxt = TVarRefinementContext(this, getSourceVariable(), result) and
|
ctxt = TVarRefinementContext(this, this.getSourceVariable(), result) and
|
||||||
getRefinement().eval(ctxt).getABooleanValue() = true
|
this.getRefinement().eval(ctxt).getABooleanValue() = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,13 +294,13 @@ class AnalyzedPositiveConditionGuard extends AnalyzedRefinement {
|
|||||||
* the beginning of `t` to those that are falsy.
|
* the beginning of `t` to those that are falsy.
|
||||||
*/
|
*/
|
||||||
class AnalyzedNegativeConditionGuard extends AnalyzedRefinement {
|
class AnalyzedNegativeConditionGuard extends AnalyzedRefinement {
|
||||||
AnalyzedNegativeConditionGuard() { getGuard().(ConditionGuardNode).getOutcome() = false }
|
AnalyzedNegativeConditionGuard() { this.getGuard().(ConditionGuardNode).getOutcome() = false }
|
||||||
|
|
||||||
override AbstractValue getAnRhsValue() {
|
override AbstractValue getAnRhsValue() {
|
||||||
result = getAnInputRhsValue() and
|
result = this.getAnInputRhsValue() and
|
||||||
exists(RefinementContext ctxt |
|
exists(RefinementContext ctxt |
|
||||||
ctxt = TVarRefinementContext(this, getSourceVariable(), result) and
|
ctxt = TVarRefinementContext(this, this.getSourceVariable(), result) and
|
||||||
getRefinement().eval(ctxt).getABooleanValue() = false
|
this.getRefinement().eval(ctxt).getABooleanValue() = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -389,7 +389,7 @@ private class AnalyzedGlobalVarUse extends DataFlow::AnalyzedValueNode {
|
|||||||
* of the global object.
|
* of the global object.
|
||||||
*/
|
*/
|
||||||
private DataFlow::PropWrite getAnAssigningPropWrite() {
|
private DataFlow::PropWrite getAnAssigningPropWrite() {
|
||||||
result.getPropertyName() = getVariableName() and
|
result.getPropertyName() = this.getVariableName() and
|
||||||
result.getBase().analyze().getALocalValue() instanceof AbstractGlobalObject
|
result.getBase().analyze().getALocalValue() instanceof AbstractGlobalObject
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +400,7 @@ private class AnalyzedGlobalVarUse extends DataFlow::AnalyzedValueNode {
|
|||||||
override AbstractValue getALocalValue() {
|
override AbstractValue getALocalValue() {
|
||||||
result = super.getALocalValue()
|
result = super.getALocalValue()
|
||||||
or
|
or
|
||||||
result = getAnAssigningPropWrite().getRhs().analyze().getALocalValue()
|
result = this.getAnAssigningPropWrite().getRhs().analyze().getALocalValue()
|
||||||
or
|
or
|
||||||
result = agv.getAnAssignedValue()
|
result = agv.getAnAssignedValue()
|
||||||
}
|
}
|
||||||
@@ -668,8 +668,8 @@ abstract private class CallWithAnalyzedParameters extends FunctionWithAnalyzedPa
|
|||||||
abstract DataFlow::InvokeNode getAnInvocation();
|
abstract DataFlow::InvokeNode getAnInvocation();
|
||||||
|
|
||||||
override predicate argumentPassing(Parameter p, Expr arg) {
|
override predicate argumentPassing(Parameter p, Expr arg) {
|
||||||
exists(DataFlow::InvokeNode invk, int argIdx | invk = getAnInvocation() |
|
exists(DataFlow::InvokeNode invk, int argIdx | invk = this.getAnInvocation() |
|
||||||
p = getParameter(argIdx) and
|
p = this.getParameter(argIdx) and
|
||||||
not p.isRestParameter() and
|
not p.isRestParameter() and
|
||||||
arg = invk.getArgument(argIdx).asExpr()
|
arg = invk.getArgument(argIdx).asExpr()
|
||||||
)
|
)
|
||||||
@@ -677,13 +677,13 @@ abstract private class CallWithAnalyzedParameters extends FunctionWithAnalyzedPa
|
|||||||
|
|
||||||
override predicate mayReceiveArgument(Parameter p) {
|
override predicate mayReceiveArgument(Parameter p) {
|
||||||
exists(int argIdx |
|
exists(int argIdx |
|
||||||
p = getParameter(argIdx) and
|
p = this.getParameter(argIdx) and
|
||||||
getAnInvocation().getNumArgument() > argIdx
|
this.getAnInvocation().getNumArgument() > argIdx
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// All parameters may receive an argument if invoked with a spread argument
|
// All parameters may receive an argument if invoked with a spread argument
|
||||||
p = getAParameter() and
|
p = this.getAParameter() and
|
||||||
getAnInvocation().asExpr().(InvokeExpr).isSpreadArgument(_)
|
this.getAnInvocation().asExpr().(InvokeExpr).isSpreadArgument(_)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ private class BackwardExploringConfiguration extends DataFlow::Configuration {
|
|||||||
override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() }
|
override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() }
|
||||||
|
|
||||||
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
|
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||||
exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) |
|
exists(DataFlow::PathNode src, DataFlow::PathNode snk | this.hasFlowPath(src, snk) |
|
||||||
source = src.getNode() and
|
source = src.getNode() and
|
||||||
sink = snk.getNode()
|
sink = snk.getNode()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ private class ForwardExploringConfiguration extends DataFlow::Configuration {
|
|||||||
override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() }
|
override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() }
|
||||||
|
|
||||||
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
|
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
|
||||||
exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) |
|
exists(DataFlow::PathNode src, DataFlow::PathNode snk | this.hasFlowPath(src, snk) |
|
||||||
source = src.getNode() and
|
source = src.getNode() and
|
||||||
sink = snk.getNode()
|
sink = snk.getNode()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -196,19 +196,19 @@ module Angular2 {
|
|||||||
this = httpClient().getAMethodCall("request") and argumentOffset = 1
|
this = httpClient().getAMethodCall("request") and argumentOffset = 1
|
||||||
or
|
or
|
||||||
this = httpClient().getAMethodCall() and
|
this = httpClient().getAMethodCall() and
|
||||||
not getMethodName() = "request" and
|
not this.getMethodName() = "request" and
|
||||||
argumentOffset = 0
|
argumentOffset = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getUrl() { result = getArgument(argumentOffset) }
|
override DataFlow::Node getUrl() { result = this.getArgument(argumentOffset) }
|
||||||
|
|
||||||
override DataFlow::Node getHost() { none() }
|
override DataFlow::Node getHost() { none() }
|
||||||
|
|
||||||
override DataFlow::Node getADataNode() {
|
override DataFlow::Node getADataNode() {
|
||||||
getMethodName() = ["patch", "post", "put"] and
|
this.getMethodName() = ["patch", "post", "put"] and
|
||||||
result = getArgument(argumentOffset + 1)
|
result = this.getArgument(argumentOffset + 1)
|
||||||
or
|
or
|
||||||
result = getOptionArgument(argumentOffset + 1, "body")
|
result = this.getOptionArgument(argumentOffset + 1, "body")
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
|
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
|
||||||
@@ -268,7 +268,7 @@ module Angular2 {
|
|||||||
DataFlow::CallNode decorator;
|
DataFlow::CallNode decorator;
|
||||||
|
|
||||||
ComponentClass() {
|
ComponentClass() {
|
||||||
decorator = getADecorator() and
|
decorator = this.getADecorator() and
|
||||||
decorator = DataFlow::moduleMember("@angular/core", "Component").getACall()
|
decorator = DataFlow::moduleMember("@angular/core", "Component").getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,9 +289,9 @@ module Angular2 {
|
|||||||
* this component.
|
* this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getFieldInputNode(string name) {
|
DataFlow::Node getFieldInputNode(string name) {
|
||||||
result = getFieldNode(name)
|
result = this.getFieldNode(name)
|
||||||
or
|
or
|
||||||
result = getInstanceMember(name, DataFlow::MemberKind::setter()).getParameter(0)
|
result = this.getInstanceMember(name, DataFlow::MemberKind::setter()).getParameter(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -299,11 +299,11 @@ module Angular2 {
|
|||||||
* of this component.
|
* of this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getFieldOutputNode(string name) {
|
DataFlow::Node getFieldOutputNode(string name) {
|
||||||
result = getFieldNode(name)
|
result = this.getFieldNode(name)
|
||||||
or
|
or
|
||||||
result = getInstanceMember(name, DataFlow::MemberKind::getter()).getReturnNode()
|
result = this.getInstanceMember(name, DataFlow::MemberKind::getter()).getReturnNode()
|
||||||
or
|
or
|
||||||
result = getInstanceMethod(name)
|
result = this.getInstanceMethod(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -312,7 +312,7 @@ module Angular2 {
|
|||||||
string getSelector() { decorator.getOptionArgument(0, "selector").mayHaveStringValue(result) }
|
string getSelector() { decorator.getOptionArgument(0, "selector").mayHaveStringValue(result) }
|
||||||
|
|
||||||
/** Gets an HTML element that instantiates this component. */
|
/** Gets an HTML element that instantiates this component. */
|
||||||
HTML::Element getATemplateInstantiation() { result.getName() = getSelector() }
|
HTML::Element getATemplateInstantiation() { result.getName() = this.getSelector() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an argument that flows into the `name` field of this component.
|
* Gets an argument that flows into the `name` field of this component.
|
||||||
@@ -323,7 +323,8 @@ module Angular2 {
|
|||||||
*/
|
*/
|
||||||
DataFlow::Node getATemplateArgument(string name) {
|
DataFlow::Node getATemplateArgument(string name) {
|
||||||
result =
|
result =
|
||||||
getAttributeValueAsNode(getATemplateInstantiation().getAttributeByName("[" + name + "]"))
|
getAttributeValueAsNode(this.getATemplateInstantiation()
|
||||||
|
.getAttributeByName("[" + name + "]"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -338,7 +339,7 @@ module Angular2 {
|
|||||||
|
|
||||||
/** Gets an element in the HTML template of this component. */
|
/** Gets an element in the HTML template of this component. */
|
||||||
HTML::Element getATemplateElement() {
|
HTML::Element getATemplateElement() {
|
||||||
result.getFile() = getTemplateFile()
|
result.getFile() = this.getTemplateFile()
|
||||||
or
|
or
|
||||||
result.getParent*() =
|
result.getParent*() =
|
||||||
HTML::getHtmlElementFromExpr(decorator.getOptionArgument(0, "template").asExpr(), _)
|
HTML::getHtmlElementFromExpr(decorator.getOptionArgument(0, "template").asExpr(), _)
|
||||||
@@ -349,7 +350,7 @@ module Angular2 {
|
|||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getATemplateVarAccess(string name) {
|
DataFlow::SourceNode getATemplateVarAccess(string name) {
|
||||||
result =
|
result =
|
||||||
getATemplateElement()
|
this.getATemplateElement()
|
||||||
.getAnAttribute()
|
.getAnAttribute()
|
||||||
.getCodeInAttribute()
|
.getCodeInAttribute()
|
||||||
.(TemplateTopLevel)
|
.(TemplateTopLevel)
|
||||||
@@ -363,14 +364,14 @@ module Angular2 {
|
|||||||
|
|
||||||
PipeClass() {
|
PipeClass() {
|
||||||
decorator = DataFlow::moduleMember("@angular/core", "Pipe").getACall() and
|
decorator = DataFlow::moduleMember("@angular/core", "Pipe").getACall() and
|
||||||
decorator = getADecorator()
|
decorator = this.getADecorator()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the value of the `name` option passed to the `@Pipe` decorator. */
|
/** Gets the value of the `name` option passed to the `@Pipe` decorator. */
|
||||||
string getPipeName() { decorator.getOptionArgument(0, "name").mayHaveStringValue(result) }
|
string getPipeName() { decorator.getOptionArgument(0, "name").mayHaveStringValue(result) }
|
||||||
|
|
||||||
/** Gets a reference to this pipe. */
|
/** Gets a reference to this pipe. */
|
||||||
DataFlow::Node getAPipeRef() { result.asExpr().(PipeRefExpr).getName() = getPipeName() }
|
DataFlow::Node getAPipeRef() { result.asExpr().(PipeRefExpr).getName() = this.getPipeName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ComponentSteps extends PreCallGraphStep {
|
private class ComponentSteps extends PreCallGraphStep {
|
||||||
@@ -413,25 +414,25 @@ module Angular2 {
|
|||||||
* attribute. There is no AST node for the implied for-of loop.
|
* attribute. There is no AST node for the implied for-of loop.
|
||||||
*/
|
*/
|
||||||
private class ForLoopAttribute extends HTML::Attribute {
|
private class ForLoopAttribute extends HTML::Attribute {
|
||||||
ForLoopAttribute() { getName() = "*ngFor" }
|
ForLoopAttribute() { this.getName() = "*ngFor" }
|
||||||
|
|
||||||
/** Gets a data-flow node holding the value being iterated over. */
|
/** Gets a data-flow node holding the value being iterated over. */
|
||||||
DataFlow::Node getIterationDomain() { result = getAttributeValueAsNode(this) }
|
DataFlow::Node getIterationDomain() { result = getAttributeValueAsNode(this) }
|
||||||
|
|
||||||
/** Gets the name of the variable holding the element of the current iteration. */
|
/** Gets the name of the variable holding the element of the current iteration. */
|
||||||
string getIteratorName() { result = getValue().regexpCapture(" *let +(\\w+).*", 1) }
|
string getIteratorName() { result = this.getValue().regexpCapture(" *let +(\\w+).*", 1) }
|
||||||
|
|
||||||
/** Gets an HTML element in which the iterator variable is in scope. */
|
/** Gets an HTML element in which the iterator variable is in scope. */
|
||||||
HTML::Element getAnElementInScope() { result.getParent*() = getElement() }
|
HTML::Element getAnElementInScope() { result.getParent*() = this.getElement() }
|
||||||
|
|
||||||
/** Gets a reference to the iterator variable. */
|
/** Gets a reference to the iterator variable. */
|
||||||
DataFlow::Node getAnIteratorAccess() {
|
DataFlow::Node getAnIteratorAccess() {
|
||||||
result =
|
result =
|
||||||
getAnElementInScope()
|
this.getAnElementInScope()
|
||||||
.getAnAttribute()
|
.getAnAttribute()
|
||||||
.getCodeInAttribute()
|
.getCodeInAttribute()
|
||||||
.(TemplateTopLevel)
|
.(TemplateTopLevel)
|
||||||
.getAVariableUse(getIteratorName())
|
.getAVariableUse(this.getIteratorName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,11 +486,11 @@ module Angular2 {
|
|||||||
* A `<mat-table>` element.
|
* A `<mat-table>` element.
|
||||||
*/
|
*/
|
||||||
class MatTableElement extends HTML::Element {
|
class MatTableElement extends HTML::Element {
|
||||||
MatTableElement() { getName() = "mat-table" }
|
MatTableElement() { this.getName() = "mat-table" }
|
||||||
|
|
||||||
/** Gets the data flow node corresponding to the `[dataSource]` attribute. */
|
/** Gets the data flow node corresponding to the `[dataSource]` attribute. */
|
||||||
DataFlow::Node getDataSourceNode() {
|
DataFlow::Node getDataSourceNode() {
|
||||||
result = getAttributeValueAsNode(getAttributeByName("[dataSource]"))
|
result = getAttributeValueAsNode(this.getAttributeByName("[dataSource]"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -506,7 +507,7 @@ module Angular2 {
|
|||||||
DataFlow::Node getARowRef() {
|
DataFlow::Node getARowRef() {
|
||||||
exists(string rowBinding |
|
exists(string rowBinding |
|
||||||
result =
|
result =
|
||||||
getATableCell(rowBinding)
|
this.getATableCell(rowBinding)
|
||||||
.getChild*()
|
.getChild*()
|
||||||
.getAnAttribute()
|
.getAnAttribute()
|
||||||
.getCodeInAttribute()
|
.getCodeInAttribute()
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ private DataFlow::CallNode angularInjector() { result = angular().getAMemberCall
|
|||||||
class InjectorInvokeCall extends DataFlow::CallNode, DependencyInjection {
|
class InjectorInvokeCall extends DataFlow::CallNode, DependencyInjection {
|
||||||
InjectorInvokeCall() { this = angularInjector().getAMemberCall("invoke") }
|
InjectorInvokeCall() { this = angularInjector().getAMemberCall("invoke") }
|
||||||
|
|
||||||
override DataFlow::Node getAnInjectableFunction() { result = getArgument(0) }
|
override DataFlow::Node getAnInjectableFunction() { result = this.getArgument(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,13 +52,13 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
|
|||||||
* Gets a node for the `name` dependency declaration.
|
* Gets a node for the `name` dependency declaration.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getADependencyDeclaration(string name) {
|
DataFlow::Node getADependencyDeclaration(string name) {
|
||||||
result = getDependencyDeclaration(_, name)
|
result = this.getDependencyDeclaration(_, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the dataflow node for the `i`th dependency declaration.
|
* Gets the dataflow node for the `i`th dependency declaration.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getDependencyDeclaration(int i) { result = getDependencyDeclaration(i, _) }
|
DataFlow::Node getDependencyDeclaration(int i) { result = this.getDependencyDeclaration(i, _) }
|
||||||
|
|
||||||
/** Gets the function underlying this injectable function. */
|
/** Gets the function underlying this injectable function. */
|
||||||
abstract DataFlow::FunctionNode asFunction();
|
abstract DataFlow::FunctionNode asFunction();
|
||||||
@@ -72,7 +72,7 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
|
|||||||
ServiceReference getAResolvedDependency(DataFlow::ParameterNode parameter) {
|
ServiceReference getAResolvedDependency(DataFlow::ParameterNode parameter) {
|
||||||
exists(string name, InjectableFunctionServiceRequest request |
|
exists(string name, InjectableFunctionServiceRequest request |
|
||||||
this = request.getAnInjectedFunction() and
|
this = request.getAnInjectedFunction() and
|
||||||
parameter = getDependencyParameter(name) and
|
parameter = this.getDependencyParameter(name) and
|
||||||
result = request.getAServiceDefinition(name)
|
result = request.getAServiceDefinition(name)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
|
|||||||
*/
|
*/
|
||||||
DataFlow::Node getCustomServiceDependency(DataFlow::ParameterNode parameter) {
|
DataFlow::Node getCustomServiceDependency(DataFlow::ParameterNode parameter) {
|
||||||
exists(CustomServiceDefinition custom |
|
exists(CustomServiceDefinition custom |
|
||||||
custom.getServiceReference() = getAResolvedDependency(parameter) and
|
custom.getServiceReference() = this.getAResolvedDependency(parameter) and
|
||||||
result = custom.getAService()
|
result = custom.getAService()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -138,7 +138,7 @@ private class FunctionWithInjectProperty extends InjectableFunction instanceof D
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::ParameterNode getDependencyParameter(string name) {
|
override DataFlow::ParameterNode getDependencyParameter(string name) {
|
||||||
exists(int i | exists(getDependencyDeclaration(i, name)) | result = super.getParameter(i))
|
exists(int i | exists(this.getDependencyDeclaration(i, name)) | result = super.getParameter(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getDependencyDeclaration(int i, string name) {
|
override DataFlow::Node getDependencyDeclaration(int i, string name) {
|
||||||
|
|||||||
@@ -37,22 +37,22 @@ module AsyncPackage {
|
|||||||
/**
|
/**
|
||||||
* Gets the array of tasks, if it can be found.
|
* Gets the array of tasks, if it can be found.
|
||||||
*/
|
*/
|
||||||
DataFlow::ArrayCreationNode getTaskArray() { result.flowsTo(getArgument(0)) }
|
DataFlow::ArrayCreationNode getTaskArray() { result.flowsTo(this.getArgument(0)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the callback to invoke after the last task in the array completes.
|
* Gets the callback to invoke after the last task in the array completes.
|
||||||
*/
|
*/
|
||||||
DataFlow::FunctionNode getFinalCallback() { result.flowsTo(getArgument(1)) }
|
DataFlow::FunctionNode getFinalCallback() { result.flowsTo(this.getArgument(1)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `n`th task, if it can be found.
|
* Gets the `n`th task, if it can be found.
|
||||||
*/
|
*/
|
||||||
DataFlow::FunctionNode getTask(int n) { result.flowsTo(getTaskArray().getElement(n)) }
|
DataFlow::FunctionNode getTask(int n) { result.flowsTo(this.getTaskArray().getElement(n)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of tasks.
|
* Gets the number of tasks.
|
||||||
*/
|
*/
|
||||||
int getNumTasks() { result = strictcount(getTaskArray().getAnElement()) }
|
int getNumTasks() { result = strictcount(this.getTaskArray().getAnElement()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,18 +80,18 @@ module AsyncPackage {
|
|||||||
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
|
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
|
||||||
// Pass results to next task
|
// Pass results to next task
|
||||||
index >= 0 and
|
index >= 0 and
|
||||||
argument = getArgument(index + 1) and
|
argument = this.getArgument(index + 1) and
|
||||||
callback = waterfall.getTask(n + 1)
|
callback = waterfall.getTask(n + 1)
|
||||||
or
|
or
|
||||||
// For the last task, pass results to the final callback
|
// For the last task, pass results to the final callback
|
||||||
index >= 1 and
|
index >= 1 and
|
||||||
n = waterfall.getNumTasks() - 1 and
|
n = waterfall.getNumTasks() - 1 and
|
||||||
argument = getArgument(index) and
|
argument = this.getArgument(index) and
|
||||||
callback = waterfall.getFinalCallback()
|
callback = waterfall.getFinalCallback()
|
||||||
or
|
or
|
||||||
// Always pass error to the final callback
|
// Always pass error to the final callback
|
||||||
index = 0 and
|
index = 0 and
|
||||||
argument = getArgument(0) and
|
argument = this.getArgument(0) and
|
||||||
callback = waterfall.getFinalCallback()
|
callback = waterfall.getFinalCallback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,17 +120,17 @@ module AsyncPackage {
|
|||||||
/**
|
/**
|
||||||
* Gets the node holding the collection being iterated over.
|
* Gets the node holding the collection being iterated over.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getCollection() { result = getArgument(0) }
|
DataFlow::Node getCollection() { result = this.getArgument(0) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node holding the function being called for each element in the collection.
|
* Gets the node holding the function being called for each element in the collection.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getIteratorCallback() { result = getArgument(getNumArgument() - 2) }
|
DataFlow::Node getIteratorCallback() { result = this.getArgument(this.getNumArgument() - 2) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node holding the function being invoked after iteration is complete.
|
* Gets the node holding the function being invoked after iteration is complete.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getFinalCallback() { result = getArgument(getNumArgument() - 1) }
|
DataFlow::Node getFinalCallback() { result = this.getArgument(this.getNumArgument() - 1) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module Babel {
|
|||||||
*/
|
*/
|
||||||
class Config extends JsonObject {
|
class Config extends JsonObject {
|
||||||
Config() {
|
Config() {
|
||||||
isTopLevel() and getJsonFile().getBaseName().matches(".babelrc%")
|
this.isTopLevel() and this.getJsonFile().getBaseName().matches(".babelrc%")
|
||||||
or
|
or
|
||||||
this = any(PackageJson pkg).getPropValue("babel")
|
this = any(PackageJson pkg).getPropValue("babel")
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ module Babel {
|
|||||||
*/
|
*/
|
||||||
JsonValue getPluginConfig(string pluginName) {
|
JsonValue getPluginConfig(string pluginName) {
|
||||||
exists(JsonArray plugins |
|
exists(JsonArray plugins |
|
||||||
plugins = getPropValue("plugins") and
|
plugins = this.getPropValue("plugins") and
|
||||||
result = plugins.getElementValue(_)
|
result = plugins.getElementValue(_)
|
||||||
|
|
|
|
||||||
result.getStringValue() = pluginName
|
result.getStringValue() = pluginName
|
||||||
@@ -34,9 +34,9 @@ module Babel {
|
|||||||
* Gets a file affected by this Babel configuration.
|
* Gets a file affected by this Babel configuration.
|
||||||
*/
|
*/
|
||||||
Container getAContainerInScope() {
|
Container getAContainerInScope() {
|
||||||
result = getJsonFile().getParentContainer()
|
result = this.getJsonFile().getParentContainer()
|
||||||
or
|
or
|
||||||
result = getAContainerInScope().getAChildContainer() and
|
result = this.getAContainerInScope().getAChildContainer() and
|
||||||
// File-relative .babelrc search stops at any package.json or .babelrc file.
|
// File-relative .babelrc search stops at any package.json or .babelrc file.
|
||||||
not result.getAChildContainer() = any(PackageJson pkg).getJsonFile() and
|
not result.getAChildContainer() = any(PackageJson pkg).getJsonFile() and
|
||||||
not result.getAChildContainer() = any(Config pkg).getJsonFile()
|
not result.getAChildContainer() = any(Config pkg).getJsonFile()
|
||||||
@@ -45,7 +45,7 @@ module Babel {
|
|||||||
/**
|
/**
|
||||||
* Holds if this configuration applies to `tl`.
|
* Holds if this configuration applies to `tl`.
|
||||||
*/
|
*/
|
||||||
predicate appliesTo(TopLevel tl) { tl.getFile() = getAContainerInScope() }
|
predicate appliesTo(TopLevel tl) { tl.getFile() = this.getAContainerInScope() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +67,7 @@ module Babel {
|
|||||||
JsonValue getOptions() { result = this.(JsonArray).getElementValue(1) }
|
JsonValue getOptions() { result = this.(JsonArray).getElementValue(1) }
|
||||||
|
|
||||||
/** Gets a named option from the option object, if present. */
|
/** Gets a named option from the option object, if present. */
|
||||||
JsonValue getOption(string name) { result = getOptions().getPropValue(name) }
|
JsonValue getOption(string name) { result = this.getOptions().getPropValue(name) }
|
||||||
|
|
||||||
/** Holds if this plugin applies to `tl`. */
|
/** Holds if this plugin applies to `tl`. */
|
||||||
predicate appliesTo(TopLevel tl) { cfg.appliesTo(tl) }
|
predicate appliesTo(TopLevel tl) { cfg.appliesTo(tl) }
|
||||||
@@ -88,11 +88,11 @@ module Babel {
|
|||||||
* Gets the root specified for the given prefix.
|
* Gets the root specified for the given prefix.
|
||||||
*/
|
*/
|
||||||
string getRoot(string prefix) {
|
string getRoot(string prefix) {
|
||||||
result = getExplicitRoot(prefix)
|
result = this.getExplicitRoot(prefix)
|
||||||
or
|
or
|
||||||
// by default, `~` is mapped to the folder containing the configuration
|
// by default, `~` is mapped to the folder containing the configuration
|
||||||
prefix = "~" and
|
prefix = "~" and
|
||||||
not exists(getExplicitRoot(prefix)) and
|
not exists(this.getExplicitRoot(prefix)) and
|
||||||
result = "."
|
result = "."
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,15 +101,15 @@ module Babel {
|
|||||||
*/
|
*/
|
||||||
private JsonObject getARootPathSpec() {
|
private JsonObject getARootPathSpec() {
|
||||||
// ["babel-plugin-root-import", <spec>]
|
// ["babel-plugin-root-import", <spec>]
|
||||||
result = getOptions() and
|
result = this.getOptions() and
|
||||||
exists(result.getPropValue("rootPathSuffix"))
|
exists(result.getPropValue("rootPathSuffix"))
|
||||||
or
|
or
|
||||||
exists(JsonArray pathSpecs |
|
exists(JsonArray pathSpecs |
|
||||||
// ["babel-plugin-root-import", [ <spec>... ] ]
|
// ["babel-plugin-root-import", [ <spec>... ] ]
|
||||||
pathSpecs = getOptions()
|
pathSpecs = this.getOptions()
|
||||||
or
|
or
|
||||||
// ["babel-plugin-root-import", { "paths": [ <spec> ... ] }]
|
// ["babel-plugin-root-import", { "paths": [ <spec> ... ] }]
|
||||||
pathSpecs = getOption("paths")
|
pathSpecs = this.getOption("paths")
|
||||||
|
|
|
|
||||||
result = pathSpecs.getElementValue(_)
|
result = pathSpecs.getElementValue(_)
|
||||||
)
|
)
|
||||||
@@ -120,7 +120,7 @@ module Babel {
|
|||||||
*/
|
*/
|
||||||
private string getExplicitRoot(string prefix) {
|
private string getExplicitRoot(string prefix) {
|
||||||
exists(JsonObject rootPathSpec |
|
exists(JsonObject rootPathSpec |
|
||||||
rootPathSpec = getARootPathSpec() and
|
rootPathSpec = this.getARootPathSpec() and
|
||||||
result = rootPathSpec.getPropStringValue("rootPathSuffix")
|
result = rootPathSpec.getPropStringValue("rootPathSuffix")
|
||||||
|
|
|
|
||||||
if exists(rootPathSpec.getPropStringValue("rootPathPrefix"))
|
if exists(rootPathSpec.getPropStringValue("rootPathPrefix"))
|
||||||
@@ -132,7 +132,7 @@ module Babel {
|
|||||||
/**
|
/**
|
||||||
* Gets the folder in which this configuration is located.
|
* Gets the folder in which this configuration is located.
|
||||||
*/
|
*/
|
||||||
Folder getFolder() { result = getJsonFile().getParentContainer() }
|
Folder getFolder() { result = this.getJsonFile().getParentContainer() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,9 +146,9 @@ module Babel {
|
|||||||
|
|
||||||
BabelRootTransformedPathExpr() {
|
BabelRootTransformedPathExpr() {
|
||||||
this instanceof PathExpr and
|
this instanceof PathExpr and
|
||||||
plugin.appliesTo(getTopLevel()) and
|
plugin.appliesTo(this.getTopLevel()) and
|
||||||
prefix = getStringValue().regexpCapture("(.)/(.*)", 1) and
|
prefix = this.getStringValue().regexpCapture("(.)/(.*)", 1) and
|
||||||
suffix = getStringValue().regexpCapture("(.)/(.*)", 2) and
|
suffix = this.getStringValue().regexpCapture("(.)/(.*)", 2) and
|
||||||
mappedPrefix = plugin.getRoot(prefix)
|
mappedPrefix = plugin.getRoot(prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ module Babel {
|
|||||||
TransformReactJsxConfig() { pluginName = "transform-react-jsx" }
|
TransformReactJsxConfig() { pluginName = "transform-react-jsx" }
|
||||||
|
|
||||||
/** Gets the name of the variable used to create JSX elements. */
|
/** Gets the name of the variable used to create JSX elements. */
|
||||||
string getJsxFactoryVariableName() { result = getOption("pragma").getStringValue() }
|
string getJsxFactoryVariableName() { result = this.getOption("pragma").getStringValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ predicate isMultiPartBundle(TopLevel tl) {
|
|||||||
* A comment that starts with '!'. Minifiers avoid removing such comments.
|
* A comment that starts with '!'. Minifiers avoid removing such comments.
|
||||||
*/
|
*/
|
||||||
class ExclamationPointComment extends Comment {
|
class ExclamationPointComment extends Comment {
|
||||||
ExclamationPointComment() { getLine(0).matches("!%") }
|
ExclamationPointComment() { this.getLine(0).matches("!%") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class FunctionCompositionCall extends DataFlow::CallNode instanceof FunctionComp
|
|||||||
DataFlow::Node getOperandNode(int i) { result = super.getOperandNode(i) }
|
DataFlow::Node getOperandNode(int i) { result = super.getOperandNode(i) }
|
||||||
|
|
||||||
/** Gets a node holding one of the functions to be composed. */
|
/** Gets a node holding one of the functions to be composed. */
|
||||||
final DataFlow::Node getAnOperandNode() { result = getOperandNode(_) }
|
final DataFlow::Node getAnOperandNode() { result = this.getOperandNode(_) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the function flowing into the `i`th function in the composition `f(g(h(...)))`.
|
* Gets the function flowing into the `i`th function in the composition `f(g(h(...)))`.
|
||||||
@@ -27,11 +27,11 @@ class FunctionCompositionCall extends DataFlow::CallNode instanceof FunctionComp
|
|||||||
* that is, `g` occurs later than `f` in `f(g(...))` but is invoked before `f`.
|
* that is, `g` occurs later than `f` in `f(g(...))` but is invoked before `f`.
|
||||||
*/
|
*/
|
||||||
final DataFlow::FunctionNode getOperandFunction(int i) {
|
final DataFlow::FunctionNode getOperandFunction(int i) {
|
||||||
result = getOperandNode(i).getALocalSource()
|
result = this.getOperandNode(i).getALocalSource()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets any of the functions being composed. */
|
/** Gets any of the functions being composed. */
|
||||||
final DataFlow::FunctionNode getAnOperandFunction() { result = getOperandFunction(_) }
|
final DataFlow::FunctionNode getAnOperandFunction() { result = this.getOperandFunction(_) }
|
||||||
|
|
||||||
/** Gets the number of functions being composed. */
|
/** Gets the number of functions being composed. */
|
||||||
int getNumOperand() { result = super.getNumOperand() }
|
int getNumOperand() { result = super.getNumOperand() }
|
||||||
@@ -65,17 +65,17 @@ module FunctionCompositionCall {
|
|||||||
abstract private class WithArrayOverloading extends Range {
|
abstract private class WithArrayOverloading extends Range {
|
||||||
/** Gets the `i`th argument to the call or the `i`th array element passed into the call. */
|
/** Gets the `i`th argument to the call or the `i`th array element passed into the call. */
|
||||||
DataFlow::Node getEffectiveArgument(int i) {
|
DataFlow::Node getEffectiveArgument(int i) {
|
||||||
result = getArgument(0).(DataFlow::ArrayCreationNode).getElement(i)
|
result = this.getArgument(0).(DataFlow::ArrayCreationNode).getElement(i)
|
||||||
or
|
or
|
||||||
not getArgument(0) instanceof DataFlow::ArrayCreationNode and
|
not this.getArgument(0) instanceof DataFlow::ArrayCreationNode and
|
||||||
result = getArgument(i)
|
result = this.getArgument(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
override int getNumOperand() {
|
override int getNumOperand() {
|
||||||
result = getArgument(0).(DataFlow::ArrayCreationNode).getSize()
|
result = this.getArgument(0).(DataFlow::ArrayCreationNode).getSize()
|
||||||
or
|
or
|
||||||
not getArgument(0) instanceof DataFlow::ArrayCreationNode and
|
not this.getArgument(0) instanceof DataFlow::ArrayCreationNode and
|
||||||
result = getNumArgument()
|
result = this.getNumArgument()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ module FunctionCompositionCall {
|
|||||||
this = LodashUnderscore::member("flowRight").getACall()
|
this = LodashUnderscore::member("flowRight").getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getOperandNode(int i) { result = getEffectiveArgument(i) }
|
override DataFlow::Node getOperandNode(int i) { result = this.getEffectiveArgument(i) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A call whose arguments are functions `f,g,h` which are composed into `h(g(f(...))` */
|
/** A call whose arguments are functions `f,g,h` which are composed into `h(g(f(...))` */
|
||||||
@@ -103,7 +103,7 @@ module FunctionCompositionCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getOperandNode(int i) {
|
override DataFlow::Node getOperandNode(int i) {
|
||||||
result = getEffectiveArgument(getNumOperand() - i - 1)
|
result = this.getEffectiveArgument(this.getNumOperand() - i - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,14 +36,14 @@ module Connect {
|
|||||||
* Gets the parameter of the route handler that contains the request object.
|
* Gets the parameter of the route handler that contains the request object.
|
||||||
*/
|
*/
|
||||||
override DataFlow::ParameterNode getRequestParameter() {
|
override DataFlow::ParameterNode getRequestParameter() {
|
||||||
result = getRouteHandlerParameter("request")
|
result = this.getRouteHandlerParameter("request")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the parameter of the route handler that contains the response object.
|
* Gets the parameter of the route handler that contains the response object.
|
||||||
*/
|
*/
|
||||||
override DataFlow::ParameterNode getResponseParameter() {
|
override DataFlow::ParameterNode getResponseParameter() {
|
||||||
result = getRouteHandlerParameter("response")
|
result = this.getRouteHandlerParameter("response")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ module Connect {
|
|||||||
ServerDefinition server;
|
ServerDefinition server;
|
||||||
|
|
||||||
RouteSetup() {
|
RouteSetup() {
|
||||||
getMethodName() = "use" and
|
this.getMethodName() = "use" and
|
||||||
(
|
(
|
||||||
// app.use(fun)
|
// app.use(fun)
|
||||||
server.ref().getAMethodCall() = this
|
server.ref().getAMethodCall() = this
|
||||||
@@ -76,14 +76,14 @@ module Connect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getARouteHandler() {
|
override DataFlow::SourceNode getARouteHandler() {
|
||||||
result = getARouteHandler(DataFlow::TypeBackTracker::end())
|
result = this.getARouteHandler(DataFlow::TypeBackTracker::end())
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataFlow::SourceNode getARouteHandler(DataFlow::TypeBackTracker t) {
|
private DataFlow::SourceNode getARouteHandler(DataFlow::TypeBackTracker t) {
|
||||||
t.start() and
|
t.start() and
|
||||||
result = getARouteHandlerNode().getALocalSource()
|
result = this.getARouteHandlerNode().getALocalSource()
|
||||||
or
|
or
|
||||||
exists(DataFlow::TypeBackTracker t2 | result = getARouteHandler(t2).backtrack(t2, t))
|
exists(DataFlow::TypeBackTracker t2 | result = this.getARouteHandler(t2).backtrack(t2, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getServer() { result = server }
|
override DataFlow::Node getServer() { result = server }
|
||||||
@@ -92,12 +92,12 @@ module Connect {
|
|||||||
* DEPRECATED: Use `getARouteHandlerNode` instead.
|
* DEPRECATED: Use `getARouteHandlerNode` instead.
|
||||||
* Gets an argument that represents a route handler being registered.
|
* Gets an argument that represents a route handler being registered.
|
||||||
*/
|
*/
|
||||||
deprecated Expr getARouteHandlerExpr() { result = getARouteHandlerNode().asExpr() }
|
deprecated Expr getARouteHandlerExpr() { result = this.getARouteHandlerNode().asExpr() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an argument that represents a route handler being registered.
|
* Gets an argument that represents a route handler being registered.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getARouteHandlerNode() { result = getAnArgument() }
|
DataFlow::Node getARouteHandlerNode() { result = this.getAnArgument() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An expression that is passed as `basicAuthConnect(<user>, <password>)`. */
|
/** An expression that is passed as `basicAuthConnect(<user>, <password>)`. */
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ abstract class EmscriptenMarkerComment extends GeneratedCodeMarkerComment { }
|
|||||||
* An `EMSCRIPTEN_START_ASM` marker comment.
|
* An `EMSCRIPTEN_START_ASM` marker comment.
|
||||||
*/
|
*/
|
||||||
class EmscriptenStartAsmComment extends EmscriptenMarkerComment {
|
class EmscriptenStartAsmComment extends EmscriptenMarkerComment {
|
||||||
EmscriptenStartAsmComment() { getText().trim() = "EMSCRIPTEN_START_ASM" }
|
EmscriptenStartAsmComment() { this.getText().trim() = "EMSCRIPTEN_START_ASM" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for EmscriptenStartAsmComment */
|
/** DEPRECATED: Alias for EmscriptenStartAsmComment */
|
||||||
@@ -24,14 +24,14 @@ deprecated class EmscriptenStartASMComment = EmscriptenStartAsmComment;
|
|||||||
* An `EMSCRIPTEN_START_FUNCS` marker comment.
|
* An `EMSCRIPTEN_START_FUNCS` marker comment.
|
||||||
*/
|
*/
|
||||||
class EmscriptenStartFuncsComment extends EmscriptenMarkerComment {
|
class EmscriptenStartFuncsComment extends EmscriptenMarkerComment {
|
||||||
EmscriptenStartFuncsComment() { getText().trim() = "EMSCRIPTEN_START_FUNCS" }
|
EmscriptenStartFuncsComment() { this.getText().trim() = "EMSCRIPTEN_START_FUNCS" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `EMSCRIPTEN_END_ASM` marker comment.
|
* An `EMSCRIPTEN_END_ASM` marker comment.
|
||||||
*/
|
*/
|
||||||
class EmscriptenEndAsmComment extends EmscriptenMarkerComment {
|
class EmscriptenEndAsmComment extends EmscriptenMarkerComment {
|
||||||
EmscriptenEndAsmComment() { getText().trim() = "EMSCRIPTEN_END_ASM" }
|
EmscriptenEndAsmComment() { this.getText().trim() = "EMSCRIPTEN_END_ASM" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for EmscriptenEndAsmComment */
|
/** DEPRECATED: Alias for EmscriptenEndAsmComment */
|
||||||
@@ -41,7 +41,7 @@ deprecated class EmscriptenEndASMComment = EmscriptenEndAsmComment;
|
|||||||
* An `EMSCRIPTEN_END_FUNCS` marker comment.
|
* An `EMSCRIPTEN_END_FUNCS` marker comment.
|
||||||
*/
|
*/
|
||||||
class EmscriptenEndFuncsComment extends EmscriptenMarkerComment {
|
class EmscriptenEndFuncsComment extends EmscriptenMarkerComment {
|
||||||
EmscriptenEndFuncsComment() { getText().trim() = "EMSCRIPTEN_END_FUNCS" }
|
EmscriptenEndFuncsComment() { this.getText().trim() = "EMSCRIPTEN_END_FUNCS" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -111,10 +111,10 @@ module ExpressLibraries {
|
|||||||
/**
|
/**
|
||||||
* Gets the expression for property `name` of the options object of this call.
|
* Gets the expression for property `name` of the options object of this call.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getOption(string name) { result = getOptionArgument(0, name) }
|
DataFlow::Node getOption(string name) { result = this.getOptionArgument(0, name) }
|
||||||
|
|
||||||
override DataFlow::Node getASecretKey() {
|
override DataFlow::Node getASecretKey() {
|
||||||
exists(DataFlow::Node secret | secret = getOption("secret") |
|
exists(DataFlow::Node secret | secret = this.getOption("secret") |
|
||||||
if exists(DataFlow::ArrayCreationNode arr | arr.flowsTo(secret))
|
if exists(DataFlow::ArrayCreationNode arr | arr.flowsTo(secret))
|
||||||
then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(secret)).getAnElement()
|
then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(secret)).getAnElement()
|
||||||
else result = secret
|
else result = secret
|
||||||
@@ -138,10 +138,10 @@ module ExpressLibraries {
|
|||||||
/**
|
/**
|
||||||
* Gets the expression for property `name` of the options object of this call.
|
* Gets the expression for property `name` of the options object of this call.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getOption(string name) { result = getOptionArgument(1, name) }
|
DataFlow::Node getOption(string name) { result = this.getOptionArgument(1, name) }
|
||||||
|
|
||||||
override DataFlow::Node getASecretKey() {
|
override DataFlow::Node getASecretKey() {
|
||||||
exists(DataFlow::Node arg0 | arg0 = getArgument(0) |
|
exists(DataFlow::Node arg0 | arg0 = this.getArgument(0) |
|
||||||
if exists(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0))
|
if exists(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0))
|
||||||
then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0)).getAnElement()
|
then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0)).getAnElement()
|
||||||
else result = arg0
|
else result = arg0
|
||||||
@@ -167,13 +167,13 @@ module ExpressLibraries {
|
|||||||
/**
|
/**
|
||||||
* Gets the expression for property `name` of the options object of this call.
|
* Gets the expression for property `name` of the options object of this call.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getOption(string name) { result = getOptionArgument(0, name) }
|
DataFlow::Node getOption(string name) { result = this.getOptionArgument(0, name) }
|
||||||
|
|
||||||
override DataFlow::Node getASecretKey() {
|
override DataFlow::Node getASecretKey() {
|
||||||
result = getOption("secret")
|
result = this.getOption("secret")
|
||||||
or
|
or
|
||||||
exists(DataFlow::ArrayCreationNode keys |
|
exists(DataFlow::ArrayCreationNode keys |
|
||||||
keys.flowsTo(getOption("keys")) and
|
keys.flowsTo(this.getOption("keys")) and
|
||||||
result = keys.getAnElement()
|
result = keys.getAnElement()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -213,14 +213,14 @@ module ExpressLibraries {
|
|||||||
*/
|
*/
|
||||||
predicate isExtendedUrlEncoded() {
|
predicate isExtendedUrlEncoded() {
|
||||||
kind = "urlencoded" and
|
kind = "urlencoded" and
|
||||||
not getOptionArgument(0, "extended").mayHaveBooleanValue(false)
|
not this.getOptionArgument(0, "extended").mayHaveBooleanValue(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this parses the input as JSON or extended URL-encoding, resulting
|
* Holds if this parses the input as JSON or extended URL-encoding, resulting
|
||||||
* in user-controlled objects (as opposed to user-controlled strings).
|
* in user-controlled objects (as opposed to user-controlled strings).
|
||||||
*/
|
*/
|
||||||
predicate producesUserControlledObjects() { isJson() or isExtendedUrlEncoded() }
|
predicate producesUserControlledObjects() { this.isJson() or this.isExtendedUrlEncoded() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ module FileUpload {
|
|||||||
this = filesRef(_, DataFlow::TypeTracker::end()).getAPropertyRead().getAMethodCall("mv")
|
this = filesRef(_, DataFlow::TypeTracker::end()).getAPropertyRead().getAMethodCall("mv")
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
|
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override DataFlow::Node getADataNode() { none() }
|
override DataFlow::Node getADataNode() { none() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import javascript
|
|||||||
* A `$gwt_version` variable.
|
* A `$gwt_version` variable.
|
||||||
*/
|
*/
|
||||||
class GwtVersionVariable extends GlobalVariable {
|
class GwtVersionVariable extends GlobalVariable {
|
||||||
GwtVersionVariable() { getName() = "$gwt_version" }
|
GwtVersionVariable() { this.getName() = "$gwt_version" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for GwtVersionVariable */
|
/** DEPRECATED: Alias for GwtVersionVariable */
|
||||||
@@ -33,7 +33,7 @@ class GwtHeader extends InlineScript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for getGwtVersion */
|
/** DEPRECATED: Alias for getGwtVersion */
|
||||||
deprecated string getGWTVersion() { result = getGwtVersion() }
|
deprecated string getGWTVersion() { result = this.getGwtVersion() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for GwtHeader */
|
/** DEPRECATED: Alias for GwtHeader */
|
||||||
@@ -43,7 +43,7 @@ deprecated class GWTHeader = GwtHeader;
|
|||||||
* A toplevel in a file that appears to be GWT-generated.
|
* A toplevel in a file that appears to be GWT-generated.
|
||||||
*/
|
*/
|
||||||
class GwtGeneratedTopLevel extends TopLevel {
|
class GwtGeneratedTopLevel extends TopLevel {
|
||||||
GwtGeneratedTopLevel() { exists(GwtHeader h | getFile() = h.getFile()) }
|
GwtGeneratedTopLevel() { exists(GwtHeader h | this.getFile() = h.getFile()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DEPRECATED: Alias for GwtGeneratedTopLevel */
|
/** DEPRECATED: Alias for GwtGeneratedTopLevel */
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ private module HttpProxy {
|
|||||||
.getACall()
|
.getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getUrl() { result = getParameter(0).getMember("target").asSink() }
|
override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("target").asSink() }
|
||||||
|
|
||||||
override DataFlow::Node getHost() {
|
override DataFlow::Node getHost() {
|
||||||
result = getParameter(0).getMember("target").getMember("host").asSink()
|
result = this.getParameter(0).getMember("target").getMember("host").asSink()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getADataNode() { none() }
|
override DataFlow::Node getADataNode() { none() }
|
||||||
@@ -45,14 +45,16 @@ private module HttpProxy {
|
|||||||
or
|
or
|
||||||
method = "ws" and optionsIndex = 3
|
method = "ws" and optionsIndex = 3
|
||||||
|
|
|
|
||||||
result = getParameter(optionsIndex)
|
result = this.getParameter(optionsIndex)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getUrl() { result = getOptionsObject().getMember("target").asSink() }
|
override DataFlow::Node getUrl() {
|
||||||
|
result = this.getOptionsObject().getMember("target").asSink()
|
||||||
|
}
|
||||||
|
|
||||||
override DataFlow::Node getHost() {
|
override DataFlow::Node getHost() {
|
||||||
result = getOptionsObject().getMember("target").getMember("host").asSink()
|
result = this.getOptionsObject().getMember("target").getMember("host").asSink()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getADataNode() { none() }
|
override DataFlow::Node getADataNode() { none() }
|
||||||
@@ -84,11 +86,11 @@ private module HttpProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::ParameterNode getRequestParameter() {
|
override DataFlow::ParameterNode getRequestParameter() {
|
||||||
exists(int req | routeHandlingEventHandler(event, req, _) | result = getParameter(req))
|
exists(int req | routeHandlingEventHandler(event, req, _) | result = this.getParameter(req))
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::ParameterNode getResponseParameter() {
|
override DataFlow::ParameterNode getResponseParameter() {
|
||||||
exists(int res | routeHandlingEventHandler(event, _, res) | result = getParameter(res))
|
exists(int res | routeHandlingEventHandler(event, _, res) | result = this.getParameter(res))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ private class LodashCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode:
|
|||||||
LodashCallbackAsPartialInvoke() {
|
LodashCallbackAsPartialInvoke() {
|
||||||
exists(string name, int argumentCount |
|
exists(string name, int argumentCount |
|
||||||
this = LodashUnderscore::member(name).getACall() and
|
this = LodashUnderscore::member(name).getACall() and
|
||||||
getNumArgument() = argumentCount
|
this.getNumArgument() = argumentCount
|
||||||
|
|
|
|
||||||
name = ["bind", "callback", "iteratee"] and
|
name = ["bind", "callback", "iteratee"] and
|
||||||
callbackIndex = 0 and
|
callbackIndex = 0 and
|
||||||
@@ -219,7 +219,7 @@ private class LodashCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode:
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
||||||
callback = getArgument(callbackIndex) and
|
callback = this.getArgument(callbackIndex) and
|
||||||
result = getArgument(contextIndex)
|
result = this.getArgument(contextIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,11 +63,11 @@ private module Console {
|
|||||||
override DataFlow::Node getAMessageComponent() {
|
override DataFlow::Node getAMessageComponent() {
|
||||||
(
|
(
|
||||||
if name = "assert"
|
if name = "assert"
|
||||||
then result = getArgument([1 .. getNumArgument()])
|
then result = this.getArgument([1 .. this.getNumArgument()])
|
||||||
else result = getAnArgument()
|
else result = this.getAnArgument()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
result = getASpreadArgument()
|
result = this.getASpreadArgument()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,7 +89,7 @@ private module Loglevel {
|
|||||||
this = API::moduleImport("loglevel").getMember(getAStandardLoggerMethodName()).getACall()
|
this = API::moduleImport("loglevel").getMember(getAStandardLoggerMethodName()).getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAMessageComponent() { result = getAnArgument() }
|
override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,9 +111,9 @@ private module Winston {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAMessageComponent() {
|
override DataFlow::Node getAMessageComponent() {
|
||||||
if getMethodName() = "log"
|
if this.getMethodName() = "log"
|
||||||
then result = getOptionArgument(0, "message")
|
then result = this.getOptionArgument(0, "message")
|
||||||
else result = getAnArgument()
|
else result = this.getAnArgument()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ private module Log4js {
|
|||||||
.getACall()
|
.getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAMessageComponent() { result = getAnArgument() }
|
override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,11 +157,11 @@ private module Npmlog {
|
|||||||
override DataFlow::Node getAMessageComponent() {
|
override DataFlow::Node getAMessageComponent() {
|
||||||
(
|
(
|
||||||
if name = "log"
|
if name = "log"
|
||||||
then result = getArgument([1 .. getNumArgument()])
|
then result = this.getArgument([1 .. this.getNumArgument()])
|
||||||
else result = getAnArgument()
|
else result = this.getAnArgument()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
result = getASpreadArgument()
|
result = this.getASpreadArgument()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,7 @@ private module Fancylog {
|
|||||||
this = API::moduleImport("fancy-log").getACall()
|
this = API::moduleImport("fancy-log").getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAMessageComponent() { result = getAnArgument() }
|
override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ private module Fancylog {
|
|||||||
private class DebugLoggerCall extends LoggerCall, API::CallNode {
|
private class DebugLoggerCall extends LoggerCall, API::CallNode {
|
||||||
DebugLoggerCall() { this = API::moduleImport("debug").getReturn().getACall() }
|
DebugLoggerCall() { this = API::moduleImport("debug").getReturn().getACall() }
|
||||||
|
|
||||||
override DataFlow::Node getAMessageComponent() { result = getAnArgument() }
|
override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -293,11 +293,11 @@ class KleurStep extends TaintTracking::SharedTaintStep {
|
|||||||
private API::Node kleurInstance() {
|
private API::Node kleurInstance() {
|
||||||
result = API::moduleImport("kleur")
|
result = API::moduleImport("kleur")
|
||||||
or
|
or
|
||||||
result = kleurInstance().getAMember().getReturn()
|
result = this.kleurInstance().getAMember().getReturn()
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) {
|
override predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||||
exists(API::CallNode call | call = kleurInstance().getAMember().getACall() |
|
exists(API::CallNode call | call = this.kleurInstance().getAMember().getACall() |
|
||||||
pred = call.getArgument(0) and
|
pred = call.getArgument(0) and
|
||||||
succ = call
|
succ = call
|
||||||
)
|
)
|
||||||
@@ -363,7 +363,7 @@ private module Pino {
|
|||||||
this = pino().getMember(["trace", "debug", "info", "warn", "error", "fatal"]).getACall()
|
this = pino().getMember(["trace", "debug", "info", "warn", "error", "fatal"]).getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAMessageComponent() { result = getAnArgument() }
|
override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ private module Micro {
|
|||||||
override string getKind() { result = "body" }
|
override string getKind() { result = "body" }
|
||||||
|
|
||||||
override Http::RouteHandler getRouteHandler() {
|
override Http::RouteHandler getRouteHandler() {
|
||||||
result = getRouteHandlerFromReqRes(getArgument(0))
|
result = getRouteHandlerFromReqRes(this.getArgument(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isUserControlledObject() { name = "json" }
|
override predicate isUserControlledObject() { name = "json" }
|
||||||
|
|||||||
@@ -114,9 +114,9 @@ private class SimplePropertyProjection extends PropertyProjection::Range {
|
|||||||
this = getASimplePropertyProjectionCallee(singleton, selectorIndex, objectIndex).getACall()
|
this = getASimplePropertyProjectionCallee(singleton, selectorIndex, objectIndex).getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getObject() { result = getArgument(objectIndex) }
|
override DataFlow::Node getObject() { result = this.getArgument(objectIndex) }
|
||||||
|
|
||||||
override DataFlow::Node getASelector() { result = getArgument(selectorIndex) }
|
override DataFlow::Node getASelector() { result = this.getArgument(selectorIndex) }
|
||||||
|
|
||||||
override predicate isSingletonProjection() { singleton = true }
|
override predicate isSingletonProjection() { singleton = true }
|
||||||
}
|
}
|
||||||
@@ -127,9 +127,9 @@ private class SimplePropertyProjection extends PropertyProjection::Range {
|
|||||||
private class VarArgsPropertyProjection extends PropertyProjection::Range {
|
private class VarArgsPropertyProjection extends PropertyProjection::Range {
|
||||||
VarArgsPropertyProjection() { this = LodashUnderscore::member("pick").getACall() }
|
VarArgsPropertyProjection() { this = LodashUnderscore::member("pick").getACall() }
|
||||||
|
|
||||||
override DataFlow::Node getObject() { result = getArgument(0) }
|
override DataFlow::Node getObject() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override DataFlow::Node getASelector() { result = getArgument(any(int i | i > 0)) }
|
override DataFlow::Node getASelector() { result = this.getArgument(any(int i | i > 0)) }
|
||||||
|
|
||||||
override predicate isSingletonProjection() { none() }
|
override predicate isSingletonProjection() { none() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ module Puppeteer {
|
|||||||
private class PuppeteerGotoCall extends ClientRequest::Range, API::InvokeNode {
|
private class PuppeteerGotoCall extends ClientRequest::Range, API::InvokeNode {
|
||||||
PuppeteerGotoCall() { this = page().getMember("goto").getACall() }
|
PuppeteerGotoCall() { this = page().getMember("goto").getACall() }
|
||||||
|
|
||||||
override DataFlow::Node getUrl() { result = getArgument(0) }
|
override DataFlow::Node getUrl() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override DataFlow::Node getHost() { none() }
|
override DataFlow::Node getHost() { none() }
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ module Puppeteer {
|
|||||||
this = page().getMember(["addStyleTag", "addScriptTag"]).getACall()
|
this = page().getMember(["addStyleTag", "addScriptTag"]).getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getUrl() { result = getParameter(0).getMember("url").asSink() }
|
override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("url").asSink() }
|
||||||
|
|
||||||
override DataFlow::Node getHost() { none() }
|
override DataFlow::Node getHost() { none() }
|
||||||
|
|
||||||
|
|||||||
@@ -53,18 +53,18 @@ abstract class ReactComponent extends AstNode {
|
|||||||
* Gets a reference to an instance of this component.
|
* Gets a reference to an instance of this component.
|
||||||
*/
|
*/
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
DataFlow::SourceNode getAnInstanceReference() { result = ref() }
|
DataFlow::SourceNode getAnInstanceReference() { result = this.ref() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a reference to this component.
|
* Gets a reference to this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node ref() { result.analyze().getAValue() = getAbstractComponent() }
|
DataFlow::Node ref() { result.analyze().getAValue() = this.getAbstractComponent() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `this` node in an instance method of this component.
|
* Gets the `this` node in an instance method of this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getAThisNode() {
|
DataFlow::SourceNode getAThisNode() {
|
||||||
result.(DataFlow::ThisNode).getBinder().getFunction() = getInstanceMethod(_)
|
result.(DataFlow::ThisNode).getBinder().getFunction() = this.getInstanceMethod(_)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -76,19 +76,19 @@ abstract class ReactComponent extends AstNode {
|
|||||||
* Gets an access to the `state` object of this component.
|
* Gets an access to the `state` object of this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getADirectStateAccess() {
|
DataFlow::SourceNode getADirectStateAccess() {
|
||||||
result = getAnInstanceReference().getAPropertyReference("state")
|
result = this.getAnInstanceReference().getAPropertyReference("state")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a data flow node that reads a prop of this component.
|
* Gets a data flow node that reads a prop of this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::PropRead getAPropRead() { result = getADirectPropsAccess().getAPropertyRead() }
|
DataFlow::PropRead getAPropRead() { result = this.getADirectPropsAccess().getAPropertyRead() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a data flow node that reads prop `name` of this component.
|
* Gets a data flow node that reads prop `name` of this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::PropRead getAPropRead(string name) {
|
DataFlow::PropRead getAPropRead(string name) {
|
||||||
result = getADirectPropsAccess().getAPropertyRead(name)
|
result = this.getADirectPropsAccess().getAPropertyRead(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,16 +96,16 @@ abstract class ReactComponent extends AstNode {
|
|||||||
* of the state object of this component.
|
* of the state object of this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getAStateAccess() {
|
DataFlow::SourceNode getAStateAccess() {
|
||||||
result = getADirectStateAccess()
|
result = this.getADirectStateAccess()
|
||||||
or
|
or
|
||||||
result = getAStateAccess().getAPropertyReference()
|
result = this.getAStateAccess().getAPropertyReference()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this component specifies default values for (some of) its
|
* Holds if this component specifies default values for (some of) its
|
||||||
* props.
|
* props.
|
||||||
*/
|
*/
|
||||||
predicate hasDefaultProps() { exists(getADefaultPropsSource()) }
|
predicate hasDefaultProps() { exists(this.getADefaultPropsSource()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the object that specifies default values for (some of) this
|
* Gets the object that specifies default values for (some of) this
|
||||||
@@ -116,13 +116,13 @@ abstract class ReactComponent extends AstNode {
|
|||||||
/**
|
/**
|
||||||
* Gets the render method of this component.
|
* Gets the render method of this component.
|
||||||
*/
|
*/
|
||||||
Function getRenderMethod() { result = getInstanceMethod("render") }
|
Function getRenderMethod() { result = this.getInstanceMethod("render") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a call to method `name` on this component.
|
* Gets a call to method `name` on this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::MethodCallNode getAMethodCall(string name) {
|
DataFlow::MethodCallNode getAMethodCall(string name) {
|
||||||
result = getAnInstanceReference().getAMethodCall(name)
|
result = this.getAnInstanceReference().getAMethodCall(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,11 +131,11 @@ abstract class ReactComponent extends AstNode {
|
|||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getACandidateStateSource() {
|
DataFlow::SourceNode getACandidateStateSource() {
|
||||||
// a direct definition: `this.state = o`
|
// a direct definition: `this.state = o`
|
||||||
result = getAnInstanceReference().getAPropertySource("state")
|
result = this.getAnInstanceReference().getAPropertySource("state")
|
||||||
or
|
or
|
||||||
exists(DataFlow::MethodCallNode mce, DataFlow::SourceNode arg0 |
|
exists(DataFlow::MethodCallNode mce, DataFlow::SourceNode arg0 |
|
||||||
mce = getAMethodCall("setState") or
|
mce = this.getAMethodCall("setState") or
|
||||||
mce = getAMethodCall("forceUpdate")
|
mce = this.getAMethodCall("forceUpdate")
|
||||||
|
|
|
|
||||||
arg0.flowsTo(mce.getArgument(0)) and
|
arg0.flowsTo(mce.getArgument(0)) and
|
||||||
if arg0 instanceof DataFlow::FunctionNode
|
if arg0 instanceof DataFlow::FunctionNode
|
||||||
@@ -151,11 +151,12 @@ abstract class ReactComponent extends AstNode {
|
|||||||
staticMember = "getDerivedStateFromProps" or
|
staticMember = "getDerivedStateFromProps" or
|
||||||
staticMember = "getDerivedStateFromError"
|
staticMember = "getDerivedStateFromError"
|
||||||
|
|
|
|
||||||
result.flowsToExpr(getStaticMethod(staticMember).getAReturnedExpr())
|
result.flowsToExpr(this.getStaticMethod(staticMember).getAReturnedExpr())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// shouldComponentUpdate: (nextProps, nextState)
|
// shouldComponentUpdate: (nextProps, nextState)
|
||||||
result = DataFlow::parameterNode(getInstanceMethod("shouldComponentUpdate").getParameter(1))
|
result =
|
||||||
|
DataFlow::parameterNode(this.getInstanceMethod("shouldComponentUpdate").getParameter(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,19 +170,19 @@ abstract class ReactComponent extends AstNode {
|
|||||||
callback.getParameter(stateParameterIndex).flowsTo(result)
|
callback.getParameter(stateParameterIndex).flowsTo(result)
|
||||||
|
|
|
|
||||||
// setState: (prevState, props)
|
// setState: (prevState, props)
|
||||||
callback = getAMethodCall("setState").getCallback(0) and
|
callback = this.getAMethodCall("setState").getCallback(0) and
|
||||||
stateParameterIndex = 0
|
stateParameterIndex = 0
|
||||||
or
|
or
|
||||||
stateParameterIndex = 1 and
|
stateParameterIndex = 1 and
|
||||||
(
|
(
|
||||||
// componentDidUpdate: (prevProps, prevState)
|
// componentDidUpdate: (prevProps, prevState)
|
||||||
callback = getInstanceMethod("componentDidUpdate").flow()
|
callback = this.getInstanceMethod("componentDidUpdate").flow()
|
||||||
or
|
or
|
||||||
// getDerivedStateFromProps: (props, state)
|
// getDerivedStateFromProps: (props, state)
|
||||||
callback = getStaticMethod("getDerivedStateFromProps").flow()
|
callback = this.getStaticMethod("getDerivedStateFromProps").flow()
|
||||||
or
|
or
|
||||||
// getSnapshotBeforeUpdate: (prevProps, prevState)
|
// getSnapshotBeforeUpdate: (prevProps, prevState)
|
||||||
callback = getInstanceMethod("getSnapshotBeforeUpdate").flow()
|
callback = this.getInstanceMethod("getSnapshotBeforeUpdate").flow()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -192,12 +193,13 @@ abstract class ReactComponent extends AstNode {
|
|||||||
* constructor of this component.
|
* constructor of this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::SourceNode getACandidatePropsSource() {
|
DataFlow::SourceNode getACandidatePropsSource() {
|
||||||
result.flowsTo(getAComponentCreatorReference().getAnInvocation().getArgument(0))
|
result.flowsTo(this.getAComponentCreatorReference().getAnInvocation().getArgument(0))
|
||||||
or
|
or
|
||||||
result = getADefaultPropsSource()
|
result = this.getADefaultPropsSource()
|
||||||
or
|
or
|
||||||
// shouldComponentUpdate: (nextProps, nextState)
|
// shouldComponentUpdate: (nextProps, nextState)
|
||||||
result = DataFlow::parameterNode(getInstanceMethod("shouldComponentUpdate").getParameter(0))
|
result =
|
||||||
|
DataFlow::parameterNode(this.getInstanceMethod("shouldComponentUpdate").getParameter(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,7 +208,7 @@ abstract class ReactComponent extends AstNode {
|
|||||||
* element that instantiates this component.
|
* element that instantiates this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getACandidatePropsValue(string name) {
|
DataFlow::Node getACandidatePropsValue(string name) {
|
||||||
getACandidatePropsSource().hasPropertyWrite(name, result)
|
this.getACandidatePropsSource().hasPropertyWrite(name, result)
|
||||||
or
|
or
|
||||||
exists(ReactJsxElement e, JsxAttribute attr |
|
exists(ReactJsxElement e, JsxAttribute attr |
|
||||||
this = e.getComponent() and
|
this = e.getComponent() and
|
||||||
@@ -226,19 +228,19 @@ abstract class ReactComponent extends AstNode {
|
|||||||
callback.getParameter(propsParameterIndex).flowsTo(result)
|
callback.getParameter(propsParameterIndex).flowsTo(result)
|
||||||
|
|
|
|
||||||
// setState: (prevState, props)
|
// setState: (prevState, props)
|
||||||
callback = getAMethodCall("setState").getCallback(0) and
|
callback = this.getAMethodCall("setState").getCallback(0) and
|
||||||
propsParameterIndex = 1
|
propsParameterIndex = 1
|
||||||
or
|
or
|
||||||
propsParameterIndex = 0 and
|
propsParameterIndex = 0 and
|
||||||
(
|
(
|
||||||
// componentDidUpdate: (prevProps, prevState)
|
// componentDidUpdate: (prevProps, prevState)
|
||||||
callback = getInstanceMethod("componentDidUpdate").flow()
|
callback = this.getInstanceMethod("componentDidUpdate").flow()
|
||||||
or
|
or
|
||||||
// getDerivedStateFromProps: (props, state)
|
// getDerivedStateFromProps: (props, state)
|
||||||
callback = getStaticMethod("getDerivedStateFromProps").flow()
|
callback = this.getStaticMethod("getDerivedStateFromProps").flow()
|
||||||
or
|
or
|
||||||
// getSnapshotBeforeUpdate: (prevProps, prevState)
|
// getSnapshotBeforeUpdate: (prevProps, prevState)
|
||||||
callback = getInstanceMethod("getSnapshotBeforeUpdate").flow()
|
callback = this.getInstanceMethod("getSnapshotBeforeUpdate").flow()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -266,8 +268,8 @@ class FunctionalComponent extends ReactComponent, Function {
|
|||||||
// heuristic: a function with a single parameter named `props`
|
// heuristic: a function with a single parameter named `props`
|
||||||
// that always returns a JSX element or fragment, or a React
|
// that always returns a JSX element or fragment, or a React
|
||||||
// element is probably a component
|
// element is probably a component
|
||||||
getNumParameter() = 1 and
|
this.getNumParameter() = 1 and
|
||||||
exists(Parameter p | p = getParameter(0) |
|
exists(Parameter p | p = this.getParameter(0) |
|
||||||
p.getName().regexpMatch("(?i).*props.*") or
|
p.getName().regexpMatch("(?i).*props.*") or
|
||||||
p instanceof ObjectPattern
|
p instanceof ObjectPattern
|
||||||
) and
|
) and
|
||||||
@@ -279,7 +281,7 @@ class FunctionalComponent extends ReactComponent, Function {
|
|||||||
override Function getStaticMethod(string name) { none() }
|
override Function getStaticMethod(string name) { none() }
|
||||||
|
|
||||||
override DataFlow::SourceNode getADirectPropsAccess() {
|
override DataFlow::SourceNode getADirectPropsAccess() {
|
||||||
result = DataFlow::parameterNode(getParameter(0))
|
result = DataFlow::parameterNode(this.getParameter(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) }
|
override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) }
|
||||||
@@ -288,11 +290,11 @@ class FunctionalComponent extends ReactComponent, Function {
|
|||||||
t.start() and
|
t.start() and
|
||||||
result = DataFlow::valueNode(this)
|
result = DataFlow::valueNode(this)
|
||||||
or
|
or
|
||||||
exists(DataFlow::TypeTracker t2 | result = getAComponentCreatorReference(t2).track(t2, t))
|
exists(DataFlow::TypeTracker t2 | result = this.getAComponentCreatorReference(t2).track(t2, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getAComponentCreatorReference() {
|
override DataFlow::SourceNode getAComponentCreatorReference() {
|
||||||
result = getAComponentCreatorReference(DataFlow::TypeTracker::end())
|
result = this.getAComponentCreatorReference(DataFlow::TypeTracker::end())
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getComponentCreatorSource() { result = DataFlow::valueNode(this) }
|
override DataFlow::SourceNode getComponentCreatorSource() { result = DataFlow::valueNode(this) }
|
||||||
@@ -315,16 +317,16 @@ abstract private class SharedReactPreactClassComponent extends ReactComponent, C
|
|||||||
|
|
||||||
override Function getStaticMethod(string name) {
|
override Function getStaticMethod(string name) {
|
||||||
exists(MethodDeclaration decl |
|
exists(MethodDeclaration decl |
|
||||||
decl = getMethod(name) and
|
decl = this.getMethod(name) and
|
||||||
decl.isStatic() and
|
decl.isStatic() and
|
||||||
result = decl.getBody()
|
result = decl.getBody()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getADirectPropsAccess() {
|
override DataFlow::SourceNode getADirectPropsAccess() {
|
||||||
result = getAnInstanceReference().getAPropertyRead("props")
|
result = this.getAnInstanceReference().getAPropertyRead("props")
|
||||||
or
|
or
|
||||||
result = DataFlow::parameterNode(getConstructor().getBody().getParameter(0))
|
result = DataFlow::parameterNode(this.getConstructor().getBody().getParameter(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) }
|
override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) }
|
||||||
@@ -337,7 +339,7 @@ abstract private class SharedReactPreactClassComponent extends ReactComponent, C
|
|||||||
|
|
||||||
override DataFlow::SourceNode getACandidateStateSource() {
|
override DataFlow::SourceNode getACandidateStateSource() {
|
||||||
result = ReactComponent.super.getACandidateStateSource() or
|
result = ReactComponent.super.getACandidateStateSource() or
|
||||||
result.flowsToExpr(getField("state").getInit())
|
result.flowsToExpr(this.getField("state").getInit())
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getADefaultPropsSource() {
|
override DataFlow::SourceNode getADefaultPropsSource() {
|
||||||
@@ -359,7 +361,7 @@ abstract class ES2015Component extends SharedReactPreactClassComponent { }
|
|||||||
*/
|
*/
|
||||||
private class DefiniteES2015Component extends ES2015Component {
|
private class DefiniteES2015Component extends ES2015Component {
|
||||||
DefiniteES2015Component() {
|
DefiniteES2015Component() {
|
||||||
exists(DataFlow::SourceNode sup | sup.flowsToExpr(getSuperClass()) |
|
exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.getSuperClass()) |
|
||||||
exists(PropAccess access, string globalReactName |
|
exists(PropAccess access, string globalReactName |
|
||||||
(globalReactName = "react" or globalReactName = "React") and
|
(globalReactName = "react" or globalReactName = "React") and
|
||||||
access = sup.asExpr()
|
access = sup.asExpr()
|
||||||
@@ -383,12 +385,12 @@ private class DefiniteES2015Component extends ES2015Component {
|
|||||||
abstract class PreactComponent extends SharedReactPreactClassComponent {
|
abstract class PreactComponent extends SharedReactPreactClassComponent {
|
||||||
override DataFlow::SourceNode getADirectPropsAccess() {
|
override DataFlow::SourceNode getADirectPropsAccess() {
|
||||||
result = super.getADirectPropsAccess() or
|
result = super.getADirectPropsAccess() or
|
||||||
result = DataFlow::parameterNode(getInstanceMethod("render").getParameter(0))
|
result = DataFlow::parameterNode(this.getInstanceMethod("render").getParameter(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getADirectStateAccess() {
|
override DataFlow::SourceNode getADirectStateAccess() {
|
||||||
result = super.getADirectStateAccess() or
|
result = super.getADirectStateAccess() or
|
||||||
result = DataFlow::parameterNode(getInstanceMethod("render").getParameter(1))
|
result = DataFlow::parameterNode(this.getInstanceMethod("render").getParameter(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,7 +399,7 @@ abstract class PreactComponent extends SharedReactPreactClassComponent {
|
|||||||
*/
|
*/
|
||||||
private class DefinitePreactComponent extends PreactComponent {
|
private class DefinitePreactComponent extends PreactComponent {
|
||||||
DefinitePreactComponent() {
|
DefinitePreactComponent() {
|
||||||
exists(DataFlow::SourceNode sup | sup.flowsToExpr(getSuperClass()) |
|
exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.getSuperClass()) |
|
||||||
exists(PropAccess access, string globalPreactName |
|
exists(PropAccess access, string globalPreactName |
|
||||||
(globalPreactName = "preact" or globalPreactName = "Preact") and
|
(globalPreactName = "preact" or globalPreactName = "Preact") and
|
||||||
access = sup.asExpr()
|
access = sup.asExpr()
|
||||||
@@ -420,7 +422,7 @@ private class HeuristicReactPreactComponent extends ClassDefinition, PreactCompo
|
|||||||
ES2015Component
|
ES2015Component
|
||||||
{
|
{
|
||||||
HeuristicReactPreactComponent() {
|
HeuristicReactPreactComponent() {
|
||||||
any(DataFlow::GlobalVarRefNode c | c.getName() = "Component").flowsToExpr(getSuperClass()) and
|
any(DataFlow::GlobalVarRefNode c | c.getName() = "Component").flowsToExpr(this.getSuperClass()) and
|
||||||
alwaysReturnsJsxOrReactElements(ClassDefinition.super.getInstanceMethod("render"))
|
alwaysReturnsJsxOrReactElements(ClassDefinition.super.getInstanceMethod("render"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,12 +444,14 @@ class ES5Component extends ReactComponent, ObjectExpr {
|
|||||||
create.getArgument(0).getALocalSource().asExpr() = this
|
create.getArgument(0).getALocalSource().asExpr() = this
|
||||||
}
|
}
|
||||||
|
|
||||||
override Function getInstanceMethod(string name) { result = getPropertyByName(name).getInit() }
|
override Function getInstanceMethod(string name) {
|
||||||
|
result = this.getPropertyByName(name).getInit()
|
||||||
|
}
|
||||||
|
|
||||||
override Function getStaticMethod(string name) { none() }
|
override Function getStaticMethod(string name) { none() }
|
||||||
|
|
||||||
override DataFlow::SourceNode getADirectPropsAccess() {
|
override DataFlow::SourceNode getADirectPropsAccess() {
|
||||||
result = getAnInstanceReference().getAPropertyRead("props")
|
result = this.getAnInstanceReference().getAPropertyRead("props")
|
||||||
}
|
}
|
||||||
|
|
||||||
override AbstractValue getAbstractComponent() { result = TAbstractObjectLiteral(this) }
|
override AbstractValue getAbstractComponent() { result = TAbstractObjectLiteral(this) }
|
||||||
@@ -456,23 +460,23 @@ class ES5Component extends ReactComponent, ObjectExpr {
|
|||||||
t.start() and
|
t.start() and
|
||||||
result = create
|
result = create
|
||||||
or
|
or
|
||||||
exists(DataFlow::TypeTracker t2 | result = getAComponentCreatorReference(t2).track(t2, t))
|
exists(DataFlow::TypeTracker t2 | result = this.getAComponentCreatorReference(t2).track(t2, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getAComponentCreatorReference() {
|
override DataFlow::SourceNode getAComponentCreatorReference() {
|
||||||
result = getAComponentCreatorReference(DataFlow::TypeTracker::end())
|
result = this.getAComponentCreatorReference(DataFlow::TypeTracker::end())
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getComponentCreatorSource() { result = create }
|
override DataFlow::SourceNode getComponentCreatorSource() { result = create }
|
||||||
|
|
||||||
override DataFlow::SourceNode getACandidateStateSource() {
|
override DataFlow::SourceNode getACandidateStateSource() {
|
||||||
result = ReactComponent.super.getACandidateStateSource() or
|
result = ReactComponent.super.getACandidateStateSource() or
|
||||||
result.flowsToExpr(getInstanceMethod("getInitialState").getAReturnedExpr())
|
result.flowsToExpr(this.getInstanceMethod("getInitialState").getAReturnedExpr())
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::SourceNode getADefaultPropsSource() {
|
override DataFlow::SourceNode getADefaultPropsSource() {
|
||||||
exists(Function f |
|
exists(Function f |
|
||||||
f = getInstanceMethod("getDefaultProps") and
|
f = this.getInstanceMethod("getDefaultProps") and
|
||||||
result.flowsToExpr(f.getAReturnedExpr())
|
result.flowsToExpr(f.getAReturnedExpr())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -538,13 +542,13 @@ private class ReactCallbackPartialInvoke extends DataFlow::PartialInvokeNode::Ra
|
|||||||
name = "forEach"
|
name = "forEach"
|
||||||
|
|
|
|
||||||
this = react().getAPropertyRead("Children").getAMemberCall(name) and
|
this = react().getAPropertyRead("Children").getAMemberCall(name) and
|
||||||
3 = getNumArgument()
|
3 = this.getNumArgument()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
||||||
callback = getArgument(1) and
|
callback = this.getArgument(1) and
|
||||||
result = getArgument(2)
|
result = this.getArgument(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,7 +558,7 @@ private class ReactCallbackPartialInvoke extends DataFlow::PartialInvokeNode::Ra
|
|||||||
private class ReactJsxElement extends JsxElement {
|
private class ReactJsxElement extends JsxElement {
|
||||||
ReactComponent component;
|
ReactComponent component;
|
||||||
|
|
||||||
ReactJsxElement() { component.getAComponentCreatorReference().flowsToExpr(getNameExpr()) }
|
ReactJsxElement() { component.getAComponentCreatorReference().flowsToExpr(this.getNameExpr()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the component this element instantiates.
|
* Gets the component this element instantiates.
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ module Redux {
|
|||||||
*/
|
*/
|
||||||
class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range {
|
class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range {
|
||||||
/** Gets a reference to the store. */
|
/** Gets a reference to the store. */
|
||||||
DataFlow::SourceNode ref() { result = asApiNode().getAValueReachableFromSource() }
|
DataFlow::SourceNode ref() { result = this.asApiNode().getAValueReachableFromSource() }
|
||||||
|
|
||||||
/** Gets an API node that refers to this store creation. */
|
/** Gets an API node that refers to this store creation. */
|
||||||
API::Node asApiNode() { result.asSource() = this }
|
API::Node asApiNode() { result.asSource() = this }
|
||||||
@@ -67,7 +67,9 @@ module Redux {
|
|||||||
DataFlow::Node getReducerArg() { result = super.getReducerArg() }
|
DataFlow::Node getReducerArg() { result = super.getReducerArg() }
|
||||||
|
|
||||||
/** Gets a data flow node referring to the root reducer. */
|
/** Gets a data flow node referring to the root reducer. */
|
||||||
DataFlow::SourceNode getAReducerSource() { result = getReducerArg().(ReducerArg).getASource() }
|
DataFlow::SourceNode getAReducerSource() {
|
||||||
|
result = this.getReducerArg().(ReducerArg).getASource()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Companion module to the `StoreCreation` class. */
|
/** Companion module to the `StoreCreation` class. */
|
||||||
@@ -85,7 +87,7 @@ module Redux {
|
|||||||
this = API::moduleImport(["redux", "@reduxjs/toolkit"]).getMember("createStore").getACall()
|
this = API::moduleImport(["redux", "@reduxjs/toolkit"]).getMember("createStore").getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getReducerArg() { result = getArgument(0) }
|
override DataFlow::Node getReducerArg() { result = this.getArgument(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ToolkitStore extends API::CallNode, Range {
|
private class ToolkitStore extends API::CallNode, Range {
|
||||||
@@ -94,7 +96,7 @@ module Redux {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getReducerArg() {
|
override DataFlow::Node getReducerArg() {
|
||||||
result = getParameter(0).getMember("reducer").asSink()
|
result = this.getParameter(0).getMember("reducer").asSink()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,7 +195,7 @@ module Redux {
|
|||||||
CombineReducers() { this = combineReducers().getACall() }
|
CombineReducers() { this = combineReducers().getACall() }
|
||||||
|
|
||||||
override DataFlow::Node getStateHandlerArg(string prop) {
|
override DataFlow::Node getStateHandlerArg(string prop) {
|
||||||
result = getParameter(0).getMember(prop).asSink()
|
result = this.getParameter(0).getMember(prop).asSink()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +213,7 @@ module Redux {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getStateHandlerArg(string prop) {
|
override DataFlow::Node getStateHandlerArg(string prop) {
|
||||||
result = getAPropertyWrite(prop).getRhs()
|
result = this.getAPropertyWrite(prop).getRhs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +237,7 @@ module Redux {
|
|||||||
|
|
||||||
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
||||||
exists(DataFlow::PropWrite write |
|
exists(DataFlow::PropWrite write |
|
||||||
result = getParameter(0).getAMember().asSink() and
|
result = this.getParameter(0).getAMember().asSink() and
|
||||||
write.getRhs() = result and
|
write.getRhs() = result and
|
||||||
actionType = write.getPropertyNameExpr().flow()
|
actionType = write.getPropertyNameExpr().flow()
|
||||||
)
|
)
|
||||||
@@ -258,8 +260,8 @@ module Redux {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
||||||
actionType = getArgument(0) and
|
actionType = this.getArgument(0) and
|
||||||
result = getArgument(1)
|
result = this.getArgument(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +273,7 @@ module Redux {
|
|||||||
this = API::moduleImport("redux-persist").getMember("persistReducer").getACall()
|
this = API::moduleImport("redux-persist").getMember("persistReducer").getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAPlainHandlerArg() { result = getArgument(1) }
|
override DataFlow::Node getAPlainHandlerArg() { result = this.getArgument(1) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -284,7 +286,7 @@ module Redux {
|
|||||||
this = API::moduleImport("immer").getMember("produce").getACall()
|
this = API::moduleImport("immer").getMember("produce").getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAPlainHandlerArg() { result = getArgument(0) }
|
override DataFlow::Node getAPlainHandlerArg() { result = this.getArgument(0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -312,9 +314,9 @@ module Redux {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAPlainHandlerArg() {
|
override DataFlow::Node getAPlainHandlerArg() {
|
||||||
result = getAnArgument()
|
result = this.getAnArgument()
|
||||||
or
|
or
|
||||||
result = getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
|
result = this.getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,14 +337,14 @@ module Redux {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private API::Node getABuilderRef() {
|
private API::Node getABuilderRef() {
|
||||||
result = getParameter(1).getParameter(0)
|
result = this.getParameter(1).getParameter(0)
|
||||||
or
|
or
|
||||||
result = getABuilderRef().getAMember().getReturn()
|
result = this.getABuilderRef().getAMember().getReturn()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
||||||
exists(API::CallNode addCase |
|
exists(API::CallNode addCase |
|
||||||
addCase = getABuilderRef().getMember("addCase").getACall() and
|
addCase = this.getABuilderRef().getMember("addCase").getACall() and
|
||||||
actionType = addCase.getArgument(0) and
|
actionType = addCase.getArgument(0) and
|
||||||
result = addCase.getArgument(1)
|
result = addCase.getArgument(1)
|
||||||
)
|
)
|
||||||
@@ -380,7 +382,7 @@ module Redux {
|
|||||||
private API::Node getABuilderRef() {
|
private API::Node getABuilderRef() {
|
||||||
result = call.getParameter(0).getMember("extraReducers").getParameter(0)
|
result = call.getParameter(0).getMember("extraReducers").getParameter(0)
|
||||||
or
|
or
|
||||||
result = getABuilderRef().getAMember().getReturn()
|
result = this.getABuilderRef().getAMember().getReturn()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
||||||
@@ -400,7 +402,7 @@ module Redux {
|
|||||||
// Builder callback to 'extraReducers':
|
// Builder callback to 'extraReducers':
|
||||||
// extraReducers: builder => builder.addCase(action, reducer)
|
// extraReducers: builder => builder.addCase(action, reducer)
|
||||||
exists(API::CallNode addCase |
|
exists(API::CallNode addCase |
|
||||||
addCase = getABuilderRef().getMember("addCase").getACall() and
|
addCase = this.getABuilderRef().getMember("addCase").getACall() and
|
||||||
actionType = addCase.getArgument(0) and
|
actionType = addCase.getArgument(0) and
|
||||||
result = addCase.getArgument(1)
|
result = addCase.getArgument(1)
|
||||||
)
|
)
|
||||||
@@ -444,7 +446,7 @@ module Redux {
|
|||||||
or
|
or
|
||||||
// x -> bindActionCreators({ x, ... })
|
// x -> bindActionCreators({ x, ... })
|
||||||
exists(BindActionCreatorsCall bind, string prop |
|
exists(BindActionCreatorsCall bind, string prop |
|
||||||
ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).asSink()) and
|
this.ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).asSink()) and
|
||||||
result = bind.getReturn().getMember(prop).asSource()
|
result = bind.getReturn().getMember(prop).asSource()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -454,32 +456,32 @@ module Redux {
|
|||||||
API::moduleImport(["redux-actions", "redux-ts-utils"])
|
API::moduleImport(["redux-actions", "redux-ts-utils"])
|
||||||
.getMember("combineActions")
|
.getMember("combineActions")
|
||||||
.getACall() and
|
.getACall() and
|
||||||
ref(t.continue()).flowsTo(combiner.getAnArgument()) and
|
this.ref(t.continue()).flowsTo(combiner.getAnArgument()) and
|
||||||
result = combiner
|
result = combiner
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// x -> x.fulfilled, for async action creators
|
// x -> x.fulfilled, for async action creators
|
||||||
result = ref(t.continue()).getAPropertyRead("fulfilled")
|
result = this.ref(t.continue()).getAPropertyRead("fulfilled")
|
||||||
or
|
or
|
||||||
// follow flow through mapDispatchToProps
|
// follow flow through mapDispatchToProps
|
||||||
ReactRedux::dispatchToPropsStep(ref(t.continue()).getALocalUse(), result)
|
ReactRedux::dispatchToPropsStep(this.ref(t.continue()).getALocalUse(), result)
|
||||||
or
|
or
|
||||||
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
|
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a data flow node referring to this action creator. */
|
/** Gets a data flow node referring to this action creator. */
|
||||||
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
|
DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a block that is executed when a check has determined that `action` originated from this action creator.
|
* Gets a block that is executed when a check has determined that `action` originated from this action creator.
|
||||||
*/
|
*/
|
||||||
private ReachableBasicBlock getASuccessfulTypeCheckBlock(DataFlow::SourceNode action) {
|
private ReachableBasicBlock getASuccessfulTypeCheckBlock(DataFlow::SourceNode action) {
|
||||||
action = getAnUntypedActionInReducer() and
|
action = getAnUntypedActionInReducer() and
|
||||||
result = getASuccessfulTypeCheckBlock(action, getTypeTag())
|
result = getASuccessfulTypeCheckBlock(action, this.getTypeTag())
|
||||||
or
|
or
|
||||||
// some action creators implement a .match method for this purpose
|
// some action creators implement a .match method for this purpose
|
||||||
exists(ConditionGuardNode guard, DataFlow::CallNode call |
|
exists(ConditionGuardNode guard, DataFlow::CallNode call |
|
||||||
call = ref().getAMethodCall("match") and
|
call = this.ref().getAMethodCall("match") and
|
||||||
guard.getTest() = call.asExpr() and
|
guard.getTest() = call.asExpr() and
|
||||||
action.flowsTo(call.getArgument(0)) and
|
action.flowsTo(call.getArgument(0)) and
|
||||||
guard.getOutcome() = true and
|
guard.getOutcome() = true and
|
||||||
@@ -497,9 +499,9 @@ module Redux {
|
|||||||
*/
|
*/
|
||||||
DataFlow::FunctionNode getAReducerFunction() {
|
DataFlow::FunctionNode getAReducerFunction() {
|
||||||
exists(ReducerArg reducer |
|
exists(ReducerArg reducer |
|
||||||
reducer.isTypeTagHandler(getTypeTag())
|
reducer.isTypeTagHandler(this.getTypeTag())
|
||||||
or
|
or
|
||||||
reducer.isActionTypeHandler(ref().getALocalUse())
|
reducer.isActionTypeHandler(this.ref().getALocalUse())
|
||||||
|
|
|
|
||||||
result = reducer.getASource()
|
result = reducer.getASource()
|
||||||
)
|
)
|
||||||
@@ -511,16 +513,17 @@ module Redux {
|
|||||||
exists(DataFlow::SourceNode actionSrc |
|
exists(DataFlow::SourceNode actionSrc |
|
||||||
actionSrc = getAnUntypedActionInReducer() and
|
actionSrc = getAnUntypedActionInReducer() and
|
||||||
result = actionSrc.getAPropertyRead("payload") and
|
result = actionSrc.getAPropertyRead("payload") and
|
||||||
getASuccessfulTypeCheckBlock(actionSrc).dominates(result.getBasicBlock())
|
this.getASuccessfulTypeCheckBlock(actionSrc).dominates(result.getBasicBlock())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
result = getAReducerFunction().getParameter(1).getAPropertyRead("payload")
|
result = this.getAReducerFunction().getParameter(1).getAPropertyRead("payload")
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a data flow node referring to the first argument of the action creator invocation. */
|
/** Gets a data flow node referring to the first argument of the action creator invocation. */
|
||||||
DataFlow::SourceNode getAMetaArgReference() {
|
DataFlow::SourceNode getAMetaArgReference() {
|
||||||
exists(ReducerArg reducer |
|
exists(ReducerArg reducer |
|
||||||
reducer.isActionTypeHandler(ref().getAPropertyRead(["fulfilled", "rejected", "pending"])) and
|
reducer
|
||||||
|
.isActionTypeHandler(this.ref().getAPropertyRead(["fulfilled", "rejected", "pending"])) and
|
||||||
result =
|
result =
|
||||||
reducer
|
reducer
|
||||||
.getASource()
|
.getASource()
|
||||||
@@ -558,10 +561,10 @@ module Redux {
|
|||||||
.getACall()
|
.getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override string getTypeTag() { getArgument(0).mayHaveStringValue(result) }
|
override string getTypeTag() { this.getArgument(0).mayHaveStringValue(result) }
|
||||||
|
|
||||||
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
|
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
|
||||||
result = getCallback(1) and async = false
|
result = this.getCallback(1) and async = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,7 +587,7 @@ module Redux {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
|
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
|
||||||
result.flowsTo(createActions.getParameter(0).getMember(getTypeTag()).asSink()) and
|
result.flowsTo(createActions.getParameter(0).getMember(this.getTypeTag()).asSink()) and
|
||||||
async = false
|
async = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,10 +643,10 @@ module Redux {
|
|||||||
|
|
||||||
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
|
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
|
||||||
async = true and
|
async = true and
|
||||||
result = getParameter(1).getAValueReachingSink()
|
result = this.getParameter(1).getAValueReachingSink()
|
||||||
}
|
}
|
||||||
|
|
||||||
override string getTypeTag() { getArgument(0).mayHaveStringValue(result) }
|
override string getTypeTag() { this.getArgument(0).mayHaveStringValue(result) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -681,26 +684,27 @@ module Redux {
|
|||||||
/** Gets a data flow node that flows to this reducer argument. */
|
/** Gets a data flow node that flows to this reducer argument. */
|
||||||
DataFlow::SourceNode getASource(DataFlow::TypeBackTracker t) {
|
DataFlow::SourceNode getASource(DataFlow::TypeBackTracker t) {
|
||||||
t.start() and
|
t.start() and
|
||||||
result = getALocalSource()
|
result = this.getALocalSource()
|
||||||
or
|
or
|
||||||
// Step through forwarding functions
|
// Step through forwarding functions
|
||||||
DataFlow::functionForwardingStep(result.getALocalUse(), getASource(t.continue()))
|
DataFlow::functionForwardingStep(result.getALocalUse(), this.getASource(t.continue()))
|
||||||
or
|
or
|
||||||
// Step through library functions like `redux-persist`
|
// Step through library functions like `redux-persist`
|
||||||
result.getALocalUse() = getASource(t.continue()).(DelegatingReducer).getAPlainHandlerArg()
|
result.getALocalUse() =
|
||||||
|
this.getASource(t.continue()).(DelegatingReducer).getAPlainHandlerArg()
|
||||||
or
|
or
|
||||||
// Step through function composition (usually composed with various state "enhancer" functions)
|
// Step through function composition (usually composed with various state "enhancer" functions)
|
||||||
exists(FunctionCompositionCall compose, DataFlow::CallNode call |
|
exists(FunctionCompositionCall compose, DataFlow::CallNode call |
|
||||||
getASource(t.continue()) = call and
|
this.getASource(t.continue()) = call and
|
||||||
call = compose.getACall() and
|
call = compose.getACall() and
|
||||||
result.getALocalUse() = [compose.getAnOperandNode(), call.getAnArgument()]
|
result.getALocalUse() = [compose.getAnOperandNode(), call.getAnArgument()]
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(DataFlow::TypeBackTracker t2 | result = getASource(t2).backtrack(t2, t))
|
exists(DataFlow::TypeBackTracker t2 | result = this.getASource(t2).backtrack(t2, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a data flow node that flows to this reducer argument. */
|
/** Gets a data flow node that flows to this reducer argument. */
|
||||||
DataFlow::SourceNode getASource() { result = getASource(DataFlow::TypeBackTracker::end()) }
|
DataFlow::SourceNode getASource() { result = this.getASource(DataFlow::TypeBackTracker::end()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the actions dispatched to this reducer have the given type, that is,
|
* Holds if the actions dispatched to this reducer have the given type, that is,
|
||||||
@@ -721,7 +725,7 @@ module Redux {
|
|||||||
*/
|
*/
|
||||||
predicate isTypeTagHandler(string actionType) {
|
predicate isTypeTagHandler(string actionType) {
|
||||||
exists(DataFlow::Node node |
|
exists(DataFlow::Node node |
|
||||||
isActionTypeHandler(node) and
|
this.isActionTypeHandler(node) and
|
||||||
actionType = getATypeTagFromNode(node)
|
actionType = getATypeTagFromNode(node)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1035,7 +1039,7 @@ module Redux {
|
|||||||
result = this
|
result = this
|
||||||
or
|
or
|
||||||
exists(FunctionCompositionCall compose |
|
exists(FunctionCompositionCall compose |
|
||||||
getAComponentTransformer().flowsTo(compose.getAnOperandNode()) and
|
this.getAComponentTransformer().flowsTo(compose.getAnOperandNode()) and
|
||||||
result = compose
|
result = compose
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1048,19 +1052,19 @@ module Redux {
|
|||||||
//
|
//
|
||||||
// const mapDispatchToProps = { foo }
|
// const mapDispatchToProps = { foo }
|
||||||
//
|
//
|
||||||
result = getMapDispatchToProps().getMember(name).asSink()
|
result = this.getMapDispatchToProps().getMember(name).asSink()
|
||||||
or
|
or
|
||||||
//
|
//
|
||||||
// const mapDispatchToProps = dispatch => ( { foo } )
|
// const mapDispatchToProps = dispatch => ( { foo } )
|
||||||
//
|
//
|
||||||
result = getMapDispatchToProps().getReturn().getMember(name).asSink()
|
result = this.getMapDispatchToProps().getReturn().getMember(name).asSink()
|
||||||
or
|
or
|
||||||
// Explicitly bound by bindActionCreators:
|
// Explicitly bound by bindActionCreators:
|
||||||
//
|
//
|
||||||
// const mapDispatchToProps = dispatch => bindActionCreators({ foo }, dispatch);
|
// const mapDispatchToProps = dispatch => bindActionCreators({ foo }, dispatch);
|
||||||
//
|
//
|
||||||
exists(BindActionCreatorsCall bind |
|
exists(BindActionCreatorsCall bind |
|
||||||
bind.flowsTo(getMapDispatchToProps().getReturn().asSink()) and
|
bind.flowsTo(this.getMapDispatchToProps().getReturn().asSink()) and
|
||||||
result = bind.getOptionArgument(0, name)
|
result = bind.getOptionArgument(0, name)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1070,9 +1074,9 @@ module Redux {
|
|||||||
*/
|
*/
|
||||||
ReactComponent getReactComponent() {
|
ReactComponent getReactComponent() {
|
||||||
exists(DataFlow::SourceNode component | component = result.getAComponentCreatorReference() |
|
exists(DataFlow::SourceNode component | component = result.getAComponentCreatorReference() |
|
||||||
component.flowsTo(getAComponentTransformer().getACall().getArgument(0))
|
component.flowsTo(this.getAComponentTransformer().getACall().getArgument(0))
|
||||||
or
|
or
|
||||||
component.(DataFlow::ClassNode).getADecorator() = getAComponentTransformer()
|
component.(DataFlow::ClassNode).getADecorator() = this.getAComponentTransformer()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1083,9 +1087,9 @@ module Redux {
|
|||||||
this = API::moduleImport("react-redux").getMember("connect").getACall()
|
this = API::moduleImport("react-redux").getMember("connect").getACall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override API::Node getMapStateToProps() { result = getParameter(0) }
|
override API::Node getMapStateToProps() { result = this.getParameter(0) }
|
||||||
|
|
||||||
override API::Node getMapDispatchToProps() { result = getParameter(1) }
|
override API::Node getMapDispatchToProps() { result = this.getParameter(1) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1114,12 +1118,12 @@ module Redux {
|
|||||||
HeuristicConnectFunction() { this = any(HeuristicConnectEntryPoint e).getANode().getACall() }
|
HeuristicConnectFunction() { this = any(HeuristicConnectEntryPoint e).getANode().getACall() }
|
||||||
|
|
||||||
override API::Node getMapStateToProps() {
|
override API::Node getMapStateToProps() {
|
||||||
result = getAParameter() and
|
result = this.getAParameter() and
|
||||||
result.asSink().asExpr().(Identifier).getName() = "mapStateToProps"
|
result.asSink().asExpr().(Identifier).getName() = "mapStateToProps"
|
||||||
}
|
}
|
||||||
|
|
||||||
override API::Node getMapDispatchToProps() {
|
override API::Node getMapDispatchToProps() {
|
||||||
result = getAParameter() and
|
result = this.getAParameter() and
|
||||||
result.asSink().asExpr().(Identifier).getName() = "mapDispatchToProps"
|
result.asSink().asExpr().(Identifier).getName() = "mapDispatchToProps"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1199,12 +1203,12 @@ module Redux {
|
|||||||
/** Gets the `i`th selector callback, that is, a callback other than the result function. */
|
/** Gets the `i`th selector callback, that is, a callback other than the result function. */
|
||||||
API::Node getSelectorFunction(int i) {
|
API::Node getSelectorFunction(int i) {
|
||||||
// When there are multiple callbacks, exclude the last one
|
// When there are multiple callbacks, exclude the last one
|
||||||
result = getParameter(i) and
|
result = this.getParameter(i) and
|
||||||
(i = 0 or i < getNumArgument() - 1)
|
(i = 0 or i < this.getNumArgument() - 1)
|
||||||
or
|
or
|
||||||
// Selector functions may be given as an array
|
// Selector functions may be given as an array
|
||||||
exists(DataFlow::ArrayCreationNode array |
|
exists(DataFlow::ArrayCreationNode array |
|
||||||
array.flowsTo(getArgument(0)) and
|
array.flowsTo(this.getArgument(0)) and
|
||||||
result.getAValueReachableFromSource() = array.getElement(i)
|
result.getAValueReachableFromSource() = array.getElement(i)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,14 +64,16 @@ module ShellJS {
|
|||||||
/** Holds if the first argument starts with a `-`, indicating it is an option. */
|
/** Holds if the first argument starts with a `-`, indicating it is an option. */
|
||||||
predicate hasOptionsArg() {
|
predicate hasOptionsArg() {
|
||||||
exists(string val |
|
exists(string val |
|
||||||
getArgument(0).mayHaveStringValue(val) and
|
this.getArgument(0).mayHaveStringValue(val) and
|
||||||
val.matches("-%")
|
val.matches("-%")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the `n`th argument after the initial options argument, if any. */
|
/** Gets the `n`th argument after the initial options argument, if any. */
|
||||||
DataFlow::Node getTranslatedArgument(int n) {
|
DataFlow::Node getTranslatedArgument(int n) {
|
||||||
if hasOptionsArg() then result = getArgument(n + 1) else result = getArgument(n)
|
if this.hasOptionsArg()
|
||||||
|
then result = this.getArgument(n + 1)
|
||||||
|
else result = this.getArgument(n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ module ShellJS {
|
|||||||
name = ["cd", "cp", "touch", "chmod", "pushd", "find", "ls", "ln", "mkdir", "mv", "rm"]
|
name = ["cd", "cp", "touch", "chmod", "pushd", "find", "ls", "ln", "mkdir", "mv", "rm"]
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAPathArgument() { result = getAnArgument() }
|
override DataFlow::Node getAPathArgument() { result = this.getAnArgument() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -102,7 +104,7 @@ module ShellJS {
|
|||||||
private class ShellJSRead extends FileSystemReadAccess, ShellJSCall {
|
private class ShellJSRead extends FileSystemReadAccess, ShellJSCall {
|
||||||
ShellJSRead() { name = ["cat", "head", "sort", "tail", "uniq"] }
|
ShellJSRead() { name = ["cat", "head", "sort", "tail", "uniq"] }
|
||||||
|
|
||||||
override DataFlow::Node getAPathArgument() { result = getAnArgument() }
|
override DataFlow::Node getAPathArgument() { result = this.getAnArgument() }
|
||||||
|
|
||||||
override DataFlow::Node getADataNode() { result = this }
|
override DataFlow::Node getADataNode() { result = this }
|
||||||
}
|
}
|
||||||
@@ -124,7 +126,7 @@ module ShellJS {
|
|||||||
// Do not treat regex patterns as filenames.
|
// Do not treat regex patterns as filenames.
|
||||||
exists(int arg |
|
exists(int arg |
|
||||||
arg >= offset and
|
arg >= offset and
|
||||||
result = getTranslatedArgument(arg)
|
result = this.getTranslatedArgument(arg)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,15 +139,15 @@ module ShellJS {
|
|||||||
private class ShellJSExec extends SystemCommandExecution, ShellJSCall {
|
private class ShellJSExec extends SystemCommandExecution, ShellJSCall {
|
||||||
ShellJSExec() { name = "exec" }
|
ShellJSExec() { name = "exec" }
|
||||||
|
|
||||||
override DataFlow::Node getACommandArgument() { result = getArgument(0) }
|
override DataFlow::Node getACommandArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate isShellInterpreted(DataFlow::Node arg) { arg = getACommandArgument() }
|
override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getACommandArgument() }
|
||||||
|
|
||||||
override predicate isSync() { none() }
|
override predicate isSync() { none() }
|
||||||
|
|
||||||
override DataFlow::Node getOptionsArg() {
|
override DataFlow::Node getOptionsArg() {
|
||||||
result = getLastArgument() and
|
result = this.getLastArgument() and
|
||||||
not result = getArgument(0) and
|
not result = this.getArgument(0) and
|
||||||
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
|
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
|
||||||
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode // looks like argumentlist
|
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode // looks like argumentlist
|
||||||
}
|
}
|
||||||
@@ -163,8 +165,8 @@ module ShellJS {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
|
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override DataFlow::Node getADataNode() { result = getReceiver() }
|
override DataFlow::Node getADataNode() { result = this.getReceiver() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,11 +87,11 @@ private class LibraryFormatter extends PrintfStyleCall {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getFormatString() { result = getArgument(formatIndex) }
|
override DataFlow::Node getFormatString() { result = this.getArgument(formatIndex) }
|
||||||
|
|
||||||
override DataFlow::Node getFormatArgument(int i) {
|
override DataFlow::Node getFormatArgument(int i) {
|
||||||
i >= 0 and
|
i >= 0 and
|
||||||
result = getArgument(formatIndex + 1 + i)
|
result = this.getArgument(formatIndex + 1 + i)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate returnsFormatted() { returns = true }
|
override predicate returnsFormatted() { returns = true }
|
||||||
|
|||||||
@@ -79,13 +79,13 @@ private class SystemCommandExecutors extends SystemCommandExecution, DataFlow::I
|
|||||||
sync = true
|
sync = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getACommandArgument() { result = getArgument(cmdArg) }
|
override DataFlow::Node getACommandArgument() { result = this.getArgument(cmdArg) }
|
||||||
|
|
||||||
override predicate isShellInterpreted(DataFlow::Node arg) {
|
override predicate isShellInterpreted(DataFlow::Node arg) {
|
||||||
arg = getACommandArgument() and shell = true
|
arg = this.getACommandArgument() and shell = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getArgumentList() { shell = false and result = getArgument(1) }
|
override DataFlow::Node getArgumentList() { shell = false and result = this.getArgument(1) }
|
||||||
|
|
||||||
override predicate isSync() { sync = true }
|
override predicate isSync() { sync = true }
|
||||||
|
|
||||||
@@ -93,9 +93,9 @@ private class SystemCommandExecutors extends SystemCommandExecution, DataFlow::I
|
|||||||
(
|
(
|
||||||
if optionsArg < 0
|
if optionsArg < 0
|
||||||
then
|
then
|
||||||
result = getArgument(getNumArgument() + optionsArg) and
|
result = this.getArgument(this.getNumArgument() + optionsArg) and
|
||||||
getNumArgument() + optionsArg > cmdArg
|
this.getNumArgument() + optionsArg > cmdArg
|
||||||
else result = getArgument(optionsArg)
|
else result = this.getArgument(optionsArg)
|
||||||
) and
|
) and
|
||||||
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
|
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
|
||||||
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode // looks like argumentlist
|
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode // looks like argumentlist
|
||||||
@@ -131,9 +131,9 @@ private class RemoteCommandExecutor extends SystemCommandExecution, DataFlow::In
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getACommandArgument() { result = getArgument(cmdArg) }
|
override DataFlow::Node getACommandArgument() { result = this.getArgument(cmdArg) }
|
||||||
|
|
||||||
override predicate isShellInterpreted(DataFlow::Node arg) { arg = getACommandArgument() }
|
override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getACommandArgument() }
|
||||||
|
|
||||||
override predicate isSync() { none() }
|
override predicate isSync() { none() }
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ private class RemoteCommandExecutor extends SystemCommandExecution, DataFlow::In
|
|||||||
private class Opener extends SystemCommandExecution, DataFlow::InvokeNode {
|
private class Opener extends SystemCommandExecution, DataFlow::InvokeNode {
|
||||||
Opener() { this = API::moduleImport("opener").getACall() }
|
Opener() { this = API::moduleImport("opener").getACall() }
|
||||||
|
|
||||||
override DataFlow::Node getACommandArgument() { result = getOptionArgument(1, "command") }
|
override DataFlow::Node getACommandArgument() { result = this.getOptionArgument(1, "command") }
|
||||||
|
|
||||||
override predicate isShellInterpreted(DataFlow::Node arg) { none() }
|
override predicate isShellInterpreted(DataFlow::Node arg) { none() }
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class JestTest extends Test, @call_expr {
|
|||||||
exists(call.getArgument(0).getStringValue()) and
|
exists(call.getArgument(0).getStringValue()) and
|
||||||
exists(call.getArgument(1).flow().getAFunctionValue(0))
|
exists(call.getArgument(1).flow().getAFunctionValue(0))
|
||||||
) and
|
) and
|
||||||
getFile() = getTestFile(any(File f), "test")
|
this.getFile() = getTestFile(any(File f), "test")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ module TrustedTypes {
|
|||||||
|
|
||||||
/** Gets the function passed as the given option. */
|
/** Gets the function passed as the given option. */
|
||||||
DataFlow::FunctionNode getPolicyCallback(string method) {
|
DataFlow::FunctionNode getPolicyCallback(string method) {
|
||||||
result = getParameter(1).getMember(method).getAValueReachingSink()
|
result = this.getParameter(1).getMember(method).getAValueReachingSink()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ module Vue {
|
|||||||
/** Gets a component which is extended by this one. */
|
/** Gets a component which is extended by this one. */
|
||||||
Component getABaseComponent() {
|
Component getABaseComponent() {
|
||||||
result.getComponentRef().getAValueReachableFromSource() =
|
result.getComponentRef().getAValueReachableFromSource() =
|
||||||
getOwnOptions().getMember(["extends", "mixins"]).asSink()
|
this.getOwnOptions().getMember(["extends", "mixins"]).asSink()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,13 +176,13 @@ module Vue {
|
|||||||
* of its base component.
|
* of its base component.
|
||||||
*/
|
*/
|
||||||
API::Node getOptions() {
|
API::Node getOptions() {
|
||||||
result = getOwnOptions()
|
result = this.getOwnOptions()
|
||||||
or
|
or
|
||||||
result = getOwnOptions().getMember(["extends", "mixins"]).getAMember()
|
result = this.getOwnOptions().getMember(["extends", "mixins"]).getAMember()
|
||||||
or
|
or
|
||||||
result = getABaseComponent().getOptions()
|
result = this.getABaseComponent().getOptions()
|
||||||
or
|
or
|
||||||
result = getAsClassComponent().getDecoratorOptions()
|
result = this.getAsClassComponent().getDecoratorOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -191,7 +191,7 @@ module Vue {
|
|||||||
* Gets the options passed to the Vue object, such as the object literal `{...}` in `new Vue{{...})`
|
* Gets the options passed to the Vue object, such as the object literal `{...}` in `new Vue{{...})`
|
||||||
* or the default export of a single-file component.
|
* or the default export of a single-file component.
|
||||||
*/
|
*/
|
||||||
deprecated DataFlow::Node getOwnOptionsObject() { result = getOwnOptions().asSink() }
|
deprecated DataFlow::Node getOwnOptionsObject() { result = this.getOwnOptions().asSink() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the class implementing this Vue component, if any.
|
* Gets the class implementing this Vue component, if any.
|
||||||
@@ -199,19 +199,21 @@ module Vue {
|
|||||||
* Specifically, this is a class annotated with `@Component` which flows to the options
|
* Specifically, this is a class annotated with `@Component` which flows to the options
|
||||||
* object of this Vue component.
|
* object of this Vue component.
|
||||||
*/
|
*/
|
||||||
ClassComponent getAsClassComponent() { result = getOwnOptions().getAValueReachingSink() }
|
ClassComponent getAsClassComponent() { result = this.getOwnOptions().getAValueReachingSink() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node for option `name` for this component, not including
|
* Gets the node for option `name` for this component, not including
|
||||||
* those from extended objects and mixins.
|
* those from extended objects and mixins.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getOwnOption(string name) { result = getOwnOptions().getMember(name).asSink() }
|
DataFlow::Node getOwnOption(string name) {
|
||||||
|
result = this.getOwnOptions().getMember(name).asSink()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node for option `name` for this component, including those from
|
* Gets the node for option `name` for this component, including those from
|
||||||
* extended objects and mixins.
|
* extended objects and mixins.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getOption(string name) { result = getOptions().getMember(name).asSink() }
|
DataFlow::Node getOption(string name) { result = this.getOptions().getMember(name).asSink() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a source node flowing into the option `name` of this component, including those from
|
* Gets a source node flowing into the option `name` of this component, including those from
|
||||||
@@ -219,7 +221,7 @@ module Vue {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
DataFlow::SourceNode getOptionSource(string name) {
|
DataFlow::SourceNode getOptionSource(string name) {
|
||||||
result = getOptions().getMember(name).getAValueReachingSink()
|
result = this.getOptions().getMember(name).getAValueReachingSink()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -231,55 +233,55 @@ module Vue {
|
|||||||
* Gets the node for the `data` option object of this component.
|
* Gets the node for the `data` option object of this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getData() {
|
DataFlow::Node getData() {
|
||||||
result = getOption("data")
|
result = this.getOption("data")
|
||||||
or
|
or
|
||||||
result = getOptionSource("data").(DataFlow::FunctionNode).getReturnNode()
|
result = this.getOptionSource("data").(DataFlow::FunctionNode).getReturnNode()
|
||||||
or
|
or
|
||||||
result = getAsClassComponent().getAReceiverNode()
|
result = this.getAsClassComponent().getAReceiverNode()
|
||||||
or
|
or
|
||||||
result = getAsClassComponent().getInstanceMethod("data").getAReturn()
|
result = this.getAsClassComponent().getInstanceMethod("data").getAReturn()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node for the `template` option of this component.
|
* Gets the node for the `template` option of this component.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
DataFlow::SourceNode getTemplate() { result = getOptionSource("template") }
|
DataFlow::SourceNode getTemplate() { result = this.getOptionSource("template") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node for the `render` option of this component.
|
* Gets the node for the `render` option of this component.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
DataFlow::SourceNode getRender() {
|
DataFlow::SourceNode getRender() {
|
||||||
result = getOptionSource("render")
|
result = this.getOptionSource("render")
|
||||||
or
|
or
|
||||||
result = getAsClassComponent().getInstanceMethod("render")
|
result = this.getAsClassComponent().getInstanceMethod("render")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node for the `methods` option of this component.
|
* Gets the node for the `methods` option of this component.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
DataFlow::SourceNode getMethods() { result = getOptionSource("methods") }
|
DataFlow::SourceNode getMethods() { result = this.getOptionSource("methods") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node for the `computed` option of this component.
|
* Gets the node for the `computed` option of this component.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
DataFlow::SourceNode getComputed() { result = getOptionSource("computed") }
|
DataFlow::SourceNode getComputed() { result = this.getOptionSource("computed") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the node for the `watch` option of this component.
|
* Gets the node for the `watch` option of this component.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
DataFlow::SourceNode getWatch() { result = getOptionSource("watch") }
|
DataFlow::SourceNode getWatch() { result = this.getOptionSource("watch") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the function responding to changes to the given `propName`.
|
* Gets the function responding to changes to the given `propName`.
|
||||||
*/
|
*/
|
||||||
DataFlow::FunctionNode getWatchHandler(string propName) {
|
DataFlow::FunctionNode getWatchHandler(string propName) {
|
||||||
exists(API::Node propWatch |
|
exists(API::Node propWatch |
|
||||||
propWatch = getOptions().getMember("watch").getMember(propName) and
|
propWatch = this.getOptions().getMember("watch").getMember(propName) and
|
||||||
result = [propWatch, propWatch.getMember("handler")].getAValueReachingSink()
|
result = [propWatch, propWatch.getMember("handler")].getAValueReachingSink()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -288,11 +290,11 @@ module Vue {
|
|||||||
* Gets a node for a member `name` of the `computed` option of this component that matches `kind`.
|
* Gets a node for a member `name` of the `computed` option of this component that matches `kind`.
|
||||||
*/
|
*/
|
||||||
private DataFlow::SourceNode getAccessor(string name, DataFlow::MemberKind kind) {
|
private DataFlow::SourceNode getAccessor(string name, DataFlow::MemberKind kind) {
|
||||||
result = getComputed().getAPropertySource(name) and kind = DataFlow::MemberKind::getter()
|
result = this.getComputed().getAPropertySource(name) and kind = DataFlow::MemberKind::getter()
|
||||||
or
|
or
|
||||||
result = getComputed().getAPropertySource(name).getAPropertySource(memberKindVerb(kind))
|
result = this.getComputed().getAPropertySource(name).getAPropertySource(memberKindVerb(kind))
|
||||||
or
|
or
|
||||||
result = getAsClassComponent().getInstanceMember(name, kind) and
|
result = this.getAsClassComponent().getInstanceMember(name, kind) and
|
||||||
kind.isAccessor()
|
kind.isAccessor()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,9 +305,9 @@ module Vue {
|
|||||||
DataFlow::SourceNode getALifecycleHook(string hookName) {
|
DataFlow::SourceNode getALifecycleHook(string hookName) {
|
||||||
hookName = lifecycleHookName() and
|
hookName = lifecycleHookName() and
|
||||||
(
|
(
|
||||||
result = getOptionSource(hookName)
|
result = this.getOptionSource(hookName)
|
||||||
or
|
or
|
||||||
result = getAsClassComponent().getInstanceMethod(hookName)
|
result = this.getAsClassComponent().getInstanceMethod(hookName)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,22 +315,22 @@ module Vue {
|
|||||||
* Gets a node for a function that will be invoked with `this` bound to this component.
|
* Gets a node for a function that will be invoked with `this` bound to this component.
|
||||||
*/
|
*/
|
||||||
DataFlow::FunctionNode getABoundFunction() {
|
DataFlow::FunctionNode getABoundFunction() {
|
||||||
result = getOptions().getAMember+().getAValueReachingSink()
|
result = this.getOptions().getAMember+().getAValueReachingSink()
|
||||||
or
|
or
|
||||||
result = getAsClassComponent().getAnInstanceMember()
|
result = this.getAsClassComponent().getAnInstanceMember()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets an API node referring to an instance of this component. */
|
/** Gets an API node referring to an instance of this component. */
|
||||||
API::Node getInstance() { result.asSource() = getABoundFunction().getReceiver() }
|
API::Node getInstance() { result.asSource() = this.getABoundFunction().getReceiver() }
|
||||||
|
|
||||||
/** Gets a data flow node referring to an instance of this component. */
|
/** Gets a data flow node referring to an instance of this component. */
|
||||||
DataFlow::SourceNode getAnInstanceRef() { result = getInstance().asSource() }
|
DataFlow::SourceNode getAnInstanceRef() { result = this.getInstance().asSource() }
|
||||||
|
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private DataFlow::PropWrite getAPropertyValueWrite(string name) {
|
private DataFlow::PropWrite getAPropertyValueWrite(string name) {
|
||||||
result = getData().getALocalSource().getAPropertyWrite(name)
|
result = this.getData().getALocalSource().getAPropertyWrite(name)
|
||||||
or
|
or
|
||||||
result = getAnInstanceRef().getAPropertyWrite(name)
|
result = this.getAnInstanceRef().getAPropertyWrite(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -336,10 +338,10 @@ module Vue {
|
|||||||
* returned form a getter defining that property.
|
* returned form a getter defining that property.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getAPropertyValue(string name) {
|
DataFlow::Node getAPropertyValue(string name) {
|
||||||
result = getAPropertyValueWrite(name).getRhs()
|
result = this.getAPropertyValueWrite(name).getRhs()
|
||||||
or
|
or
|
||||||
exists(DataFlow::FunctionNode getter |
|
exists(DataFlow::FunctionNode getter |
|
||||||
getter.flowsTo(getAccessor(name, DataFlow::MemberKind::getter())) and
|
getter.flowsTo(this.getAccessor(name, DataFlow::MemberKind::getter())) and
|
||||||
result = getter.getAReturn()
|
result = getter.getAReturn()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -498,7 +500,7 @@ module Vue {
|
|||||||
|
|
||||||
override API::Node getOwnOptions() {
|
override API::Node getOwnOptions() {
|
||||||
// Use the entry point generated by `VueExportEntryPoint`
|
// Use the entry point generated by `VueExportEntryPoint`
|
||||||
result.asSink() = getModule().getDefaultOrBulkExport()
|
result.asSink() = this.getModule().getDefaultOrBulkExport()
|
||||||
}
|
}
|
||||||
|
|
||||||
override string toString() { result = file.toString() }
|
override string toString() { result = file.toString() }
|
||||||
@@ -508,7 +510,7 @@ module Vue {
|
|||||||
* A `.vue` file.
|
* A `.vue` file.
|
||||||
*/
|
*/
|
||||||
class VueFile extends File {
|
class VueFile extends File {
|
||||||
VueFile() { getExtension() = "vue" }
|
VueFile() { this.getExtension() = "vue" }
|
||||||
}
|
}
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
@@ -584,7 +586,7 @@ module Vue {
|
|||||||
*/
|
*/
|
||||||
abstract class Element extends TElement {
|
abstract class Element extends TElement {
|
||||||
/** Gets a textual representation of this element. */
|
/** Gets a textual representation of this element. */
|
||||||
string toString() { result = "<" + getName() + ">...</>" }
|
string toString() { result = "<" + this.getName() + ">...</>" }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this element is at the specified location.
|
* Holds if this element is at the specified location.
|
||||||
|
|||||||
@@ -87,11 +87,11 @@ module Vuex {
|
|||||||
/** Gets the namespace prefix to use, or an empty string if no namespace was given. */
|
/** Gets the namespace prefix to use, or an empty string if no namespace was given. */
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
string getNamespace() {
|
string getNamespace() {
|
||||||
getNumArgument() = 2 and
|
this.getNumArgument() = 2 and
|
||||||
result =
|
result =
|
||||||
appendToNamespace(namespace, getParameter(0).getAValueReachingSink().getStringValue())
|
appendToNamespace(namespace, this.getParameter(0).getAValueReachingSink().getStringValue())
|
||||||
or
|
or
|
||||||
getNumArgument() = 1 and
|
this.getNumArgument() = 1 and
|
||||||
result = namespace
|
result = namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,24 +100,25 @@ module Vuex {
|
|||||||
*/
|
*/
|
||||||
predicate hasMapping(string localName, string storeName) {
|
predicate hasMapping(string localName, string storeName) {
|
||||||
// mapGetters('foo')
|
// mapGetters('foo')
|
||||||
getLastParameter().getAValueReachingSink().getStringValue() = localName and
|
this.getLastParameter().getAValueReachingSink().getStringValue() = localName and
|
||||||
storeName = getNamespace() + localName
|
storeName = this.getNamespace() + localName
|
||||||
or
|
or
|
||||||
// mapGetters(['foo', 'bar'])
|
// mapGetters(['foo', 'bar'])
|
||||||
getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() = localName and
|
this.getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() =
|
||||||
storeName = getNamespace() + localName
|
localName and
|
||||||
|
storeName = this.getNamespace() + localName
|
||||||
or
|
or
|
||||||
// mapGetters({foo: 'bar'})
|
// mapGetters({foo: 'bar'})
|
||||||
storeName =
|
storeName =
|
||||||
getNamespace() +
|
this.getNamespace() +
|
||||||
getLastParameter().getMember(localName).getAValueReachingSink().getStringValue() and
|
this.getLastParameter().getMember(localName).getAValueReachingSink().getStringValue() and
|
||||||
localName != "*" // ignore special API graph member named "*"
|
localName != "*" // ignore special API graph member named "*"
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the Vue component in which the generated functions are installed. */
|
/** Gets the Vue component in which the generated functions are installed. */
|
||||||
Vue::Component getVueComponent() {
|
Vue::Component getVueComponent() {
|
||||||
exists(DataFlow::ObjectLiteralNode obj |
|
exists(DataFlow::ObjectLiteralNode obj |
|
||||||
obj.getASpreadProperty() = getReturn().getAValueReachableFromSource() and
|
obj.getASpreadProperty() = this.getReturn().getAValueReachableFromSource() and
|
||||||
result.getOwnOptions().getAMember().asSink() = obj
|
result.getOwnOptions().getAMember().asSink() = obj
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ module XML {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(EntityKind kind) {
|
override predicate resolvesEntities(EntityKind kind) {
|
||||||
// internal entities are always resolved
|
// internal entities are always resolved
|
||||||
@@ -54,7 +54,7 @@ module XML {
|
|||||||
or
|
or
|
||||||
// other entities are only resolved if the configuration option `noent` is set to `true`
|
// other entities are only resolved if the configuration option `noent` is set to `true`
|
||||||
exists(JS::Expr noent |
|
exists(JS::Expr noent |
|
||||||
hasOptionArgument(1, "noent", noent) and
|
this.hasOptionArgument(1, "noent", noent) and
|
||||||
noent.mayHaveBooleanValue(true)
|
noent.mayHaveBooleanValue(true)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -66,23 +66,24 @@ module XML {
|
|||||||
private API::Node doc() {
|
private API::Node doc() {
|
||||||
result = call.getReturn()
|
result = call.getReturn()
|
||||||
or
|
or
|
||||||
result = doc().getMember("encoding").getReturn()
|
result = this.doc().getMember("encoding").getReturn()
|
||||||
or
|
or
|
||||||
result = element().getMember("doc").getReturn()
|
result = this.element().getMember("doc").getReturn()
|
||||||
or
|
or
|
||||||
result = element().getMember("parent").getReturn()
|
result = this.element().getMember("parent").getReturn()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an `Element` from the `libxmljs` library.
|
* Gets an `Element` from the `libxmljs` library.
|
||||||
*/
|
*/
|
||||||
private API::Node element() {
|
private API::Node element() {
|
||||||
result = doc().getMember(["child", "get", "node", "root"]).getReturn()
|
result = this.doc().getMember(["child", "get", "node", "root"]).getReturn()
|
||||||
or
|
|
||||||
result = [doc(), element()].getMember(["childNodes", "find"]).getReturn().getAMember()
|
|
||||||
or
|
or
|
||||||
result =
|
result =
|
||||||
element()
|
[this.doc(), this.element()].getMember(["childNodes", "find"]).getReturn().getAMember()
|
||||||
|
or
|
||||||
|
result =
|
||||||
|
this.element()
|
||||||
.getMember([
|
.getMember([
|
||||||
"parent", "prevSibling", "nextSibling", "remove", "clone", "node", "child",
|
"parent", "prevSibling", "nextSibling", "remove", "clone", "node", "child",
|
||||||
"prevElement", "nextElement"
|
"prevElement", "nextElement"
|
||||||
@@ -94,19 +95,20 @@ module XML {
|
|||||||
* Gets an `Attr` from the `libxmljs` library.
|
* Gets an `Attr` from the `libxmljs` library.
|
||||||
*/
|
*/
|
||||||
private API::Node attr() {
|
private API::Node attr() {
|
||||||
result = element().getMember("attr").getReturn()
|
result = this.element().getMember("attr").getReturn()
|
||||||
or
|
or
|
||||||
result = element().getMember("attrs").getReturn().getAMember()
|
result = this.element().getMember("attrs").getReturn().getAMember()
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Node getAResult() {
|
override DataFlow::Node getAResult() {
|
||||||
result = [doc(), element(), attr()].asSource()
|
result = [this.doc(), this.element(), this.attr()].asSource()
|
||||||
or
|
or
|
||||||
result = element().getMember(["name", "text"]).getACall()
|
result = this.element().getMember(["name", "text"]).getACall()
|
||||||
or
|
or
|
||||||
result = attr().getMember(["name", "value"]).getACall()
|
result = this.attr().getMember(["name", "value"]).getACall()
|
||||||
or
|
or
|
||||||
result = element().getMember("namespace").getReturn().getMember(["href", "prefix"]).getACall()
|
result =
|
||||||
|
this.element().getMember("namespace").getReturn().getMember(["href", "prefix"]).getACall()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +123,7 @@ module XML {
|
|||||||
this = parser.getMember("parseString").getACall().asExpr()
|
this = parser.getMember("parseString").getACall().asExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(EntityKind kind) {
|
override predicate resolvesEntities(EntityKind kind) {
|
||||||
// entities are resolved by default
|
// entities are resolved by default
|
||||||
@@ -144,7 +146,7 @@ module XML {
|
|||||||
this = parser.getMember("push").getACall().asExpr()
|
this = parser.getMember("push").getACall().asExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(EntityKind kind) {
|
override predicate resolvesEntities(EntityKind kind) {
|
||||||
// entities are resolved by default
|
// entities are resolved by default
|
||||||
@@ -167,7 +169,7 @@ module XML {
|
|||||||
this = parser.getMember(["parse", "write"]).getACall().asExpr()
|
this = parser.getMember(["parse", "write"]).getACall().asExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(EntityKind kind) {
|
override predicate resolvesEntities(EntityKind kind) {
|
||||||
// only internal entities are resolved by default
|
// only internal entities are resolved by default
|
||||||
@@ -190,10 +192,10 @@ module XML {
|
|||||||
.getAMethodCall("parseFromString")
|
.getAMethodCall("parseFromString")
|
||||||
.asExpr() and
|
.asExpr() and
|
||||||
// type contains the string `xml`, that is, it's not `text/html`
|
// type contains the string `xml`, that is, it's not `text/html`
|
||||||
getArgument(1).mayHaveStringValue(any(string tp | tp.matches("%xml%")))
|
this.getArgument(1).mayHaveStringValue(any(string tp | tp.matches("%xml%")))
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
|
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
|
||||||
|
|
||||||
@@ -215,7 +217,7 @@ module XML {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(XML::EntityKind kind) { any() }
|
override predicate resolvesEntities(XML::EntityKind kind) { any() }
|
||||||
}
|
}
|
||||||
@@ -228,7 +230,7 @@ module XML {
|
|||||||
this.getCallee().(JS::PropAccess).getQualifiedName() = "goog.dom.xml.loadXml"
|
this.getCallee().(JS::PropAccess).getQualifiedName() = "goog.dom.xml.loadXml"
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
|
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
|
||||||
}
|
}
|
||||||
@@ -246,7 +248,7 @@ module XML {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(XML::EntityKind kind) {
|
override predicate resolvesEntities(XML::EntityKind kind) {
|
||||||
// sax-js (the parser used) does not expand entities.
|
// sax-js (the parser used) does not expand entities.
|
||||||
@@ -273,7 +275,7 @@ module XML {
|
|||||||
this = parser.getAMemberCall("write").asExpr()
|
this = parser.getAMemberCall("write").asExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(XML::EntityKind kind) {
|
override predicate resolvesEntities(XML::EntityKind kind) {
|
||||||
// sax-js does not expand entities.
|
// sax-js does not expand entities.
|
||||||
@@ -298,7 +300,7 @@ module XML {
|
|||||||
.asExpr()
|
.asExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(XML::EntityKind kind) {
|
override predicate resolvesEntities(XML::EntityKind kind) {
|
||||||
// xml-js does not expand custom entities.
|
// xml-js does not expand custom entities.
|
||||||
@@ -319,7 +321,7 @@ module XML {
|
|||||||
this = parser.getReturn().getMember("write").getACall().asExpr()
|
this = parser.getReturn().getMember("write").getACall().asExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||||
|
|
||||||
override predicate resolvesEntities(XML::EntityKind kind) {
|
override predicate resolvesEntities(XML::EntityKind kind) {
|
||||||
// htmlparser2 does not expand entities.
|
// htmlparser2 does not expand entities.
|
||||||
|
|||||||
@@ -119,10 +119,10 @@ class XUnitAnnotation extends Expr {
|
|||||||
Expr getAttribute(int i) { result = this.(BracketedListOfExpressions).getElement(i) }
|
Expr getAttribute(int i) { result = this.(BracketedListOfExpressions).getElement(i) }
|
||||||
|
|
||||||
/** Gets an attribute of this annotation. */
|
/** Gets an attribute of this annotation. */
|
||||||
Expr getAnAttribute() { result = getAttribute(_) }
|
Expr getAnAttribute() { result = this.getAttribute(_) }
|
||||||
|
|
||||||
/** Gets the number of attributes of this annotation. */
|
/** Gets the number of attributes of this annotation. */
|
||||||
int getNumAttribute() { result = strictcount(getAnAttribute()) }
|
int getNumAttribute() { result = strictcount(this.getAnAttribute()) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this element is at the specified location.
|
* Holds if this element is at the specified location.
|
||||||
@@ -136,8 +136,8 @@ class XUnitAnnotation extends Expr {
|
|||||||
) {
|
) {
|
||||||
// extend location to cover brackets
|
// extend location to cover brackets
|
||||||
exists(Location l1, Location l2 |
|
exists(Location l1, Location l2 |
|
||||||
l1 = getFirstToken().getLocation() and
|
l1 = this.getFirstToken().getLocation() and
|
||||||
l2 = getLastToken().getLocation()
|
l2 = this.getLastToken().getLocation()
|
||||||
|
|
|
|
||||||
filepath = l1.getFile().getAbsolutePath() and
|
filepath = l1.getFile().getAbsolutePath() and
|
||||||
startline = l1.getStartLine() and
|
startline = l1.getStartLine() and
|
||||||
@@ -176,10 +176,10 @@ class XUnitAttribute extends Expr {
|
|||||||
Expr getParameter(int i) { result = this.(CallExpr).getArgument(i) }
|
Expr getParameter(int i) { result = this.(CallExpr).getArgument(i) }
|
||||||
|
|
||||||
/** Gets a parameter of this attribute. */
|
/** Gets a parameter of this attribute. */
|
||||||
Expr getAParameter() { result = getParameter(_) }
|
Expr getAParameter() { result = this.getParameter(_) }
|
||||||
|
|
||||||
/** Gets the number of parameters of this attribute. */
|
/** Gets the number of parameters of this attribute. */
|
||||||
int getNumParameter() { result = count(getAParameter()) }
|
int getNumParameter() { result = count(this.getAParameter()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -205,26 +205,26 @@ private class XUnitAnnotatedFunction extends Function {
|
|||||||
* An xUnit.js `Fixture` annotation.
|
* An xUnit.js `Fixture` annotation.
|
||||||
*/
|
*/
|
||||||
class XUnitFixtureAnnotation extends XUnitAnnotation {
|
class XUnitFixtureAnnotation extends XUnitAnnotation {
|
||||||
XUnitFixtureAnnotation() { getAnAttribute().accessesGlobal("Fixture") }
|
XUnitFixtureAnnotation() { this.getAnAttribute().accessesGlobal("Fixture") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An xUnit.js fixture.
|
* An xUnit.js fixture.
|
||||||
*/
|
*/
|
||||||
class XUnitFixture extends XUnitAnnotatedFunction {
|
class XUnitFixture extends XUnitAnnotatedFunction {
|
||||||
XUnitFixture() { getAnAnnotation() instanceof XUnitFixtureAnnotation }
|
XUnitFixture() { this.getAnAnnotation() instanceof XUnitFixtureAnnotation }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An xUnit.js `Fact` annotation.
|
* An xUnit.js `Fact` annotation.
|
||||||
*/
|
*/
|
||||||
class XUnitFactAnnotation extends XUnitAnnotation {
|
class XUnitFactAnnotation extends XUnitAnnotation {
|
||||||
XUnitFactAnnotation() { getAnAttribute().accessesGlobal("Fact") }
|
XUnitFactAnnotation() { this.getAnAttribute().accessesGlobal("Fact") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An xUnit.js fact.
|
* An xUnit.js fact.
|
||||||
*/
|
*/
|
||||||
class XUnitFact extends XUnitAnnotatedFunction {
|
class XUnitFact extends XUnitAnnotatedFunction {
|
||||||
XUnitFact() { getAnAnnotation() instanceof XUnitFactAnnotation }
|
XUnitFact() { this.getAnAnnotation() instanceof XUnitFactAnnotation }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,5 @@
|
|||||||
import javascript
|
import javascript
|
||||||
|
|
||||||
private class PromotedPromiseCandidate extends PromiseDefinition, PromiseCandidate {
|
private class PromotedPromiseCandidate extends PromiseDefinition, PromiseCandidate {
|
||||||
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
|
override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ module Linting {
|
|||||||
* Holds if this directive applies to `gva` and declares the variable it references.
|
* Holds if this directive applies to `gva` and declares the variable it references.
|
||||||
*/
|
*/
|
||||||
predicate declaresGlobalForAccess(GlobalVarAccess gva) {
|
predicate declaresGlobalForAccess(GlobalVarAccess gva) {
|
||||||
appliesTo(gva) and declaresGlobal(gva.getName(), _)
|
this.appliesTo(gva) and this.declaresGlobal(gva.getName(), _)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,14 +50,14 @@ class StringReplaceCallSequence extends DataFlow::CallNode instanceof StringRepl
|
|||||||
|
|
||||||
/** Gets a string that is the replacement of this call. */
|
/** Gets a string that is the replacement of this call. */
|
||||||
string getAReplacementString() {
|
string getAReplacementString() {
|
||||||
getAMember().replaces(_, result)
|
this.getAMember().replaces(_, result)
|
||||||
or
|
or
|
||||||
// StringReplaceCall::replaces/2 can't always find the `old` string, so this is added as a fallback.
|
// StringReplaceCall::replaces/2 can't always find the `old` string, so this is added as a fallback.
|
||||||
getAMember().getRawReplacement().getStringValue() = result
|
this.getAMember().getRawReplacement().getStringValue() = result
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a string that is being replaced by this call. */
|
/** Gets a string that is being replaced by this call. */
|
||||||
string getAReplacedString() { getAMember().getAReplacedString() = result }
|
string getAReplacedString() { this.getAMember().getAReplacedString() = result }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class Configuration extends TaintTracking::Configuration {
|
|||||||
isIndirectCommandArgument(sink, highlight)
|
isIndirectCommandArgument(sink, highlight)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) }
|
override predicate isSink(DataFlow::Node sink) { this.isSinkWithHighlight(sink, _) }
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ class SensitiveActionGuardComparison extends Comparison {
|
|||||||
class SensitiveActionGuardComparisonOperand extends Sink {
|
class SensitiveActionGuardComparisonOperand extends Sink {
|
||||||
SensitiveActionGuardComparison comparison;
|
SensitiveActionGuardComparison comparison;
|
||||||
|
|
||||||
SensitiveActionGuardComparisonOperand() { asExpr() = comparison.getAnOperand() }
|
SensitiveActionGuardComparisonOperand() { this.asExpr() = comparison.getAnOperand() }
|
||||||
|
|
||||||
override SensitiveAction getAction() { result = comparison.getGuard().getAction() }
|
override SensitiveAction getAction() { result = comparison.getGuard().getAction() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,6 @@ module DifferentKindsComparisonBypass {
|
|||||||
* A data flow sink for a potential suspicious comparisons.
|
* A data flow sink for a potential suspicious comparisons.
|
||||||
*/
|
*/
|
||||||
private class ComparisonOperandSink extends Sink {
|
private class ComparisonOperandSink extends Sink {
|
||||||
ComparisonOperandSink() { asExpr() = any(Comparison c).getAnOperand() }
|
ComparisonOperandSink() { this.asExpr() = any(Comparison c).getAnOperand() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ class DifferentKindsComparison extends Comparison {
|
|||||||
|
|
||||||
DifferentKindsComparison() {
|
DifferentKindsComparison() {
|
||||||
exists(Configuration cfg |
|
exists(Configuration cfg |
|
||||||
cfg.hasFlow(lSource, DataFlow::valueNode(getLeftOperand())) and
|
cfg.hasFlow(lSource, DataFlow::valueNode(this.getLeftOperand())) and
|
||||||
cfg.hasFlow(rSource, DataFlow::valueNode(getRightOperand())) and
|
cfg.hasFlow(rSource, DataFlow::valueNode(this.getRightOperand())) and
|
||||||
lSource.isSuspiciousToCompareWith(rSource)
|
lSource.isSuspiciousToCompareWith(rSource)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
|
|||||||
|
|
||||||
/** Gets the number of untrusted sources used with this external API. */
|
/** Gets the number of untrusted sources used with this external API. */
|
||||||
int getNumberOfUntrustedSources() {
|
int getNumberOfUntrustedSources() {
|
||||||
result = count(getUntrustedDataNode().getAnUntrustedSource())
|
result = count(this.getUntrustedDataNode().getAnUntrustedSource())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a textual representation of this element. */
|
/** Gets a textual representation of this element. */
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class Configuration extends TaintTracking::Configuration {
|
|||||||
|
|
||||||
override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) {
|
override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) {
|
||||||
lbl = Label::characterToLabel(node.(StringReplaceCall).getAReplacedString()) or
|
lbl = Label::characterToLabel(node.(StringReplaceCall).getAReplacedString()) or
|
||||||
isSanitizer(node)
|
this.isSanitizer(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node n) {
|
override predicate isSanitizer(DataFlow::Node n) {
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class Configuration extends TaintTracking::Configuration {
|
|||||||
isIndirectCommandArgument(sink, highlight)
|
isIndirectCommandArgument(sink, highlight)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) }
|
override predicate isSink(DataFlow::Node sink) { this.isSinkWithHighlight(sink, _) }
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
||||||
|
|
||||||
|
|||||||
@@ -72,12 +72,12 @@ module RegExpInjection {
|
|||||||
*/
|
*/
|
||||||
class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall {
|
class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall {
|
||||||
MetacharEscapeSanitizer() {
|
MetacharEscapeSanitizer() {
|
||||||
isGlobal() and
|
this.isGlobal() and
|
||||||
(
|
(
|
||||||
RegExp::alwaysMatchesMetaCharacter(getRegExp().getRoot(), ["{", "[", "+"])
|
RegExp::alwaysMatchesMetaCharacter(this.getRegExp().getRoot(), ["{", "[", "+"])
|
||||||
or
|
or
|
||||||
// or it's like a wild-card.
|
// or it's like a wild-card.
|
||||||
RegExp::isWildcardLike(getRegExp().getRoot())
|
RegExp::isWildcardLike(this.getRegExp().getRoot())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class Configuration extends TaintTracking::Configuration {
|
|||||||
isIndirectCommandArgument(sink, highlight)
|
isIndirectCommandArgument(sink, highlight)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) }
|
override predicate isSink(DataFlow::Node sink) { this.isSinkWithHighlight(sink, _) }
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ module TemplateObjectInjection {
|
|||||||
exists(
|
exists(
|
||||||
Express::RouteSetup setup, Express::RouterDefinition router, Express::RouterDefinition top
|
Express::RouteSetup setup, Express::RouterDefinition router, Express::RouterDefinition top
|
||||||
|
|
|
|
||||||
setup.getARouteHandler() = getRouteHandler() and
|
setup.getARouteHandler() = this.getRouteHandler() and
|
||||||
setup.getRouter() = router and
|
setup.getRouter() = router and
|
||||||
top.getASubRouter*() = router and
|
top.getASubRouter*() = router and
|
||||||
usesVulnerableTemplateEngine(top)
|
usesVulnerableTemplateEngine(top)
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ private class IsArrayBarrier extends DataFlow::BarrierGuardNode, DataFlow::CallN
|
|||||||
IsArrayBarrier() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") }
|
IsArrayBarrier() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") }
|
||||||
|
|
||||||
override predicate blocks(boolean outcome, Expr e) {
|
override predicate blocks(boolean outcome, Expr e) {
|
||||||
e = getArgument(0).asExpr() and
|
e = this.getArgument(0).asExpr() and
|
||||||
outcome = [true, false] // separation between string/array removes type confusion in both branches
|
outcome = [true, false] // separation between string/array removes type confusion in both branches
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class Configuration extends TaintTracking::Configuration {
|
|||||||
) {
|
) {
|
||||||
// Reading a property of the global object or of a function
|
// Reading a property of the global object or of a function
|
||||||
exists(DataFlow::PropRead read |
|
exists(DataFlow::PropRead read |
|
||||||
hasUnsafeMethods(read.getBase().getALocalSource()) and
|
this.hasUnsafeMethods(read.getBase().getALocalSource()) and
|
||||||
src = read.getPropertyNameExpr().flow() and
|
src = read.getPropertyNameExpr().flow() and
|
||||||
dst = read and
|
dst = read and
|
||||||
srclabel.isTaint() and
|
srclabel.isTaint() and
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ module UnsafeJQueryPlugin {
|
|||||||
{
|
{
|
||||||
AmbiguousHtmlOrSelectorArgument() {
|
AmbiguousHtmlOrSelectorArgument() {
|
||||||
// any fixed prefix makes the call unambiguous
|
// any fixed prefix makes the call unambiguous
|
||||||
not exists(getAPrefix())
|
not exists(this.getAPrefix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,12 +91,12 @@ module UnsafeJQueryPlugin {
|
|||||||
if method.getAParameter().getName().regexpMatch(optionsPattern)
|
if method.getAParameter().getName().regexpMatch(optionsPattern)
|
||||||
then (
|
then (
|
||||||
// use the last parameter named something like "options" if it exists ...
|
// use the last parameter named something like "options" if it exists ...
|
||||||
getName().regexpMatch(optionsPattern) and
|
this.getName().regexpMatch(optionsPattern) and
|
||||||
this = method.getAParameter()
|
this = method.getAParameter()
|
||||||
) else (
|
) else (
|
||||||
// ... otherwise, use the last parameter, unless it looks like a DOM node
|
// ... otherwise, use the last parameter, unless it looks like a DOM node
|
||||||
this = method.getLastParameter() and
|
this = method.getLastParameter() and
|
||||||
not getName().regexpMatch("(?i)(e(l(em(ent(s)?)?)?)?)")
|
not this.getName().regexpMatch("(?i)(e(l(em(ent(s)?)?)?)?)")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -113,13 +113,13 @@ module UnsafeJQueryPlugin {
|
|||||||
class IsElementSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
|
class IsElementSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
|
||||||
IsElementSanitizer() {
|
IsElementSanitizer() {
|
||||||
// common ad hoc sanitizing calls
|
// common ad hoc sanitizing calls
|
||||||
exists(string name | getCalleeName() = name |
|
exists(string name | this.getCalleeName() = name |
|
||||||
name = "isElement" or name = "isDocument" or name = "isWindow"
|
name = "isElement" or name = "isDocument" or name = "isWindow"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate sanitizes(boolean outcome, Expr e) {
|
override predicate sanitizes(boolean outcome, Expr e) {
|
||||||
outcome = true and e = getArgument(0).asExpr()
|
outcome = true and e = this.getArgument(0).asExpr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,10 +101,10 @@ predicate hostnameSanitizingPrefixEdge(DataFlow::Node source, DataFlow::Node sin
|
|||||||
* A check that sanitizes the hostname of a URL.
|
* A check that sanitizes the hostname of a URL.
|
||||||
*/
|
*/
|
||||||
class HostnameSanitizerGuard extends TaintTracking::SanitizerGuardNode, StringOps::StartsWith {
|
class HostnameSanitizerGuard extends TaintTracking::SanitizerGuardNode, StringOps::StartsWith {
|
||||||
HostnameSanitizerGuard() { hasHostnameSanitizingSubstring(getSubstring()) }
|
HostnameSanitizerGuard() { hasHostnameSanitizingSubstring(this.getSubstring()) }
|
||||||
|
|
||||||
override predicate sanitizes(boolean outcome, Expr e) {
|
override predicate sanitizes(boolean outcome, Expr e) {
|
||||||
outcome = getPolarity() and
|
outcome = this.getPolarity() and
|
||||||
e = getBaseString().asExpr()
|
e = this.getBaseString().asExpr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class TopLevel extends @toplevel {
|
|||||||
Location getLocation() { hasLocation(this, result) }
|
Location getLocation() { hasLocation(this, result) }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate startsAtLine(@file file, int line) { getLocation().startsAtLine(file, line) }
|
predicate startsAtLine(@file file, int line) { this.getLocation().startsAtLine(file, line) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class XmlNode extends @xmllocatable {
|
class XmlNode extends @xmllocatable {
|
||||||
@@ -19,7 +19,7 @@ class XmlNode extends @xmllocatable {
|
|||||||
Location getLocation() { xmllocations(this, result) }
|
Location getLocation() { xmllocations(this, result) }
|
||||||
|
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate startsAtLine(@file file, int line) { getLocation().startsAtLine(file, line) }
|
predicate startsAtLine(@file file, int line) { this.getLocation().startsAtLine(file, line) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on previous implementation on HTMLNode.getCodeInAttribute and getInlineScript,
|
// Based on previous implementation on HTMLNode.getCodeInAttribute and getInlineScript,
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ class CommentedOutCode extends Comment {
|
|||||||
predicate hasLocationInfo(
|
predicate hasLocationInfo(
|
||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
exists(Location loc, File f | loc = getLocation() and f = loc.getFile() |
|
exists(Location loc, File f | loc = this.getLocation() and f = loc.getFile() |
|
||||||
filepath = f.getAbsolutePath() and
|
filepath = f.getAbsolutePath() and
|
||||||
startline = loc.getStartLine() and
|
startline = loc.getStartLine() and
|
||||||
startcolumn = loc.getStartColumn() and
|
startcolumn = loc.getStartColumn() and
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class EvilTwin extends DataFlow::CallNode {
|
|||||||
EvilTwin() {
|
EvilTwin() {
|
||||||
exists(string fn | fn = "setTimeout" or fn = "setInterval" |
|
exists(string fn | fn = "setTimeout" or fn = "setInterval" |
|
||||||
this = DataFlow::globalVarRef(fn).getACall() and
|
this = DataFlow::globalVarRef(fn).getACall() and
|
||||||
getArgument(0).asExpr() instanceof ConstantString
|
this.getArgument(0).asExpr() instanceof ConstantString
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ predicate isCommonPredefinedTypeName(string name) {
|
|||||||
*/
|
*/
|
||||||
class DefiniteTypeDecl extends TypeDecl {
|
class DefiniteTypeDecl extends TypeDecl {
|
||||||
DefiniteTypeDecl() {
|
DefiniteTypeDecl() {
|
||||||
this = any(ImportSpecifier im).getLocal() implies exists(getLocalTypeName().getAnAccess())
|
this = any(ImportSpecifier im).getLocal() implies exists(this.getLocalTypeName().getAnAccess())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ predicate isImportedAtRuntime(Module source, Module destination) {
|
|||||||
*/
|
*/
|
||||||
class CandidateVarAccess extends VarAccess {
|
class CandidateVarAccess extends VarAccess {
|
||||||
CandidateVarAccess() {
|
CandidateVarAccess() {
|
||||||
isImmediatelyExecutedContainer(getContainer()) and
|
isImmediatelyExecutedContainer(this.getContainer()) and
|
||||||
not exists(ExportSpecifier spec | spec.getLocal() = this)
|
not exists(ExportSpecifier spec | spec.getLocal() = this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ class ImportVarDeclProvider extends Stmt {
|
|||||||
* Gets an unacceptable unused variable declared by this import.
|
* Gets an unacceptable unused variable declared by this import.
|
||||||
*/
|
*/
|
||||||
UnusedLocal getAnUnacceptableUnusedLocal() {
|
UnusedLocal getAnUnacceptableUnusedLocal() {
|
||||||
result = getAVarDecl().getVariable() and
|
result = this.getAVarDecl().getVariable() and
|
||||||
not whitelisted(result)
|
not whitelisted(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ import Clones
|
|||||||
abstract class RedundantOperand extends StructurallyCompared {
|
abstract class RedundantOperand extends StructurallyCompared {
|
||||||
RedundantOperand() { exists(BinaryExpr parent | this = parent.getLeftOperand()) }
|
RedundantOperand() { exists(BinaryExpr parent | this = parent.getLeftOperand()) }
|
||||||
|
|
||||||
override Expr candidate() { result = getParent().(BinaryExpr).getRightOperand() }
|
override Expr candidate() { result = this.getParent().(BinaryExpr).getRightOperand() }
|
||||||
|
|
||||||
/** Gets the expression to report when a pair of clones is found. */
|
/** Gets the expression to report when a pair of clones is found. */
|
||||||
Expr toReport() { result = getParent() }
|
Expr toReport() { result = this.getParent() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,7 +50,7 @@ class IdemnecantExpr extends BinaryExpr {
|
|||||||
class RedundantIdemnecantOperand extends RedundantOperand {
|
class RedundantIdemnecantOperand extends RedundantOperand {
|
||||||
RedundantIdemnecantOperand() {
|
RedundantIdemnecantOperand() {
|
||||||
exists(IdemnecantExpr parent |
|
exists(IdemnecantExpr parent |
|
||||||
parent = getParent() and
|
parent = this.getParent() and
|
||||||
// exclude trivial cases like `1-1`
|
// exclude trivial cases like `1-1`
|
||||||
not parent.getRightOperand().getUnderlyingValue() instanceof Literal
|
not parent.getRightOperand().getUnderlyingValue() instanceof Literal
|
||||||
)
|
)
|
||||||
@@ -65,7 +65,7 @@ class RedundantIdemnecantOperand extends RedundantOperand {
|
|||||||
*/
|
*/
|
||||||
class RedundantIdempotentOperand extends RedundantOperand {
|
class RedundantIdempotentOperand extends RedundantOperand {
|
||||||
RedundantIdempotentOperand() {
|
RedundantIdempotentOperand() {
|
||||||
getParent() instanceof LogicalBinaryExpr and
|
this.getParent() instanceof LogicalBinaryExpr and
|
||||||
not exists(UpdateExpr e | e.getParentExpr+() = this)
|
not exists(UpdateExpr e | e.getParentExpr+() = this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,8 +75,8 @@ class RedundantIdempotentOperand extends RedundantOperand {
|
|||||||
*/
|
*/
|
||||||
class AverageExpr extends DivExpr {
|
class AverageExpr extends DivExpr {
|
||||||
AverageExpr() {
|
AverageExpr() {
|
||||||
getLeftOperand().getUnderlyingValue() instanceof AddExpr and
|
this.getLeftOperand().getUnderlyingValue() instanceof AddExpr and
|
||||||
getRightOperand().getIntValue() = 2
|
this.getRightOperand().getIntValue() = 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,10 +85,14 @@ class AverageExpr extends DivExpr {
|
|||||||
*/
|
*/
|
||||||
class RedundantAverageOperand extends RedundantOperand {
|
class RedundantAverageOperand extends RedundantOperand {
|
||||||
RedundantAverageOperand() {
|
RedundantAverageOperand() {
|
||||||
exists(AverageExpr aver | getParent().(AddExpr) = aver.getLeftOperand().getUnderlyingValue())
|
exists(AverageExpr aver |
|
||||||
|
this.getParent().(AddExpr) = aver.getLeftOperand().getUnderlyingValue()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AverageExpr toReport() { getParent() = result.getLeftOperand().getUnderlyingValue() }
|
override AverageExpr toReport() {
|
||||||
|
this.getParent() = result.getLeftOperand().getUnderlyingValue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from RedundantOperand e, Expr f
|
from RedundantOperand e, Expr f
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import javascript
|
|||||||
class OmittedArrayElement extends ArrayExpr {
|
class OmittedArrayElement extends ArrayExpr {
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
OmittedArrayElement() { idx = min(int i | elementIsOmitted(i)) }
|
OmittedArrayElement() { idx = min(int i | this.elementIsOmitted(i)) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if this element is at the specified location.
|
* Holds if this element is at the specified location.
|
||||||
@@ -35,9 +35,9 @@ class OmittedArrayElement extends ArrayExpr {
|
|||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
exists(Token pre, Location before, Location after |
|
exists(Token pre, Location before, Location after |
|
||||||
idx = 0 and pre = getFirstToken()
|
idx = 0 and pre = this.getFirstToken()
|
||||||
or
|
or
|
||||||
pre = getElement(idx - 1).getLastToken().getNextToken()
|
pre = this.getElement(idx - 1).getLastToken().getNextToken()
|
||||||
|
|
|
|
||||||
before = pre.getLocation() and
|
before = pre.getLocation() and
|
||||||
after = pre.getNextToken().getLocation() and
|
after = pre.getNextToken().getLocation() and
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ class RootDestructuringPattern extends DestructuringPattern {
|
|||||||
/** Holds if this pattern has multiple bindings for `name`. */
|
/** Holds if this pattern has multiple bindings for `name`. */
|
||||||
predicate hasConflictingBindings(string name) {
|
predicate hasConflictingBindings(string name) {
|
||||||
exists(VarRef v, VarRef w |
|
exists(VarRef v, VarRef w |
|
||||||
v = getABindingVarRef() and
|
v = this.getABindingVarRef() and
|
||||||
w = getABindingVarRef() and
|
w = this.getABindingVarRef() and
|
||||||
name = v.getName() and
|
name = v.getName() and
|
||||||
name = w.getName() and
|
name = w.getName() and
|
||||||
v != w
|
v != w
|
||||||
@@ -33,10 +33,10 @@ class RootDestructuringPattern extends DestructuringPattern {
|
|||||||
|
|
||||||
/** Gets the first occurrence of the conflicting binding `name`. */
|
/** Gets the first occurrence of the conflicting binding `name`. */
|
||||||
VarDecl getFirstClobberedVarDecl(string name) {
|
VarDecl getFirstClobberedVarDecl(string name) {
|
||||||
hasConflictingBindings(name) and
|
this.hasConflictingBindings(name) and
|
||||||
result =
|
result =
|
||||||
min(VarDecl decl |
|
min(VarDecl decl |
|
||||||
decl = getABindingVarRef() and decl.getName() = name
|
decl = this.getABindingVarRef() and decl.getName() = name
|
||||||
|
|
|
|
||||||
decl order by decl.getLocation().getStartLine(), decl.getLocation().getStartColumn()
|
decl order by decl.getLocation().getStartLine(), decl.getLocation().getStartColumn()
|
||||||
)
|
)
|
||||||
@@ -44,11 +44,11 @@ class RootDestructuringPattern extends DestructuringPattern {
|
|||||||
|
|
||||||
/** Holds if variables in this pattern may resemble type annotations. */
|
/** Holds if variables in this pattern may resemble type annotations. */
|
||||||
predicate resemblesTypeAnnotation() {
|
predicate resemblesTypeAnnotation() {
|
||||||
hasConflictingBindings(_) and // Restrict size of predicate.
|
this.hasConflictingBindings(_) and // Restrict size of predicate.
|
||||||
this instanceof Parameter and
|
this instanceof Parameter and
|
||||||
this instanceof ObjectPattern and
|
this instanceof ObjectPattern and
|
||||||
not exists(getTypeAnnotation()) and
|
not exists(this.getTypeAnnotation()) and
|
||||||
getFile().getFileType().isTypeScript()
|
this.getFile().getFileType().isTypeScript()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class SpuriousArguments extends Expr {
|
|||||||
* expected by any potential callee.
|
* expected by any potential callee.
|
||||||
*/
|
*/
|
||||||
int getCount() {
|
int getCount() {
|
||||||
result = count(int i | exists(invk.getArgument(i)) and i >= maxArity(getCall()))
|
result = count(int i | exists(invk.getArgument(i)) and i >= maxArity(this.getCall()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +73,7 @@ class SpuriousArguments extends Expr {
|
|||||||
predicate hasLocationInfo(
|
predicate hasLocationInfo(
|
||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||||
exists(DataFlow::Node lastArg |
|
exists(DataFlow::Node lastArg |
|
||||||
lastArg = max(DataFlow::Node arg, int i | arg = invk.getArgument(i) | arg order by i)
|
lastArg = max(DataFlow::Node arg, int i | arg = invk.getArgument(i) | arg order by i)
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ class RegExpSearchCall extends DataFlow::MethodCallNode, RegExpQuery {
|
|||||||
DataFlow::RegExpCreationNode regexp;
|
DataFlow::RegExpCreationNode regexp;
|
||||||
|
|
||||||
RegExpSearchCall() {
|
RegExpSearchCall() {
|
||||||
getMethodName() = "search" and
|
this.getMethodName() = "search" and
|
||||||
regexp.getAReference().flowsTo(getArgument(0))
|
regexp.getAReference().flowsTo(this.getArgument(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
override RegExpTerm getRegExp() { result = regexp.getRoot() }
|
override RegExpTerm getRegExp() { result = regexp.getRoot() }
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ class RegExpPatternMistake extends TRegExpPatternMistake {
|
|||||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||||
) {
|
) {
|
||||||
exists(int srcStartcolumn, int srcEndcolumn, int index |
|
exists(int srcStartcolumn, int srcEndcolumn, int index |
|
||||||
index = getIndex() and
|
index = this.getIndex() and
|
||||||
getRawStringNode()
|
this.getRawStringNode()
|
||||||
.getLocation()
|
.getLocation()
|
||||||
.hasLocationInfo(filepath, startline, srcStartcolumn, endline, srcEndcolumn)
|
.hasLocationInfo(filepath, startline, srcStartcolumn, endline, srcEndcolumn)
|
||||||
|
|
|
|
||||||
@@ -89,7 +89,7 @@ class RegExpPatternMistake extends TRegExpPatternMistake {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a textual representation of this element. */
|
/** Gets a textual representation of this element. */
|
||||||
string toString() { result = getMessage() }
|
string toString() { result = this.getMessage() }
|
||||||
|
|
||||||
abstract AstNode getRawStringNode();
|
abstract AstNode getRawStringNode();
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ private import semmle.javascript.dataflow.InferredTypes
|
|||||||
*/
|
*/
|
||||||
class SplitCall extends StringSplitCall {
|
class SplitCall extends StringSplitCall {
|
||||||
SplitCall() {
|
SplitCall() {
|
||||||
getSeparator() = "." and
|
this.getSeparator() = "." and
|
||||||
getBaseString().getALocalSource() instanceof ParameterNode
|
this.getBaseString().getALocalSource() instanceof ParameterNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ class SplitPropName extends SourceNode {
|
|||||||
SourceNode getArray() { result = array }
|
SourceNode getArray() { result = array }
|
||||||
|
|
||||||
/** Gets an element accessed on the same underlying array. */
|
/** Gets an element accessed on the same underlying array. */
|
||||||
SplitPropName getAnAlias() { result.getArray() = getArray() }
|
SplitPropName getAnAlias() { result.getArray() = this.getArray() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -434,13 +434,13 @@ class DenyListInclusionGuard extends DataFlow::LabeledBarrierGuardNode, Inclusio
|
|||||||
DenyListInclusionGuard() {
|
DenyListInclusionGuard() {
|
||||||
exists(DataFlow::ArrayCreationNode array |
|
exists(DataFlow::ArrayCreationNode array |
|
||||||
array.getAnElement().getStringValue() = label and
|
array.getAnElement().getStringValue() = label and
|
||||||
array.flowsTo(getContainerNode())
|
array.flowsTo(this.getContainerNode())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
|
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
|
||||||
outcome = getPolarity().booleanNot() and
|
outcome = this.getPolarity().booleanNot() and
|
||||||
e = getContainedNode().asExpr() and
|
e = this.getContainedNode().asExpr() and
|
||||||
label = lbl
|
label = lbl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -475,7 +475,7 @@ class IsPlainObjectGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::Ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
|
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
|
||||||
e = getArgument(0).asExpr() and
|
e = this.getArgument(0).asExpr() and
|
||||||
outcome = true and
|
outcome = true and
|
||||||
lbl = "constructor"
|
lbl = "constructor"
|
||||||
}
|
}
|
||||||
@@ -561,7 +561,7 @@ DataFlow::SourceNode getANodeLeadingToBaseBase(Node base) {
|
|||||||
class ObjectCreateNullCall extends CallNode {
|
class ObjectCreateNullCall extends CallNode {
|
||||||
ObjectCreateNullCall() {
|
ObjectCreateNullCall() {
|
||||||
this = globalVarRef("Object").getAMemberCall("create") and
|
this = globalVarRef("Object").getAMemberCall("create") and
|
||||||
getArgument(0).asExpr() instanceof NullLiteral
|
this.getArgument(0).asExpr() instanceof NullLiteral
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user