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;
|
||||
|
||||
DecodingCall() {
|
||||
getCalleeName().matches("decodeURI%") and
|
||||
input = getArgument(0) and
|
||||
this.getCalleeName().matches("decodeURI%") and
|
||||
input = this.getArgument(0) and
|
||||
kind = "URI decoding"
|
||||
or
|
||||
input = this.(JsonParserCall).getInput() and
|
||||
|
||||
@@ -11,7 +11,7 @@ import LanguageFeatures.UnusedIndexVariable
|
||||
*/
|
||||
class UnusedLocal extends LocalVariable {
|
||||
UnusedLocal() {
|
||||
not exists(getAnAccess()) and
|
||||
not exists(this.getAnAccess()) and
|
||||
not exists(Parameter p | this = p.getAVariable()) and
|
||||
not exists(FunctionExpr fe | this = fe.getVariable()) and
|
||||
not exists(ClassExpr ce | this = ce.getVariable()) and
|
||||
@@ -20,6 +20,6 @@ class UnusedLocal extends LocalVariable {
|
||||
// avoid double reporting
|
||||
not unusedIndexVariable(_, this, _) and
|
||||
// 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.
|
||||
*/
|
||||
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 {
|
||||
AmdModuleDefinition() {
|
||||
inVoidContext(this) and
|
||||
getCallee().(GlobalVarAccess).getName() = "define" and
|
||||
exists(int n | n = getNumArgument() |
|
||||
this.getCallee().(GlobalVarAccess).getName() = "define" and
|
||||
exists(int n | n = this.getNumArgument() |
|
||||
n = 1
|
||||
or
|
||||
n = 2 and getArgument(0) instanceof ArrayExpr
|
||||
n = 2 and this.getArgument(0) instanceof ArrayExpr
|
||||
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. */
|
||||
ArrayExpr getDependencies() {
|
||||
result = getArgument(0) or
|
||||
result = getArgument(1)
|
||||
result = this.getArgument(0) or
|
||||
result = this.getArgument(1)
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
PathExpr getADependency() {
|
||||
result = getDependency(_) or
|
||||
result = getARequireCall().getAnArgument()
|
||||
result = this.getDependency(_) or
|
||||
result = this.getARequireCall().getAnArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,19 +60,19 @@ class AmdModuleDefinition extends CallExpr {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
DataFlow::SourceNode getFactoryNode() {
|
||||
result = getFactoryNodeInternal() and
|
||||
result = this.getFactoryNodeInternal() and
|
||||
result instanceof DataFlow::ValueNode
|
||||
}
|
||||
|
||||
private DataFlow::Node getFactoryNodeInternal() {
|
||||
// To avoid recursion, this should not depend on `SourceNode`.
|
||||
result = DataFlow::valueNode(getLastArgument()) or
|
||||
result = getFactoryNodeInternal().getAPredecessor()
|
||||
result = DataFlow::valueNode(this.getLastArgument()) or
|
||||
result = this.getFactoryNodeInternal().getAPredecessor()
|
||||
}
|
||||
|
||||
/** Gets the expression defining this module. */
|
||||
Expr getModuleExpr() {
|
||||
exists(DataFlow::Node f | f = getFactoryNode() |
|
||||
exists(DataFlow::Node f | f = this.getFactoryNode() |
|
||||
if f instanceof DataFlow::FunctionNode
|
||||
then
|
||||
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. */
|
||||
DataFlow::SourceNode getAModuleSource() { result.flowsToExpr(getModuleExpr()) }
|
||||
DataFlow::SourceNode getAModuleSource() { result.flowsToExpr(this.getModuleExpr()) }
|
||||
|
||||
/**
|
||||
* Holds if `p` is the parameter corresponding to dependency `dep`.
|
||||
*/
|
||||
predicate dependencyParameter(PathExpr dep, Parameter p) {
|
||||
exists(int i |
|
||||
dep = getDependency(i) and
|
||||
p = getFactoryParameter(i)
|
||||
dep = this.getDependency(i) and
|
||||
p = this.getFactoryParameter(i)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -107,7 +109,7 @@ class AmdModuleDefinition extends CallExpr {
|
||||
*/
|
||||
Parameter getDependencyParameter(string name) {
|
||||
exists(PathExpr dep |
|
||||
dependencyParameter(dep, result) and
|
||||
this.dependencyParameter(dep, result) and
|
||||
dep.getValue() = name
|
||||
)
|
||||
}
|
||||
@@ -116,40 +118,40 @@ class AmdModuleDefinition extends CallExpr {
|
||||
* Gets the `i`th parameter of the factory function of this module.
|
||||
*/
|
||||
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`.
|
||||
*/
|
||||
Parameter getRequireParameter() {
|
||||
result = getDependencyParameter("require")
|
||||
result = this.getDependencyParameter("require")
|
||||
or
|
||||
// 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]
|
||||
private Variable getRequireVariable() { result = getRequireParameter().getVariable() }
|
||||
private Variable getRequireVariable() { result = this.getRequireParameter().getVariable() }
|
||||
|
||||
/**
|
||||
* Gets the parameter corresponding to the pseudo-dependency `exports`.
|
||||
*/
|
||||
Parameter getExportsParameter() {
|
||||
result = getDependencyParameter("exports")
|
||||
result = this.getDependencyParameter("exports")
|
||||
or
|
||||
// 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`.
|
||||
*/
|
||||
Parameter getModuleParameter() {
|
||||
result = getDependencyParameter("module")
|
||||
result = this.getDependencyParameter("module")
|
||||
or
|
||||
// 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.
|
||||
*/
|
||||
DefiniteAbstractValue getAModuleExportsValue() {
|
||||
result = [getAnImplicitExportsValue(), getAnExplicitExportsValue()]
|
||||
result = [this.getAnImplicitExportsValue(), this.getAnExplicitExportsValue()]
|
||||
}
|
||||
|
||||
pragma[noinline, nomagic]
|
||||
private AbstractValue getAnImplicitExportsValue() {
|
||||
// implicit exports: anything that is returned from the factory function
|
||||
result = getModuleExpr().analyze().getAValue()
|
||||
result = this.getModuleExpr().analyze().getAValue()
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
@@ -182,7 +184,7 @@ class AmdModuleDefinition extends CallExpr {
|
||||
* Gets a call to `require` inside this module.
|
||||
*/
|
||||
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 {
|
||||
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() {
|
||||
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")
|
||||
or
|
||||
@@ -262,7 +264,7 @@ private class AmdDependencyImport extends Import {
|
||||
private predicate targetCandidate(
|
||||
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.getAbsolutePath() = abspath 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.
|
||||
*/
|
||||
private Module resolveByAbsolutePath() {
|
||||
result.getFile() = unique(File file | file = guessTarget())
|
||||
result.getFile() = unique(File file | file = this.guessTarget())
|
||||
}
|
||||
|
||||
override Module getImportedModule() {
|
||||
result = super.getImportedModule()
|
||||
or
|
||||
not exists(super.getImportedModule()) and
|
||||
result = resolveByAbsolutePath()
|
||||
result = this.resolveByAbsolutePath()
|
||||
}
|
||||
|
||||
override DataFlow::Node getImportedModuleNode() {
|
||||
@@ -314,7 +316,7 @@ class AmdModule extends Module {
|
||||
|
||||
override DataFlow::Node getAnExportedValue(string name) {
|
||||
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()
|
||||
)
|
||||
}
|
||||
@@ -329,6 +331,6 @@ class AmdModule extends Module {
|
||||
)
|
||||
or
|
||||
// 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 {
|
||||
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 }
|
||||
}
|
||||
@@ -82,7 +82,7 @@ private class Btoa extends Base64::Encode::Range, DataFlow::CallNode {
|
||||
private class Atob extends Base64::Decode::Range, DataFlow::CallNode {
|
||||
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 }
|
||||
}
|
||||
@@ -93,11 +93,11 @@ private class Atob extends Base64::Decode::Range, DataFlow::CallNode {
|
||||
*/
|
||||
private class Buffer_toString extends Base64::Encode::Range, DataFlow::MethodCallNode {
|
||||
Buffer_toString() {
|
||||
getMethodName() = "toString" and
|
||||
getArgument(0).mayHaveStringValue("base64")
|
||||
this.getMethodName() = "toString" and
|
||||
this.getArgument(0).mayHaveStringValue("base64")
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput() { result = getReceiver() }
|
||||
override DataFlow::Node getInput() { result = this.getReceiver() }
|
||||
|
||||
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 {
|
||||
Buffer_from() {
|
||||
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 }
|
||||
}
|
||||
@@ -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 }
|
||||
}
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -288,10 +288,10 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
|
||||
ControlFlowNode getAPredecessor() { this = result.getASuccessor() }
|
||||
|
||||
/** 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. */
|
||||
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
|
||||
@@ -304,14 +304,14 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
|
||||
* of that toplevel or function terminates.
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
@@ -327,7 +327,7 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
|
||||
* `s1` is unreachable, but `s2` is not.
|
||||
*/
|
||||
predicate isUnreachable() {
|
||||
forall(ControlFlowNode pred | pred = getAPredecessor() |
|
||||
forall(ControlFlowNode pred | pred = this.getAPredecessor() |
|
||||
pred.(SyntheticControlFlowNode).isUnreachable()
|
||||
)
|
||||
// note the override in ControlFlowEntryNode below
|
||||
@@ -348,7 +348,7 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
|
||||
else
|
||||
if this instanceof @decorator_list
|
||||
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 {
|
||||
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. */
|
||||
@@ -373,7 +373,7 @@ class ControlFlowExitNode extends SyntheticControlFlowNode, @exit_node {
|
||||
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
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
CanonicalName getChild(string name) {
|
||||
result = getAChild() and
|
||||
result = this.getAChild() and
|
||||
result.getName() = name
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class CanonicalName extends @symbol {
|
||||
symbol_module(this, result)
|
||||
or
|
||||
exists(PackageJson pkg |
|
||||
getModule() = pkg.getMainModule() and
|
||||
this.getModule() = pkg.getMainModule() and
|
||||
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.
|
||||
*/
|
||||
predicate hasChild() { exists(getAChild()) }
|
||||
predicate hasChild() { exists(this.getAChild()) }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
predicate isModuleRoot() {
|
||||
exists(getModule()) or
|
||||
exists(getExternalModuleName())
|
||||
exists(this.getModule()) or
|
||||
exists(this.getExternalModuleName())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,22 +98,22 @@ class CanonicalName extends @symbol {
|
||||
|
||||
/** Holds if this has the given qualified name, rooted in the global scope. */
|
||||
predicate hasQualifiedName(string globalName) {
|
||||
globalName = getGlobalName()
|
||||
globalName = this.getGlobalName()
|
||||
or
|
||||
exists(string prefix |
|
||||
getParent().hasQualifiedName(prefix) and
|
||||
globalName = prefix + "." + getName()
|
||||
this.getParent().hasQualifiedName(prefix) and
|
||||
globalName = prefix + "." + this.getName()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this has the given qualified name, rooted in the given external module. */
|
||||
predicate hasQualifiedName(string moduleName, string exportedName) {
|
||||
moduleName = getParent().getExternalModuleName() and
|
||||
exportedName = getName()
|
||||
moduleName = this.getParent().getExternalModuleName() and
|
||||
exportedName = this.getName()
|
||||
or
|
||||
exists(string prefix |
|
||||
getParent().hasQualifiedName(moduleName, prefix) and
|
||||
exportedName = prefix + "." + getName()
|
||||
this.getParent().hasQualifiedName(moduleName, prefix) and
|
||||
exportedName = prefix + "." + this.getName()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -121,16 +121,16 @@ class CanonicalName extends @symbol {
|
||||
* Gets the qualified name without the root.
|
||||
*/
|
||||
string getRelativeName() {
|
||||
if getParent().isModuleRoot()
|
||||
then result = getName()
|
||||
if this.getParent().isModuleRoot()
|
||||
then result = this.getName()
|
||||
else
|
||||
if exists(getGlobalName())
|
||||
then result = min(getGlobalName())
|
||||
if exists(this.getGlobalName())
|
||||
then result = min(this.getGlobalName())
|
||||
else
|
||||
if exists(getParent())
|
||||
then result = getParent().getRelativeName() + "." + getName()
|
||||
if exists(this.getParent())
|
||||
then result = this.getParent().getRelativeName() + "." + this.getName()
|
||||
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.
|
||||
*/
|
||||
Scope getRootScope() {
|
||||
exists(CanonicalName root | root = getRootName() |
|
||||
exists(CanonicalName root | root = this.getRootName() |
|
||||
if exists(root.getModule())
|
||||
then result = root.getModule().getScope()
|
||||
else
|
||||
if exists(root.getGlobalName())
|
||||
then result instanceof GlobalScope
|
||||
else result = getADefinition().getContainer().getScope()
|
||||
else result = this.getADefinition().getContainer().getScope()
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
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.
|
||||
*/
|
||||
string describeRoot() {
|
||||
exists(CanonicalName root | root = getRootName() |
|
||||
exists(CanonicalName root | root = this.getRootName() |
|
||||
if exists(root.getExternalModuleName())
|
||||
then result = "module '" + min(root.getExternalModuleName()) + "'"
|
||||
else
|
||||
@@ -209,9 +209,9 @@ class CanonicalName extends @symbol {
|
||||
* ```
|
||||
*/
|
||||
string toString() {
|
||||
if isModuleRoot()
|
||||
then result = describeRoot()
|
||||
else result = getRelativeName() + " in " + describeRoot()
|
||||
if this.isModuleRoot()
|
||||
then result = this.describeRoot()
|
||||
else result = this.getRelativeName() + " in " + this.describeRoot()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +263,7 @@ class TypeName extends CanonicalName {
|
||||
*/
|
||||
class Namespace extends CanonicalName {
|
||||
Namespace() {
|
||||
getAChild().isExportedMember() or
|
||||
this.getAChild().isExportedMember() or
|
||||
exists(NamespaceDefinition def | ast_node_symbol(def, this)) or
|
||||
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.
|
||||
*/
|
||||
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() }
|
||||
|
||||
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 {
|
||||
DefaultClosureProvideCall() {
|
||||
getMethodName() = "provide" and
|
||||
this.getMethodName() = "provide" and
|
||||
isTopLevelExpr(this)
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ module Closure {
|
||||
*/
|
||||
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 {
|
||||
DefaultClosureModuleDeclaration() {
|
||||
(getMethodName() = "module" or getMethodName() = "declareModuleId") and
|
||||
(this.getMethodName() = "module" or this.getMethodName() = "declareModuleId") and
|
||||
isTopLevelExpr(this)
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ module Closure {
|
||||
/**
|
||||
* Gets the namespace of this module.
|
||||
*/
|
||||
string getClosureNamespace() { result = getModuleDeclaration().getClosureNamespace() }
|
||||
string getClosureNamespace() { result = this.getModuleDeclaration().getClosureNamespace() }
|
||||
|
||||
override Module getAnImportedModule() {
|
||||
result.(ClosureModule).getClosureNamespace() =
|
||||
@@ -156,8 +156,8 @@ module Closure {
|
||||
* Has no result for ES6 modules using `goog.declareModuleId`.
|
||||
*/
|
||||
Variable getExportsVariable() {
|
||||
getModuleDeclaration().getMethodName() = "module" and
|
||||
result = getScope().getVariable("exports")
|
||||
this.getModuleDeclaration().getMethodName() = "module" and
|
||||
result = this.getScope().getVariable("exports")
|
||||
}
|
||||
|
||||
override DataFlow::Node getAnExportedValue(string name) {
|
||||
@@ -165,15 +165,15 @@ module Closure {
|
||||
result = write.getRhs() and
|
||||
write.writes(base.flow(), name, _) and
|
||||
(
|
||||
base = getExportsVariable().getAReference()
|
||||
base = this.getExportsVariable().getAReference()
|
||||
or
|
||||
base = getExportsVariable().getAnAssignedExpr()
|
||||
base = this.getExportsVariable().getAnAssignedExpr()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
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) {
|
||||
index >= 0 and
|
||||
callback = getArgument(0) and
|
||||
argument = getArgument(index + 2)
|
||||
callback = this.getArgument(0) and
|
||||
argument = this.getArgument(index + 2)
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
|
||||
boundArgs = getNumArgument() - 2 and
|
||||
callback = getArgument(0) and
|
||||
boundArgs = this.getNumArgument() - 2 and
|
||||
callback = this.getArgument(0) and
|
||||
result = this
|
||||
}
|
||||
|
||||
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
||||
callback = getArgument(0) and
|
||||
result = getArgument(1)
|
||||
callback = this.getArgument(0) and
|
||||
result = this.getArgument(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,18 +24,18 @@ class Comment extends @comment, Locatable {
|
||||
string getText() { comments(this, _, _, result, _) }
|
||||
|
||||
/** 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. */
|
||||
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) }
|
||||
|
||||
/** Holds if this comment spans lines `start` to `end` (inclusive) in file `f`. */
|
||||
predicate onLines(File f, int start, int end) {
|
||||
exists(Location loc | loc = getLocation() |
|
||||
exists(Location loc | loc = this.getLocation() |
|
||||
f = loc.getFile() and
|
||||
start = loc.getStartLine() and
|
||||
end = loc.getEndLine()
|
||||
|
||||
@@ -61,7 +61,7 @@ module SyntacticConstants {
|
||||
cached
|
||||
class UnaryConstant extends SyntacticConstant, UnaryExpr {
|
||||
cached
|
||||
UnaryConstant() { getOperand() instanceof SyntacticConstant }
|
||||
UnaryConstant() { this.getOperand() instanceof SyntacticConstant }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,8 +71,8 @@ module SyntacticConstants {
|
||||
class BinaryConstant extends SyntacticConstant, BinaryExpr {
|
||||
cached
|
||||
BinaryConstant() {
|
||||
getLeftOperand() instanceof SyntacticConstant and
|
||||
getRightOperand() instanceof SyntacticConstant
|
||||
this.getLeftOperand() instanceof SyntacticConstant and
|
||||
this.getRightOperand() instanceof SyntacticConstant
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ module SyntacticConstants {
|
||||
class ConditionalConstant extends SyntacticConstant, ConditionalExpr {
|
||||
cached
|
||||
ConditionalConstant() {
|
||||
getCondition() instanceof SyntacticConstant and
|
||||
getConsequent() instanceof SyntacticConstant and
|
||||
getAlternate() instanceof SyntacticConstant
|
||||
this.getCondition() instanceof SyntacticConstant and
|
||||
this.getConsequent() instanceof SyntacticConstant and
|
||||
this.getAlternate() instanceof SyntacticConstant
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ module SyntacticConstants {
|
||||
cached
|
||||
class WrappedConstant extends SyntacticConstant {
|
||||
cached
|
||||
WrappedConstant() { getUnderlyingValue() instanceof SyntacticConstant }
|
||||
WrappedConstant() { this.getUnderlyingValue() instanceof SyntacticConstant }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,5 +150,5 @@ module SyntacticConstants {
|
||||
cached
|
||||
class ConstantString extends ConstantExpr {
|
||||
cached
|
||||
ConstantString() { exists(getStringValue()) }
|
||||
ConstantString() { exists(this.getStringValue()) }
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ class VarDef extends ControlFlowNode {
|
||||
Expr getTarget() { defn(this, result) }
|
||||
|
||||
/** 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
|
||||
@@ -232,8 +232,8 @@ class VarUse extends ControlFlowNode, @varref instanceof RValue {
|
||||
* For global variables, each definition is considered to reach each use.
|
||||
*/
|
||||
VarDef getADef() {
|
||||
result = getSsaVariable().getDefinition().getAContributingVarDef() or
|
||||
result.getAVariable() = getVariable().(GlobalVariable)
|
||||
result = this.getSsaVariable().getDefinition().getAContributingVarDef() or
|
||||
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.
|
||||
*/
|
||||
DataFlow::SourceNode getASourceObjectRef() {
|
||||
result = AccessPath::getAnAliasedSourceNode(getSourceObject())
|
||||
result = AccessPath::getAnAliasedSourceNode(this.getSourceObject())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,7 +53,7 @@ abstract class EnumeratedPropName extends DataFlow::Node {
|
||||
SourceNode getASourceProp() {
|
||||
exists(Node base, Node key |
|
||||
dynamicPropReadStep(base, key, result) and
|
||||
getASourceObjectRef().flowsTo(base) and
|
||||
this.getASourceObjectRef().flowsTo(base) and
|
||||
key.getImmediatePredecessor*() = this
|
||||
)
|
||||
}
|
||||
|
||||
@@ -37,14 +37,14 @@ module E4X {
|
||||
* Gets the left operand of this qualified identifier, which is either
|
||||
* 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
|
||||
* an identifier, or an arbitrary expression for computed qualified
|
||||
* 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
|
||||
@@ -53,7 +53,7 @@ module E4X {
|
||||
predicate isComputed() { this instanceof @e4x_xml_dynamic_qualident }
|
||||
|
||||
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
|
||||
* 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
|
||||
@@ -85,7 +85,7 @@ module E4X {
|
||||
predicate isComputed() { this instanceof @e4x_xml_dynamic_attribute_selector }
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() {
|
||||
result = getAttribute().getFirstControlFlowNode()
|
||||
result = this.getAttribute().getFirstControlFlowNode()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,15 +105,15 @@ module E4X {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
Expr getRight() { result = getChildExpr(1) }
|
||||
Expr getRight() { result = this.getChildExpr(1) }
|
||||
|
||||
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.
|
||||
*/
|
||||
Expr getBase() { result = getChildExpr(0) }
|
||||
Expr getBase() { result = this.getChildExpr(0) }
|
||||
|
||||
/**
|
||||
* Gets the index expression of this dot-dot expression.
|
||||
*/
|
||||
Expr getIndex() { result = getChildExpr(1) }
|
||||
Expr getIndex() { result = this.getChildExpr(1) }
|
||||
|
||||
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.
|
||||
*/
|
||||
DataFlow::Node getABody() {
|
||||
result = getPlainTextBody() or
|
||||
result = getHtmlBody()
|
||||
result = this.getPlainTextBody() or
|
||||
result = this.getHtmlBody()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,13 +47,13 @@ private class NodemailerEmailSender extends EmailSender, DataFlow::MethodCallNod
|
||||
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. */
|
||||
abstract string getMessage();
|
||||
|
||||
override string toString() { result = getMessage() }
|
||||
override string toString() { result = this.getMessage() }
|
||||
|
||||
/** Holds if this error prevented the file from being extracted. */
|
||||
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. */
|
||||
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.
|
||||
*/
|
||||
DataFlow::Node getAnOperand() {
|
||||
result = getASourceOperand() or
|
||||
result = getDestinationOperand()
|
||||
result = this.getASourceOperand() or
|
||||
result = this.getDestinationOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,22 +55,22 @@ private class ExtendCallWithFlag extends ExtendCall {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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() {
|
||||
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() }
|
||||
}
|
||||
@@ -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() }
|
||||
}
|
||||
@@ -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() }
|
||||
|
||||
@@ -206,7 +210,7 @@ private class WebpackMergeDeep extends ExtendCall, DataFlow::CallNode {
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getASourceOperand() { result = getAnArgument() }
|
||||
override DataFlow::Node getASourceOperand() { result = this.getAnArgument() }
|
||||
|
||||
override DataFlow::Node getDestinationOperand() { none() }
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ module HTML {
|
||||
* An HTML file.
|
||||
*/
|
||||
class HtmlFile extends File {
|
||||
HtmlFile() { getFileType().isHtml() }
|
||||
HtmlFile() { this.getFileType().isHtml() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -18,7 +18,7 @@ module HTML {
|
||||
*/
|
||||
private class FileContainingHtml extends File {
|
||||
FileContainingHtml() {
|
||||
getFileType().isHtml()
|
||||
this.getFileType().isHtml()
|
||||
or
|
||||
// The file contains an expression containing an HTML element
|
||||
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.
|
||||
*/
|
||||
predicate isTopLevel() { not exists(getParent()) }
|
||||
predicate isTopLevel() { not exists(this.getParent()) }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
@@ -80,7 +82,7 @@ module HTML {
|
||||
/**
|
||||
* 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.
|
||||
@@ -90,17 +92,17 @@ module HTML {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
Attribute getAttributeByName(string name) {
|
||||
result = getAnAttribute() and
|
||||
result = this.getAnAttribute() and
|
||||
result.getName() = name
|
||||
}
|
||||
|
||||
override string toString() { result = "<" + getName() + ">...</>" }
|
||||
override string toString() { result = "<" + this.getName() + ">...</>" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "HTML::Element" }
|
||||
}
|
||||
@@ -136,7 +138,7 @@ module HTML {
|
||||
* Gets the root element in which the element to which this attribute
|
||||
* belongs is contained.
|
||||
*/
|
||||
Element getRoot() { result = getElement().getRoot() }
|
||||
Element getRoot() { result = this.getElement().getRoot() }
|
||||
|
||||
/**
|
||||
* Gets the name of this attribute.
|
||||
@@ -151,7 +153,7 @@ module HTML {
|
||||
*/
|
||||
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" }
|
||||
}
|
||||
@@ -170,7 +172,7 @@ module HTML {
|
||||
* ```
|
||||
*/
|
||||
class DocumentElement extends Element {
|
||||
DocumentElement() { getName() = "html" }
|
||||
DocumentElement() { this.getName() = "html" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,12 +185,12 @@ module HTML {
|
||||
* ```
|
||||
*/
|
||||
class IframeElement extends Element {
|
||||
IframeElement() { getName() = "iframe" }
|
||||
IframeElement() { this.getName() = "iframe" }
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
ScriptElement() { getName() = "script" }
|
||||
ScriptElement() { this.getName() = "script" }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
string resolveSourcePath() {
|
||||
exists(string path | path = getSourcePath() |
|
||||
exists(string path | path = this.getSourcePath() |
|
||||
result = path.regexpCapture("file://(/.*)", 1)
|
||||
or
|
||||
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.
|
||||
*/
|
||||
string getSourcePath() { result = getAttributeByName("src").getValue() }
|
||||
string getSourcePath() { result = this.getAttributeByName("src").getValue() }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
Folder getSearchRoot() {
|
||||
if getSourcePath().matches("/%")
|
||||
if this.getSourcePath().matches("/%")
|
||||
then result.getBaseName() = ""
|
||||
else result = getFile().getParentContainer()
|
||||
else result = this.getFile().getParentContainer()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the script referred to by the `src` attribute,
|
||||
* 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.
|
||||
@@ -251,15 +253,15 @@ module HTML {
|
||||
private InlineScript getInlineScript() {
|
||||
toplevel_parent_xml_node(result, this) and
|
||||
// the src attribute has precedence
|
||||
not exists(getSourcePath())
|
||||
not exists(this.getSourcePath())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the script of this element, if it can be determined.
|
||||
*/
|
||||
Script getScript() {
|
||||
result = getInlineScript() or
|
||||
result = resolveSource()
|
||||
result = this.getInlineScript() or
|
||||
result = this.resolveSource()
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "HTML::ScriptElement" }
|
||||
@@ -301,7 +303,7 @@ module HTML {
|
||||
class TextNode extends Locatable, @xmlcharacters {
|
||||
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.
|
||||
@@ -344,7 +346,7 @@ module HTML {
|
||||
Element getParent() { xmlComments(this, _, result, _) }
|
||||
|
||||
/** 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, _, _) }
|
||||
|
||||
|
||||
@@ -65,11 +65,11 @@ private class DefaultHtmlSanitizerCall extends HtmlSanitizerCall {
|
||||
this = htmlSanitizerFunction().getACall()
|
||||
or
|
||||
// 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).*(?<!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. */
|
||||
JSDocTag getATagByTitle(string title) {
|
||||
result = getATag() and
|
||||
result = this.getATag() and
|
||||
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. */
|
||||
cached
|
||||
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). */
|
||||
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. */
|
||||
TopLevel getTopLevel() { result = getParent().getComment().getTopLevel() }
|
||||
TopLevel getTopLevel() { result = this.getParent().getComment().getTopLevel() }
|
||||
|
||||
override JSDoc getJSDocComment() { result.getATag() = this }
|
||||
}
|
||||
@@ -139,12 +139,12 @@ class JSDocTag extends @jsdoc_tag, JSDocTypeExprParent {
|
||||
* ```
|
||||
*/
|
||||
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. */
|
||||
Variable getDocumentedParameter() {
|
||||
exists(Parameterized parm | parm.getDocumentation() = getParent() |
|
||||
result = pragma[only_bind_out](parm).getParameterVariable(getName())
|
||||
exists(Parameterized parm | parm.getDocumentation() = this.getParent() |
|
||||
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 JSDoc getJSDocComment() { result = getParent().getJSDocComment() }
|
||||
override JSDoc getJSDocComment() { result = this.getParent().getJSDocComment() }
|
||||
|
||||
override Stmt getEnclosingStmt() {
|
||||
exists(Documentable astNode | astNode.getDocumentation() = getJSDocComment() |
|
||||
exists(Documentable astNode | astNode.getDocumentation() = this.getJSDocComment() |
|
||||
result = astNode
|
||||
or
|
||||
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 {
|
||||
/** 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() {
|
||||
exists(string name | name = getName() |
|
||||
exists(string name | name = this.getName() |
|
||||
name = "string" or
|
||||
name = "String"
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isNumber() { getName() = "number" }
|
||||
override predicate isNumber() { this.getName() = "number" }
|
||||
|
||||
override predicate isNumbery() {
|
||||
exists(string name | name = getName() |
|
||||
exists(string name | name = this.getName() |
|
||||
name = ["number", "Number", "double", "Double", "int", "integer", "Integer"]
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isBoolean() { getName() = "boolean" }
|
||||
override predicate isBoolean() { this.getName() = "boolean" }
|
||||
|
||||
override predicate isBooleany() {
|
||||
getName() = "boolean" or
|
||||
getName() = "Boolean" or
|
||||
getName() = "bool"
|
||||
this.getName() = "boolean" or
|
||||
this.getName() = "Boolean" or
|
||||
this.getName() = "bool"
|
||||
}
|
||||
|
||||
override predicate isRawFunction() { getName() = "Function" }
|
||||
override predicate isRawFunction() { this.getName() = "Function" }
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
exists(string regex, string name | regex = "([^.]+)(.*)" |
|
||||
name = getName() and
|
||||
name = this.getName() and
|
||||
prefix = name.regexpCapture(regex, 1) and
|
||||
suffix = name.regexpCapture(regex, 2)
|
||||
)
|
||||
@@ -325,8 +325,8 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
||||
pragma[nomagic]
|
||||
private predicate hasNamePartsAndEnv(string prefix, string suffix, JSDoc::Environment env) {
|
||||
// Force join ordering
|
||||
hasNameParts(prefix, suffix) and
|
||||
env.isContainerInScope(getContainer())
|
||||
this.hasNameParts(prefix, suffix) and
|
||||
env.isContainerInScope(this.getContainer())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,28 +335,28 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
|
||||
cached
|
||||
private string resolvedName() {
|
||||
exists(string prefix, string suffix, JSDoc::Environment env |
|
||||
hasNamePartsAndEnv(prefix, suffix, env) and
|
||||
this.hasNamePartsAndEnv(prefix, suffix, env) and
|
||||
result = env.resolveAlias(prefix) + suffix
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasQualifiedName(string globalName) {
|
||||
globalName = resolvedName()
|
||||
globalName = this.resolvedName()
|
||||
or
|
||||
not exists(resolvedName()) and
|
||||
globalName = getName()
|
||||
not exists(this.resolvedName()) and
|
||||
globalName = this.getName()
|
||||
}
|
||||
|
||||
override DataFlow::ClassNode getClass() {
|
||||
exists(string name |
|
||||
hasQualifiedName(name) and
|
||||
this.hasQualifiedName(name) and
|
||||
result.hasQualifiedName(name)
|
||||
)
|
||||
or
|
||||
// Handle case where a local variable has a reference to the class,
|
||||
// but the class doesn't have a globally qualified name.
|
||||
exists(string alias, JSDoc::Environment env |
|
||||
hasNamePartsAndEnv(alias, "", env) and
|
||||
this.hasNamePartsAndEnv(alias, "", env) and
|
||||
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 {
|
||||
/** 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 {
|
||||
/** 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. */
|
||||
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 {
|
||||
/** 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. */
|
||||
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) }
|
||||
|
||||
/** 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. */
|
||||
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. */
|
||||
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 {
|
||||
/** 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. */
|
||||
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 {
|
||||
/** 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 {
|
||||
/** 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. */
|
||||
JSDocTypeExpr getReceiverType() { result = getChild(-2) }
|
||||
JSDocTypeExpr getReceiverType() { result = this.getChild(-2) }
|
||||
|
||||
/** 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. */
|
||||
JSDocTypeExpr getAParameterType() { result = getParameterType(_) }
|
||||
JSDocTypeExpr getAParameterType() { result = this.getParameterType(_) }
|
||||
|
||||
/** Holds if this function type is a constructor type. */
|
||||
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 {
|
||||
/** Gets the underlying type of this optional type. */
|
||||
JSDocTypeExpr getUnderlyingType() { result = getChild(0) }
|
||||
JSDocTypeExpr getUnderlyingType() { result = this.getChild(0) }
|
||||
|
||||
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 {
|
||||
/** 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.
|
||||
*/
|
||||
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`.
|
||||
*/
|
||||
final predicate isContainerInScope(StmtContainer container) {
|
||||
exists(resolveAlias(_)) and // restrict size of predicate
|
||||
exists(this.resolveAlias(_)) and // restrict size of predicate
|
||||
container = this
|
||||
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, _) }
|
||||
|
||||
/** 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) }
|
||||
|
||||
@@ -167,7 +167,7 @@ class JsonArray extends @json_array, JsonValue {
|
||||
override string getAPrimaryQlClass() { result = "JsonArray" }
|
||||
|
||||
/** 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 */
|
||||
@@ -186,7 +186,7 @@ class JsonObject extends @json_object, JsonValue {
|
||||
override string getAPrimaryQlClass() { result = "JsonObject" }
|
||||
|
||||
/** 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 */
|
||||
|
||||
@@ -17,10 +17,10 @@ import javascript
|
||||
*/
|
||||
class JsxNode extends Expr, @jsx_element {
|
||||
/** 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. */
|
||||
Expr getABodyElement() { result = getBodyElement(_) }
|
||||
Expr getABodyElement() { result = this.getBodyElement(_) }
|
||||
|
||||
/**
|
||||
* Gets the parent JSX element or fragment of this element.
|
||||
@@ -46,7 +46,7 @@ deprecated class JSXNode = JsxNode;
|
||||
class JsxElement extends JsxNode {
|
||||
JsxName name;
|
||||
|
||||
JsxElement() { name = getChildExpr(-1) }
|
||||
JsxElement() { name = this.getChildExpr(-1) }
|
||||
|
||||
/** Gets the expression denoting the name of this element. */
|
||||
JsxName getNameExpr() { result = name }
|
||||
@@ -58,13 +58,15 @@ class JsxElement extends JsxNode {
|
||||
JsxAttribute getAttribute(int i) { properties(result, this, i, _, _) }
|
||||
|
||||
/** 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. */
|
||||
JsxAttribute getAttributeByName(string n) { result = getAnAttribute() and result.getName() = n }
|
||||
JsxAttribute getAttributeByName(string n) {
|
||||
result = this.getAnAttribute() and result.getName() = n
|
||||
}
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() {
|
||||
result = getNameExpr().getFirstControlFlowNode()
|
||||
result = this.getNameExpr().getFirstControlFlowNode()
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "JsxElement" }
|
||||
@@ -73,10 +75,10 @@ class JsxElement extends JsxNode {
|
||||
* Holds if this JSX element is an HTML element.
|
||||
* 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 predicate isHTMLElement() { isHtmlElement() }
|
||||
deprecated predicate isHTMLElement() { this.isHtmlElement() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for JsxElement */
|
||||
@@ -92,12 +94,12 @@ deprecated class JSXElement = JsxElement;
|
||||
* ```
|
||||
*/
|
||||
class JsxFragment extends JsxNode {
|
||||
JsxFragment() { not exists(getChildExpr(-1)) }
|
||||
JsxFragment() { not exists(this.getChildExpr(-1)) }
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() {
|
||||
result = getBodyElement(0).getFirstControlFlowNode()
|
||||
result = this.getBodyElement(0).getFirstControlFlowNode()
|
||||
or
|
||||
not exists(getABodyElement()) and result = this
|
||||
not exists(this.getABodyElement()) and result = this
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "JsxFragment" }
|
||||
@@ -123,28 +125,28 @@ class JsxAttribute extends AstNode, @jsx_attribute {
|
||||
*
|
||||
* This is not defined for spread attributes.
|
||||
*/
|
||||
JsxName getNameExpr() { result = getChildExpr(0) }
|
||||
JsxName getNameExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/**
|
||||
* Gets the name of this attribute.
|
||||
*
|
||||
* 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. */
|
||||
Expr getValue() { result = getChildExpr(1) }
|
||||
Expr getValue() { result = this.getChildExpr(1) }
|
||||
|
||||
/** 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. */
|
||||
JsxElement getElement() { this = result.getAnAttribute() }
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() {
|
||||
result = getNameExpr().getFirstControlFlowNode()
|
||||
result = this.getNameExpr().getFirstControlFlowNode()
|
||||
or
|
||||
not exists(getNameExpr()) and result = getValue().getFirstControlFlowNode()
|
||||
not exists(this.getNameExpr()) and result = this.getValue().getFirstControlFlowNode()
|
||||
}
|
||||
|
||||
override string toString() { properties(this, _, _, _, result) }
|
||||
@@ -165,7 +167,7 @@ deprecated class JSXAttribute = JsxAttribute;
|
||||
* ```
|
||||
*/
|
||||
class JsxSpreadAttribute extends JsxAttribute {
|
||||
JsxSpreadAttribute() { not exists(getNameExpr()) }
|
||||
JsxSpreadAttribute() { not exists(this.getNameExpr()) }
|
||||
|
||||
override SpreadElement getValue() {
|
||||
// override for more precise result type
|
||||
@@ -187,13 +189,13 @@ deprecated class JSXSpreadAttribute = JsxSpreadAttribute;
|
||||
*/
|
||||
class JsxQualifiedName extends Expr, @jsx_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. */
|
||||
Identifier getName() { result = getChildExpr(1) }
|
||||
Identifier getName() { result = this.getChildExpr(1) }
|
||||
|
||||
override ControlFlowNode getFirstControlFlowNode() {
|
||||
result = getNamespace().getFirstControlFlowNode()
|
||||
result = this.getNamespace().getFirstControlFlowNode()
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "JsxQualifiedName" }
|
||||
@@ -271,16 +273,16 @@ deprecated class JSXEmptyExpr = JsxEmptyExpr;
|
||||
* ```
|
||||
*/
|
||||
class JsxPragma extends JSDocTag {
|
||||
JsxPragma() { getTitle() = "jsx" }
|
||||
JsxPragma() { this.getTitle() = "jsx" }
|
||||
|
||||
/**
|
||||
* Gets the DOM name specified by the pragma; for `@jsx React.DOM`,
|
||||
* the result is `React.DOM`.
|
||||
*/
|
||||
string getDomName() { result = getDescription().trim() }
|
||||
string getDomName() { result = this.getDescription().trim() }
|
||||
|
||||
/** DEPRECATED: Alias for getDomName */
|
||||
deprecated string getDOMName() { result = getDomName() }
|
||||
deprecated string getDOMName() { result = this.getDomName() }
|
||||
}
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
DataFlow::Node getInput() { result = getArgument(0) }
|
||||
DataFlow::Node getInput() { result = this.getArgument(0) }
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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 PackageJSON getPackageJSON() { result = getPackageJson() }
|
||||
deprecated PackageJSON getPackageJSON() { result = this.getPackageJson() }
|
||||
|
||||
override string getValue() { result = this.(JsonString).getValue() }
|
||||
|
||||
@@ -259,7 +259,7 @@ private class FilesPath extends PathExpr, @json_string {
|
||||
PackageJson getPackageJson() { result = pkg }
|
||||
|
||||
/** DEPRECATED: Alias for getPackageJson */
|
||||
deprecated PackageJSON getPackageJSON() { result = getPackageJson() }
|
||||
deprecated PackageJSON getPackageJSON() { result = this.getPackageJson() }
|
||||
|
||||
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
|
||||
) {
|
||||
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
|
||||
if xl = startline
|
||||
then endcolumn = xc
|
||||
@@ -49,7 +49,7 @@ class LastLineOf extends Locatable {
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
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
|
||||
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. */
|
||||
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)
|
||||
)
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
string toString() { result = getDefinition().prettyPrintRef() }
|
||||
string toString() { result = this.getDefinition().prettyPrintRef() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
@@ -422,7 +422,7 @@ class SsaVariable extends TSsaDefinition {
|
||||
predicate hasLocationInfo(
|
||||
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();
|
||||
|
||||
/** 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.
|
||||
@@ -489,7 +489,7 @@ class SsaDefinition extends TSsaDefinition {
|
||||
);
|
||||
|
||||
/** 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, _) }
|
||||
|
||||
/** 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 VarDef getAContributingVarDef() { result = getDef() }
|
||||
override VarDef getAContributingVarDef() { result = this.getDef() }
|
||||
|
||||
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(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
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)
|
||||
)
|
||||
}
|
||||
@@ -549,7 +549,9 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
|
||||
abstract string getKind();
|
||||
|
||||
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(
|
||||
@@ -558,7 +560,7 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
|
||||
endline = startline and
|
||||
endcolumn = startcolumn and
|
||||
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, _, _)
|
||||
)
|
||||
}
|
||||
@@ -570,7 +572,7 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
|
||||
*/
|
||||
class SsaImplicitInit extends SsaImplicitDefinition, TImplicitInit {
|
||||
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, _) }
|
||||
@@ -581,7 +583,9 @@ class SsaImplicitInit extends SsaImplicitDefinition, TImplicitInit {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 prettyPrintDef() { result = "capture variable " + getSourceVariable() }
|
||||
override string prettyPrintDef() { result = "capture variable " + this.getSourceVariable() }
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
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)
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
@@ -631,14 +635,14 @@ abstract class SsaPseudoDefinition extends SsaImplicitDefinition {
|
||||
abstract SsaVariable getAnInput();
|
||||
|
||||
override VarDef getAContributingVarDef() {
|
||||
result = getAnInput().getDefinition().getAContributingVarDef()
|
||||
result = this.getAnInput().getDefinition().getAContributingVarDef()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a textual representation of the inputs of this pseudo-definition
|
||||
* 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
|
||||
SsaVariable getInputFromBlock(BasicBlock bb) {
|
||||
bb = getBasicBlock().getAPredecessor() and
|
||||
result = getDefReachingEndOf(bb, getSourceVariable())
|
||||
bb = this.getBasicBlock().getAPredecessor() and
|
||||
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) {
|
||||
bb = getBasicBlock() and v = getSourceVariable() and i = -1
|
||||
bb = this.getBasicBlock() and v = this.getSourceVariable() and i = -1
|
||||
}
|
||||
|
||||
override ReachableBasicBlock getBasicBlock() { this = TPhi(result, _) }
|
||||
@@ -668,14 +672,16 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
|
||||
|
||||
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,
|
||||
* gets that variable.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
Refinement getRefinement() { result = getGuard().getTest() }
|
||||
Refinement getRefinement() { result = this.getGuard().getTest() }
|
||||
|
||||
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))
|
||||
then result.(SsaPhiNode).definesAt(bb, _, v)
|
||||
else result = getDefReachingEndOf(bb.getAPredecessor(), v)
|
||||
@@ -724,16 +732,19 @@ class SsaRefinementNode extends SsaPseudoDefinition, TRefinement {
|
||||
|
||||
override SsaSourceVariable getSourceVariable() { this = TRefinement(_, _, _, result) }
|
||||
|
||||
override string getKind() { result = "refine[" + getGuard() + "]" }
|
||||
override string getKind() { result = "refine[" + this.getGuard() + "]" }
|
||||
|
||||
override string prettyPrintDef() {
|
||||
result = getSourceVariable() + " = refine[" + getGuard() + "](" + ppInputs() + ")"
|
||||
result =
|
||||
this.getSourceVariable() + " = refine[" + this.getGuard() + "](" + this.ppInputs() + ")"
|
||||
}
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
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 }
|
||||
|
||||
/** 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 {
|
||||
/** Gets the tagging expression of this tagged template. */
|
||||
Expr getTag() { result = getChildExpr(0) }
|
||||
Expr getTag() { result = this.getChildExpr(0) }
|
||||
|
||||
/** 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. */
|
||||
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. */
|
||||
TypeExpr getATypeArgument() { result = getTypeArgument(_) }
|
||||
TypeExpr getATypeArgument() { result = this.getTypeArgument(_) }
|
||||
|
||||
/** 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() }
|
||||
|
||||
@@ -46,19 +46,19 @@ class TemplateLiteral extends Expr, @template_literal {
|
||||
* Gets the `i`th element of this template literal, which may either
|
||||
* 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.
|
||||
*/
|
||||
Expr getAnElement() { result = getElement(_) }
|
||||
Expr getAnElement() { result = this.getElement(_) }
|
||||
|
||||
/**
|
||||
* 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" }
|
||||
}
|
||||
@@ -80,7 +80,7 @@ class TemplateElement extends Expr, @template_element {
|
||||
* elements with invalid escape sequences, which only have a raw value but
|
||||
* no cooked value.
|
||||
*/
|
||||
predicate hasValue() { exists(getValue()) }
|
||||
predicate hasValue() { exists(this.getValue()) }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
AbstractValue getAnInitialValue() {
|
||||
result = getAnInitialPropertyValue(getBase(), getPropertyName())
|
||||
result = getAnInitialPropertyValue(this.getBase(), this.getPropertyName())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value of this property for the purposes of `AnalyzedNode.getALocalValue`.
|
||||
*/
|
||||
AbstractValue getALocalValue() {
|
||||
result = getAnInitialPropertyValue(getBase(), getPropertyName())
|
||||
result = getAnInitialPropertyValue(this.getBase(), this.getPropertyName())
|
||||
or
|
||||
shouldAlwaysTrackProperties(getBase()) and
|
||||
result = getAnAssignedValue(getBase(), getPropertyName())
|
||||
shouldAlwaysTrackProperties(this.getBase()) and
|
||||
result = getAnAssignedValue(this.getBase(), this.getPropertyName())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value of this property for the purposes of `AnalyzedNode.getAValue`.
|
||||
*/
|
||||
AbstractValue getAValue() {
|
||||
result = getALocalValue() or
|
||||
result = getAnAssignedValue(getBase(), getPropertyName())
|
||||
result = this.getALocalValue() or
|
||||
result = getAnAssignedValue(this.getBase(), this.getPropertyName())
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 AbstractProtoProperty extends AbstractProperty {
|
||||
AbstractProtoProperty() { getPropertyName() = "__proto__" }
|
||||
AbstractProtoProperty() { this.getPropertyName() = "__proto__" }
|
||||
|
||||
override AbstractValue getAValue() {
|
||||
result = super.getAValue() and
|
||||
@@ -62,7 +62,7 @@ class AbstractProtoProperty extends AbstractProperty {
|
||||
result instanceof AbstractNull
|
||||
)
|
||||
or
|
||||
exists(AbstractCallable ctor | getBase() = TAbstractInstance(ctor) |
|
||||
exists(AbstractCallable ctor | this.getBase() = TAbstractInstance(ctor) |
|
||||
// the value of `ctor.prototype`
|
||||
exists(AbstractProperty prototype |
|
||||
prototype = MkAbstractProperty(ctor.(AbstractFunction), "prototype") and
|
||||
|
||||
@@ -170,7 +170,7 @@ class AbstractBoolean extends PrimitiveAbstractValue, TAbstractBoolean {
|
||||
|
||||
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 {
|
||||
override Function getFunction() { this = TAbstractFunction(result) }
|
||||
|
||||
override AST::ValueNode getDefinition() { result = getFunction() }
|
||||
override AST::ValueNode getDefinition() { result = this.getFunction() }
|
||||
|
||||
override boolean getBooleanValue() { result = true }
|
||||
|
||||
@@ -293,10 +293,12 @@ class AbstractFunction extends AbstractCallable, TAbstractFunction {
|
||||
override predicate hasLocationInfo(
|
||||
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) }
|
||||
|
||||
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 }
|
||||
|
||||
@@ -323,10 +325,10 @@ class AbstractClass extends AbstractCallable, TAbstractClass {
|
||||
override predicate hasLocationInfo(
|
||||
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(
|
||||
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(
|
||||
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(
|
||||
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(
|
||||
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" }
|
||||
@@ -476,10 +482,10 @@ class AbstractInstance extends DefiniteAbstractValue, TAbstractInstance {
|
||||
override predicate hasLocationInfo(
|
||||
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 {
|
||||
@@ -526,7 +532,7 @@ class IndefiniteFunctionOrClass extends AbstractValue, TIndefiniteFunctionOrClas
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(DataFlow::Incompleteness cause | isIndefinite(cause) |
|
||||
exists(DataFlow::Incompleteness cause | this.isIndefinite(cause) |
|
||||
result = "indefinite function or class (" + cause + ")"
|
||||
)
|
||||
}
|
||||
@@ -553,7 +559,7 @@ class IndefiniteObject extends AbstractValue, TIndefiniteObject {
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(DataFlow::Incompleteness cause | isIndefinite(cause) |
|
||||
exists(DataFlow::Incompleteness cause | this.isIndefinite(cause) |
|
||||
result = "indefinite object (" + cause + ")"
|
||||
)
|
||||
}
|
||||
@@ -576,7 +582,7 @@ class IndefiniteAbstractValue extends AbstractValue, TIndefiniteAbstractValue {
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(DataFlow::Incompleteness cause | isIndefinite(cause) |
|
||||
exists(DataFlow::Incompleteness cause | this.isIndefinite(cause) |
|
||||
result = "indefinite value (" + cause + ")"
|
||||
)
|
||||
}
|
||||
@@ -589,7 +595,7 @@ class IndefiniteAbstractValue extends AbstractValue, TIndefiniteAbstractValue {
|
||||
* set of concrete values represented by this abstract value.
|
||||
*/
|
||||
AbstractValue split() {
|
||||
exists(string cause | isIndefinite(cause) |
|
||||
exists(string cause | this.isIndefinite(cause) |
|
||||
result = TIndefiniteFunctionOrClass(cause) or
|
||||
result = TIndefiniteObject(cause) or
|
||||
result = abstractValueOfType(any(PrimitiveType pt))
|
||||
|
||||
@@ -63,7 +63,7 @@ class LocalObject extends DataFlow::SourceNode {
|
||||
LocalObject() {
|
||||
// pragmatic limitation: object literals only
|
||||
this instanceof DataFlow::ObjectLiteralNode and
|
||||
not flowsTo(getAnEscape()) and
|
||||
not this.flowsTo(getAnEscape()) and
|
||||
not exposedAsReceiver(this)
|
||||
}
|
||||
|
||||
@@ -72,16 +72,16 @@ class LocalObject extends DataFlow::SourceNode {
|
||||
// the property is defined in the initializer,
|
||||
any(DataFlow::PropWrite write).writes(this, name, _) and
|
||||
// and it is never deleted
|
||||
not hasDeleteWithName(name) and
|
||||
not this.hasDeleteWithName(name) and
|
||||
// and there is no deleted property with computed name
|
||||
not hasDeleteWithComputedProperty()
|
||||
not this.hasDeleteWithComputedProperty()
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasDeleteWithName(string name) {
|
||||
exists(DeleteExpr del, DataFlow::PropRef ref |
|
||||
del.getOperand().flow() = ref and
|
||||
flowsTo(ref.getBase()) and
|
||||
this.flowsTo(ref.getBase()) and
|
||||
ref.getPropertyName() = name
|
||||
)
|
||||
}
|
||||
@@ -90,7 +90,7 @@ class LocalObject extends DataFlow::SourceNode {
|
||||
private predicate hasDeleteWithComputedProperty() {
|
||||
exists(DeleteExpr del, DataFlow::PropRef ref |
|
||||
del.getOperand().flow() = ref and
|
||||
flowsTo(ref.getBase()) and
|
||||
this.flowsTo(ref.getBase()) and
|
||||
not exists(ref.getPropertyName())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -71,7 +71,9 @@ class Refinement extends Expr instanceof RefinementCandidate {
|
||||
abstract private class LiteralRefinement extends RefinementCandidate, Literal {
|
||||
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.
|
||||
@@ -87,13 +89,13 @@ private class NullLiteralRefinement extends LiteralRefinement, NullLiteral {
|
||||
/** A Boolean literal, viewed as a refinement expression. */
|
||||
private class BoolRefinement extends LiteralRefinement, BooleanLiteral {
|
||||
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. */
|
||||
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. */
|
||||
@@ -108,9 +110,9 @@ abstract private class NumberRefinement extends LiteralRefinement, NumberLiteral
|
||||
* other integer values.
|
||||
*/
|
||||
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. */
|
||||
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) {
|
||||
ctxt.appliesTo(this) and
|
||||
@@ -141,28 +143,28 @@ private class VariableRefinement extends RefinementCandidate, VarUse {
|
||||
|
||||
/** A parenthesized refinement expression. */
|
||||
private class ParRefinement extends RefinementCandidate, ParExpr {
|
||||
ParRefinement() { getExpression() instanceof RefinementCandidate }
|
||||
ParRefinement() { this.getExpression() instanceof RefinementCandidate }
|
||||
|
||||
override SsaSourceVariable getARefinedVar() {
|
||||
result = getExpression().(RefinementCandidate).getARefinedVar()
|
||||
result = this.getExpression().(RefinementCandidate).getARefinedVar()
|
||||
}
|
||||
|
||||
override RefinementValue eval(RefinementContext ctxt) {
|
||||
result = getExpression().(RefinementCandidate).eval(ctxt)
|
||||
result = this.getExpression().(RefinementCandidate).eval(ctxt)
|
||||
}
|
||||
}
|
||||
|
||||
/** A `typeof` refinement expression. */
|
||||
private class TypeofRefinement extends RefinementCandidate, TypeofExpr {
|
||||
TypeofRefinement() { getOperand() instanceof RefinementCandidate }
|
||||
TypeofRefinement() { this.getOperand() instanceof RefinementCandidate }
|
||||
|
||||
override SsaSourceVariable getARefinedVar() {
|
||||
result = getOperand().(RefinementCandidate).getARefinedVar()
|
||||
result = this.getOperand().(RefinementCandidate).getARefinedVar()
|
||||
}
|
||||
|
||||
override RefinementValue eval(RefinementContext ctxt) {
|
||||
exists(RefinementValue opVal |
|
||||
opVal = getOperand().(RefinementCandidate).eval(ctxt) and
|
||||
opVal = this.getOperand().(RefinementCandidate).eval(ctxt) and
|
||||
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. */
|
||||
private class EqRefinement extends RefinementCandidate, EqualityTest {
|
||||
EqRefinement() {
|
||||
getLeftOperand() instanceof RefinementCandidate and
|
||||
getRightOperand() instanceof RefinementCandidate
|
||||
this.getLeftOperand() instanceof RefinementCandidate and
|
||||
this.getRightOperand() instanceof RefinementCandidate
|
||||
}
|
||||
|
||||
override SsaSourceVariable getARefinedVar() {
|
||||
result = getLeftOperand().(RefinementCandidate).getARefinedVar() or
|
||||
result = getRightOperand().(RefinementCandidate).getARefinedVar()
|
||||
result = this.getLeftOperand().(RefinementCandidate).getARefinedVar() or
|
||||
result = this.getRightOperand().(RefinementCandidate).getARefinedVar()
|
||||
}
|
||||
|
||||
override RefinementValue eval(RefinementContext ctxt) {
|
||||
exists(RefinementCandidate l, RefinementValue lv, RefinementCandidate r, RefinementValue rv |
|
||||
l = getLeftOperand() and
|
||||
r = getRightOperand() and
|
||||
l = this.getLeftOperand() and
|
||||
r = this.getRightOperand() and
|
||||
lv = l.eval(ctxt) and
|
||||
rv = r.eval(ctxt)
|
||||
|
|
||||
// if both sides evaluate to a constant, compare them
|
||||
if lv instanceof SingletonRefinementValue and rv instanceof SingletonRefinementValue
|
||||
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)
|
||||
then result = TBoolConstant(p)
|
||||
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. */
|
||||
private class IndexRefinement extends RefinementCandidate, IndexExpr {
|
||||
IndexRefinement() {
|
||||
getBase() instanceof RefinementCandidate and
|
||||
getIndex() instanceof RefinementCandidate
|
||||
this.getBase() instanceof RefinementCandidate and
|
||||
this.getIndex() instanceof RefinementCandidate
|
||||
}
|
||||
|
||||
override SsaSourceVariable getARefinedVar() {
|
||||
result = getBase().(RefinementCandidate).getARefinedVar() or
|
||||
result = getIndex().(RefinementCandidate).getARefinedVar()
|
||||
result = this.getBase().(RefinementCandidate).getARefinedVar() or
|
||||
result = this.getIndex().(RefinementCandidate).getARefinedVar()
|
||||
}
|
||||
|
||||
override RefinementValue eval(RefinementContext ctxt) {
|
||||
@@ -223,8 +225,8 @@ private class IndexRefinement extends RefinementCandidate, IndexExpr {
|
||||
RefinementCandidate base, RefinementValue baseVal, RefinementCandidate index,
|
||||
RefinementValue indexVal
|
||||
|
|
||||
base = getBase() and
|
||||
index = getIndex() and
|
||||
base = this.getBase() and
|
||||
index = this.getIndex() and
|
||||
baseVal = base.eval(ctxt) and
|
||||
indexVal = index.eval(ctxt)
|
||||
|
|
||||
@@ -424,21 +426,21 @@ private class AnyValue extends RefinementValue, TAny {
|
||||
private class ValueWithType extends RefinementValue, TValueWithType {
|
||||
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() {
|
||||
result = true
|
||||
or
|
||||
// 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`. */
|
||||
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 }
|
||||
|
||||
@@ -501,7 +503,7 @@ private class StringConstant extends SingletonRefinementValue, TStringConstant {
|
||||
or
|
||||
isStrict = false and
|
||||
(
|
||||
isEmptyOrZero() and that = TBoolConstant(false)
|
||||
this.isEmptyOrZero() and that = TBoolConstant(false)
|
||||
or
|
||||
value = "1" and that = TBoolConstant(true)
|
||||
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,
|
||||
* 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.
|
||||
*/
|
||||
DataFlow::Node getALocalUse() { flowsTo(result) }
|
||||
DataFlow::Node getALocalUse() { this.flowsTo(result) }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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]
|
||||
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.
|
||||
*/
|
||||
DataFlow::PropRead getAPropertyRead() { result = getAPropertyReference() }
|
||||
DataFlow::PropRead getAPropertyRead() { result = this.getAPropertyReference() }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
* 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.
|
||||
@@ -126,7 +130,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
||||
* that is, `o.m(...)` or `o[p](...)`.
|
||||
*/
|
||||
DataFlow::CallNode getAMethodCall(string methodName) {
|
||||
result = getAMemberInvocation(methodName) and
|
||||
result = this.getAMemberInvocation(methodName) and
|
||||
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,
|
||||
* 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.
|
||||
@@ -146,14 +150,14 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
|
||||
*/
|
||||
DataFlow::CallNode getAChainedMethodCall(string methodName) {
|
||||
// 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
DataFlow::CallNode getACall() { result = getAnInvocation() }
|
||||
DataFlow::CallNode getACall() { result = this.getAnInvocation() }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -45,7 +45,7 @@ class AnalyzedNode extends DataFlow::Node {
|
||||
* Gets another data flow node whose value flows into this node in one local step
|
||||
* (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.
|
||||
@@ -57,7 +57,7 @@ class AnalyzedNode extends DataFlow::Node {
|
||||
* instances is also performed.
|
||||
*/
|
||||
cached
|
||||
AbstractValue getAValue() { result = getALocalValue() }
|
||||
AbstractValue getAValue() { result = this.getALocalValue() }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
@@ -76,31 +76,31 @@ class AnalyzedNode extends DataFlow::Node {
|
||||
// feed back the results from the (value) flow analysis into
|
||||
// the control flow analysis, so all flow predecessors are
|
||||
// considered as sources
|
||||
result = localFlowPred().getALocalValue()
|
||||
result = this.localFlowPred().getALocalValue()
|
||||
or
|
||||
// model flow that isn't captured by the data flow graph
|
||||
exists(DataFlow::Incompleteness cause |
|
||||
isIncomplete(cause) and result = TIndefiniteAbstractValue(cause)
|
||||
this.isIncomplete(cause) and result = TIndefiniteAbstractValue(cause)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a type inferred for this node. */
|
||||
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.
|
||||
*/
|
||||
PrimitiveType getAPrimitiveType() { result = getAValue().toPrimitive().getType() }
|
||||
PrimitiveType getAPrimitiveType() { result = this.getAValue().toPrimitive().getType() }
|
||||
|
||||
/** 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. */
|
||||
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. */
|
||||
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
|
||||
@@ -110,19 +110,19 @@ class AnalyzedNode extends DataFlow::Node {
|
||||
* particular addition) may have more than one inferred type.
|
||||
*/
|
||||
string ppTypes() {
|
||||
exists(int n | n = getNumTypes() |
|
||||
exists(int n | n = this.getNumTypes() |
|
||||
// inferred no types
|
||||
n = 0 and result = ""
|
||||
or
|
||||
// inferred a single type
|
||||
n = 1 and result = getAType().toString()
|
||||
n = 1 and result = this.getAType().toString()
|
||||
or
|
||||
// inferred all types
|
||||
n = count(InferredType it) and result = ppAllTypeTags()
|
||||
or
|
||||
// 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"
|
||||
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.
|
||||
*/
|
||||
private string getType(int i) {
|
||||
getNumTypes() in [2 .. count(InferredType it) - 1] and
|
||||
result = rank[i](InferredType tp | tp = getAType() | tp.toString())
|
||||
this.getNumTypes() in [2 .. count(InferredType it) - 1] and
|
||||
result = rank[i](InferredType tp | tp = this.getAType() | tp.toString())
|
||||
}
|
||||
|
||||
/** 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,
|
||||
@@ -147,15 +147,15 @@ class AnalyzedNode extends DataFlow::Node {
|
||||
* the all-types case are handled specially above.
|
||||
*/
|
||||
private string ppTypes(int i) {
|
||||
exists(int n | n = getNumTypes() and n in [2 .. count(InferredType it) - 1] |
|
||||
i = n and result = getType(i)
|
||||
exists(int n | n = this.getNumTypes() and n in [2 .. count(InferredType it) - 1] |
|
||||
i = n and result = this.getType(i)
|
||||
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. */
|
||||
predicate hasFlow() { exists(getAValue()) }
|
||||
predicate hasFlow() { exists(this.getAValue()) }
|
||||
|
||||
/**
|
||||
* INTERNAL. Use `isIncomplete()` instead.
|
||||
@@ -194,7 +194,7 @@ class AnalyzedModule extends TopLevel instanceof Module {
|
||||
* property.
|
||||
*/
|
||||
AbstractProperty getExportsProperty() {
|
||||
result.getBase() = getModuleObject() and
|
||||
result.getBase() = this.getModuleObject() and
|
||||
result.getPropertyName() = "exports"
|
||||
}
|
||||
|
||||
@@ -202,14 +202,14 @@ class AnalyzedModule extends TopLevel instanceof Module {
|
||||
* Gets an abstract value inferred for this module's `module.exports`
|
||||
* property.
|
||||
*/
|
||||
AbstractValue getAnExportsValue() { result = getExportsProperty().getAValue() }
|
||||
AbstractValue getAnExportsValue() { result = this.getExportsProperty().getAValue() }
|
||||
|
||||
/**
|
||||
* Gets an abstract value representing a value exported by this module
|
||||
* under the given `name`.
|
||||
*/
|
||||
AbstractValue getAnExportedValue(string name) {
|
||||
exists(AbstractValue exports | exports = getAnExportsValue() |
|
||||
exists(AbstractValue exports | exports = this.getAnExportsValue() |
|
||||
// CommonJS modules export `module.exports` as their `default`
|
||||
// export in an ES2015 setting
|
||||
not this instanceof ES2015Module and
|
||||
@@ -243,7 +243,7 @@ class AnalyzedFunction extends DataFlow::AnalyzedValueNode {
|
||||
// implicit return value
|
||||
(
|
||||
// either because execution of the function may terminate normally
|
||||
mayReturnImplicitly()
|
||||
this.mayReturnImplicitly()
|
||||
or
|
||||
// or because there is a bare `return;` statement
|
||||
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.
|
||||
*/
|
||||
Expr getAnInstance() { result = getAnInstanceIn(_) }
|
||||
Expr getAnInstance() { result = this.getAnInstanceIn(_) }
|
||||
|
||||
/**
|
||||
* Gets a textual representation of this access path.
|
||||
|
||||
@@ -24,21 +24,21 @@ class AnalyzedParameter extends AnalyzedValueNode {
|
||||
|
||||
override AbstractValue getALocalValue() {
|
||||
exists(DataFlow::AnalyzedNode pred |
|
||||
getFunction().argumentPassing(astNode, pred.asExpr()) and
|
||||
this.getFunction().argumentPassing(astNode, pred.asExpr()) and
|
||||
result = pred.getALocalValue()
|
||||
)
|
||||
or
|
||||
not getFunction().mayReceiveArgument(astNode) and
|
||||
not this.getFunction().mayReceiveArgument(astNode) and
|
||||
result = TAbstractUndefined()
|
||||
or
|
||||
result = astNode.getDefault().analyze().getALocalValue()
|
||||
}
|
||||
|
||||
override predicate hasAdditionalIncompleteness(DataFlow::Incompleteness cause) {
|
||||
getFunction().isIncomplete(cause)
|
||||
this.getFunction().isIncomplete(cause)
|
||||
or
|
||||
not getFunction().argumentPassing(astNode, _) and
|
||||
getFunction().mayReceiveArgument(astNode) and
|
||||
not this.getFunction().argumentPassing(astNode, _) and
|
||||
this.getFunction().mayReceiveArgument(astNode) and
|
||||
cause = "call"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +104,9 @@ private class AnalyzedNamespaceDeclaration extends DataFlow::AnalyzedValueNode {
|
||||
override NamespaceDeclaration astNode;
|
||||
|
||||
override AbstractValue getALocalValue() {
|
||||
result = TAbstractOtherObject() and getPreviousValue().getBooleanValue() = false
|
||||
result = TAbstractOtherObject() and this.getPreviousValue().getBooleanValue() = false
|
||||
or
|
||||
result = getPreviousValue() and result.getBooleanValue() = true
|
||||
result = this.getPreviousValue() and result.getBooleanValue() = true
|
||||
}
|
||||
|
||||
AbstractValue getPreviousValue() {
|
||||
@@ -161,7 +161,7 @@ private class AnalyzedSuperCall extends DataFlow::AnalyzedValueNode {
|
||||
|
||||
override AbstractValue getALocalValue() {
|
||||
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
|
||||
supVal = sup.getALocalValue()
|
||||
|
|
||||
@@ -183,7 +183,7 @@ private class AnalyzedNewExpr extends DataFlow::AnalyzedValueNode {
|
||||
override NewExpr astNode;
|
||||
|
||||
override AbstractValue getALocalValue() {
|
||||
isIndefinite() and
|
||||
this.isIndefinite() and
|
||||
(
|
||||
result = TIndefiniteFunctionOrClass("call") or
|
||||
result = TIndefiniteObject("call")
|
||||
|
||||
@@ -426,7 +426,7 @@ private class AnalyzedExportNamespaceSpecifier extends AnalyzedPropertyWrite, Da
|
||||
}
|
||||
|
||||
override predicate writesValue(AbstractValue baseVal, string propName, AbstractValue value) {
|
||||
baseVal = TAbstractExportsObject(getTopLevel()) and
|
||||
baseVal = TAbstractExportsObject(this.getTopLevel()) and
|
||||
propName = astNode.getExportedName() and
|
||||
value = TAbstractExportsObject(decl.getReExportedModule())
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ private import semmle.javascript.dataflow.LocalObjects
|
||||
abstract private class AnalyzedThisExpr extends DataFlow::AnalyzedNode, DataFlow::ThisNode {
|
||||
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 {
|
||||
NodeModule m;
|
||||
|
||||
AnalyzedThisAsModuleExports() { m = getBindingContainer() }
|
||||
AnalyzedThisAsModuleExports() { m = this.getBindingContainer() }
|
||||
|
||||
override AbstractValue getALocalValue() { result = TAbstractExportsObject(m) }
|
||||
}
|
||||
@@ -143,7 +143,7 @@ abstract class CallWithAnalyzedReturnFlow extends DataFlow::AnalyzedValueNode {
|
||||
abstract AnalyzedFunction getACallee();
|
||||
|
||||
override AbstractValue getALocalValue() {
|
||||
result = getACallee().getAReturnValue() and
|
||||
result = this.getACallee().getAReturnValue() and
|
||||
not this instanceof DataFlow::NewNode
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ abstract class CallWithNonLocalAnalyzedReturnFlow extends DataFlow::AnalyzedValu
|
||||
abstract AnalyzedFunction getACallee();
|
||||
|
||||
override AbstractValue getAValue() {
|
||||
result = getACallee().getAReturnValue()
|
||||
result = this.getACallee().getAReturnValue()
|
||||
or
|
||||
// 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
|
||||
@@ -213,7 +213,7 @@ class LocalFunction extends Function {
|
||||
) and
|
||||
// if the function is non-strict and its `arguments` object is accessed, we
|
||||
// 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. */
|
||||
@@ -307,7 +307,7 @@ private class AnalyzedThisInPartialInvokeCallback extends AnalyzedNode, DataFlow
|
||||
AnalyzedThisInPartialInvokeCallback() {
|
||||
exists(DataFlow::Node callbackArg |
|
||||
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);
|
||||
|
||||
override AbstractValue getAValue() {
|
||||
result = getASourceProperty().getAValue() or
|
||||
result = this.getASourceProperty().getAValue() or
|
||||
result = DataFlow::AnalyzedNode.super.getAValue()
|
||||
}
|
||||
|
||||
override AbstractValue getALocalValue() {
|
||||
result = getASourceProperty().getALocalValue() or
|
||||
result = this.getASourceProperty().getALocalValue() or
|
||||
result = DataFlow::AnalyzedNode.super.getALocalValue()
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ abstract class AnalyzedPropertyRead extends DataFlow::AnalyzedNode {
|
||||
*/
|
||||
pragma[noinline]
|
||||
private AbstractProperty getASourceProperty() {
|
||||
exists(AbstractValue base, string prop | reads(base, prop) |
|
||||
exists(AbstractValue base, string prop | this.reads(base, prop) |
|
||||
result = MkAbstractProperty(base, prop)
|
||||
)
|
||||
}
|
||||
@@ -45,7 +45,7 @@ abstract class AnalyzedPropertyRead extends DataFlow::AnalyzedNode {
|
||||
override predicate isIncomplete(DataFlow::Incompleteness cause) {
|
||||
super.isIncomplete(cause)
|
||||
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) {
|
||||
exists(AnalyzedNode source |
|
||||
writes(baseVal, propName, source) and
|
||||
this.writes(baseVal, propName, source) and
|
||||
val = source.getALocalValue()
|
||||
)
|
||||
}
|
||||
@@ -151,7 +151,7 @@ private class AnalyzedArgumentsCallee extends AnalyzedNonNumericPropertyRead {
|
||||
AnalyzedArgumentsCallee() { propName = "callee" }
|
||||
|
||||
override AbstractValue getALocalValue() {
|
||||
exists(AbstractArguments baseVal | reads(baseVal, _) |
|
||||
exists(AbstractArguments baseVal | this.reads(baseVal, _) |
|
||||
result = TAbstractFunction(baseVal.getFunction())
|
||||
)
|
||||
or
|
||||
|
||||
@@ -20,7 +20,7 @@ private class AnalyzedCapturedVariable extends @variable {
|
||||
* Gets an abstract value that may be assigned to this variable.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
AbstractValue getALocalValue() { result = getADef().getAnAssignedValue() }
|
||||
AbstractValue getALocalValue() { result = this.getADef().getAnAssignedValue() }
|
||||
|
||||
/**
|
||||
* Gets a definition of this variable.
|
||||
@@ -44,7 +44,7 @@ private class AnalyzedSsaDefinitionNode extends AnalyzedNode, DataFlow::SsaDefin
|
||||
private class SsaDefinitionWithNonLocalFlow extends SsaExplicitDefinition {
|
||||
CallWithNonLocalAnalyzedReturnFlow source;
|
||||
|
||||
SsaDefinitionWithNonLocalFlow() { source = getDef().getSource().flow() }
|
||||
SsaDefinitionWithNonLocalFlow() { source = this.getDef().getSource().flow() }
|
||||
|
||||
CallWithNonLocalAnalyzedReturnFlow getSource() { result = source }
|
||||
}
|
||||
@@ -84,10 +84,10 @@ class AnalyzedVarDef extends VarDef {
|
||||
* cannot be analyzed completely.
|
||||
*/
|
||||
AbstractValue getAnAssignedValue() {
|
||||
result = getAnRhsValue()
|
||||
result = this.getAnRhsValue()
|
||||
or
|
||||
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.
|
||||
*/
|
||||
AbstractValue getAnRhsValue() {
|
||||
result = getRhs().getALocalValue()
|
||||
result = this.getRhs().getALocalValue()
|
||||
or
|
||||
this = any(ForInStmt fis).getIteratorExpr() and result = abstractValueOfType(TTString())
|
||||
or
|
||||
@@ -109,7 +109,7 @@ class AnalyzedVarDef extends VarDef {
|
||||
* this `VarDef`.
|
||||
*/
|
||||
DataFlow::AnalyzedNode getRhs() {
|
||||
result = getSource().analyze() and getTarget() instanceof VarRef
|
||||
result = this.getSource().analyze() and this.getTarget() instanceof VarRef
|
||||
or
|
||||
result.asExpr() = this.(CompoundAssignExpr)
|
||||
or
|
||||
@@ -132,7 +132,7 @@ class AnalyzedVarDef extends VarDef {
|
||||
or
|
||||
exists(ComprehensionBlock cb | this = cb.getIterator()) and cause = "yield"
|
||||
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 {
|
||||
override AbstractValue getAnRhsValue() {
|
||||
result = getDef().(AnalyzedVarDef).getAnAssignedValue()
|
||||
result = this.getDef().(AnalyzedVarDef).getAnAssignedValue()
|
||||
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.
|
||||
*/
|
||||
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 {
|
||||
override AbstractValue getAnRhsValue() {
|
||||
exists(LocalVariable v | v = getSourceVariable() |
|
||||
exists(LocalVariable v | v = this.getSourceVariable() |
|
||||
result = v.(AnalyzedCapturedVariable).getALocalValue()
|
||||
or
|
||||
result = any(AnalyzedExplicitDefinition def | def.getSourceVariable() = v).getAnRhsValue()
|
||||
@@ -230,7 +230,7 @@ private class AnalyzedVariableCapture extends AnalyzedSsaDefinition, SsaVariable
|
||||
*/
|
||||
private class AnalyzedPhiNode extends AnalyzedSsaDefinition, SsaPhiNode {
|
||||
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 {
|
||||
override AbstractValue getAnRhsValue() {
|
||||
// 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
class AnalyzedConditionGuard extends AnalyzedRefinement {
|
||||
AnalyzedConditionGuard() { getGuard() instanceof ConditionGuardNode }
|
||||
AnalyzedConditionGuard() { this.getGuard() instanceof ConditionGuardNode }
|
||||
|
||||
override AbstractValue getAnInputRhsValue() {
|
||||
exists(AbstractValue input | input = super.getAnInputRhsValue() |
|
||||
@@ -276,13 +276,13 @@ class AnalyzedConditionGuard extends AnalyzedRefinement {
|
||||
* the beginning of `s` to those that are truthy.
|
||||
*/
|
||||
class AnalyzedPositiveConditionGuard extends AnalyzedRefinement {
|
||||
AnalyzedPositiveConditionGuard() { getGuard().(ConditionGuardNode).getOutcome() = true }
|
||||
AnalyzedPositiveConditionGuard() { this.getGuard().(ConditionGuardNode).getOutcome() = true }
|
||||
|
||||
override AbstractValue getAnRhsValue() {
|
||||
result = getAnInputRhsValue() and
|
||||
result = this.getAnInputRhsValue() and
|
||||
exists(RefinementContext ctxt |
|
||||
ctxt = TVarRefinementContext(this, getSourceVariable(), result) and
|
||||
getRefinement().eval(ctxt).getABooleanValue() = true
|
||||
ctxt = TVarRefinementContext(this, this.getSourceVariable(), result) and
|
||||
this.getRefinement().eval(ctxt).getABooleanValue() = true
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -294,13 +294,13 @@ class AnalyzedPositiveConditionGuard extends AnalyzedRefinement {
|
||||
* the beginning of `t` to those that are falsy.
|
||||
*/
|
||||
class AnalyzedNegativeConditionGuard extends AnalyzedRefinement {
|
||||
AnalyzedNegativeConditionGuard() { getGuard().(ConditionGuardNode).getOutcome() = false }
|
||||
AnalyzedNegativeConditionGuard() { this.getGuard().(ConditionGuardNode).getOutcome() = false }
|
||||
|
||||
override AbstractValue getAnRhsValue() {
|
||||
result = getAnInputRhsValue() and
|
||||
result = this.getAnInputRhsValue() and
|
||||
exists(RefinementContext ctxt |
|
||||
ctxt = TVarRefinementContext(this, getSourceVariable(), result) and
|
||||
getRefinement().eval(ctxt).getABooleanValue() = false
|
||||
ctxt = TVarRefinementContext(this, this.getSourceVariable(), result) and
|
||||
this.getRefinement().eval(ctxt).getABooleanValue() = false
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -389,7 +389,7 @@ private class AnalyzedGlobalVarUse extends DataFlow::AnalyzedValueNode {
|
||||
* of the global object.
|
||||
*/
|
||||
private DataFlow::PropWrite getAnAssigningPropWrite() {
|
||||
result.getPropertyName() = getVariableName() and
|
||||
result.getPropertyName() = this.getVariableName() and
|
||||
result.getBase().analyze().getALocalValue() instanceof AbstractGlobalObject
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ private class AnalyzedGlobalVarUse extends DataFlow::AnalyzedValueNode {
|
||||
override AbstractValue getALocalValue() {
|
||||
result = super.getALocalValue()
|
||||
or
|
||||
result = getAnAssigningPropWrite().getRhs().analyze().getALocalValue()
|
||||
result = this.getAnAssigningPropWrite().getRhs().analyze().getALocalValue()
|
||||
or
|
||||
result = agv.getAnAssignedValue()
|
||||
}
|
||||
@@ -668,8 +668,8 @@ abstract private class CallWithAnalyzedParameters extends FunctionWithAnalyzedPa
|
||||
abstract DataFlow::InvokeNode getAnInvocation();
|
||||
|
||||
override predicate argumentPassing(Parameter p, Expr arg) {
|
||||
exists(DataFlow::InvokeNode invk, int argIdx | invk = getAnInvocation() |
|
||||
p = getParameter(argIdx) and
|
||||
exists(DataFlow::InvokeNode invk, int argIdx | invk = this.getAnInvocation() |
|
||||
p = this.getParameter(argIdx) and
|
||||
not p.isRestParameter() and
|
||||
arg = invk.getArgument(argIdx).asExpr()
|
||||
)
|
||||
@@ -677,13 +677,13 @@ abstract private class CallWithAnalyzedParameters extends FunctionWithAnalyzedPa
|
||||
|
||||
override predicate mayReceiveArgument(Parameter p) {
|
||||
exists(int argIdx |
|
||||
p = getParameter(argIdx) and
|
||||
getAnInvocation().getNumArgument() > argIdx
|
||||
p = this.getParameter(argIdx) and
|
||||
this.getAnInvocation().getNumArgument() > argIdx
|
||||
)
|
||||
or
|
||||
// All parameters may receive an argument if invoked with a spread argument
|
||||
p = getAParameter() and
|
||||
getAnInvocation().asExpr().(InvokeExpr).isSpreadArgument(_)
|
||||
p = this.getAParameter() and
|
||||
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 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
|
||||
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 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
|
||||
sink = snk.getNode()
|
||||
)
|
||||
|
||||
@@ -196,19 +196,19 @@ module Angular2 {
|
||||
this = httpClient().getAMethodCall("request") and argumentOffset = 1
|
||||
or
|
||||
this = httpClient().getAMethodCall() and
|
||||
not getMethodName() = "request" and
|
||||
not this.getMethodName() = "request" and
|
||||
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 getADataNode() {
|
||||
getMethodName() = ["patch", "post", "put"] and
|
||||
result = getArgument(argumentOffset + 1)
|
||||
this.getMethodName() = ["patch", "post", "put"] and
|
||||
result = this.getArgument(argumentOffset + 1)
|
||||
or
|
||||
result = getOptionArgument(argumentOffset + 1, "body")
|
||||
result = this.getOptionArgument(argumentOffset + 1, "body")
|
||||
}
|
||||
|
||||
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
|
||||
@@ -268,7 +268,7 @@ module Angular2 {
|
||||
DataFlow::CallNode decorator;
|
||||
|
||||
ComponentClass() {
|
||||
decorator = getADecorator() and
|
||||
decorator = this.getADecorator() and
|
||||
decorator = DataFlow::moduleMember("@angular/core", "Component").getACall()
|
||||
}
|
||||
|
||||
@@ -289,9 +289,9 @@ module Angular2 {
|
||||
* this component.
|
||||
*/
|
||||
DataFlow::Node getFieldInputNode(string name) {
|
||||
result = getFieldNode(name)
|
||||
result = this.getFieldNode(name)
|
||||
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.
|
||||
*/
|
||||
DataFlow::Node getFieldOutputNode(string name) {
|
||||
result = getFieldNode(name)
|
||||
result = this.getFieldNode(name)
|
||||
or
|
||||
result = getInstanceMember(name, DataFlow::MemberKind::getter()).getReturnNode()
|
||||
result = this.getInstanceMember(name, DataFlow::MemberKind::getter()).getReturnNode()
|
||||
or
|
||||
result = getInstanceMethod(name)
|
||||
result = this.getInstanceMethod(name)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,7 +312,7 @@ module Angular2 {
|
||||
string getSelector() { decorator.getOptionArgument(0, "selector").mayHaveStringValue(result) }
|
||||
|
||||
/** 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.
|
||||
@@ -323,7 +323,8 @@ module Angular2 {
|
||||
*/
|
||||
DataFlow::Node getATemplateArgument(string name) {
|
||||
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. */
|
||||
HTML::Element getATemplateElement() {
|
||||
result.getFile() = getTemplateFile()
|
||||
result.getFile() = this.getTemplateFile()
|
||||
or
|
||||
result.getParent*() =
|
||||
HTML::getHtmlElementFromExpr(decorator.getOptionArgument(0, "template").asExpr(), _)
|
||||
@@ -349,7 +350,7 @@ module Angular2 {
|
||||
*/
|
||||
DataFlow::SourceNode getATemplateVarAccess(string name) {
|
||||
result =
|
||||
getATemplateElement()
|
||||
this.getATemplateElement()
|
||||
.getAnAttribute()
|
||||
.getCodeInAttribute()
|
||||
.(TemplateTopLevel)
|
||||
@@ -363,14 +364,14 @@ module Angular2 {
|
||||
|
||||
PipeClass() {
|
||||
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. */
|
||||
string getPipeName() { decorator.getOptionArgument(0, "name").mayHaveStringValue(result) }
|
||||
|
||||
/** 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 {
|
||||
@@ -413,25 +414,25 @@ module Angular2 {
|
||||
* attribute. There is no AST node for the implied for-of loop.
|
||||
*/
|
||||
private class ForLoopAttribute extends HTML::Attribute {
|
||||
ForLoopAttribute() { getName() = "*ngFor" }
|
||||
ForLoopAttribute() { this.getName() = "*ngFor" }
|
||||
|
||||
/** Gets a data-flow node holding the value being iterated over. */
|
||||
DataFlow::Node getIterationDomain() { result = getAttributeValueAsNode(this) }
|
||||
|
||||
/** 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. */
|
||||
HTML::Element getAnElementInScope() { result.getParent*() = getElement() }
|
||||
HTML::Element getAnElementInScope() { result.getParent*() = this.getElement() }
|
||||
|
||||
/** Gets a reference to the iterator variable. */
|
||||
DataFlow::Node getAnIteratorAccess() {
|
||||
result =
|
||||
getAnElementInScope()
|
||||
this.getAnElementInScope()
|
||||
.getAnAttribute()
|
||||
.getCodeInAttribute()
|
||||
.(TemplateTopLevel)
|
||||
.getAVariableUse(getIteratorName())
|
||||
.getAVariableUse(this.getIteratorName())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,11 +486,11 @@ module Angular2 {
|
||||
* A `<mat-table>` 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. */
|
||||
DataFlow::Node getDataSourceNode() {
|
||||
result = getAttributeValueAsNode(getAttributeByName("[dataSource]"))
|
||||
result = getAttributeValueAsNode(this.getAttributeByName("[dataSource]"))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -506,7 +507,7 @@ module Angular2 {
|
||||
DataFlow::Node getARowRef() {
|
||||
exists(string rowBinding |
|
||||
result =
|
||||
getATableCell(rowBinding)
|
||||
this.getATableCell(rowBinding)
|
||||
.getChild*()
|
||||
.getAnAttribute()
|
||||
.getCodeInAttribute()
|
||||
|
||||
@@ -22,7 +22,7 @@ private DataFlow::CallNode angularInjector() { result = angular().getAMemberCall
|
||||
class InjectorInvokeCall extends DataFlow::CallNode, DependencyInjection {
|
||||
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.
|
||||
*/
|
||||
DataFlow::Node getADependencyDeclaration(string name) {
|
||||
result = getDependencyDeclaration(_, name)
|
||||
result = this.getDependencyDeclaration(_, name)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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. */
|
||||
abstract DataFlow::FunctionNode asFunction();
|
||||
@@ -72,7 +72,7 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
|
||||
ServiceReference getAResolvedDependency(DataFlow::ParameterNode parameter) {
|
||||
exists(string name, InjectableFunctionServiceRequest request |
|
||||
this = request.getAnInjectedFunction() and
|
||||
parameter = getDependencyParameter(name) and
|
||||
parameter = this.getDependencyParameter(name) and
|
||||
result = request.getAServiceDefinition(name)
|
||||
)
|
||||
}
|
||||
@@ -83,7 +83,7 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
|
||||
*/
|
||||
DataFlow::Node getCustomServiceDependency(DataFlow::ParameterNode parameter) {
|
||||
exists(CustomServiceDefinition custom |
|
||||
custom.getServiceReference() = getAResolvedDependency(parameter) and
|
||||
custom.getServiceReference() = this.getAResolvedDependency(parameter) and
|
||||
result = custom.getAService()
|
||||
)
|
||||
}
|
||||
@@ -138,7 +138,7 @@ private class FunctionWithInjectProperty extends InjectableFunction instanceof D
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -37,22 +37,22 @@ module AsyncPackage {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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) {
|
||||
// Pass results to next task
|
||||
index >= 0 and
|
||||
argument = getArgument(index + 1) and
|
||||
argument = this.getArgument(index + 1) and
|
||||
callback = waterfall.getTask(n + 1)
|
||||
or
|
||||
// For the last task, pass results to the final callback
|
||||
index >= 1 and
|
||||
n = waterfall.getNumTasks() - 1 and
|
||||
argument = getArgument(index) and
|
||||
argument = this.getArgument(index) and
|
||||
callback = waterfall.getFinalCallback()
|
||||
or
|
||||
// Always pass error to the final callback
|
||||
index = 0 and
|
||||
argument = getArgument(0) and
|
||||
argument = this.getArgument(0) and
|
||||
callback = waterfall.getFinalCallback()
|
||||
}
|
||||
}
|
||||
@@ -120,17 +120,17 @@ module AsyncPackage {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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 {
|
||||
Config() {
|
||||
isTopLevel() and getJsonFile().getBaseName().matches(".babelrc%")
|
||||
this.isTopLevel() and this.getJsonFile().getBaseName().matches(".babelrc%")
|
||||
or
|
||||
this = any(PackageJson pkg).getPropValue("babel")
|
||||
}
|
||||
@@ -21,7 +21,7 @@ module Babel {
|
||||
*/
|
||||
JsonValue getPluginConfig(string pluginName) {
|
||||
exists(JsonArray plugins |
|
||||
plugins = getPropValue("plugins") and
|
||||
plugins = this.getPropValue("plugins") and
|
||||
result = plugins.getElementValue(_)
|
||||
|
|
||||
result.getStringValue() = pluginName
|
||||
@@ -34,9 +34,9 @@ module Babel {
|
||||
* Gets a file affected by this Babel configuration.
|
||||
*/
|
||||
Container getAContainerInScope() {
|
||||
result = getJsonFile().getParentContainer()
|
||||
result = this.getJsonFile().getParentContainer()
|
||||
or
|
||||
result = getAContainerInScope().getAChildContainer() and
|
||||
result = this.getAContainerInScope().getAChildContainer() and
|
||||
// File-relative .babelrc search stops at any package.json or .babelrc file.
|
||||
not result.getAChildContainer() = any(PackageJson pkg).getJsonFile() and
|
||||
not result.getAChildContainer() = any(Config pkg).getJsonFile()
|
||||
@@ -45,7 +45,7 @@ module Babel {
|
||||
/**
|
||||
* 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) }
|
||||
|
||||
/** 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`. */
|
||||
predicate appliesTo(TopLevel tl) { cfg.appliesTo(tl) }
|
||||
@@ -88,11 +88,11 @@ module Babel {
|
||||
* Gets the root specified for the given prefix.
|
||||
*/
|
||||
string getRoot(string prefix) {
|
||||
result = getExplicitRoot(prefix)
|
||||
result = this.getExplicitRoot(prefix)
|
||||
or
|
||||
// by default, `~` is mapped to the folder containing the configuration
|
||||
prefix = "~" and
|
||||
not exists(getExplicitRoot(prefix)) and
|
||||
not exists(this.getExplicitRoot(prefix)) and
|
||||
result = "."
|
||||
}
|
||||
|
||||
@@ -101,15 +101,15 @@ module Babel {
|
||||
*/
|
||||
private JsonObject getARootPathSpec() {
|
||||
// ["babel-plugin-root-import", <spec>]
|
||||
result = getOptions() and
|
||||
result = this.getOptions() and
|
||||
exists(result.getPropValue("rootPathSuffix"))
|
||||
or
|
||||
exists(JsonArray pathSpecs |
|
||||
// ["babel-plugin-root-import", [ <spec>... ] ]
|
||||
pathSpecs = getOptions()
|
||||
pathSpecs = this.getOptions()
|
||||
or
|
||||
// ["babel-plugin-root-import", { "paths": [ <spec> ... ] }]
|
||||
pathSpecs = getOption("paths")
|
||||
pathSpecs = this.getOption("paths")
|
||||
|
|
||||
result = pathSpecs.getElementValue(_)
|
||||
)
|
||||
@@ -120,7 +120,7 @@ module Babel {
|
||||
*/
|
||||
private string getExplicitRoot(string prefix) {
|
||||
exists(JsonObject rootPathSpec |
|
||||
rootPathSpec = getARootPathSpec() and
|
||||
rootPathSpec = this.getARootPathSpec() and
|
||||
result = rootPathSpec.getPropStringValue("rootPathSuffix")
|
||||
|
|
||||
if exists(rootPathSpec.getPropStringValue("rootPathPrefix"))
|
||||
@@ -132,7 +132,7 @@ module Babel {
|
||||
/**
|
||||
* 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() {
|
||||
this instanceof PathExpr and
|
||||
plugin.appliesTo(getTopLevel()) and
|
||||
prefix = getStringValue().regexpCapture("(.)/(.*)", 1) and
|
||||
suffix = getStringValue().regexpCapture("(.)/(.*)", 2) and
|
||||
plugin.appliesTo(this.getTopLevel()) and
|
||||
prefix = this.getStringValue().regexpCapture("(.)/(.*)", 1) and
|
||||
suffix = this.getStringValue().regexpCapture("(.)/(.*)", 2) and
|
||||
mappedPrefix = plugin.getRoot(prefix)
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ module Babel {
|
||||
TransformReactJsxConfig() { pluginName = "transform-react-jsx" }
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
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) }
|
||||
|
||||
/** 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(...)))`.
|
||||
@@ -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`.
|
||||
*/
|
||||
final DataFlow::FunctionNode getOperandFunction(int i) {
|
||||
result = getOperandNode(i).getALocalSource()
|
||||
result = this.getOperandNode(i).getALocalSource()
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
int getNumOperand() { result = super.getNumOperand() }
|
||||
@@ -65,17 +65,17 @@ module FunctionCompositionCall {
|
||||
abstract private class WithArrayOverloading extends Range {
|
||||
/** Gets the `i`th argument to the call or the `i`th array element passed into the call. */
|
||||
DataFlow::Node getEffectiveArgument(int i) {
|
||||
result = getArgument(0).(DataFlow::ArrayCreationNode).getElement(i)
|
||||
result = this.getArgument(0).(DataFlow::ArrayCreationNode).getElement(i)
|
||||
or
|
||||
not getArgument(0) instanceof DataFlow::ArrayCreationNode and
|
||||
result = getArgument(i)
|
||||
not this.getArgument(0) instanceof DataFlow::ArrayCreationNode and
|
||||
result = this.getArgument(i)
|
||||
}
|
||||
|
||||
override int getNumOperand() {
|
||||
result = getArgument(0).(DataFlow::ArrayCreationNode).getSize()
|
||||
result = this.getArgument(0).(DataFlow::ArrayCreationNode).getSize()
|
||||
or
|
||||
not getArgument(0) instanceof DataFlow::ArrayCreationNode and
|
||||
result = getNumArgument()
|
||||
not this.getArgument(0) instanceof DataFlow::ArrayCreationNode and
|
||||
result = this.getNumArgument()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ module FunctionCompositionCall {
|
||||
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(...))` */
|
||||
@@ -103,7 +103,7 @@ module FunctionCompositionCall {
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
override DataFlow::ParameterNode getRequestParameter() {
|
||||
result = getRouteHandlerParameter("request")
|
||||
result = this.getRouteHandlerParameter("request")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameter of the route handler that contains the response object.
|
||||
*/
|
||||
override DataFlow::ParameterNode getResponseParameter() {
|
||||
result = getRouteHandlerParameter("response")
|
||||
result = this.getRouteHandlerParameter("response")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ module Connect {
|
||||
ServerDefinition server;
|
||||
|
||||
RouteSetup() {
|
||||
getMethodName() = "use" and
|
||||
this.getMethodName() = "use" and
|
||||
(
|
||||
// app.use(fun)
|
||||
server.ref().getAMethodCall() = this
|
||||
@@ -76,14 +76,14 @@ module Connect {
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getARouteHandler() {
|
||||
result = getARouteHandler(DataFlow::TypeBackTracker::end())
|
||||
result = this.getARouteHandler(DataFlow::TypeBackTracker::end())
|
||||
}
|
||||
|
||||
private DataFlow::SourceNode getARouteHandler(DataFlow::TypeBackTracker t) {
|
||||
t.start() and
|
||||
result = getARouteHandlerNode().getALocalSource()
|
||||
result = this.getARouteHandlerNode().getALocalSource()
|
||||
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 }
|
||||
@@ -92,12 +92,12 @@ module Connect {
|
||||
* DEPRECATED: Use `getARouteHandlerNode` instead.
|
||||
* 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.
|
||||
*/
|
||||
DataFlow::Node getARouteHandlerNode() { result = getAnArgument() }
|
||||
DataFlow::Node getARouteHandlerNode() { result = this.getAnArgument() }
|
||||
}
|
||||
|
||||
/** An expression that is passed as `basicAuthConnect(<user>, <password>)`. */
|
||||
|
||||
@@ -14,7 +14,7 @@ abstract class EmscriptenMarkerComment extends GeneratedCodeMarkerComment { }
|
||||
* An `EMSCRIPTEN_START_ASM` marker comment.
|
||||
*/
|
||||
class EmscriptenStartAsmComment extends EmscriptenMarkerComment {
|
||||
EmscriptenStartAsmComment() { getText().trim() = "EMSCRIPTEN_START_ASM" }
|
||||
EmscriptenStartAsmComment() { this.getText().trim() = "EMSCRIPTEN_START_ASM" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for EmscriptenStartAsmComment */
|
||||
@@ -24,14 +24,14 @@ deprecated class EmscriptenStartASMComment = EmscriptenStartAsmComment;
|
||||
* An `EMSCRIPTEN_START_FUNCS` marker comment.
|
||||
*/
|
||||
class EmscriptenStartFuncsComment extends EmscriptenMarkerComment {
|
||||
EmscriptenStartFuncsComment() { getText().trim() = "EMSCRIPTEN_START_FUNCS" }
|
||||
EmscriptenStartFuncsComment() { this.getText().trim() = "EMSCRIPTEN_START_FUNCS" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An `EMSCRIPTEN_END_ASM` marker comment.
|
||||
*/
|
||||
class EmscriptenEndAsmComment extends EmscriptenMarkerComment {
|
||||
EmscriptenEndAsmComment() { getText().trim() = "EMSCRIPTEN_END_ASM" }
|
||||
EmscriptenEndAsmComment() { this.getText().trim() = "EMSCRIPTEN_END_ASM" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for EmscriptenEndAsmComment */
|
||||
@@ -41,7 +41,7 @@ deprecated class EmscriptenEndASMComment = EmscriptenEndAsmComment;
|
||||
* An `EMSCRIPTEN_END_FUNCS` marker comment.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
DataFlow::Node getOption(string name) { result = getOptionArgument(0, name) }
|
||||
DataFlow::Node getOption(string name) { result = this.getOptionArgument(0, name) }
|
||||
|
||||
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))
|
||||
then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(secret)).getAnElement()
|
||||
else result = secret
|
||||
@@ -138,10 +138,10 @@ module ExpressLibraries {
|
||||
/**
|
||||
* 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() {
|
||||
exists(DataFlow::Node arg0 | arg0 = getArgument(0) |
|
||||
exists(DataFlow::Node arg0 | arg0 = this.getArgument(0) |
|
||||
if exists(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0))
|
||||
then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0)).getAnElement()
|
||||
else result = arg0
|
||||
@@ -167,13 +167,13 @@ module ExpressLibraries {
|
||||
/**
|
||||
* 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() {
|
||||
result = getOption("secret")
|
||||
result = this.getOption("secret")
|
||||
or
|
||||
exists(DataFlow::ArrayCreationNode keys |
|
||||
keys.flowsTo(getOption("keys")) and
|
||||
keys.flowsTo(this.getOption("keys")) and
|
||||
result = keys.getAnElement()
|
||||
)
|
||||
}
|
||||
@@ -213,14 +213,14 @@ module ExpressLibraries {
|
||||
*/
|
||||
predicate isExtendedUrlEncoded() {
|
||||
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
|
||||
* 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")
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getADataNode() { none() }
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import javascript
|
||||
* A `$gwt_version` variable.
|
||||
*/
|
||||
class GwtVersionVariable extends GlobalVariable {
|
||||
GwtVersionVariable() { getName() = "$gwt_version" }
|
||||
GwtVersionVariable() { this.getName() = "$gwt_version" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for GwtVersionVariable */
|
||||
@@ -33,7 +33,7 @@ class GwtHeader extends InlineScript {
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getGwtVersion */
|
||||
deprecated string getGWTVersion() { result = getGwtVersion() }
|
||||
deprecated string getGWTVersion() { result = this.getGwtVersion() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for GwtHeader */
|
||||
@@ -43,7 +43,7 @@ deprecated class GWTHeader = GwtHeader;
|
||||
* A toplevel in a file that appears to be GWT-generated.
|
||||
*/
|
||||
class GwtGeneratedTopLevel extends TopLevel {
|
||||
GwtGeneratedTopLevel() { exists(GwtHeader h | getFile() = h.getFile()) }
|
||||
GwtGeneratedTopLevel() { exists(GwtHeader h | this.getFile() = h.getFile()) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for GwtGeneratedTopLevel */
|
||||
|
||||
@@ -19,10 +19,10 @@ private module HttpProxy {
|
||||
.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() {
|
||||
result = getParameter(0).getMember("target").getMember("host").asSink()
|
||||
result = this.getParameter(0).getMember("target").getMember("host").asSink()
|
||||
}
|
||||
|
||||
override DataFlow::Node getADataNode() { none() }
|
||||
@@ -45,14 +45,16 @@ private module HttpProxy {
|
||||
or
|
||||
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() {
|
||||
result = getOptionsObject().getMember("target").getMember("host").asSink()
|
||||
result = this.getOptionsObject().getMember("target").getMember("host").asSink()
|
||||
}
|
||||
|
||||
override DataFlow::Node getADataNode() { none() }
|
||||
@@ -84,11 +86,11 @@ private module HttpProxy {
|
||||
}
|
||||
|
||||
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() {
|
||||
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() {
|
||||
exists(string name, int argumentCount |
|
||||
this = LodashUnderscore::member(name).getACall() and
|
||||
getNumArgument() = argumentCount
|
||||
this.getNumArgument() = argumentCount
|
||||
|
|
||||
name = ["bind", "callback", "iteratee"] and
|
||||
callbackIndex = 0 and
|
||||
@@ -219,7 +219,7 @@ private class LodashCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode:
|
||||
}
|
||||
|
||||
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
||||
callback = getArgument(callbackIndex) and
|
||||
result = getArgument(contextIndex)
|
||||
callback = this.getArgument(callbackIndex) and
|
||||
result = this.getArgument(contextIndex)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,11 +63,11 @@ private module Console {
|
||||
override DataFlow::Node getAMessageComponent() {
|
||||
(
|
||||
if name = "assert"
|
||||
then result = getArgument([1 .. getNumArgument()])
|
||||
else result = getAnArgument()
|
||||
then result = this.getArgument([1 .. this.getNumArgument()])
|
||||
else result = this.getAnArgument()
|
||||
)
|
||||
or
|
||||
result = getASpreadArgument()
|
||||
result = this.getASpreadArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +89,7 @@ private module Loglevel {
|
||||
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() {
|
||||
if getMethodName() = "log"
|
||||
then result = getOptionArgument(0, "message")
|
||||
else result = getAnArgument()
|
||||
if this.getMethodName() = "log"
|
||||
then result = this.getOptionArgument(0, "message")
|
||||
else result = this.getAnArgument()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ private module Log4js {
|
||||
.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() {
|
||||
(
|
||||
if name = "log"
|
||||
then result = getArgument([1 .. getNumArgument()])
|
||||
else result = getAnArgument()
|
||||
then result = this.getArgument([1 .. this.getNumArgument()])
|
||||
else result = this.getAnArgument()
|
||||
)
|
||||
or
|
||||
result = getASpreadArgument()
|
||||
result = this.getASpreadArgument()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,7 +179,7 @@ private module Fancylog {
|
||||
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 {
|
||||
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() {
|
||||
result = API::moduleImport("kleur")
|
||||
or
|
||||
result = kleurInstance().getAMember().getReturn()
|
||||
result = this.kleurInstance().getAMember().getReturn()
|
||||
}
|
||||
|
||||
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
|
||||
succ = call
|
||||
)
|
||||
@@ -363,7 +363,7 @@ private module Pino {
|
||||
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 Http::RouteHandler getRouteHandler() {
|
||||
result = getRouteHandlerFromReqRes(getArgument(0))
|
||||
result = getRouteHandlerFromReqRes(this.getArgument(0))
|
||||
}
|
||||
|
||||
override predicate isUserControlledObject() { name = "json" }
|
||||
|
||||
@@ -114,9 +114,9 @@ private class SimplePropertyProjection extends PropertyProjection::Range {
|
||||
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 }
|
||||
}
|
||||
@@ -127,9 +127,9 @@ private class SimplePropertyProjection extends PropertyProjection::Range {
|
||||
private class VarArgsPropertyProjection extends PropertyProjection::Range {
|
||||
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() }
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ module Puppeteer {
|
||||
private class PuppeteerGotoCall extends ClientRequest::Range, API::InvokeNode {
|
||||
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() }
|
||||
|
||||
@@ -86,7 +86,7 @@ module Puppeteer {
|
||||
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() }
|
||||
|
||||
|
||||
@@ -53,18 +53,18 @@ abstract class ReactComponent extends AstNode {
|
||||
* Gets a reference to an instance of this component.
|
||||
*/
|
||||
pragma[noinline]
|
||||
DataFlow::SourceNode getAnInstanceReference() { result = ref() }
|
||||
DataFlow::SourceNode getAnInstanceReference() { result = this.ref() }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
DataFlow::SourceNode getADirectStateAccess() {
|
||||
result = getAnInstanceReference().getAPropertyReference("state")
|
||||
result = this.getAnInstanceReference().getAPropertyReference("state")
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
DataFlow::SourceNode getAStateAccess() {
|
||||
result = getADirectStateAccess()
|
||||
result = this.getADirectStateAccess()
|
||||
or
|
||||
result = getAStateAccess().getAPropertyReference()
|
||||
result = this.getAStateAccess().getAPropertyReference()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this component specifies default values for (some of) its
|
||||
* props.
|
||||
*/
|
||||
predicate hasDefaultProps() { exists(getADefaultPropsSource()) }
|
||||
predicate hasDefaultProps() { exists(this.getADefaultPropsSource()) }
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
Function getRenderMethod() { result = getInstanceMethod("render") }
|
||||
Function getRenderMethod() { result = this.getInstanceMethod("render") }
|
||||
|
||||
/**
|
||||
* Gets a call to method `name` on this component.
|
||||
*/
|
||||
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() {
|
||||
// a direct definition: `this.state = o`
|
||||
result = getAnInstanceReference().getAPropertySource("state")
|
||||
result = this.getAnInstanceReference().getAPropertySource("state")
|
||||
or
|
||||
exists(DataFlow::MethodCallNode mce, DataFlow::SourceNode arg0 |
|
||||
mce = getAMethodCall("setState") or
|
||||
mce = getAMethodCall("forceUpdate")
|
||||
mce = this.getAMethodCall("setState") or
|
||||
mce = this.getAMethodCall("forceUpdate")
|
||||
|
|
||||
arg0.flowsTo(mce.getArgument(0)) and
|
||||
if arg0 instanceof DataFlow::FunctionNode
|
||||
@@ -151,11 +151,12 @@ abstract class ReactComponent extends AstNode {
|
||||
staticMember = "getDerivedStateFromProps" or
|
||||
staticMember = "getDerivedStateFromError"
|
||||
|
|
||||
result.flowsToExpr(getStaticMethod(staticMember).getAReturnedExpr())
|
||||
result.flowsToExpr(this.getStaticMethod(staticMember).getAReturnedExpr())
|
||||
)
|
||||
or
|
||||
// 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)
|
||||
|
|
||||
// setState: (prevState, props)
|
||||
callback = getAMethodCall("setState").getCallback(0) and
|
||||
callback = this.getAMethodCall("setState").getCallback(0) and
|
||||
stateParameterIndex = 0
|
||||
or
|
||||
stateParameterIndex = 1 and
|
||||
(
|
||||
// componentDidUpdate: (prevProps, prevState)
|
||||
callback = getInstanceMethod("componentDidUpdate").flow()
|
||||
callback = this.getInstanceMethod("componentDidUpdate").flow()
|
||||
or
|
||||
// getDerivedStateFromProps: (props, state)
|
||||
callback = getStaticMethod("getDerivedStateFromProps").flow()
|
||||
callback = this.getStaticMethod("getDerivedStateFromProps").flow()
|
||||
or
|
||||
// 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.
|
||||
*/
|
||||
DataFlow::SourceNode getACandidatePropsSource() {
|
||||
result.flowsTo(getAComponentCreatorReference().getAnInvocation().getArgument(0))
|
||||
result.flowsTo(this.getAComponentCreatorReference().getAnInvocation().getArgument(0))
|
||||
or
|
||||
result = getADefaultPropsSource()
|
||||
result = this.getADefaultPropsSource()
|
||||
or
|
||||
// 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.
|
||||
*/
|
||||
DataFlow::Node getACandidatePropsValue(string name) {
|
||||
getACandidatePropsSource().hasPropertyWrite(name, result)
|
||||
this.getACandidatePropsSource().hasPropertyWrite(name, result)
|
||||
or
|
||||
exists(ReactJsxElement e, JsxAttribute attr |
|
||||
this = e.getComponent() and
|
||||
@@ -226,19 +228,19 @@ abstract class ReactComponent extends AstNode {
|
||||
callback.getParameter(propsParameterIndex).flowsTo(result)
|
||||
|
|
||||
// setState: (prevState, props)
|
||||
callback = getAMethodCall("setState").getCallback(0) and
|
||||
callback = this.getAMethodCall("setState").getCallback(0) and
|
||||
propsParameterIndex = 1
|
||||
or
|
||||
propsParameterIndex = 0 and
|
||||
(
|
||||
// componentDidUpdate: (prevProps, prevState)
|
||||
callback = getInstanceMethod("componentDidUpdate").flow()
|
||||
callback = this.getInstanceMethod("componentDidUpdate").flow()
|
||||
or
|
||||
// getDerivedStateFromProps: (props, state)
|
||||
callback = getStaticMethod("getDerivedStateFromProps").flow()
|
||||
callback = this.getStaticMethod("getDerivedStateFromProps").flow()
|
||||
or
|
||||
// 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`
|
||||
// that always returns a JSX element or fragment, or a React
|
||||
// element is probably a component
|
||||
getNumParameter() = 1 and
|
||||
exists(Parameter p | p = getParameter(0) |
|
||||
this.getNumParameter() = 1 and
|
||||
exists(Parameter p | p = this.getParameter(0) |
|
||||
p.getName().regexpMatch("(?i).*props.*") or
|
||||
p instanceof ObjectPattern
|
||||
) and
|
||||
@@ -279,7 +281,7 @@ class FunctionalComponent extends ReactComponent, Function {
|
||||
override Function getStaticMethod(string name) { none() }
|
||||
|
||||
override DataFlow::SourceNode getADirectPropsAccess() {
|
||||
result = DataFlow::parameterNode(getParameter(0))
|
||||
result = DataFlow::parameterNode(this.getParameter(0))
|
||||
}
|
||||
|
||||
override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) }
|
||||
@@ -288,11 +290,11 @@ class FunctionalComponent extends ReactComponent, Function {
|
||||
t.start() and
|
||||
result = DataFlow::valueNode(this)
|
||||
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() {
|
||||
result = getAComponentCreatorReference(DataFlow::TypeTracker::end())
|
||||
result = this.getAComponentCreatorReference(DataFlow::TypeTracker::end())
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getComponentCreatorSource() { result = DataFlow::valueNode(this) }
|
||||
@@ -315,16 +317,16 @@ abstract private class SharedReactPreactClassComponent extends ReactComponent, C
|
||||
|
||||
override Function getStaticMethod(string name) {
|
||||
exists(MethodDeclaration decl |
|
||||
decl = getMethod(name) and
|
||||
decl = this.getMethod(name) and
|
||||
decl.isStatic() and
|
||||
result = decl.getBody()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getADirectPropsAccess() {
|
||||
result = getAnInstanceReference().getAPropertyRead("props")
|
||||
result = this.getAnInstanceReference().getAPropertyRead("props")
|
||||
or
|
||||
result = DataFlow::parameterNode(getConstructor().getBody().getParameter(0))
|
||||
result = DataFlow::parameterNode(this.getConstructor().getBody().getParameter(0))
|
||||
}
|
||||
|
||||
override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) }
|
||||
@@ -337,7 +339,7 @@ abstract private class SharedReactPreactClassComponent extends ReactComponent, C
|
||||
|
||||
override DataFlow::SourceNode getACandidateStateSource() {
|
||||
result = ReactComponent.super.getACandidateStateSource() or
|
||||
result.flowsToExpr(getField("state").getInit())
|
||||
result.flowsToExpr(this.getField("state").getInit())
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getADefaultPropsSource() {
|
||||
@@ -359,7 +361,7 @@ abstract class ES2015Component extends SharedReactPreactClassComponent { }
|
||||
*/
|
||||
private class DefiniteES2015Component extends ES2015Component {
|
||||
DefiniteES2015Component() {
|
||||
exists(DataFlow::SourceNode sup | sup.flowsToExpr(getSuperClass()) |
|
||||
exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.getSuperClass()) |
|
||||
exists(PropAccess access, string globalReactName |
|
||||
(globalReactName = "react" or globalReactName = "React") and
|
||||
access = sup.asExpr()
|
||||
@@ -383,12 +385,12 @@ private class DefiniteES2015Component extends ES2015Component {
|
||||
abstract class PreactComponent extends SharedReactPreactClassComponent {
|
||||
override DataFlow::SourceNode getADirectPropsAccess() {
|
||||
result = super.getADirectPropsAccess() or
|
||||
result = DataFlow::parameterNode(getInstanceMethod("render").getParameter(0))
|
||||
result = DataFlow::parameterNode(this.getInstanceMethod("render").getParameter(0))
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getADirectStateAccess() {
|
||||
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 {
|
||||
DefinitePreactComponent() {
|
||||
exists(DataFlow::SourceNode sup | sup.flowsToExpr(getSuperClass()) |
|
||||
exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.getSuperClass()) |
|
||||
exists(PropAccess access, string globalPreactName |
|
||||
(globalPreactName = "preact" or globalPreactName = "Preact") and
|
||||
access = sup.asExpr()
|
||||
@@ -420,7 +422,7 @@ private class HeuristicReactPreactComponent extends ClassDefinition, PreactCompo
|
||||
ES2015Component
|
||||
{
|
||||
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"))
|
||||
}
|
||||
}
|
||||
@@ -442,12 +444,14 @@ class ES5Component extends ReactComponent, ObjectExpr {
|
||||
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 DataFlow::SourceNode getADirectPropsAccess() {
|
||||
result = getAnInstanceReference().getAPropertyRead("props")
|
||||
result = this.getAnInstanceReference().getAPropertyRead("props")
|
||||
}
|
||||
|
||||
override AbstractValue getAbstractComponent() { result = TAbstractObjectLiteral(this) }
|
||||
@@ -456,23 +460,23 @@ class ES5Component extends ReactComponent, ObjectExpr {
|
||||
t.start() and
|
||||
result = create
|
||||
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() {
|
||||
result = getAComponentCreatorReference(DataFlow::TypeTracker::end())
|
||||
result = this.getAComponentCreatorReference(DataFlow::TypeTracker::end())
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getComponentCreatorSource() { result = create }
|
||||
|
||||
override DataFlow::SourceNode getACandidateStateSource() {
|
||||
result = ReactComponent.super.getACandidateStateSource() or
|
||||
result.flowsToExpr(getInstanceMethod("getInitialState").getAReturnedExpr())
|
||||
result.flowsToExpr(this.getInstanceMethod("getInitialState").getAReturnedExpr())
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getADefaultPropsSource() {
|
||||
exists(Function f |
|
||||
f = getInstanceMethod("getDefaultProps") and
|
||||
f = this.getInstanceMethod("getDefaultProps") and
|
||||
result.flowsToExpr(f.getAReturnedExpr())
|
||||
)
|
||||
}
|
||||
@@ -538,13 +542,13 @@ private class ReactCallbackPartialInvoke extends DataFlow::PartialInvokeNode::Ra
|
||||
name = "forEach"
|
||||
|
|
||||
this = react().getAPropertyRead("Children").getAMemberCall(name) and
|
||||
3 = getNumArgument()
|
||||
3 = this.getNumArgument()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
||||
callback = getArgument(1) and
|
||||
result = getArgument(2)
|
||||
callback = this.getArgument(1) and
|
||||
result = this.getArgument(2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,7 +558,7 @@ private class ReactCallbackPartialInvoke extends DataFlow::PartialInvokeNode::Ra
|
||||
private class ReactJsxElement extends JsxElement {
|
||||
ReactComponent component;
|
||||
|
||||
ReactJsxElement() { component.getAComponentCreatorReference().flowsToExpr(getNameExpr()) }
|
||||
ReactJsxElement() { component.getAComponentCreatorReference().flowsToExpr(this.getNameExpr()) }
|
||||
|
||||
/**
|
||||
* Gets the component this element instantiates.
|
||||
|
||||
@@ -58,7 +58,7 @@ module Redux {
|
||||
*/
|
||||
class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range {
|
||||
/** 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. */
|
||||
API::Node asApiNode() { result.asSource() = this }
|
||||
@@ -67,7 +67,9 @@ module Redux {
|
||||
DataFlow::Node getReducerArg() { result = super.getReducerArg() }
|
||||
|
||||
/** 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. */
|
||||
@@ -85,7 +87,7 @@ module Redux {
|
||||
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 {
|
||||
@@ -94,7 +96,7 @@ module Redux {
|
||||
}
|
||||
|
||||
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() }
|
||||
|
||||
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) {
|
||||
result = getAPropertyWrite(prop).getRhs()
|
||||
result = this.getAPropertyWrite(prop).getRhs()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +237,7 @@ module Redux {
|
||||
|
||||
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
||||
exists(DataFlow::PropWrite write |
|
||||
result = getParameter(0).getAMember().asSink() and
|
||||
result = this.getParameter(0).getAMember().asSink() and
|
||||
write.getRhs() = result and
|
||||
actionType = write.getPropertyNameExpr().flow()
|
||||
)
|
||||
@@ -258,8 +260,8 @@ module Redux {
|
||||
}
|
||||
|
||||
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
||||
actionType = getArgument(0) and
|
||||
result = getArgument(1)
|
||||
actionType = this.getArgument(0) and
|
||||
result = this.getArgument(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +273,7 @@ module Redux {
|
||||
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()
|
||||
}
|
||||
|
||||
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() {
|
||||
result = getAnArgument()
|
||||
result = this.getAnArgument()
|
||||
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() {
|
||||
result = getParameter(1).getParameter(0)
|
||||
result = this.getParameter(1).getParameter(0)
|
||||
or
|
||||
result = getABuilderRef().getAMember().getReturn()
|
||||
result = this.getABuilderRef().getAMember().getReturn()
|
||||
}
|
||||
|
||||
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
||||
exists(API::CallNode addCase |
|
||||
addCase = getABuilderRef().getMember("addCase").getACall() and
|
||||
addCase = this.getABuilderRef().getMember("addCase").getACall() and
|
||||
actionType = addCase.getArgument(0) and
|
||||
result = addCase.getArgument(1)
|
||||
)
|
||||
@@ -380,7 +382,7 @@ module Redux {
|
||||
private API::Node getABuilderRef() {
|
||||
result = call.getParameter(0).getMember("extraReducers").getParameter(0)
|
||||
or
|
||||
result = getABuilderRef().getAMember().getReturn()
|
||||
result = this.getABuilderRef().getAMember().getReturn()
|
||||
}
|
||||
|
||||
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
|
||||
@@ -400,7 +402,7 @@ module Redux {
|
||||
// Builder callback to 'extraReducers':
|
||||
// extraReducers: builder => builder.addCase(action, reducer)
|
||||
exists(API::CallNode addCase |
|
||||
addCase = getABuilderRef().getMember("addCase").getACall() and
|
||||
addCase = this.getABuilderRef().getMember("addCase").getACall() and
|
||||
actionType = addCase.getArgument(0) and
|
||||
result = addCase.getArgument(1)
|
||||
)
|
||||
@@ -444,7 +446,7 @@ module Redux {
|
||||
or
|
||||
// x -> bindActionCreators({ x, ... })
|
||||
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()
|
||||
)
|
||||
or
|
||||
@@ -454,32 +456,32 @@ module Redux {
|
||||
API::moduleImport(["redux-actions", "redux-ts-utils"])
|
||||
.getMember("combineActions")
|
||||
.getACall() and
|
||||
ref(t.continue()).flowsTo(combiner.getAnArgument()) and
|
||||
this.ref(t.continue()).flowsTo(combiner.getAnArgument()) and
|
||||
result = combiner
|
||||
)
|
||||
or
|
||||
// x -> x.fulfilled, for async action creators
|
||||
result = ref(t.continue()).getAPropertyRead("fulfilled")
|
||||
result = this.ref(t.continue()).getAPropertyRead("fulfilled")
|
||||
or
|
||||
// follow flow through mapDispatchToProps
|
||||
ReactRedux::dispatchToPropsStep(ref(t.continue()).getALocalUse(), result)
|
||||
ReactRedux::dispatchToPropsStep(this.ref(t.continue()).getALocalUse(), result)
|
||||
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. */
|
||||
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.
|
||||
*/
|
||||
private ReachableBasicBlock getASuccessfulTypeCheckBlock(DataFlow::SourceNode action) {
|
||||
action = getAnUntypedActionInReducer() and
|
||||
result = getASuccessfulTypeCheckBlock(action, getTypeTag())
|
||||
result = getASuccessfulTypeCheckBlock(action, this.getTypeTag())
|
||||
or
|
||||
// some action creators implement a .match method for this purpose
|
||||
exists(ConditionGuardNode guard, DataFlow::CallNode call |
|
||||
call = ref().getAMethodCall("match") and
|
||||
call = this.ref().getAMethodCall("match") and
|
||||
guard.getTest() = call.asExpr() and
|
||||
action.flowsTo(call.getArgument(0)) and
|
||||
guard.getOutcome() = true and
|
||||
@@ -497,9 +499,9 @@ module Redux {
|
||||
*/
|
||||
DataFlow::FunctionNode getAReducerFunction() {
|
||||
exists(ReducerArg reducer |
|
||||
reducer.isTypeTagHandler(getTypeTag())
|
||||
reducer.isTypeTagHandler(this.getTypeTag())
|
||||
or
|
||||
reducer.isActionTypeHandler(ref().getALocalUse())
|
||||
reducer.isActionTypeHandler(this.ref().getALocalUse())
|
||||
|
|
||||
result = reducer.getASource()
|
||||
)
|
||||
@@ -511,16 +513,17 @@ module Redux {
|
||||
exists(DataFlow::SourceNode actionSrc |
|
||||
actionSrc = getAnUntypedActionInReducer() and
|
||||
result = actionSrc.getAPropertyRead("payload") and
|
||||
getASuccessfulTypeCheckBlock(actionSrc).dominates(result.getBasicBlock())
|
||||
this.getASuccessfulTypeCheckBlock(actionSrc).dominates(result.getBasicBlock())
|
||||
)
|
||||
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. */
|
||||
DataFlow::SourceNode getAMetaArgReference() {
|
||||
exists(ReducerArg reducer |
|
||||
reducer.isActionTypeHandler(ref().getAPropertyRead(["fulfilled", "rejected", "pending"])) and
|
||||
reducer
|
||||
.isActionTypeHandler(this.ref().getAPropertyRead(["fulfilled", "rejected", "pending"])) and
|
||||
result =
|
||||
reducer
|
||||
.getASource()
|
||||
@@ -558,10 +561,10 @@ module Redux {
|
||||
.getACall()
|
||||
}
|
||||
|
||||
override string getTypeTag() { getArgument(0).mayHaveStringValue(result) }
|
||||
override string getTypeTag() { this.getArgument(0).mayHaveStringValue(result) }
|
||||
|
||||
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) {
|
||||
result.flowsTo(createActions.getParameter(0).getMember(getTypeTag()).asSink()) and
|
||||
result.flowsTo(createActions.getParameter(0).getMember(this.getTypeTag()).asSink()) and
|
||||
async = false
|
||||
}
|
||||
|
||||
@@ -640,10 +643,10 @@ module Redux {
|
||||
|
||||
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
|
||||
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. */
|
||||
DataFlow::SourceNode getASource(DataFlow::TypeBackTracker t) {
|
||||
t.start() and
|
||||
result = getALocalSource()
|
||||
result = this.getALocalSource()
|
||||
or
|
||||
// Step through forwarding functions
|
||||
DataFlow::functionForwardingStep(result.getALocalUse(), getASource(t.continue()))
|
||||
DataFlow::functionForwardingStep(result.getALocalUse(), this.getASource(t.continue()))
|
||||
or
|
||||
// Step through library functions like `redux-persist`
|
||||
result.getALocalUse() = getASource(t.continue()).(DelegatingReducer).getAPlainHandlerArg()
|
||||
result.getALocalUse() =
|
||||
this.getASource(t.continue()).(DelegatingReducer).getAPlainHandlerArg()
|
||||
or
|
||||
// Step through function composition (usually composed with various state "enhancer" functions)
|
||||
exists(FunctionCompositionCall compose, DataFlow::CallNode call |
|
||||
getASource(t.continue()) = call and
|
||||
this.getASource(t.continue()) = call and
|
||||
call = compose.getACall() and
|
||||
result.getALocalUse() = [compose.getAnOperandNode(), call.getAnArgument()]
|
||||
)
|
||||
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. */
|
||||
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,
|
||||
@@ -721,7 +725,7 @@ module Redux {
|
||||
*/
|
||||
predicate isTypeTagHandler(string actionType) {
|
||||
exists(DataFlow::Node node |
|
||||
isActionTypeHandler(node) and
|
||||
this.isActionTypeHandler(node) and
|
||||
actionType = getATypeTagFromNode(node)
|
||||
)
|
||||
}
|
||||
@@ -1035,7 +1039,7 @@ module Redux {
|
||||
result = this
|
||||
or
|
||||
exists(FunctionCompositionCall compose |
|
||||
getAComponentTransformer().flowsTo(compose.getAnOperandNode()) and
|
||||
this.getAComponentTransformer().flowsTo(compose.getAnOperandNode()) and
|
||||
result = compose
|
||||
)
|
||||
}
|
||||
@@ -1048,19 +1052,19 @@ module Redux {
|
||||
//
|
||||
// const mapDispatchToProps = { foo }
|
||||
//
|
||||
result = getMapDispatchToProps().getMember(name).asSink()
|
||||
result = this.getMapDispatchToProps().getMember(name).asSink()
|
||||
or
|
||||
//
|
||||
// const mapDispatchToProps = dispatch => ( { foo } )
|
||||
//
|
||||
result = getMapDispatchToProps().getReturn().getMember(name).asSink()
|
||||
result = this.getMapDispatchToProps().getReturn().getMember(name).asSink()
|
||||
or
|
||||
// Explicitly bound by bindActionCreators:
|
||||
//
|
||||
// const mapDispatchToProps = dispatch => bindActionCreators({ foo }, dispatch);
|
||||
//
|
||||
exists(BindActionCreatorsCall bind |
|
||||
bind.flowsTo(getMapDispatchToProps().getReturn().asSink()) and
|
||||
bind.flowsTo(this.getMapDispatchToProps().getReturn().asSink()) and
|
||||
result = bind.getOptionArgument(0, name)
|
||||
)
|
||||
}
|
||||
@@ -1070,9 +1074,9 @@ module Redux {
|
||||
*/
|
||||
ReactComponent getReactComponent() {
|
||||
exists(DataFlow::SourceNode component | component = result.getAComponentCreatorReference() |
|
||||
component.flowsTo(getAComponentTransformer().getACall().getArgument(0))
|
||||
component.flowsTo(this.getAComponentTransformer().getACall().getArgument(0))
|
||||
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()
|
||||
}
|
||||
|
||||
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() }
|
||||
|
||||
override API::Node getMapStateToProps() {
|
||||
result = getAParameter() and
|
||||
result = this.getAParameter() and
|
||||
result.asSink().asExpr().(Identifier).getName() = "mapStateToProps"
|
||||
}
|
||||
|
||||
override API::Node getMapDispatchToProps() {
|
||||
result = getAParameter() and
|
||||
result = this.getAParameter() and
|
||||
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. */
|
||||
API::Node getSelectorFunction(int i) {
|
||||
// When there are multiple callbacks, exclude the last one
|
||||
result = getParameter(i) and
|
||||
(i = 0 or i < getNumArgument() - 1)
|
||||
result = this.getParameter(i) and
|
||||
(i = 0 or i < this.getNumArgument() - 1)
|
||||
or
|
||||
// Selector functions may be given as an array
|
||||
exists(DataFlow::ArrayCreationNode array |
|
||||
array.flowsTo(getArgument(0)) and
|
||||
array.flowsTo(this.getArgument(0)) and
|
||||
result.getAValueReachableFromSource() = array.getElement(i)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -64,14 +64,16 @@ module ShellJS {
|
||||
/** Holds if the first argument starts with a `-`, indicating it is an option. */
|
||||
predicate hasOptionsArg() {
|
||||
exists(string val |
|
||||
getArgument(0).mayHaveStringValue(val) and
|
||||
this.getArgument(0).mayHaveStringValue(val) and
|
||||
val.matches("-%")
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the `n`th argument after the initial options argument, if any. */
|
||||
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"]
|
||||
}
|
||||
|
||||
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 {
|
||||
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 }
|
||||
}
|
||||
@@ -124,7 +126,7 @@ module ShellJS {
|
||||
// Do not treat regex patterns as filenames.
|
||||
exists(int arg |
|
||||
arg >= offset and
|
||||
result = getTranslatedArgument(arg)
|
||||
result = this.getTranslatedArgument(arg)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -137,15 +139,15 @@ module ShellJS {
|
||||
private class ShellJSExec extends SystemCommandExecution, ShellJSCall {
|
||||
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 DataFlow::Node getOptionsArg() {
|
||||
result = getLastArgument() and
|
||||
not result = getArgument(0) and
|
||||
result = this.getLastArgument() and
|
||||
not result = this.getArgument(0) and
|
||||
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
|
||||
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) {
|
||||
i >= 0 and
|
||||
result = getArgument(formatIndex + 1 + i)
|
||||
result = this.getArgument(formatIndex + 1 + i)
|
||||
}
|
||||
|
||||
override predicate returnsFormatted() { returns = true }
|
||||
|
||||
@@ -79,13 +79,13 @@ private class SystemCommandExecutors extends SystemCommandExecution, DataFlow::I
|
||||
sync = true
|
||||
}
|
||||
|
||||
override DataFlow::Node getACommandArgument() { result = getArgument(cmdArg) }
|
||||
override DataFlow::Node getACommandArgument() { result = this.getArgument(cmdArg) }
|
||||
|
||||
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 }
|
||||
|
||||
@@ -93,9 +93,9 @@ private class SystemCommandExecutors extends SystemCommandExecution, DataFlow::I
|
||||
(
|
||||
if optionsArg < 0
|
||||
then
|
||||
result = getArgument(getNumArgument() + optionsArg) and
|
||||
getNumArgument() + optionsArg > cmdArg
|
||||
else result = getArgument(optionsArg)
|
||||
result = this.getArgument(this.getNumArgument() + optionsArg) and
|
||||
this.getNumArgument() + optionsArg > cmdArg
|
||||
else result = this.getArgument(optionsArg)
|
||||
) and
|
||||
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
|
||||
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() }
|
||||
|
||||
@@ -143,7 +143,7 @@ private class RemoteCommandExecutor extends SystemCommandExecution, DataFlow::In
|
||||
private class Opener extends SystemCommandExecution, DataFlow::InvokeNode {
|
||||
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() }
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class JestTest extends Test, @call_expr {
|
||||
exists(call.getArgument(0).getStringValue()) and
|
||||
exists(call.getArgument(1).flow().getAFunctionValue(0))
|
||||
) 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. */
|
||||
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. */
|
||||
Component getABaseComponent() {
|
||||
result.getComponentRef().getAValueReachableFromSource() =
|
||||
getOwnOptions().getMember(["extends", "mixins"]).asSink()
|
||||
this.getOwnOptions().getMember(["extends", "mixins"]).asSink()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,13 +176,13 @@ module Vue {
|
||||
* of its base component.
|
||||
*/
|
||||
API::Node getOptions() {
|
||||
result = getOwnOptions()
|
||||
result = this.getOwnOptions()
|
||||
or
|
||||
result = getOwnOptions().getMember(["extends", "mixins"]).getAMember()
|
||||
result = this.getOwnOptions().getMember(["extends", "mixins"]).getAMember()
|
||||
or
|
||||
result = getABaseComponent().getOptions()
|
||||
result = this.getABaseComponent().getOptions()
|
||||
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{{...})`
|
||||
* 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.
|
||||
@@ -199,19 +199,21 @@ module Vue {
|
||||
* Specifically, this is a class annotated with `@Component` which flows to the options
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
@@ -219,7 +221,7 @@ module Vue {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
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.
|
||||
*/
|
||||
DataFlow::Node getData() {
|
||||
result = getOption("data")
|
||||
result = this.getOption("data")
|
||||
or
|
||||
result = getOptionSource("data").(DataFlow::FunctionNode).getReturnNode()
|
||||
result = this.getOptionSource("data").(DataFlow::FunctionNode).getReturnNode()
|
||||
or
|
||||
result = getAsClassComponent().getAReceiverNode()
|
||||
result = this.getAsClassComponent().getAReceiverNode()
|
||||
or
|
||||
result = getAsClassComponent().getInstanceMethod("data").getAReturn()
|
||||
result = this.getAsClassComponent().getInstanceMethod("data").getAReturn()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node for the `template` option of this component.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
DataFlow::SourceNode getRender() {
|
||||
result = getOptionSource("render")
|
||||
result = this.getOptionSource("render")
|
||||
or
|
||||
result = getAsClassComponent().getInstanceMethod("render")
|
||||
result = this.getAsClassComponent().getInstanceMethod("render")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node for the `methods` option of this component.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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`.
|
||||
*/
|
||||
DataFlow::FunctionNode getWatchHandler(string propName) {
|
||||
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()
|
||||
)
|
||||
}
|
||||
@@ -288,11 +290,11 @@ module Vue {
|
||||
* 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) {
|
||||
result = getComputed().getAPropertySource(name) and kind = DataFlow::MemberKind::getter()
|
||||
result = this.getComputed().getAPropertySource(name) and kind = DataFlow::MemberKind::getter()
|
||||
or
|
||||
result = getComputed().getAPropertySource(name).getAPropertySource(memberKindVerb(kind))
|
||||
result = this.getComputed().getAPropertySource(name).getAPropertySource(memberKindVerb(kind))
|
||||
or
|
||||
result = getAsClassComponent().getInstanceMember(name, kind) and
|
||||
result = this.getAsClassComponent().getInstanceMember(name, kind) and
|
||||
kind.isAccessor()
|
||||
}
|
||||
|
||||
@@ -303,9 +305,9 @@ module Vue {
|
||||
DataFlow::SourceNode getALifecycleHook(string hookName) {
|
||||
hookName = lifecycleHookName() and
|
||||
(
|
||||
result = getOptionSource(hookName)
|
||||
result = this.getOptionSource(hookName)
|
||||
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.
|
||||
*/
|
||||
DataFlow::FunctionNode getABoundFunction() {
|
||||
result = getOptions().getAMember+().getAValueReachingSink()
|
||||
result = this.getOptions().getAMember+().getAValueReachingSink()
|
||||
or
|
||||
result = getAsClassComponent().getAnInstanceMember()
|
||||
result = this.getAsClassComponent().getAnInstanceMember()
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
DataFlow::SourceNode getAnInstanceRef() { result = getInstance().asSource() }
|
||||
DataFlow::SourceNode getAnInstanceRef() { result = this.getInstance().asSource() }
|
||||
|
||||
pragma[noinline]
|
||||
private DataFlow::PropWrite getAPropertyValueWrite(string name) {
|
||||
result = getData().getALocalSource().getAPropertyWrite(name)
|
||||
result = this.getData().getALocalSource().getAPropertyWrite(name)
|
||||
or
|
||||
result = getAnInstanceRef().getAPropertyWrite(name)
|
||||
result = this.getAnInstanceRef().getAPropertyWrite(name)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,10 +338,10 @@ module Vue {
|
||||
* returned form a getter defining that property.
|
||||
*/
|
||||
DataFlow::Node getAPropertyValue(string name) {
|
||||
result = getAPropertyValueWrite(name).getRhs()
|
||||
result = this.getAPropertyValueWrite(name).getRhs()
|
||||
or
|
||||
exists(DataFlow::FunctionNode getter |
|
||||
getter.flowsTo(getAccessor(name, DataFlow::MemberKind::getter())) and
|
||||
getter.flowsTo(this.getAccessor(name, DataFlow::MemberKind::getter())) and
|
||||
result = getter.getAReturn()
|
||||
)
|
||||
}
|
||||
@@ -498,7 +500,7 @@ module Vue {
|
||||
|
||||
override API::Node getOwnOptions() {
|
||||
// Use the entry point generated by `VueExportEntryPoint`
|
||||
result.asSink() = getModule().getDefaultOrBulkExport()
|
||||
result.asSink() = this.getModule().getDefaultOrBulkExport()
|
||||
}
|
||||
|
||||
override string toString() { result = file.toString() }
|
||||
@@ -508,7 +510,7 @@ module Vue {
|
||||
* A `.vue` file.
|
||||
*/
|
||||
class VueFile extends File {
|
||||
VueFile() { getExtension() = "vue" }
|
||||
VueFile() { this.getExtension() = "vue" }
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -584,7 +586,7 @@ module Vue {
|
||||
*/
|
||||
abstract class Element extends TElement {
|
||||
/** 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.
|
||||
|
||||
@@ -87,11 +87,11 @@ module Vuex {
|
||||
/** Gets the namespace prefix to use, or an empty string if no namespace was given. */
|
||||
pragma[noinline]
|
||||
string getNamespace() {
|
||||
getNumArgument() = 2 and
|
||||
this.getNumArgument() = 2 and
|
||||
result =
|
||||
appendToNamespace(namespace, getParameter(0).getAValueReachingSink().getStringValue())
|
||||
appendToNamespace(namespace, this.getParameter(0).getAValueReachingSink().getStringValue())
|
||||
or
|
||||
getNumArgument() = 1 and
|
||||
this.getNumArgument() = 1 and
|
||||
result = namespace
|
||||
}
|
||||
|
||||
@@ -100,24 +100,25 @@ module Vuex {
|
||||
*/
|
||||
predicate hasMapping(string localName, string storeName) {
|
||||
// mapGetters('foo')
|
||||
getLastParameter().getAValueReachingSink().getStringValue() = localName and
|
||||
storeName = getNamespace() + localName
|
||||
this.getLastParameter().getAValueReachingSink().getStringValue() = localName and
|
||||
storeName = this.getNamespace() + localName
|
||||
or
|
||||
// mapGetters(['foo', 'bar'])
|
||||
getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() = localName and
|
||||
storeName = getNamespace() + localName
|
||||
this.getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() =
|
||||
localName and
|
||||
storeName = this.getNamespace() + localName
|
||||
or
|
||||
// mapGetters({foo: 'bar'})
|
||||
storeName =
|
||||
getNamespace() +
|
||||
getLastParameter().getMember(localName).getAValueReachingSink().getStringValue() and
|
||||
this.getNamespace() +
|
||||
this.getLastParameter().getMember(localName).getAValueReachingSink().getStringValue() and
|
||||
localName != "*" // ignore special API graph member named "*"
|
||||
}
|
||||
|
||||
/** Gets the Vue component in which the generated functions are installed. */
|
||||
Vue::Component getVueComponent() {
|
||||
exists(DataFlow::ObjectLiteralNode obj |
|
||||
obj.getASpreadProperty() = getReturn().getAValueReachableFromSource() and
|
||||
obj.getASpreadProperty() = this.getReturn().getAValueReachableFromSource() and
|
||||
result.getOwnOptions().getAMember().asSink() = obj
|
||||
)
|
||||
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) {
|
||||
// internal entities are always resolved
|
||||
@@ -54,7 +54,7 @@ module XML {
|
||||
or
|
||||
// other entities are only resolved if the configuration option `noent` is set to `true`
|
||||
exists(JS::Expr noent |
|
||||
hasOptionArgument(1, "noent", noent) and
|
||||
this.hasOptionArgument(1, "noent", noent) and
|
||||
noent.mayHaveBooleanValue(true)
|
||||
)
|
||||
}
|
||||
@@ -66,23 +66,24 @@ module XML {
|
||||
private API::Node doc() {
|
||||
result = call.getReturn()
|
||||
or
|
||||
result = doc().getMember("encoding").getReturn()
|
||||
result = this.doc().getMember("encoding").getReturn()
|
||||
or
|
||||
result = element().getMember("doc").getReturn()
|
||||
result = this.element().getMember("doc").getReturn()
|
||||
or
|
||||
result = element().getMember("parent").getReturn()
|
||||
result = this.element().getMember("parent").getReturn()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an `Element` from the `libxmljs` library.
|
||||
*/
|
||||
private API::Node element() {
|
||||
result = doc().getMember(["child", "get", "node", "root"]).getReturn()
|
||||
or
|
||||
result = [doc(), element()].getMember(["childNodes", "find"]).getReturn().getAMember()
|
||||
result = this.doc().getMember(["child", "get", "node", "root"]).getReturn()
|
||||
or
|
||||
result =
|
||||
element()
|
||||
[this.doc(), this.element()].getMember(["childNodes", "find"]).getReturn().getAMember()
|
||||
or
|
||||
result =
|
||||
this.element()
|
||||
.getMember([
|
||||
"parent", "prevSibling", "nextSibling", "remove", "clone", "node", "child",
|
||||
"prevElement", "nextElement"
|
||||
@@ -94,19 +95,20 @@ module XML {
|
||||
* Gets an `Attr` from the `libxmljs` library.
|
||||
*/
|
||||
private API::Node attr() {
|
||||
result = element().getMember("attr").getReturn()
|
||||
result = this.element().getMember("attr").getReturn()
|
||||
or
|
||||
result = element().getMember("attrs").getReturn().getAMember()
|
||||
result = this.element().getMember("attrs").getReturn().getAMember()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
result = [doc(), element(), attr()].asSource()
|
||||
result = [this.doc(), this.element(), this.attr()].asSource()
|
||||
or
|
||||
result = element().getMember(["name", "text"]).getACall()
|
||||
result = this.element().getMember(["name", "text"]).getACall()
|
||||
or
|
||||
result = attr().getMember(["name", "value"]).getACall()
|
||||
result = this.attr().getMember(["name", "value"]).getACall()
|
||||
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()
|
||||
}
|
||||
|
||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
||||
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||
|
||||
override predicate resolvesEntities(EntityKind kind) {
|
||||
// entities are resolved by default
|
||||
@@ -144,7 +146,7 @@ module XML {
|
||||
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) {
|
||||
// entities are resolved by default
|
||||
@@ -167,7 +169,7 @@ module XML {
|
||||
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) {
|
||||
// only internal entities are resolved by default
|
||||
@@ -190,10 +192,10 @@ module XML {
|
||||
.getAMethodCall("parseFromString")
|
||||
.asExpr() and
|
||||
// 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() }
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
@@ -228,7 +230,7 @@ module XML {
|
||||
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() }
|
||||
}
|
||||
@@ -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) {
|
||||
// sax-js (the parser used) does not expand entities.
|
||||
@@ -273,7 +275,7 @@ module XML {
|
||||
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) {
|
||||
// sax-js does not expand entities.
|
||||
@@ -298,7 +300,7 @@ module XML {
|
||||
.asExpr()
|
||||
}
|
||||
|
||||
override JS::Expr getSourceArgument() { result = getArgument(0) }
|
||||
override JS::Expr getSourceArgument() { result = this.getArgument(0) }
|
||||
|
||||
override predicate resolvesEntities(XML::EntityKind kind) {
|
||||
// xml-js does not expand custom entities.
|
||||
@@ -319,7 +321,7 @@ module XML {
|
||||
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) {
|
||||
// htmlparser2 does not expand entities.
|
||||
|
||||
@@ -119,10 +119,10 @@ class XUnitAnnotation extends Expr {
|
||||
Expr getAttribute(int i) { result = this.(BracketedListOfExpressions).getElement(i) }
|
||||
|
||||
/** Gets an attribute of this annotation. */
|
||||
Expr getAnAttribute() { result = getAttribute(_) }
|
||||
Expr getAnAttribute() { result = this.getAttribute(_) }
|
||||
|
||||
/** 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.
|
||||
@@ -136,8 +136,8 @@ class XUnitAnnotation extends Expr {
|
||||
) {
|
||||
// extend location to cover brackets
|
||||
exists(Location l1, Location l2 |
|
||||
l1 = getFirstToken().getLocation() and
|
||||
l2 = getLastToken().getLocation()
|
||||
l1 = this.getFirstToken().getLocation() and
|
||||
l2 = this.getLastToken().getLocation()
|
||||
|
|
||||
filepath = l1.getFile().getAbsolutePath() and
|
||||
startline = l1.getStartLine() and
|
||||
@@ -176,10 +176,10 @@ class XUnitAttribute extends Expr {
|
||||
Expr getParameter(int i) { result = this.(CallExpr).getArgument(i) }
|
||||
|
||||
/** Gets a parameter of this attribute. */
|
||||
Expr getAParameter() { result = getParameter(_) }
|
||||
Expr getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
class XUnitFixtureAnnotation extends XUnitAnnotation {
|
||||
XUnitFixtureAnnotation() { getAnAttribute().accessesGlobal("Fixture") }
|
||||
XUnitFixtureAnnotation() { this.getAnAttribute().accessesGlobal("Fixture") }
|
||||
}
|
||||
|
||||
/**
|
||||
* An xUnit.js fixture.
|
||||
*/
|
||||
class XUnitFixture extends XUnitAnnotatedFunction {
|
||||
XUnitFixture() { getAnAnnotation() instanceof XUnitFixtureAnnotation }
|
||||
XUnitFixture() { this.getAnAnnotation() instanceof XUnitFixtureAnnotation }
|
||||
}
|
||||
|
||||
/**
|
||||
* An xUnit.js `Fact` annotation.
|
||||
*/
|
||||
class XUnitFactAnnotation extends XUnitAnnotation {
|
||||
XUnitFactAnnotation() { getAnAttribute().accessesGlobal("Fact") }
|
||||
XUnitFactAnnotation() { this.getAnAttribute().accessesGlobal("Fact") }
|
||||
}
|
||||
|
||||
/**
|
||||
* An xUnit.js fact.
|
||||
*/
|
||||
class XUnitFact extends XUnitAnnotatedFunction {
|
||||
XUnitFact() { getAnAnnotation() instanceof XUnitFactAnnotation }
|
||||
XUnitFact() { this.getAnAnnotation() instanceof XUnitFactAnnotation }
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
import javascript
|
||||
|
||||
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.
|
||||
*/
|
||||
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. */
|
||||
string getAReplacementString() {
|
||||
getAMember().replaces(_, result)
|
||||
this.getAMember().replaces(_, result)
|
||||
or
|
||||
// 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. */
|
||||
string getAReplacedString() { getAMember().getAReplacedString() = result }
|
||||
string getAReplacedString() { this.getAMember().getAReplacedString() = result }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
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 }
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class SensitiveActionGuardComparison extends Comparison {
|
||||
class SensitiveActionGuardComparisonOperand extends Sink {
|
||||
SensitiveActionGuardComparison comparison;
|
||||
|
||||
SensitiveActionGuardComparisonOperand() { asExpr() = comparison.getAnOperand() }
|
||||
SensitiveActionGuardComparisonOperand() { this.asExpr() = comparison.getAnOperand() }
|
||||
|
||||
override SensitiveAction getAction() { result = comparison.getGuard().getAction() }
|
||||
}
|
||||
|
||||
@@ -45,6 +45,6 @@ module DifferentKindsComparisonBypass {
|
||||
* A data flow sink for a potential suspicious comparisons.
|
||||
*/
|
||||
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() {
|
||||
exists(Configuration cfg |
|
||||
cfg.hasFlow(lSource, DataFlow::valueNode(getLeftOperand())) and
|
||||
cfg.hasFlow(rSource, DataFlow::valueNode(getRightOperand())) and
|
||||
cfg.hasFlow(lSource, DataFlow::valueNode(this.getLeftOperand())) and
|
||||
cfg.hasFlow(rSource, DataFlow::valueNode(this.getRightOperand())) and
|
||||
lSource.isSuspiciousToCompareWith(rSource)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
|
||||
|
||||
/** Gets the number of untrusted sources used with this external API. */
|
||||
int getNumberOfUntrustedSources() {
|
||||
result = count(getUntrustedDataNode().getAnUntrustedSource())
|
||||
result = count(this.getUntrustedDataNode().getAnUntrustedSource())
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
lbl = Label::characterToLabel(node.(StringReplaceCall).getAReplacedString()) or
|
||||
isSanitizer(node)
|
||||
this.isSanitizer(node)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node n) {
|
||||
|
||||
@@ -25,7 +25,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
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 }
|
||||
|
||||
|
||||
@@ -72,12 +72,12 @@ module RegExpInjection {
|
||||
*/
|
||||
class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall {
|
||||
MetacharEscapeSanitizer() {
|
||||
isGlobal() and
|
||||
this.isGlobal() and
|
||||
(
|
||||
RegExp::alwaysMatchesMetaCharacter(getRegExp().getRoot(), ["{", "[", "+"])
|
||||
RegExp::alwaysMatchesMetaCharacter(this.getRegExp().getRoot(), ["{", "[", "+"])
|
||||
or
|
||||
// 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)
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ module TemplateObjectInjection {
|
||||
exists(
|
||||
Express::RouteSetup setup, Express::RouterDefinition router, Express::RouterDefinition top
|
||||
|
|
||||
setup.getARouteHandler() = getRouteHandler() and
|
||||
setup.getARouteHandler() = this.getRouteHandler() and
|
||||
setup.getRouter() = router and
|
||||
top.getASubRouter*() = router and
|
||||
usesVulnerableTemplateEngine(top)
|
||||
|
||||
@@ -57,7 +57,7 @@ private class IsArrayBarrier extends DataFlow::BarrierGuardNode, DataFlow::CallN
|
||||
IsArrayBarrier() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") }
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
) {
|
||||
// Reading a property of the global object or of a function
|
||||
exists(DataFlow::PropRead read |
|
||||
hasUnsafeMethods(read.getBase().getALocalSource()) and
|
||||
this.hasUnsafeMethods(read.getBase().getALocalSource()) and
|
||||
src = read.getPropertyNameExpr().flow() and
|
||||
dst = read and
|
||||
srclabel.isTaint() and
|
||||
|
||||
@@ -46,7 +46,7 @@ module UnsafeJQueryPlugin {
|
||||
{
|
||||
AmbiguousHtmlOrSelectorArgument() {
|
||||
// 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)
|
||||
then (
|
||||
// use the last parameter named something like "options" if it exists ...
|
||||
getName().regexpMatch(optionsPattern) and
|
||||
this.getName().regexpMatch(optionsPattern) and
|
||||
this = method.getAParameter()
|
||||
) else (
|
||||
// ... otherwise, use the last parameter, unless it looks like a DOM node
|
||||
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 {
|
||||
IsElementSanitizer() {
|
||||
// common ad hoc sanitizing calls
|
||||
exists(string name | getCalleeName() = name |
|
||||
exists(string name | this.getCalleeName() = name |
|
||||
name = "isElement" or name = "isDocument" or name = "isWindow"
|
||||
)
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
class HostnameSanitizerGuard extends TaintTracking::SanitizerGuardNode, StringOps::StartsWith {
|
||||
HostnameSanitizerGuard() { hasHostnameSanitizingSubstring(getSubstring()) }
|
||||
HostnameSanitizerGuard() { hasHostnameSanitizingSubstring(this.getSubstring()) }
|
||||
|
||||
override predicate sanitizes(boolean outcome, Expr e) {
|
||||
outcome = getPolarity() and
|
||||
e = getBaseString().asExpr()
|
||||
outcome = this.getPolarity() and
|
||||
e = this.getBaseString().asExpr()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class TopLevel extends @toplevel {
|
||||
Location getLocation() { hasLocation(this, result) }
|
||||
|
||||
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 {
|
||||
@@ -19,7 +19,7 @@ class XmlNode extends @xmllocatable {
|
||||
Location getLocation() { xmllocations(this, result) }
|
||||
|
||||
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,
|
||||
|
||||
@@ -127,7 +127,7 @@ class CommentedOutCode extends Comment {
|
||||
predicate hasLocationInfo(
|
||||
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
|
||||
startline = loc.getStartLine() and
|
||||
startcolumn = loc.getStartColumn() and
|
||||
|
||||
@@ -20,7 +20,7 @@ class EvilTwin extends DataFlow::CallNode {
|
||||
EvilTwin() {
|
||||
exists(string fn | fn = "setTimeout" or fn = "setInterval" |
|
||||
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 {
|
||||
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 {
|
||||
CandidateVarAccess() {
|
||||
isImmediatelyExecutedContainer(getContainer()) and
|
||||
isImmediatelyExecutedContainer(this.getContainer()) and
|
||||
not exists(ExportSpecifier spec | spec.getLocal() = this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ class ImportVarDeclProvider extends Stmt {
|
||||
* Gets an unacceptable unused variable declared by this import.
|
||||
*/
|
||||
UnusedLocal getAnUnacceptableUnusedLocal() {
|
||||
result = getAVarDecl().getVariable() and
|
||||
result = this.getAVarDecl().getVariable() and
|
||||
not whitelisted(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ import Clones
|
||||
abstract class RedundantOperand extends StructurallyCompared {
|
||||
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. */
|
||||
Expr toReport() { result = getParent() }
|
||||
Expr toReport() { result = this.getParent() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +50,7 @@ class IdemnecantExpr extends BinaryExpr {
|
||||
class RedundantIdemnecantOperand extends RedundantOperand {
|
||||
RedundantIdemnecantOperand() {
|
||||
exists(IdemnecantExpr parent |
|
||||
parent = getParent() and
|
||||
parent = this.getParent() and
|
||||
// exclude trivial cases like `1-1`
|
||||
not parent.getRightOperand().getUnderlyingValue() instanceof Literal
|
||||
)
|
||||
@@ -65,7 +65,7 @@ class RedundantIdemnecantOperand extends RedundantOperand {
|
||||
*/
|
||||
class RedundantIdempotentOperand extends RedundantOperand {
|
||||
RedundantIdempotentOperand() {
|
||||
getParent() instanceof LogicalBinaryExpr and
|
||||
this.getParent() instanceof LogicalBinaryExpr and
|
||||
not exists(UpdateExpr e | e.getParentExpr+() = this)
|
||||
}
|
||||
}
|
||||
@@ -75,8 +75,8 @@ class RedundantIdempotentOperand extends RedundantOperand {
|
||||
*/
|
||||
class AverageExpr extends DivExpr {
|
||||
AverageExpr() {
|
||||
getLeftOperand().getUnderlyingValue() instanceof AddExpr and
|
||||
getRightOperand().getIntValue() = 2
|
||||
this.getLeftOperand().getUnderlyingValue() instanceof AddExpr and
|
||||
this.getRightOperand().getIntValue() = 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,10 +85,14 @@ class AverageExpr extends DivExpr {
|
||||
*/
|
||||
class RedundantAverageOperand extends RedundantOperand {
|
||||
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
|
||||
|
||||
@@ -22,7 +22,7 @@ import javascript
|
||||
class OmittedArrayElement extends ArrayExpr {
|
||||
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.
|
||||
@@ -35,9 +35,9 @@ class OmittedArrayElement extends ArrayExpr {
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
exists(Token pre, Location before, Location after |
|
||||
idx = 0 and pre = getFirstToken()
|
||||
idx = 0 and pre = this.getFirstToken()
|
||||
or
|
||||
pre = getElement(idx - 1).getLastToken().getNextToken()
|
||||
pre = this.getElement(idx - 1).getLastToken().getNextToken()
|
||||
|
|
||||
before = pre.getLocation() and
|
||||
after = pre.getNextToken().getLocation() and
|
||||
|
||||
@@ -23,8 +23,8 @@ class RootDestructuringPattern extends DestructuringPattern {
|
||||
/** Holds if this pattern has multiple bindings for `name`. */
|
||||
predicate hasConflictingBindings(string name) {
|
||||
exists(VarRef v, VarRef w |
|
||||
v = getABindingVarRef() and
|
||||
w = getABindingVarRef() and
|
||||
v = this.getABindingVarRef() and
|
||||
w = this.getABindingVarRef() and
|
||||
name = v.getName() and
|
||||
name = w.getName() and
|
||||
v != w
|
||||
@@ -33,10 +33,10 @@ class RootDestructuringPattern extends DestructuringPattern {
|
||||
|
||||
/** Gets the first occurrence of the conflicting binding `name`. */
|
||||
VarDecl getFirstClobberedVarDecl(string name) {
|
||||
hasConflictingBindings(name) and
|
||||
this.hasConflictingBindings(name) and
|
||||
result =
|
||||
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()
|
||||
)
|
||||
@@ -44,11 +44,11 @@ class RootDestructuringPattern extends DestructuringPattern {
|
||||
|
||||
/** Holds if variables in this pattern may resemble type annotations. */
|
||||
predicate resemblesTypeAnnotation() {
|
||||
hasConflictingBindings(_) and // Restrict size of predicate.
|
||||
this.hasConflictingBindings(_) and // Restrict size of predicate.
|
||||
this instanceof Parameter and
|
||||
this instanceof ObjectPattern and
|
||||
not exists(getTypeAnnotation()) and
|
||||
getFile().getFileType().isTypeScript()
|
||||
not exists(this.getTypeAnnotation()) and
|
||||
this.getFile().getFileType().isTypeScript()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ class SpuriousArguments extends Expr {
|
||||
* expected by any potential callee.
|
||||
*/
|
||||
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(
|
||||
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 |
|
||||
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;
|
||||
|
||||
RegExpSearchCall() {
|
||||
getMethodName() = "search" and
|
||||
regexp.getAReference().flowsTo(getArgument(0))
|
||||
this.getMethodName() = "search" and
|
||||
regexp.getAReference().flowsTo(this.getArgument(0))
|
||||
}
|
||||
|
||||
override RegExpTerm getRegExp() { result = regexp.getRoot() }
|
||||
|
||||
@@ -73,8 +73,8 @@ class RegExpPatternMistake extends TRegExpPatternMistake {
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
exists(int srcStartcolumn, int srcEndcolumn, int index |
|
||||
index = getIndex() and
|
||||
getRawStringNode()
|
||||
index = this.getIndex() and
|
||||
this.getRawStringNode()
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, srcStartcolumn, endline, srcEndcolumn)
|
||||
|
|
||||
@@ -89,7 +89,7 @@ class RegExpPatternMistake extends TRegExpPatternMistake {
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = getMessage() }
|
||||
string toString() { result = this.getMessage() }
|
||||
|
||||
abstract AstNode getRawStringNode();
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ private import semmle.javascript.dataflow.InferredTypes
|
||||
*/
|
||||
class SplitCall extends StringSplitCall {
|
||||
SplitCall() {
|
||||
getSeparator() = "." and
|
||||
getBaseString().getALocalSource() instanceof ParameterNode
|
||||
this.getSeparator() = "." and
|
||||
this.getBaseString().getALocalSource() instanceof ParameterNode
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ class SplitPropName extends SourceNode {
|
||||
SourceNode getArray() { result = 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() {
|
||||
exists(DataFlow::ArrayCreationNode array |
|
||||
array.getAnElement().getStringValue() = label and
|
||||
array.flowsTo(getContainerNode())
|
||||
array.flowsTo(this.getContainerNode())
|
||||
)
|
||||
}
|
||||
|
||||
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
|
||||
outcome = getPolarity().booleanNot() and
|
||||
e = getContainedNode().asExpr() and
|
||||
outcome = this.getPolarity().booleanNot() and
|
||||
e = this.getContainedNode().asExpr() and
|
||||
label = lbl
|
||||
}
|
||||
}
|
||||
@@ -475,7 +475,7 @@ class IsPlainObjectGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::Ca
|
||||
}
|
||||
|
||||
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
|
||||
e = getArgument(0).asExpr() and
|
||||
e = this.getArgument(0).asExpr() and
|
||||
outcome = true and
|
||||
lbl = "constructor"
|
||||
}
|
||||
@@ -561,7 +561,7 @@ DataFlow::SourceNode getANodeLeadingToBaseBase(Node base) {
|
||||
class ObjectCreateNullCall extends CallNode {
|
||||
ObjectCreateNullCall() {
|
||||
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