JS: Make implicit this receivers explicit

This commit is contained in:
Kasper Svendsen
2023-05-03 15:31:00 +02:00
parent ea75996932
commit 67950c8e6b
125 changed files with 1061 additions and 1002 deletions

View File

@@ -21,8 +21,8 @@ class DecodingCall extends CallNode {
Node input; Node input;
DecodingCall() { DecodingCall() {
getCalleeName().matches("decodeURI%") and this.getCalleeName().matches("decodeURI%") and
input = getArgument(0) and input = this.getArgument(0) and
kind = "URI decoding" kind = "URI decoding"
or or
input = this.(JsonParserCall).getInput() and input = this.(JsonParserCall).getInput() and

View File

@@ -11,7 +11,7 @@ import LanguageFeatures.UnusedIndexVariable
*/ */
class UnusedLocal extends LocalVariable { class UnusedLocal extends LocalVariable {
UnusedLocal() { UnusedLocal() {
not exists(getAnAccess()) and not exists(this.getAnAccess()) and
not exists(Parameter p | this = p.getAVariable()) and not exists(Parameter p | this = p.getAVariable()) and
not exists(FunctionExpr fe | this = fe.getVariable()) and not exists(FunctionExpr fe | this = fe.getVariable()) and
not exists(ClassExpr ce | this = ce.getVariable()) and not exists(ClassExpr ce | this = ce.getVariable()) and
@@ -20,6 +20,6 @@ class UnusedLocal extends LocalVariable {
// avoid double reporting // avoid double reporting
not unusedIndexVariable(_, this, _) and not unusedIndexVariable(_, this, _) and
// common convention: variables with leading underscore are intentionally unused // common convention: variables with leading underscore are intentionally unused
getName().charAt(0) != "_" this.getName().charAt(0) != "_"
} }
} }

View File

@@ -83,7 +83,7 @@ predicate isGetterProperty(string name) {
* A property access that may invoke a getter. * A property access that may invoke a getter.
*/ */
class GetterPropertyAccess extends PropAccess { class GetterPropertyAccess extends PropAccess {
override predicate isImpure() { isGetterProperty(getPropertyName()) } override predicate isImpure() { isGetterProperty(this.getPropertyName()) }
} }
/** /**

View File

@@ -28,29 +28,31 @@ private import Expressions.ExprHasNoEffect
class AmdModuleDefinition extends CallExpr { class AmdModuleDefinition extends CallExpr {
AmdModuleDefinition() { AmdModuleDefinition() {
inVoidContext(this) and inVoidContext(this) and
getCallee().(GlobalVarAccess).getName() = "define" and this.getCallee().(GlobalVarAccess).getName() = "define" and
exists(int n | n = getNumArgument() | exists(int n | n = this.getNumArgument() |
n = 1 n = 1
or or
n = 2 and getArgument(0) instanceof ArrayExpr n = 2 and this.getArgument(0) instanceof ArrayExpr
or or
n = 3 and getArgument(0) instanceof ConstantString and getArgument(1) instanceof ArrayExpr n = 3 and
this.getArgument(0) instanceof ConstantString and
this.getArgument(1) instanceof ArrayExpr
) )
} }
/** Gets the array of module dependencies, if any. */ /** Gets the array of module dependencies, if any. */
ArrayExpr getDependencies() { ArrayExpr getDependencies() {
result = getArgument(0) or result = this.getArgument(0) or
result = getArgument(1) result = this.getArgument(1)
} }
/** Gets the `i`th dependency of this module definition. */ /** Gets the `i`th dependency of this module definition. */
PathExpr getDependency(int i) { result = getDependencies().getElement(i) } PathExpr getDependency(int i) { result = this.getDependencies().getElement(i) }
/** Gets a dependency of this module definition. */ /** Gets a dependency of this module definition. */
PathExpr getADependency() { PathExpr getADependency() {
result = getDependency(_) or result = this.getDependency(_) or
result = getARequireCall().getAnArgument() result = this.getARequireCall().getAnArgument()
} }
/** /**
@@ -58,19 +60,19 @@ class AmdModuleDefinition extends CallExpr {
*/ */
pragma[nomagic] pragma[nomagic]
DataFlow::SourceNode getFactoryNode() { DataFlow::SourceNode getFactoryNode() {
result = getFactoryNodeInternal() and result = this.getFactoryNodeInternal() and
result instanceof DataFlow::ValueNode result instanceof DataFlow::ValueNode
} }
private DataFlow::Node getFactoryNodeInternal() { private DataFlow::Node getFactoryNodeInternal() {
// To avoid recursion, this should not depend on `SourceNode`. // To avoid recursion, this should not depend on `SourceNode`.
result = DataFlow::valueNode(getLastArgument()) or result = DataFlow::valueNode(this.getLastArgument()) or
result = getFactoryNodeInternal().getAPredecessor() result = this.getFactoryNodeInternal().getAPredecessor()
} }
/** Gets the expression defining this module. */ /** Gets the expression defining this module. */
Expr getModuleExpr() { Expr getModuleExpr() {
exists(DataFlow::Node f | f = getFactoryNode() | exists(DataFlow::Node f | f = this.getFactoryNode() |
if f instanceof DataFlow::FunctionNode if f instanceof DataFlow::FunctionNode
then then
exists(ReturnStmt ret | ret.getContainer() = f.(DataFlow::FunctionNode).getAstNode() | exists(ReturnStmt ret | ret.getContainer() = f.(DataFlow::FunctionNode).getAstNode() |
@@ -81,15 +83,15 @@ class AmdModuleDefinition extends CallExpr {
} }
/** Gets a source node whose value becomes the definition of this module. */ /** Gets a source node whose value becomes the definition of this module. */
DataFlow::SourceNode getAModuleSource() { result.flowsToExpr(getModuleExpr()) } DataFlow::SourceNode getAModuleSource() { result.flowsToExpr(this.getModuleExpr()) }
/** /**
* Holds if `p` is the parameter corresponding to dependency `dep`. * Holds if `p` is the parameter corresponding to dependency `dep`.
*/ */
predicate dependencyParameter(PathExpr dep, Parameter p) { predicate dependencyParameter(PathExpr dep, Parameter p) {
exists(int i | exists(int i |
dep = getDependency(i) and dep = this.getDependency(i) and
p = getFactoryParameter(i) p = this.getFactoryParameter(i)
) )
} }
@@ -107,7 +109,7 @@ class AmdModuleDefinition extends CallExpr {
*/ */
Parameter getDependencyParameter(string name) { Parameter getDependencyParameter(string name) {
exists(PathExpr dep | exists(PathExpr dep |
dependencyParameter(dep, result) and this.dependencyParameter(dep, result) and
dep.getValue() = name dep.getValue() = name
) )
} }
@@ -116,40 +118,40 @@ class AmdModuleDefinition extends CallExpr {
* Gets the `i`th parameter of the factory function of this module. * Gets the `i`th parameter of the factory function of this module.
*/ */
private Parameter getFactoryParameter(int i) { private Parameter getFactoryParameter(int i) {
getFactoryNodeInternal().asExpr().(Function).getParameter(i) = result this.getFactoryNodeInternal().asExpr().(Function).getParameter(i) = result
} }
/** /**
* Gets the parameter corresponding to the pseudo-dependency `require`. * Gets the parameter corresponding to the pseudo-dependency `require`.
*/ */
Parameter getRequireParameter() { Parameter getRequireParameter() {
result = getDependencyParameter("require") result = this.getDependencyParameter("require")
or or
// if no dependencies are listed, the first parameter is assumed to be `require` // if no dependencies are listed, the first parameter is assumed to be `require`
not exists(getDependencies()) and result = getFactoryParameter(0) not exists(this.getDependencies()) and result = this.getFactoryParameter(0)
} }
pragma[noinline] pragma[noinline]
private Variable getRequireVariable() { result = getRequireParameter().getVariable() } private Variable getRequireVariable() { result = this.getRequireParameter().getVariable() }
/** /**
* Gets the parameter corresponding to the pseudo-dependency `exports`. * Gets the parameter corresponding to the pseudo-dependency `exports`.
*/ */
Parameter getExportsParameter() { Parameter getExportsParameter() {
result = getDependencyParameter("exports") result = this.getDependencyParameter("exports")
or or
// if no dependencies are listed, the second parameter is assumed to be `exports` // if no dependencies are listed, the second parameter is assumed to be `exports`
not exists(getDependencies()) and result = getFactoryParameter(1) not exists(this.getDependencies()) and result = this.getFactoryParameter(1)
} }
/** /**
* Gets the parameter corresponding to the pseudo-dependency `module`. * Gets the parameter corresponding to the pseudo-dependency `module`.
*/ */
Parameter getModuleParameter() { Parameter getModuleParameter() {
result = getDependencyParameter("module") result = this.getDependencyParameter("module")
or or
// if no dependencies are listed, the third parameter is assumed to be `module` // if no dependencies are listed, the third parameter is assumed to be `module`
not exists(getDependencies()) and result = getFactoryParameter(2) not exists(this.getDependencies()) and result = this.getFactoryParameter(2)
} }
/** /**
@@ -157,13 +159,13 @@ class AmdModuleDefinition extends CallExpr {
* into this module's `module.exports` property. * into this module's `module.exports` property.
*/ */
DefiniteAbstractValue getAModuleExportsValue() { DefiniteAbstractValue getAModuleExportsValue() {
result = [getAnImplicitExportsValue(), getAnExplicitExportsValue()] result = [this.getAnImplicitExportsValue(), this.getAnExplicitExportsValue()]
} }
pragma[noinline, nomagic] pragma[noinline, nomagic]
private AbstractValue getAnImplicitExportsValue() { private AbstractValue getAnImplicitExportsValue() {
// implicit exports: anything that is returned from the factory function // implicit exports: anything that is returned from the factory function
result = getModuleExpr().analyze().getAValue() result = this.getModuleExpr().analyze().getAValue()
} }
pragma[noinline] pragma[noinline]
@@ -182,7 +184,7 @@ class AmdModuleDefinition extends CallExpr {
* Gets a call to `require` inside this module. * Gets a call to `require` inside this module.
*/ */
CallExpr getARequireCall() { CallExpr getARequireCall() {
result.getCallee().getUnderlyingValue() = getRequireVariable().getAnAccess() result.getCallee().getUnderlyingValue() = this.getRequireVariable().getAnAccess()
} }
} }
@@ -200,7 +202,7 @@ private class AmdDependencyPath extends PathExprCandidate {
private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString { private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString {
ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() } ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() }
override string getValue() { result = getStringValue() } override string getValue() { result = this.getStringValue() }
} }
/** /**
@@ -239,7 +241,7 @@ private class AmdDependencyImport extends Import {
*/ */
private File guessTarget() { private File guessTarget() {
exists(PathString imported, string abspath, string dirname, string basename | exists(PathString imported, string abspath, string dirname, string basename |
targetCandidate(result, abspath, imported, dirname, basename) this.targetCandidate(result, abspath, imported, dirname, basename)
| |
abspath.regexpMatch(".*/\\Q" + imported + "\\E") abspath.regexpMatch(".*/\\Q" + imported + "\\E")
or or
@@ -262,7 +264,7 @@ private class AmdDependencyImport extends Import {
private predicate targetCandidate( private predicate targetCandidate(
File f, string abspath, PathString imported, string dirname, string basename File f, string abspath, PathString imported, string dirname, string basename
) { ) {
imported = getImportedPath().getValue() and imported = this.getImportedPath().getValue() and
f.getStem() = imported.getStem() and f.getStem() = imported.getStem() and
f.getAbsolutePath() = abspath and f.getAbsolutePath() = abspath and
dirname = imported.getDirName() and dirname = imported.getDirName() and
@@ -273,14 +275,14 @@ private class AmdDependencyImport extends Import {
* Gets the module whose absolute path matches this import, if there is only a single such module. * Gets the module whose absolute path matches this import, if there is only a single such module.
*/ */
private Module resolveByAbsolutePath() { private Module resolveByAbsolutePath() {
result.getFile() = unique(File file | file = guessTarget()) result.getFile() = unique(File file | file = this.guessTarget())
} }
override Module getImportedModule() { override Module getImportedModule() {
result = super.getImportedModule() result = super.getImportedModule()
or or
not exists(super.getImportedModule()) and not exists(super.getImportedModule()) and
result = resolveByAbsolutePath() result = this.resolveByAbsolutePath()
} }
override DataFlow::Node getImportedModuleNode() { override DataFlow::Node getImportedModuleNode() {
@@ -314,7 +316,7 @@ class AmdModule extends Module {
override DataFlow::Node getAnExportedValue(string name) { override DataFlow::Node getAnExportedValue(string name) {
exists(DataFlow::PropWrite pwn | result = pwn.getRhs() | exists(DataFlow::PropWrite pwn | result = pwn.getRhs() |
pwn.getBase().analyze().getAValue() = getDefine().getAModuleExportsValue() and pwn.getBase().analyze().getAValue() = this.getDefine().getAModuleExportsValue() and
name = pwn.getPropertyName() name = pwn.getPropertyName()
) )
} }
@@ -329,6 +331,6 @@ class AmdModule extends Module {
) )
or or
// Returned from factory function // Returned from factory function
result = getDefine().getModuleExpr().flow() result = this.getDefine().getModuleExpr().flow()
} }
} }

View File

@@ -73,7 +73,7 @@ module Base64 {
private class Btoa extends Base64::Encode::Range, DataFlow::CallNode { private class Btoa extends Base64::Encode::Range, DataFlow::CallNode {
Btoa() { this = DataFlow::globalVarRef("btoa").getACall() } Btoa() { this = DataFlow::globalVarRef("btoa").getACall() }
override DataFlow::Node getInput() { result = getArgument(0) } override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::Node getOutput() { result = this } override DataFlow::Node getOutput() { result = this }
} }
@@ -82,7 +82,7 @@ private class Btoa extends Base64::Encode::Range, DataFlow::CallNode {
private class Atob extends Base64::Decode::Range, DataFlow::CallNode { private class Atob extends Base64::Decode::Range, DataFlow::CallNode {
Atob() { this = DataFlow::globalVarRef("atob").getACall() } Atob() { this = DataFlow::globalVarRef("atob").getACall() }
override DataFlow::Node getInput() { result = getArgument(0) } override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::Node getOutput() { result = this } override DataFlow::Node getOutput() { result = this }
} }
@@ -93,11 +93,11 @@ private class Atob extends Base64::Decode::Range, DataFlow::CallNode {
*/ */
private class Buffer_toString extends Base64::Encode::Range, DataFlow::MethodCallNode { private class Buffer_toString extends Base64::Encode::Range, DataFlow::MethodCallNode {
Buffer_toString() { Buffer_toString() {
getMethodName() = "toString" and this.getMethodName() = "toString" and
getArgument(0).mayHaveStringValue("base64") this.getArgument(0).mayHaveStringValue("base64")
} }
override DataFlow::Node getInput() { result = getReceiver() } override DataFlow::Node getInput() { result = this.getReceiver() }
override DataFlow::Node getOutput() { result = this } override DataFlow::Node getOutput() { result = this }
} }
@@ -106,10 +106,10 @@ private class Buffer_toString extends Base64::Encode::Range, DataFlow::MethodCal
private class Buffer_from extends Base64::Decode::Range, DataFlow::CallNode { private class Buffer_from extends Base64::Decode::Range, DataFlow::CallNode {
Buffer_from() { Buffer_from() {
this = DataFlow::globalVarRef("Buffer").getAMemberCall("from") and this = DataFlow::globalVarRef("Buffer").getAMemberCall("from") and
getArgument(1).mayHaveStringValue("base64") this.getArgument(1).mayHaveStringValue("base64")
} }
override DataFlow::Node getInput() { result = getArgument(0) } override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::Node getOutput() { result = this } override DataFlow::Node getOutput() { result = this }
} }
@@ -149,7 +149,7 @@ private class NpmBase64Encode extends Base64::Encode::Range, DataFlow::CallNode
) )
} }
override DataFlow::Node getInput() { result = getArgument(0) } override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::Node getOutput() { result = this } override DataFlow::Node getOutput() { result = this }
} }
@@ -186,7 +186,7 @@ private class NpmBase64Decode extends Base64::Decode::Range, DataFlow::CallNode
) )
} }
override DataFlow::Node getInput() { result = getArgument(0) } override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::Node getOutput() { result = this } override DataFlow::Node getOutput() { result = this }
} }

View File

@@ -288,10 +288,10 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
ControlFlowNode getAPredecessor() { this = result.getASuccessor() } ControlFlowNode getAPredecessor() { this = result.getASuccessor() }
/** Holds if this is a node with more than one successor. */ /** Holds if this is a node with more than one successor. */
predicate isBranch() { strictcount(getASuccessor()) > 1 } predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
/** Holds if this is a node with more than one predecessor. */ /** Holds if this is a node with more than one predecessor. */
predicate isJoin() { strictcount(getAPredecessor()) > 1 } predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
/** /**
* Holds if this is a start node, that is, the CFG node where execution of a * Holds if this is a start node, that is, the CFG node where execution of a
@@ -304,14 +304,14 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
* of that toplevel or function terminates. * of that toplevel or function terminates.
*/ */
predicate isAFinalNodeOfContainer(StmtContainer container) { predicate isAFinalNodeOfContainer(StmtContainer container) {
getASuccessor().(SyntheticControlFlowNode).isAFinalNodeOfContainer(container) this.getASuccessor().(SyntheticControlFlowNode).isAFinalNodeOfContainer(container)
} }
/** /**
* Holds if this is a final node, that is, a CFG node where execution of a * Holds if this is a final node, that is, a CFG node where execution of a
* toplevel or function terminates. * toplevel or function terminates.
*/ */
final predicate isAFinalNode() { isAFinalNodeOfContainer(_) } final predicate isAFinalNode() { this.isAFinalNodeOfContainer(_) }
/** /**
* Holds if this node is unreachable, that is, it has no predecessors in the CFG. * Holds if this node is unreachable, that is, it has no predecessors in the CFG.
@@ -327,7 +327,7 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
* `s1` is unreachable, but `s2` is not. * `s1` is unreachable, but `s2` is not.
*/ */
predicate isUnreachable() { predicate isUnreachable() {
forall(ControlFlowNode pred | pred = getAPredecessor() | forall(ControlFlowNode pred | pred = this.getAPredecessor() |
pred.(SyntheticControlFlowNode).isUnreachable() pred.(SyntheticControlFlowNode).isUnreachable()
) )
// note the override in ControlFlowEntryNode below // note the override in ControlFlowEntryNode below
@@ -348,7 +348,7 @@ class ControlFlowNode extends @cfg_node, Locatable, NodeInStmtContainer {
else else
if this instanceof @decorator_list if this instanceof @decorator_list
then result = "parameter decorators of " + this.(AstNode).getParent().(Function).describe() then result = "parameter decorators of " + this.(AstNode).getParent().(Function).describe()
else result = toString() else result = this.toString()
} }
} }
@@ -364,7 +364,7 @@ class SyntheticControlFlowNode extends @synthetic_cfg_node, ControlFlowNode {
class ControlFlowEntryNode extends SyntheticControlFlowNode, @entry_node { class ControlFlowEntryNode extends SyntheticControlFlowNode, @entry_node {
override predicate isUnreachable() { none() } override predicate isUnreachable() { none() }
override string toString() { result = "entry node of " + getContainer().toString() } override string toString() { result = "entry node of " + this.getContainer().toString() }
} }
/** A synthetic CFG node marking the exit of a function or toplevel script. */ /** A synthetic CFG node marking the exit of a function or toplevel script. */
@@ -373,7 +373,7 @@ class ControlFlowExitNode extends SyntheticControlFlowNode, @exit_node {
exit_cfg_node(this, container) exit_cfg_node(this, container)
} }
override string toString() { result = "exit node of " + getContainer().toString() } override string toString() { result = "exit node of " + this.getContainer().toString() }
} }
/** /**
@@ -407,7 +407,7 @@ class ConditionGuardNode extends GuardControlFlowNode, @condition_guard {
guard_node(this, 1, _) and result = true guard_node(this, 1, _) and result = true
} }
override string toString() { result = "guard: " + getTest() + " is " + getOutcome() } override string toString() { result = "guard: " + this.getTest() + " is " + this.getOutcome() }
} }
/** /**

View File

@@ -33,7 +33,7 @@ class CanonicalName extends @symbol {
* Gets the child of this canonical name that has the given `name`, if any. * Gets the child of this canonical name that has the given `name`, if any.
*/ */
CanonicalName getChild(string name) { CanonicalName getChild(string name) {
result = getAChild() and result = this.getAChild() and
result.getName() = name result.getName() = name
} }
@@ -49,7 +49,7 @@ class CanonicalName extends @symbol {
symbol_module(this, result) symbol_module(this, result)
or or
exists(PackageJson pkg | exists(PackageJson pkg |
getModule() = pkg.getMainModule() and this.getModule() = pkg.getMainModule() and
result = pkg.getPackageName() result = pkg.getPackageName()
) )
} }
@@ -68,19 +68,19 @@ class CanonicalName extends @symbol {
/** /**
* Holds if this canonical name has a child, i.e. an extension of its qualified name. * Holds if this canonical name has a child, i.e. an extension of its qualified name.
*/ */
predicate hasChild() { exists(getAChild()) } predicate hasChild() { exists(this.getAChild()) }
/** /**
* True if this has no parent. * True if this has no parent.
*/ */
predicate isRoot() { not exists(getParent()) } predicate isRoot() { not exists(this.getParent()) }
/** /**
* Holds if this is the export namespace of a module. * Holds if this is the export namespace of a module.
*/ */
predicate isModuleRoot() { predicate isModuleRoot() {
exists(getModule()) or exists(this.getModule()) or
exists(getExternalModuleName()) exists(this.getExternalModuleName())
} }
/** /**
@@ -98,22 +98,22 @@ class CanonicalName extends @symbol {
/** Holds if this has the given qualified name, rooted in the global scope. */ /** Holds if this has the given qualified name, rooted in the global scope. */
predicate hasQualifiedName(string globalName) { predicate hasQualifiedName(string globalName) {
globalName = getGlobalName() globalName = this.getGlobalName()
or or
exists(string prefix | exists(string prefix |
getParent().hasQualifiedName(prefix) and this.getParent().hasQualifiedName(prefix) and
globalName = prefix + "." + getName() globalName = prefix + "." + this.getName()
) )
} }
/** Holds if this has the given qualified name, rooted in the given external module. */ /** Holds if this has the given qualified name, rooted in the given external module. */
predicate hasQualifiedName(string moduleName, string exportedName) { predicate hasQualifiedName(string moduleName, string exportedName) {
moduleName = getParent().getExternalModuleName() and moduleName = this.getParent().getExternalModuleName() and
exportedName = getName() exportedName = this.getName()
or or
exists(string prefix | exists(string prefix |
getParent().hasQualifiedName(moduleName, prefix) and this.getParent().hasQualifiedName(moduleName, prefix) and
exportedName = prefix + "." + getName() exportedName = prefix + "." + this.getName()
) )
} }
@@ -121,16 +121,16 @@ class CanonicalName extends @symbol {
* Gets the qualified name without the root. * Gets the qualified name without the root.
*/ */
string getRelativeName() { string getRelativeName() {
if getParent().isModuleRoot() if this.getParent().isModuleRoot()
then result = getName() then result = this.getName()
else else
if exists(getGlobalName()) if exists(this.getGlobalName())
then result = min(getGlobalName()) then result = min(this.getGlobalName())
else else
if exists(getParent()) if exists(this.getParent())
then result = getParent().getRelativeName() + "." + getName() then result = this.getParent().getRelativeName() + "." + this.getName()
else ( else (
not isModuleRoot() and result = getName() not this.isModuleRoot() and result = this.getName()
) )
} }
@@ -141,20 +141,20 @@ class CanonicalName extends @symbol {
* this is the container where the type is declared. * this is the container where the type is declared.
*/ */
Scope getRootScope() { Scope getRootScope() {
exists(CanonicalName root | root = getRootName() | exists(CanonicalName root | root = this.getRootName() |
if exists(root.getModule()) if exists(root.getModule())
then result = root.getModule().getScope() then result = root.getModule().getScope()
else else
if exists(root.getGlobalName()) if exists(root.getGlobalName())
then result instanceof GlobalScope then result instanceof GlobalScope
else result = getADefinition().getContainer().getScope() else result = this.getADefinition().getContainer().getScope()
) )
} }
private CanonicalName getRootName() { private CanonicalName getRootName() {
if exists(getGlobalName()) or isModuleRoot() or not exists(getParent()) if exists(this.getGlobalName()) or this.isModuleRoot() or not exists(this.getParent())
then result = this then result = this
else result = getParent().getRootName() else result = this.getParent().getRootName()
} }
/** /**
@@ -171,7 +171,7 @@ class CanonicalName extends @symbol {
* Gets a string describing the root scope of this canonical name. * Gets a string describing the root scope of this canonical name.
*/ */
string describeRoot() { string describeRoot() {
exists(CanonicalName root | root = getRootName() | exists(CanonicalName root | root = this.getRootName() |
if exists(root.getExternalModuleName()) if exists(root.getExternalModuleName())
then result = "module '" + min(root.getExternalModuleName()) + "'" then result = "module '" + min(root.getExternalModuleName()) + "'"
else else
@@ -209,9 +209,9 @@ class CanonicalName extends @symbol {
* ``` * ```
*/ */
string toString() { string toString() {
if isModuleRoot() if this.isModuleRoot()
then result = describeRoot() then result = this.describeRoot()
else result = getRelativeName() + " in " + describeRoot() else result = this.getRelativeName() + " in " + this.describeRoot()
} }
} }
@@ -263,7 +263,7 @@ class TypeName extends CanonicalName {
*/ */
class Namespace extends CanonicalName { class Namespace extends CanonicalName {
Namespace() { Namespace() {
getAChild().isExportedMember() or this.getAChild().isExportedMember() or
exists(NamespaceDefinition def | ast_node_symbol(def, this)) or exists(NamespaceDefinition def | ast_node_symbol(def, this)) or
exists(NamespaceAccess ref | ast_node_symbol(ref, this)) exists(NamespaceAccess ref | ast_node_symbol(ref, this))
} }
@@ -334,5 +334,5 @@ class CanonicalFunctionName extends CanonicalName {
/** /**
* Gets the implementation of this function, if it exists. * Gets the implementation of this function, if it exists.
*/ */
Function getImplementation() { result = getADefinition() and result.hasBody() } Function getImplementation() { result = this.getADefinition() and result.hasBody() }
} }

View File

@@ -52,7 +52,7 @@ module Closure {
{ {
DefaultNamespaceRef() { this = DataFlow::globalVarRef("goog").getAMethodCall() } DefaultNamespaceRef() { this = DataFlow::globalVarRef("goog").getAMethodCall() }
override string getClosureNamespace() { result = getArgument(0).getStringValue() } override string getClosureNamespace() { result = this.getArgument(0).getStringValue() }
} }
/** /**
@@ -68,7 +68,7 @@ module Closure {
*/ */
private class DefaultClosureProvideCall extends DefaultNamespaceRef { private class DefaultClosureProvideCall extends DefaultNamespaceRef {
DefaultClosureProvideCall() { DefaultClosureProvideCall() {
getMethodName() = "provide" and this.getMethodName() = "provide" and
isTopLevelExpr(this) isTopLevelExpr(this)
} }
} }
@@ -84,7 +84,7 @@ module Closure {
*/ */
private class DefaultClosureRequireCall extends DefaultNamespaceRef, ClosureNamespaceAccess::Range private class DefaultClosureRequireCall extends DefaultNamespaceRef, ClosureNamespaceAccess::Range
{ {
DefaultClosureRequireCall() { getMethodName() = "require" } DefaultClosureRequireCall() { this.getMethodName() = "require" }
} }
/** /**
@@ -98,7 +98,7 @@ module Closure {
*/ */
private class DefaultClosureModuleDeclaration extends DefaultNamespaceRef { private class DefaultClosureModuleDeclaration extends DefaultNamespaceRef {
DefaultClosureModuleDeclaration() { DefaultClosureModuleDeclaration() {
(getMethodName() = "module" or getMethodName() = "declareModuleId") and (this.getMethodName() = "module" or this.getMethodName() = "declareModuleId") and
isTopLevelExpr(this) isTopLevelExpr(this)
} }
} }
@@ -140,7 +140,7 @@ module Closure {
/** /**
* Gets the namespace of this module. * Gets the namespace of this module.
*/ */
string getClosureNamespace() { result = getModuleDeclaration().getClosureNamespace() } string getClosureNamespace() { result = this.getModuleDeclaration().getClosureNamespace() }
override Module getAnImportedModule() { override Module getAnImportedModule() {
result.(ClosureModule).getClosureNamespace() = result.(ClosureModule).getClosureNamespace() =
@@ -156,8 +156,8 @@ module Closure {
* Has no result for ES6 modules using `goog.declareModuleId`. * Has no result for ES6 modules using `goog.declareModuleId`.
*/ */
Variable getExportsVariable() { Variable getExportsVariable() {
getModuleDeclaration().getMethodName() = "module" and this.getModuleDeclaration().getMethodName() = "module" and
result = getScope().getVariable("exports") result = this.getScope().getVariable("exports")
} }
override DataFlow::Node getAnExportedValue(string name) { override DataFlow::Node getAnExportedValue(string name) {
@@ -165,15 +165,15 @@ module Closure {
result = write.getRhs() and result = write.getRhs() and
write.writes(base.flow(), name, _) and write.writes(base.flow(), name, _) and
( (
base = getExportsVariable().getAReference() base = this.getExportsVariable().getAReference()
or or
base = getExportsVariable().getAnAssignedExpr() base = this.getExportsVariable().getAnAssignedExpr()
) )
) )
} }
override DataFlow::Node getABulkExportedNode() { override DataFlow::Node getABulkExportedNode() {
result = getExportsVariable().getAnAssignedExpr().flow() result = this.getExportsVariable().getAnAssignedExpr().flow()
} }
} }
@@ -263,19 +263,19 @@ module Closure {
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) { override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
index >= 0 and index >= 0 and
callback = getArgument(0) and callback = this.getArgument(0) and
argument = getArgument(index + 2) argument = this.getArgument(index + 2)
} }
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) { override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
boundArgs = getNumArgument() - 2 and boundArgs = this.getNumArgument() - 2 and
callback = getArgument(0) and callback = this.getArgument(0) and
result = this result = this
} }
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) { override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
callback = getArgument(0) and callback = this.getArgument(0) and
result = getArgument(1) result = this.getArgument(1)
} }
} }
} }

View File

@@ -24,18 +24,18 @@ class Comment extends @comment, Locatable {
string getText() { comments(this, _, _, result, _) } string getText() { comments(this, _, _, result, _) }
/** Gets the `i`th line of comment text. */ /** Gets the `i`th line of comment text. */
string getLine(int i) { result = getText().splitAt("\n", i) } string getLine(int i) { result = this.getText().splitAt("\n", i) }
/** Gets the next token after this comment. */ /** Gets the next token after this comment. */
Token getNextToken() { next_token(this, result) } Token getNextToken() { next_token(this, result) }
override int getNumLines() { result = count(getLine(_)) } override int getNumLines() { result = count(this.getLine(_)) }
override string toString() { comments(this, _, _, _, result) } override string toString() { comments(this, _, _, _, result) }
/** Holds if this comment spans lines `start` to `end` (inclusive) in file `f`. */ /** Holds if this comment spans lines `start` to `end` (inclusive) in file `f`. */
predicate onLines(File f, int start, int end) { predicate onLines(File f, int start, int end) {
exists(Location loc | loc = getLocation() | exists(Location loc | loc = this.getLocation() |
f = loc.getFile() and f = loc.getFile() and
start = loc.getStartLine() and start = loc.getStartLine() and
end = loc.getEndLine() end = loc.getEndLine()

View File

@@ -61,7 +61,7 @@ module SyntacticConstants {
cached cached
class UnaryConstant extends SyntacticConstant, UnaryExpr { class UnaryConstant extends SyntacticConstant, UnaryExpr {
cached cached
UnaryConstant() { getOperand() instanceof SyntacticConstant } UnaryConstant() { this.getOperand() instanceof SyntacticConstant }
} }
/** /**
@@ -71,8 +71,8 @@ module SyntacticConstants {
class BinaryConstant extends SyntacticConstant, BinaryExpr { class BinaryConstant extends SyntacticConstant, BinaryExpr {
cached cached
BinaryConstant() { BinaryConstant() {
getLeftOperand() instanceof SyntacticConstant and this.getLeftOperand() instanceof SyntacticConstant and
getRightOperand() instanceof SyntacticConstant this.getRightOperand() instanceof SyntacticConstant
} }
} }
@@ -83,9 +83,9 @@ module SyntacticConstants {
class ConditionalConstant extends SyntacticConstant, ConditionalExpr { class ConditionalConstant extends SyntacticConstant, ConditionalExpr {
cached cached
ConditionalConstant() { ConditionalConstant() {
getCondition() instanceof SyntacticConstant and this.getCondition() instanceof SyntacticConstant and
getConsequent() instanceof SyntacticConstant and this.getConsequent() instanceof SyntacticConstant and
getAlternate() instanceof SyntacticConstant this.getAlternate() instanceof SyntacticConstant
} }
} }
@@ -125,7 +125,7 @@ module SyntacticConstants {
cached cached
class WrappedConstant extends SyntacticConstant { class WrappedConstant extends SyntacticConstant {
cached cached
WrappedConstant() { getUnderlyingValue() instanceof SyntacticConstant } WrappedConstant() { this.getUnderlyingValue() instanceof SyntacticConstant }
} }
/** /**
@@ -150,5 +150,5 @@ module SyntacticConstants {
cached cached
class ConstantString extends ConstantExpr { class ConstantString extends ConstantExpr {
cached cached
ConstantString() { exists(getStringValue()) } ConstantString() { exists(this.getStringValue()) }
} }

View File

@@ -183,7 +183,7 @@ class VarDef extends ControlFlowNode {
Expr getTarget() { defn(this, result) } Expr getTarget() { defn(this, result) }
/** Gets a variable defined by this node, if any. */ /** Gets a variable defined by this node, if any. */
Variable getAVariable() { result = getTarget().(BindingPattern).getAVariable() } Variable getAVariable() { result = this.getTarget().(BindingPattern).getAVariable() }
/** /**
* Gets the source of this definition, that is, the data flow node representing * Gets the source of this definition, that is, the data flow node representing
@@ -232,8 +232,8 @@ class VarUse extends ControlFlowNode, @varref instanceof RValue {
* For global variables, each definition is considered to reach each use. * For global variables, each definition is considered to reach each use.
*/ */
VarDef getADef() { VarDef getADef() {
result = getSsaVariable().getDefinition().getAContributingVarDef() or result = this.getSsaVariable().getDefinition().getAContributingVarDef() or
result.getAVariable() = getVariable().(GlobalVariable) result.getAVariable() = this.getVariable().(GlobalVariable)
} }
/** /**

View File

@@ -42,7 +42,7 @@ abstract class EnumeratedPropName extends DataFlow::Node {
* Gets a source node that refers to the object whose properties are being enumerated. * Gets a source node that refers to the object whose properties are being enumerated.
*/ */
DataFlow::SourceNode getASourceObjectRef() { DataFlow::SourceNode getASourceObjectRef() {
result = AccessPath::getAnAliasedSourceNode(getSourceObject()) result = AccessPath::getAnAliasedSourceNode(this.getSourceObject())
} }
/** /**
@@ -53,7 +53,7 @@ abstract class EnumeratedPropName extends DataFlow::Node {
SourceNode getASourceProp() { SourceNode getASourceProp() {
exists(Node base, Node key | exists(Node base, Node key |
dynamicPropReadStep(base, key, result) and dynamicPropReadStep(base, key, result) and
getASourceObjectRef().flowsTo(base) and this.getASourceObjectRef().flowsTo(base) and
key.getImmediatePredecessor*() = this key.getImmediatePredecessor*() = this
) )
} }

View File

@@ -37,14 +37,14 @@ module E4X {
* Gets the left operand of this qualified identifier, which is either * Gets the left operand of this qualified identifier, which is either
* an identifier or a wildcard. * an identifier or a wildcard.
*/ */
Expr getLeft() { result = getChildExpr(0) } Expr getLeft() { result = this.getChildExpr(0) }
/** /**
* Gets the right operand of this qualified identifer, which is either * Gets the right operand of this qualified identifer, which is either
* an identifier, or an arbitrary expression for computed qualified * an identifier, or an arbitrary expression for computed qualified
* identifiers. * identifiers.
*/ */
Expr getRight() { result = getChildExpr(1) } Expr getRight() { result = this.getChildExpr(1) }
/** /**
* Holds if this is a qualified identifier with a computed name, as in * Holds if this is a qualified identifier with a computed name, as in
@@ -53,7 +53,7 @@ module E4X {
predicate isComputed() { this instanceof @e4x_xml_dynamic_qualident } predicate isComputed() { this instanceof @e4x_xml_dynamic_qualident }
override ControlFlowNode getFirstControlFlowNode() { override ControlFlowNode getFirstControlFlowNode() {
result = getLeft().getFirstControlFlowNode() result = this.getLeft().getFirstControlFlowNode()
} }
} }
@@ -76,7 +76,7 @@ module E4X {
* wildcard identifier or a possibly qualified name), or an arbitrary * wildcard identifier or a possibly qualified name), or an arbitrary
* expression for computed attribute selectors. * expression for computed attribute selectors.
*/ */
Expr getAttribute() { result = getChildExpr(0) } Expr getAttribute() { result = this.getChildExpr(0) }
/** /**
* Holds if this is an attribute selector with a computed name, as in * Holds if this is an attribute selector with a computed name, as in
@@ -85,7 +85,7 @@ module E4X {
predicate isComputed() { this instanceof @e4x_xml_dynamic_attribute_selector } predicate isComputed() { this instanceof @e4x_xml_dynamic_attribute_selector }
override ControlFlowNode getFirstControlFlowNode() { override ControlFlowNode getFirstControlFlowNode() {
result = getAttribute().getFirstControlFlowNode() result = this.getAttribute().getFirstControlFlowNode()
} }
} }
@@ -105,15 +105,15 @@ module E4X {
/** /**
* Gets the left operand of this filter expression. * Gets the left operand of this filter expression.
*/ */
Expr getLeft() { result = getChildExpr(0) } Expr getLeft() { result = this.getChildExpr(0) }
/** /**
* Gets the right operand of this filter expression. * Gets the right operand of this filter expression.
*/ */
Expr getRight() { result = getChildExpr(1) } Expr getRight() { result = this.getChildExpr(1) }
override ControlFlowNode getFirstControlFlowNode() { override ControlFlowNode getFirstControlFlowNode() {
result = getLeft().getFirstControlFlowNode() result = this.getLeft().getFirstControlFlowNode()
} }
} }
@@ -133,15 +133,15 @@ module E4X {
/** /**
* Gets the base expression of this dot-dot expression. * Gets the base expression of this dot-dot expression.
*/ */
Expr getBase() { result = getChildExpr(0) } Expr getBase() { result = this.getChildExpr(0) }
/** /**
* Gets the index expression of this dot-dot expression. * Gets the index expression of this dot-dot expression.
*/ */
Expr getIndex() { result = getChildExpr(1) } Expr getIndex() { result = this.getChildExpr(1) }
override ControlFlowNode getFirstControlFlowNode() { override ControlFlowNode getFirstControlFlowNode() {
result = getBase().getFirstControlFlowNode() result = this.getBase().getFirstControlFlowNode()
} }
} }

View File

@@ -33,8 +33,8 @@ abstract class EmailSender extends DataFlow::SourceNode {
* Gets a data flow node that refers to the HTML body or plaintext body of the email. * Gets a data flow node that refers to the HTML body or plaintext body of the email.
*/ */
DataFlow::Node getABody() { DataFlow::Node getABody() {
result = getPlainTextBody() or result = this.getPlainTextBody() or
result = getHtmlBody() result = this.getHtmlBody()
} }
} }
@@ -47,13 +47,13 @@ private class NodemailerEmailSender extends EmailSender, DataFlow::MethodCallNod
DataFlow::moduleMember("nodemailer", "createTransport").getACall().getAMethodCall("sendMail") DataFlow::moduleMember("nodemailer", "createTransport").getACall().getAMethodCall("sendMail")
} }
override DataFlow::Node getPlainTextBody() { result = getOptionArgument(0, "text") } override DataFlow::Node getPlainTextBody() { result = this.getOptionArgument(0, "text") }
override DataFlow::Node getHtmlBody() { result = getOptionArgument(0, "html") } override DataFlow::Node getHtmlBody() { result = this.getOptionArgument(0, "html") }
override DataFlow::Node getTo() { result = getOptionArgument(0, "to") } override DataFlow::Node getTo() { result = this.getOptionArgument(0, "to") }
override DataFlow::Node getFrom() { result = getOptionArgument(0, "from") } override DataFlow::Node getFrom() { result = this.getOptionArgument(0, "from") }
override DataFlow::Node getSubject() { result = getOptionArgument(0, "subject") } override DataFlow::Node getSubject() { result = this.getOptionArgument(0, "subject") }
} }

View File

@@ -9,7 +9,7 @@ abstract class Error extends Locatable {
/** Gets the message associated with this error. */ /** Gets the message associated with this error. */
abstract string getMessage(); abstract string getMessage();
override string toString() { result = getMessage() } override string toString() { result = this.getMessage() }
/** Holds if this error prevented the file from being extracted. */ /** Holds if this error prevented the file from being extracted. */
predicate isFatal() { any() } predicate isFatal() { any() }
@@ -25,5 +25,5 @@ class JSParseError extends @js_parse_error, Error {
/** Gets the source text of the line this error occurs on. */ /** Gets the source text of the line this error occurs on. */
string getLine() { js_parse_errors(this, _, _, result) } string getLine() { js_parse_errors(this, _, _, result) }
override predicate isFatal() { not getTopLevel() instanceof Angular2::TemplateTopLevel } override predicate isFatal() { not this.getTopLevel() instanceof Angular2::TemplateTopLevel }
} }

View File

@@ -29,8 +29,8 @@ abstract class ExtendCall extends DataFlow::CallNode {
* Gets an object from which properties are taken or stored. * Gets an object from which properties are taken or stored.
*/ */
DataFlow::Node getAnOperand() { DataFlow::Node getAnOperand() {
result = getASourceOperand() or result = this.getASourceOperand() or
result = getDestinationOperand() result = this.getDestinationOperand()
} }
} }
@@ -55,22 +55,22 @@ private class ExtendCallWithFlag extends ExtendCall {
/** /**
* Holds if the first argument appears to be a boolean flag. * Holds if the first argument appears to be a boolean flag.
*/ */
predicate hasFlag() { getArgument(0).mayHaveBooleanValue(_) } predicate hasFlag() { this.getArgument(0).mayHaveBooleanValue(_) }
/** /**
* Gets the `n`th argument after the optional boolean flag. * Gets the `n`th argument after the optional boolean flag.
*/ */
DataFlow::Node getTranslatedArgument(int n) { DataFlow::Node getTranslatedArgument(int n) {
if hasFlag() then result = getArgument(n + 1) else result = getArgument(n) if this.hasFlag() then result = this.getArgument(n + 1) else result = this.getArgument(n)
} }
override DataFlow::Node getASourceOperand() { override DataFlow::Node getASourceOperand() {
exists(int n | n >= 1 | result = getTranslatedArgument(n)) exists(int n | n >= 1 | result = this.getTranslatedArgument(n))
} }
override DataFlow::Node getDestinationOperand() { result = getTranslatedArgument(0) } override DataFlow::Node getDestinationOperand() { result = this.getTranslatedArgument(0) }
override predicate isDeep() { getArgument(0).mayHaveBooleanValue(true) } override predicate isDeep() { this.getArgument(0).mayHaveBooleanValue(true) }
} }
/** /**
@@ -100,9 +100,11 @@ private class ExtendCallDeep extends ExtendCall {
) )
} }
override DataFlow::Node getASourceOperand() { exists(int n | n >= 1 | result = getArgument(n)) } override DataFlow::Node getASourceOperand() {
exists(int n | n >= 1 | result = this.getArgument(n))
}
override DataFlow::Node getDestinationOperand() { result = getArgument(0) } override DataFlow::Node getDestinationOperand() { result = this.getArgument(0) }
override predicate isDeep() { any() } override predicate isDeep() { any() }
} }
@@ -130,9 +132,11 @@ private class ExtendCallShallow extends ExtendCall {
) )
} }
override DataFlow::Node getASourceOperand() { exists(int n | n >= 1 | result = getArgument(n)) } override DataFlow::Node getASourceOperand() {
exists(int n | n >= 1 | result = this.getArgument(n))
}
override DataFlow::Node getDestinationOperand() { result = getArgument(0) } override DataFlow::Node getDestinationOperand() { result = this.getArgument(0) }
override predicate isDeep() { none() } override predicate isDeep() { none() }
} }
@@ -149,7 +153,7 @@ private class FunctionalExtendCallShallow extends ExtendCall {
) )
} }
override DataFlow::Node getASourceOperand() { result = getAnArgument() } override DataFlow::Node getASourceOperand() { result = this.getAnArgument() }
override DataFlow::Node getDestinationOperand() { none() } override DataFlow::Node getDestinationOperand() { none() }
@@ -206,7 +210,7 @@ private class WebpackMergeDeep extends ExtendCall, DataFlow::CallNode {
.getACall() .getACall()
} }
override DataFlow::Node getASourceOperand() { result = getAnArgument() } override DataFlow::Node getASourceOperand() { result = this.getAnArgument() }
override DataFlow::Node getDestinationOperand() { none() } override DataFlow::Node getDestinationOperand() { none() }

View File

@@ -7,7 +7,7 @@ module HTML {
* An HTML file. * An HTML file.
*/ */
class HtmlFile extends File { class HtmlFile extends File {
HtmlFile() { getFileType().isHtml() } HtmlFile() { this.getFileType().isHtml() }
} }
/** /**
@@ -18,7 +18,7 @@ module HTML {
*/ */
private class FileContainingHtml extends File { private class FileContainingHtml extends File {
FileContainingHtml() { FileContainingHtml() {
getFileType().isHtml() this.getFileType().isHtml()
or or
// The file contains an expression containing an HTML element // The file contains an expression containing an HTML element
exists(Expr e | exists(Expr e |
@@ -60,17 +60,19 @@ module HTML {
/** /**
* Holds if this is a toplevel element, that is, if it does not have a parent element. * Holds if this is a toplevel element, that is, if it does not have a parent element.
*/ */
predicate isTopLevel() { not exists(getParent()) } predicate isTopLevel() { not exists(this.getParent()) }
/** /**
* Gets the root HTML document element in which this element is contained. * Gets the root HTML document element in which this element is contained.
*/ */
DocumentElement getDocument() { result = getRoot() } DocumentElement getDocument() { result = this.getRoot() }
/** /**
* Gets the root element in which this element is contained. * Gets the root element in which this element is contained.
*/ */
Element getRoot() { if isTopLevel() then result = this else result = getParent().getRoot() } Element getRoot() {
if this.isTopLevel() then result = this else result = this.getParent().getRoot()
}
/** /**
* Gets the `i`th child element (0-based) of this element. * Gets the `i`th child element (0-based) of this element.
@@ -80,7 +82,7 @@ module HTML {
/** /**
* Gets a child element of this element. * Gets a child element of this element.
*/ */
Element getChild() { result = getChild(_) } Element getChild() { result = this.getChild(_) }
/** /**
* Gets the `i`th attribute (0-based) of this element. * Gets the `i`th attribute (0-based) of this element.
@@ -90,17 +92,17 @@ module HTML {
/** /**
* Gets an attribute of this element. * Gets an attribute of this element.
*/ */
Attribute getAnAttribute() { result = getAttribute(_) } Attribute getAnAttribute() { result = this.getAttribute(_) }
/** /**
* Gets an attribute of this element that has the given name. * Gets an attribute of this element that has the given name.
*/ */
Attribute getAttributeByName(string name) { Attribute getAttributeByName(string name) {
result = getAnAttribute() and result = this.getAnAttribute() and
result.getName() = name result.getName() = name
} }
override string toString() { result = "<" + getName() + ">...</>" } override string toString() { result = "<" + this.getName() + ">...</>" }
override string getAPrimaryQlClass() { result = "HTML::Element" } override string getAPrimaryQlClass() { result = "HTML::Element" }
} }
@@ -136,7 +138,7 @@ module HTML {
* Gets the root element in which the element to which this attribute * Gets the root element in which the element to which this attribute
* belongs is contained. * belongs is contained.
*/ */
Element getRoot() { result = getElement().getRoot() } Element getRoot() { result = this.getElement().getRoot() }
/** /**
* Gets the name of this attribute. * Gets the name of this attribute.
@@ -151,7 +153,7 @@ module HTML {
*/ */
string getValue() { xmlAttrs(this, _, _, result, _, _) } string getValue() { xmlAttrs(this, _, _, result, _, _) }
override string toString() { result = getName() + "=" + getValue() } override string toString() { result = this.getName() + "=" + this.getValue() }
override string getAPrimaryQlClass() { result = "HTML::Attribute" } override string getAPrimaryQlClass() { result = "HTML::Attribute" }
} }
@@ -170,7 +172,7 @@ module HTML {
* ``` * ```
*/ */
class DocumentElement extends Element { class DocumentElement extends Element {
DocumentElement() { getName() = "html" } DocumentElement() { this.getName() = "html" }
} }
/** /**
@@ -183,12 +185,12 @@ module HTML {
* ``` * ```
*/ */
class IframeElement extends Element { class IframeElement extends Element {
IframeElement() { getName() = "iframe" } IframeElement() { this.getName() = "iframe" }
/** /**
* Gets the value of the `src` attribute. * Gets the value of the `src` attribute.
*/ */
string getSourcePath() { result = getAttributeByName("src").getValue() } string getSourcePath() { result = this.getAttributeByName("src").getValue() }
} }
/** /**
@@ -201,7 +203,7 @@ module HTML {
* ``` * ```
*/ */
class ScriptElement extends Element { class ScriptElement extends Element {
ScriptElement() { getName() = "script" } ScriptElement() { this.getName() = "script" }
/** /**
* Gets the absolute file system path the value of the `src` attribute * Gets the absolute file system path the value of the `src` attribute
@@ -212,38 +214,38 @@ module HTML {
* to the enclosing HTML file. Base URLs are not taken into account. * to the enclosing HTML file. Base URLs are not taken into account.
*/ */
string resolveSourcePath() { string resolveSourcePath() {
exists(string path | path = getSourcePath() | exists(string path | path = this.getSourcePath() |
result = path.regexpCapture("file://(/.*)", 1) result = path.regexpCapture("file://(/.*)", 1)
or or
not path.regexpMatch("(\\w+:)?//.*") and not path.regexpMatch("(\\w+:)?//.*") and
result = getSourcePath().(ScriptSrcPath).resolve(getSearchRoot()).toString() result = this.getSourcePath().(ScriptSrcPath).resolve(this.getSearchRoot()).toString()
) )
} }
/** /**
* Gets the value of the `src` attribute. * Gets the value of the `src` attribute.
*/ */
string getSourcePath() { result = getAttributeByName("src").getValue() } string getSourcePath() { result = this.getAttributeByName("src").getValue() }
/** /**
* Gets the value of the `integrity` attribute. * Gets the value of the `integrity` attribute.
*/ */
string getIntegrityDigest() { result = getAttributeByName("integrity").getValue() } string getIntegrityDigest() { result = this.getAttributeByName("integrity").getValue() }
/** /**
* Gets the folder relative to which the `src` attribute is resolved. * Gets the folder relative to which the `src` attribute is resolved.
*/ */
Folder getSearchRoot() { Folder getSearchRoot() {
if getSourcePath().matches("/%") if this.getSourcePath().matches("/%")
then result.getBaseName() = "" then result.getBaseName() = ""
else result = getFile().getParentContainer() else result = this.getFile().getParentContainer()
} }
/** /**
* Gets the script referred to by the `src` attribute, * Gets the script referred to by the `src` attribute,
* if it can be determined. * if it can be determined.
*/ */
Script resolveSource() { result.getFile().getAbsolutePath() = resolveSourcePath() } Script resolveSource() { result.getFile().getAbsolutePath() = this.resolveSourcePath() }
/** /**
* Gets the inline script of this script element, if any. * Gets the inline script of this script element, if any.
@@ -251,15 +253,15 @@ module HTML {
private InlineScript getInlineScript() { private InlineScript getInlineScript() {
toplevel_parent_xml_node(result, this) and toplevel_parent_xml_node(result, this) and
// the src attribute has precedence // the src attribute has precedence
not exists(getSourcePath()) not exists(this.getSourcePath())
} }
/** /**
* Gets the script of this element, if it can be determined. * Gets the script of this element, if it can be determined.
*/ */
Script getScript() { Script getScript() {
result = getInlineScript() or result = this.getInlineScript() or
result = resolveSource() result = this.resolveSource()
} }
override string getAPrimaryQlClass() { result = "HTML::ScriptElement" } override string getAPrimaryQlClass() { result = "HTML::ScriptElement" }
@@ -301,7 +303,7 @@ module HTML {
class TextNode extends Locatable, @xmlcharacters { class TextNode extends Locatable, @xmlcharacters {
TextNode() { exists(FileContainingHtml f | xmlChars(this, _, _, _, _, f)) } TextNode() { exists(FileContainingHtml f | xmlChars(this, _, _, _, _, f)) }
override string toString() { result = getText() } override string toString() { result = this.getText() }
/** /**
* Gets the content of this text node. * Gets the content of this text node.
@@ -344,7 +346,7 @@ module HTML {
Element getParent() { xmlComments(this, _, result, _) } Element getParent() { xmlComments(this, _, result, _) }
/** Gets the text of this comment, not including delimiters. */ /** Gets the text of this comment, not including delimiters. */
string getText() { result = toString().regexpCapture("(?s)<!--(.*)-->", 1) } string getText() { result = this.toString().regexpCapture("(?s)<!--(.*)-->", 1) }
override string toString() { xmlComments(this, result, _, _) } override string toString() { xmlComments(this, result, _, _) }

View File

@@ -65,11 +65,11 @@ private class DefaultHtmlSanitizerCall extends HtmlSanitizerCall {
this = htmlSanitizerFunction().getACall() this = htmlSanitizerFunction().getACall()
or or
// Match home-made sanitizers by name. // Match home-made sanitizers by name.
exists(string calleeName | calleeName = getCalleeName() | exists(string calleeName | calleeName = this.getCalleeName() |
calleeName.regexpMatch("(?i).*html.*") and calleeName.regexpMatch("(?i).*html.*") and
calleeName.regexpMatch("(?i).*(?<!un)(saniti[sz]|escape|strip).*") calleeName.regexpMatch("(?i).*(?<!un)(saniti[sz]|escape|strip).*")
) )
} }
override DataFlow::Node getInput() { result = getArgument(0) } override DataFlow::Node getInput() { result = this.getArgument(0) }
} }

View File

@@ -31,11 +31,11 @@ class JSDoc extends @jsdoc, Locatable {
/** Gets a JSDoc tag within this JSDoc comment with the given title. */ /** Gets a JSDoc tag within this JSDoc comment with the given title. */
JSDocTag getATagByTitle(string title) { JSDocTag getATagByTitle(string title) {
result = getATag() and result = this.getATag() and
result.getTitle() = title result.getTitle() = title
} }
override string toString() { result = getComment().toString() } override string toString() { result = this.getComment().toString() }
} }
/** /**
@@ -59,7 +59,7 @@ abstract class Documentable extends AstNode {
/** Gets the JSDoc comment for this element, if any. */ /** Gets the JSDoc comment for this element, if any. */
cached cached
JSDoc getDocumentation() { JSDoc getDocumentation() {
Stages::Ast::ref() and result.getComment().getNextToken() = getFirstToken() Stages::Ast::ref() and result.getComment().getNextToken() = this.getFirstToken()
} }
} }
@@ -120,11 +120,11 @@ class JSDocTag extends @jsdoc_tag, JSDocTypeExprParent {
/** Holds if this tag documents a simple name (as opposed to a name path). */ /** Holds if this tag documents a simple name (as opposed to a name path). */
predicate documentsSimpleName() { predicate documentsSimpleName() {
exists(string name | name = getName() | not name.matches("%.%")) exists(string name | name = this.getName() | not name.matches("%.%"))
} }
/** Gets the toplevel in which this tag appears. */ /** Gets the toplevel in which this tag appears. */
TopLevel getTopLevel() { result = getParent().getComment().getTopLevel() } TopLevel getTopLevel() { result = this.getParent().getComment().getTopLevel() }
override JSDoc getJSDocComment() { result.getATag() = this } override JSDoc getJSDocComment() { result.getATag() = this }
} }
@@ -139,12 +139,12 @@ class JSDocTag extends @jsdoc_tag, JSDocTypeExprParent {
* ``` * ```
*/ */
class JSDocParamTag extends JSDocTag { class JSDocParamTag extends JSDocTag {
JSDocParamTag() { getTitle().regexpMatch("param|arg(ument)?") } JSDocParamTag() { this.getTitle().regexpMatch("param|arg(ument)?") }
/** Gets the parameter this tag refers to, if it can be determined. */ /** Gets the parameter this tag refers to, if it can be determined. */
Variable getDocumentedParameter() { Variable getDocumentedParameter() {
exists(Parameterized parm | parm.getDocumentation() = getParent() | exists(Parameterized parm | parm.getDocumentation() = this.getParent() |
result = pragma[only_bind_out](parm).getParameterVariable(getName()) result = pragma[only_bind_out](parm).getParameterVariable(this.getName())
) )
} }
} }
@@ -182,10 +182,10 @@ class JSDocTypeExpr extends @jsdoc_type_expr, JSDocTypeExprParent, TypeAnnotatio
override string toString() { jsdoc_type_exprs(this, _, _, _, result) } override string toString() { jsdoc_type_exprs(this, _, _, _, result) }
override JSDoc getJSDocComment() { result = getParent().getJSDocComment() } override JSDoc getJSDocComment() { result = this.getParent().getJSDocComment() }
override Stmt getEnclosingStmt() { override Stmt getEnclosingStmt() {
exists(Documentable astNode | astNode.getDocumentation() = getJSDocComment() | exists(Documentable astNode | astNode.getDocumentation() = this.getJSDocComment() |
result = astNode result = astNode
or or
result = astNode.(ExprOrType).getEnclosingStmt() result = astNode.(ExprOrType).getEnclosingStmt()
@@ -194,9 +194,9 @@ class JSDocTypeExpr extends @jsdoc_type_expr, JSDocTypeExprParent, TypeAnnotatio
) )
} }
override Function getEnclosingFunction() { result = getContainer() } override Function getEnclosingFunction() { result = this.getContainer() }
override TopLevel getTopLevel() { result = getEnclosingStmt().getTopLevel() } override TopLevel getTopLevel() { result = this.getEnclosingStmt().getTopLevel() }
} }
/** /**
@@ -276,34 +276,34 @@ class JSDocVoidTypeExpr extends @jsdoc_void_type_expr, JSDocTypeExpr {
*/ */
class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr { class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
/** Gets the name of the type the expression refers to. */ /** Gets the name of the type the expression refers to. */
string getName() { result = toString() } string getName() { result = this.toString() }
override predicate isString() { getName() = "string" } override predicate isString() { this.getName() = "string" }
override predicate isStringy() { override predicate isStringy() {
exists(string name | name = getName() | exists(string name | name = this.getName() |
name = "string" or name = "string" or
name = "String" name = "String"
) )
} }
override predicate isNumber() { getName() = "number" } override predicate isNumber() { this.getName() = "number" }
override predicate isNumbery() { override predicate isNumbery() {
exists(string name | name = getName() | exists(string name | name = this.getName() |
name = ["number", "Number", "double", "Double", "int", "integer", "Integer"] name = ["number", "Number", "double", "Double", "int", "integer", "Integer"]
) )
} }
override predicate isBoolean() { getName() = "boolean" } override predicate isBoolean() { this.getName() = "boolean" }
override predicate isBooleany() { override predicate isBooleany() {
getName() = "boolean" or this.getName() = "boolean" or
getName() = "Boolean" or this.getName() = "Boolean" or
getName() = "bool" this.getName() = "bool"
} }
override predicate isRawFunction() { getName() = "Function" } override predicate isRawFunction() { this.getName() = "Function" }
/** /**
* Holds if this name consists of the unqualified name `prefix` * Holds if this name consists of the unqualified name `prefix`
@@ -315,7 +315,7 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
*/ */
predicate hasNameParts(string prefix, string suffix) { predicate hasNameParts(string prefix, string suffix) {
exists(string regex, string name | regex = "([^.]+)(.*)" | exists(string regex, string name | regex = "([^.]+)(.*)" |
name = getName() and name = this.getName() and
prefix = name.regexpCapture(regex, 1) and prefix = name.regexpCapture(regex, 1) and
suffix = name.regexpCapture(regex, 2) suffix = name.regexpCapture(regex, 2)
) )
@@ -325,8 +325,8 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
pragma[nomagic] pragma[nomagic]
private predicate hasNamePartsAndEnv(string prefix, string suffix, JSDoc::Environment env) { private predicate hasNamePartsAndEnv(string prefix, string suffix, JSDoc::Environment env) {
// Force join ordering // Force join ordering
hasNameParts(prefix, suffix) and this.hasNameParts(prefix, suffix) and
env.isContainerInScope(getContainer()) env.isContainerInScope(this.getContainer())
} }
/** /**
@@ -335,28 +335,28 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
cached cached
private string resolvedName() { private string resolvedName() {
exists(string prefix, string suffix, JSDoc::Environment env | exists(string prefix, string suffix, JSDoc::Environment env |
hasNamePartsAndEnv(prefix, suffix, env) and this.hasNamePartsAndEnv(prefix, suffix, env) and
result = env.resolveAlias(prefix) + suffix result = env.resolveAlias(prefix) + suffix
) )
} }
override predicate hasQualifiedName(string globalName) { override predicate hasQualifiedName(string globalName) {
globalName = resolvedName() globalName = this.resolvedName()
or or
not exists(resolvedName()) and not exists(this.resolvedName()) and
globalName = getName() globalName = this.getName()
} }
override DataFlow::ClassNode getClass() { override DataFlow::ClassNode getClass() {
exists(string name | exists(string name |
hasQualifiedName(name) and this.hasQualifiedName(name) and
result.hasQualifiedName(name) result.hasQualifiedName(name)
) )
or or
// Handle case where a local variable has a reference to the class, // Handle case where a local variable has a reference to the class,
// but the class doesn't have a globally qualified name. // but the class doesn't have a globally qualified name.
exists(string alias, JSDoc::Environment env | exists(string alias, JSDoc::Environment env |
hasNamePartsAndEnv(alias, "", env) and this.hasNamePartsAndEnv(alias, "", env) and
result.getAClassReference().flowsTo(env.getNodeFromAlias(alias)) result.getAClassReference().flowsTo(env.getNodeFromAlias(alias))
) )
} }
@@ -373,25 +373,27 @@ class JSDocNamedTypeExpr extends @jsdoc_named_type_expr, JSDocTypeExpr {
*/ */
class JSDocAppliedTypeExpr extends @jsdoc_applied_type_expr, JSDocTypeExpr { class JSDocAppliedTypeExpr extends @jsdoc_applied_type_expr, JSDocTypeExpr {
/** Gets the head type expression, such as `Array` in `Array<string>`. */ /** Gets the head type expression, such as `Array` in `Array<string>`. */
JSDocTypeExpr getHead() { result = getChild(-1) } JSDocTypeExpr getHead() { result = this.getChild(-1) }
/** /**
* Gets the `i`th argument type of the applied type expression. * Gets the `i`th argument type of the applied type expression.
* *
* For example, in `Array<string>`, `string` is the 0th argument type. * For example, in `Array<string>`, `string` is the 0th argument type.
*/ */
JSDocTypeExpr getArgument(int i) { i >= 0 and result = getChild(i) } JSDocTypeExpr getArgument(int i) { i >= 0 and result = this.getChild(i) }
/** /**
* Gets an argument type of the applied type expression. * Gets an argument type of the applied type expression.
* *
* For example, in `Array<string>`, `string` is the only argument type. * For example, in `Array<string>`, `string` is the only argument type.
*/ */
JSDocTypeExpr getAnArgument() { result = getArgument(_) } JSDocTypeExpr getAnArgument() { result = this.getArgument(_) }
override predicate hasQualifiedName(string globalName) { getHead().hasQualifiedName(globalName) } override predicate hasQualifiedName(string globalName) {
this.getHead().hasQualifiedName(globalName)
}
override DataFlow::ClassNode getClass() { result = getHead().getClass() } override DataFlow::ClassNode getClass() { result = this.getHead().getClass() }
} }
/** /**
@@ -405,14 +407,14 @@ class JSDocAppliedTypeExpr extends @jsdoc_applied_type_expr, JSDocTypeExpr {
*/ */
class JSDocNullableTypeExpr extends @jsdoc_nullable_type_expr, JSDocTypeExpr { class JSDocNullableTypeExpr extends @jsdoc_nullable_type_expr, JSDocTypeExpr {
/** Gets the argument type expression. */ /** Gets the argument type expression. */
JSDocTypeExpr getTypeExpr() { result = getChild(0) } JSDocTypeExpr getTypeExpr() { result = this.getChild(0) }
/** Holds if the `?` operator of this type expression is written in prefix notation. */ /** Holds if the `?` operator of this type expression is written in prefix notation. */
predicate isPrefix() { jsdoc_prefix_qualifier(this) } predicate isPrefix() { jsdoc_prefix_qualifier(this) }
override JSDocTypeExpr getAnUnderlyingType() { result = getTypeExpr().getAnUnderlyingType() } override JSDocTypeExpr getAnUnderlyingType() { result = this.getTypeExpr().getAnUnderlyingType() }
override DataFlow::ClassNode getClass() { result = getTypeExpr().getClass() } override DataFlow::ClassNode getClass() { result = this.getTypeExpr().getClass() }
} }
/** /**
@@ -426,14 +428,14 @@ class JSDocNullableTypeExpr extends @jsdoc_nullable_type_expr, JSDocTypeExpr {
*/ */
class JSDocNonNullableTypeExpr extends @jsdoc_non_nullable_type_expr, JSDocTypeExpr { class JSDocNonNullableTypeExpr extends @jsdoc_non_nullable_type_expr, JSDocTypeExpr {
/** Gets the argument type expression. */ /** Gets the argument type expression. */
JSDocTypeExpr getTypeExpr() { result = getChild(0) } JSDocTypeExpr getTypeExpr() { result = this.getChild(0) }
/** Holds if the `!` operator of this type expression is written in prefix notation. */ /** Holds if the `!` operator of this type expression is written in prefix notation. */
predicate isPrefix() { jsdoc_prefix_qualifier(this) } predicate isPrefix() { jsdoc_prefix_qualifier(this) }
override JSDocTypeExpr getAnUnderlyingType() { result = getTypeExpr().getAnUnderlyingType() } override JSDocTypeExpr getAnUnderlyingType() { result = this.getTypeExpr().getAnUnderlyingType() }
override DataFlow::ClassNode getClass() { result = getTypeExpr().getClass() } override DataFlow::ClassNode getClass() { result = this.getTypeExpr().getClass() }
} }
/** /**
@@ -450,14 +452,14 @@ class JSDocRecordTypeExpr extends @jsdoc_record_type_expr, JSDocTypeExpr {
string getFieldName(int i) { jsdoc_record_field_name(this, i, result) } string getFieldName(int i) { jsdoc_record_field_name(this, i, result) }
/** Gets the name of some field of the record type. */ /** Gets the name of some field of the record type. */
string getAFieldName() { result = getFieldName(_) } string getAFieldName() { result = this.getFieldName(_) }
/** Gets the type of the `i`th field of the record type. */ /** Gets the type of the `i`th field of the record type. */
JSDocTypeExpr getFieldType(int i) { result = getChild(i) } JSDocTypeExpr getFieldType(int i) { result = this.getChild(i) }
/** Gets the type of the field with the given name. */ /** Gets the type of the field with the given name. */
JSDocTypeExpr getFieldTypeByName(string fieldname) { JSDocTypeExpr getFieldTypeByName(string fieldname) {
exists(int idx | fieldname = getFieldName(idx) and result = getFieldType(idx)) exists(int idx | fieldname = this.getFieldName(idx) and result = this.getFieldType(idx))
} }
} }
@@ -472,10 +474,10 @@ class JSDocRecordTypeExpr extends @jsdoc_record_type_expr, JSDocTypeExpr {
*/ */
class JSDocArrayTypeExpr extends @jsdoc_array_type_expr, JSDocTypeExpr { class JSDocArrayTypeExpr extends @jsdoc_array_type_expr, JSDocTypeExpr {
/** Gets the type of the `i`th element of this array type. */ /** Gets the type of the `i`th element of this array type. */
JSDocTypeExpr getElementType(int i) { result = getChild(i) } JSDocTypeExpr getElementType(int i) { result = this.getChild(i) }
/** Gets an element type of this array type. */ /** Gets an element type of this array type. */
JSDocTypeExpr getAnElementType() { result = getElementType(_) } JSDocTypeExpr getAnElementType() { result = this.getElementType(_) }
} }
/** /**
@@ -489,9 +491,11 @@ class JSDocArrayTypeExpr extends @jsdoc_array_type_expr, JSDocTypeExpr {
*/ */
class JSDocUnionTypeExpr extends @jsdoc_union_type_expr, JSDocTypeExpr { class JSDocUnionTypeExpr extends @jsdoc_union_type_expr, JSDocTypeExpr {
/** Gets one of the type alternatives of this union type. */ /** Gets one of the type alternatives of this union type. */
JSDocTypeExpr getAnAlternative() { result = getChild(_) } JSDocTypeExpr getAnAlternative() { result = this.getChild(_) }
override JSDocTypeExpr getAnUnderlyingType() { result = getAnAlternative().getAnUnderlyingType() } override JSDocTypeExpr getAnUnderlyingType() {
result = this.getAnAlternative().getAnUnderlyingType()
}
} }
/** /**
@@ -505,16 +509,16 @@ class JSDocUnionTypeExpr extends @jsdoc_union_type_expr, JSDocTypeExpr {
*/ */
class JSDocFunctionTypeExpr extends @jsdoc_function_type_expr, JSDocTypeExpr { class JSDocFunctionTypeExpr extends @jsdoc_function_type_expr, JSDocTypeExpr {
/** Gets the result type of this function type. */ /** Gets the result type of this function type. */
JSDocTypeExpr getResultType() { result = getChild(-1) } JSDocTypeExpr getResultType() { result = this.getChild(-1) }
/** Gets the receiver type of this function type. */ /** Gets the receiver type of this function type. */
JSDocTypeExpr getReceiverType() { result = getChild(-2) } JSDocTypeExpr getReceiverType() { result = this.getChild(-2) }
/** Gets the `i`th parameter type of this function type. */ /** Gets the `i`th parameter type of this function type. */
JSDocTypeExpr getParameterType(int i) { i >= 0 and result = getChild(i) } JSDocTypeExpr getParameterType(int i) { i >= 0 and result = this.getChild(i) }
/** Gets a parameter type of this function type. */ /** Gets a parameter type of this function type. */
JSDocTypeExpr getAParameterType() { result = getParameterType(_) } JSDocTypeExpr getAParameterType() { result = this.getParameterType(_) }
/** Holds if this function type is a constructor type. */ /** Holds if this function type is a constructor type. */
predicate isConstructorType() { jsdoc_has_new_parameter(this) } predicate isConstructorType() { jsdoc_has_new_parameter(this) }
@@ -531,13 +535,13 @@ class JSDocFunctionTypeExpr extends @jsdoc_function_type_expr, JSDocTypeExpr {
*/ */
class JSDocOptionalParameterTypeExpr extends @jsdoc_optional_type_expr, JSDocTypeExpr { class JSDocOptionalParameterTypeExpr extends @jsdoc_optional_type_expr, JSDocTypeExpr {
/** Gets the underlying type of this optional type. */ /** Gets the underlying type of this optional type. */
JSDocTypeExpr getUnderlyingType() { result = getChild(0) } JSDocTypeExpr getUnderlyingType() { result = this.getChild(0) }
override JSDocTypeExpr getAnUnderlyingType() { override JSDocTypeExpr getAnUnderlyingType() {
result = getUnderlyingType().getAnUnderlyingType() result = this.getUnderlyingType().getAnUnderlyingType()
} }
override DataFlow::ClassNode getClass() { result = getUnderlyingType().getClass() } override DataFlow::ClassNode getClass() { result = this.getUnderlyingType().getClass() }
} }
/** /**
@@ -551,7 +555,7 @@ class JSDocOptionalParameterTypeExpr extends @jsdoc_optional_type_expr, JSDocTyp
*/ */
class JSDocRestParameterTypeExpr extends @jsdoc_rest_type_expr, JSDocTypeExpr { class JSDocRestParameterTypeExpr extends @jsdoc_rest_type_expr, JSDocTypeExpr {
/** Gets the underlying type of this rest parameter type. */ /** Gets the underlying type of this rest parameter type. */
JSDocTypeExpr getUnderlyingType() { result = getChild(0) } JSDocTypeExpr getUnderlyingType() { result = this.getChild(0) }
} }
/** /**
@@ -578,7 +582,7 @@ module JSDoc {
* within this container. * within this container.
*/ */
string resolveAlias(string alias) { string resolveAlias(string alias) {
getNodeFromAlias(alias) = AccessPath::getAReferenceOrAssignmentTo(result) this.getNodeFromAlias(alias) = AccessPath::getAReferenceOrAssignmentTo(result)
} }
/** /**
@@ -614,10 +618,10 @@ module JSDoc {
* alias and is an ancestor of `container`. * alias and is an ancestor of `container`.
*/ */
final predicate isContainerInScope(StmtContainer container) { final predicate isContainerInScope(StmtContainer container) {
exists(resolveAlias(_)) and // restrict size of predicate exists(this.resolveAlias(_)) and // restrict size of predicate
container = this container = this
or or
isContainerInScope(container.getEnclosingContainer()) this.isContainerInScope(container.getEnclosingContainer())
} }
} }

View File

@@ -29,7 +29,7 @@ class JsonValue extends @json_value, Locatable {
JsonValue getChild(int i) { json(result, _, this, i, _) } JsonValue getChild(int i) { json(result, _, this, i, _) }
/** Holds if this JSON value is the top level element in its enclosing file. */ /** Holds if this JSON value is the top level element in its enclosing file. */
predicate isTopLevel() { not exists(getParent()) } predicate isTopLevel() { not exists(this.getParent()) }
override string toString() { json(this, _, _, _, result) } override string toString() { json(this, _, _, _, result) }
@@ -167,7 +167,7 @@ class JsonArray extends @json_array, JsonValue {
override string getAPrimaryQlClass() { result = "JsonArray" } override string getAPrimaryQlClass() { result = "JsonArray" }
/** Gets the string value of the `i`th element of this array. */ /** Gets the string value of the `i`th element of this array. */
string getElementStringValue(int i) { result = getElementValue(i).getStringValue() } string getElementStringValue(int i) { result = this.getElementValue(i).getStringValue() }
} }
/** DEPRECATED: Alias for JsonArray */ /** DEPRECATED: Alias for JsonArray */
@@ -186,7 +186,7 @@ class JsonObject extends @json_object, JsonValue {
override string getAPrimaryQlClass() { result = "JsonObject" } override string getAPrimaryQlClass() { result = "JsonObject" }
/** Gets the string value of property `name` of this object. */ /** Gets the string value of property `name` of this object. */
string getPropStringValue(string name) { result = getPropValue(name).getStringValue() } string getPropStringValue(string name) { result = this.getPropValue(name).getStringValue() }
} }
/** DEPRECATED: Alias for JsonObject */ /** DEPRECATED: Alias for JsonObject */

View File

@@ -17,10 +17,10 @@ import javascript
*/ */
class JsxNode extends Expr, @jsx_element { class JsxNode extends Expr, @jsx_element {
/** Gets the `i`th element in the body of this element or fragment. */ /** Gets the `i`th element in the body of this element or fragment. */
Expr getBodyElement(int i) { i >= 0 and result = getChildExpr(-i - 2) } Expr getBodyElement(int i) { i >= 0 and result = this.getChildExpr(-i - 2) }
/** Gets an element in the body of this element or fragment. */ /** Gets an element in the body of this element or fragment. */
Expr getABodyElement() { result = getBodyElement(_) } Expr getABodyElement() { result = this.getBodyElement(_) }
/** /**
* Gets the parent JSX element or fragment of this element. * Gets the parent JSX element or fragment of this element.
@@ -46,7 +46,7 @@ deprecated class JSXNode = JsxNode;
class JsxElement extends JsxNode { class JsxElement extends JsxNode {
JsxName name; JsxName name;
JsxElement() { name = getChildExpr(-1) } JsxElement() { name = this.getChildExpr(-1) }
/** Gets the expression denoting the name of this element. */ /** Gets the expression denoting the name of this element. */
JsxName getNameExpr() { result = name } JsxName getNameExpr() { result = name }
@@ -58,13 +58,15 @@ class JsxElement extends JsxNode {
JsxAttribute getAttribute(int i) { properties(result, this, i, _, _) } JsxAttribute getAttribute(int i) { properties(result, this, i, _, _) }
/** Gets an attribute of this element. */ /** Gets an attribute of this element. */
JsxAttribute getAnAttribute() { result = getAttribute(_) } JsxAttribute getAnAttribute() { result = this.getAttribute(_) }
/** Gets the attribute of this element with the given name, if any. */ /** Gets the attribute of this element with the given name, if any. */
JsxAttribute getAttributeByName(string n) { result = getAnAttribute() and result.getName() = n } JsxAttribute getAttributeByName(string n) {
result = this.getAnAttribute() and result.getName() = n
}
override ControlFlowNode getFirstControlFlowNode() { override ControlFlowNode getFirstControlFlowNode() {
result = getNameExpr().getFirstControlFlowNode() result = this.getNameExpr().getFirstControlFlowNode()
} }
override string getAPrimaryQlClass() { result = "JsxElement" } override string getAPrimaryQlClass() { result = "JsxElement" }
@@ -73,10 +75,10 @@ class JsxElement extends JsxNode {
* Holds if this JSX element is an HTML element. * Holds if this JSX element is an HTML element.
* That is, the name starts with a lowercase letter. * That is, the name starts with a lowercase letter.
*/ */
predicate isHtmlElement() { getName().regexpMatch("[a-z].*") } predicate isHtmlElement() { this.getName().regexpMatch("[a-z].*") }
/** DEPRECATED: Alias for isHtmlElement */ /** DEPRECATED: Alias for isHtmlElement */
deprecated predicate isHTMLElement() { isHtmlElement() } deprecated predicate isHTMLElement() { this.isHtmlElement() }
} }
/** DEPRECATED: Alias for JsxElement */ /** DEPRECATED: Alias for JsxElement */
@@ -92,12 +94,12 @@ deprecated class JSXElement = JsxElement;
* ``` * ```
*/ */
class JsxFragment extends JsxNode { class JsxFragment extends JsxNode {
JsxFragment() { not exists(getChildExpr(-1)) } JsxFragment() { not exists(this.getChildExpr(-1)) }
override ControlFlowNode getFirstControlFlowNode() { override ControlFlowNode getFirstControlFlowNode() {
result = getBodyElement(0).getFirstControlFlowNode() result = this.getBodyElement(0).getFirstControlFlowNode()
or or
not exists(getABodyElement()) and result = this not exists(this.getABodyElement()) and result = this
} }
override string getAPrimaryQlClass() { result = "JsxFragment" } override string getAPrimaryQlClass() { result = "JsxFragment" }
@@ -123,28 +125,28 @@ class JsxAttribute extends AstNode, @jsx_attribute {
* *
* This is not defined for spread attributes. * This is not defined for spread attributes.
*/ */
JsxName getNameExpr() { result = getChildExpr(0) } JsxName getNameExpr() { result = this.getChildExpr(0) }
/** /**
* Gets the name of this attribute. * Gets the name of this attribute.
* *
* This is not defined for spread attributes. * This is not defined for spread attributes.
*/ */
string getName() { result = getNameExpr().getValue() } string getName() { result = this.getNameExpr().getValue() }
/** Gets the expression denoting the value of this attribute. */ /** Gets the expression denoting the value of this attribute. */
Expr getValue() { result = getChildExpr(1) } Expr getValue() { result = this.getChildExpr(1) }
/** Gets the value of this attribute as a constant string, if possible. */ /** Gets the value of this attribute as a constant string, if possible. */
string getStringValue() { result = getValue().getStringValue() } string getStringValue() { result = this.getValue().getStringValue() }
/** Gets the JSX element to which this attribute belongs. */ /** Gets the JSX element to which this attribute belongs. */
JsxElement getElement() { this = result.getAnAttribute() } JsxElement getElement() { this = result.getAnAttribute() }
override ControlFlowNode getFirstControlFlowNode() { override ControlFlowNode getFirstControlFlowNode() {
result = getNameExpr().getFirstControlFlowNode() result = this.getNameExpr().getFirstControlFlowNode()
or or
not exists(getNameExpr()) and result = getValue().getFirstControlFlowNode() not exists(this.getNameExpr()) and result = this.getValue().getFirstControlFlowNode()
} }
override string toString() { properties(this, _, _, _, result) } override string toString() { properties(this, _, _, _, result) }
@@ -165,7 +167,7 @@ deprecated class JSXAttribute = JsxAttribute;
* ``` * ```
*/ */
class JsxSpreadAttribute extends JsxAttribute { class JsxSpreadAttribute extends JsxAttribute {
JsxSpreadAttribute() { not exists(getNameExpr()) } JsxSpreadAttribute() { not exists(this.getNameExpr()) }
override SpreadElement getValue() { override SpreadElement getValue() {
// override for more precise result type // override for more precise result type
@@ -187,13 +189,13 @@ deprecated class JSXSpreadAttribute = JsxSpreadAttribute;
*/ */
class JsxQualifiedName extends Expr, @jsx_qualified_name { class JsxQualifiedName extends Expr, @jsx_qualified_name {
/** Gets the namespace component of this qualified name. */ /** Gets the namespace component of this qualified name. */
Identifier getNamespace() { result = getChildExpr(0) } Identifier getNamespace() { result = this.getChildExpr(0) }
/** Gets the name component of this qualified name. */ /** Gets the name component of this qualified name. */
Identifier getName() { result = getChildExpr(1) } Identifier getName() { result = this.getChildExpr(1) }
override ControlFlowNode getFirstControlFlowNode() { override ControlFlowNode getFirstControlFlowNode() {
result = getNamespace().getFirstControlFlowNode() result = this.getNamespace().getFirstControlFlowNode()
} }
override string getAPrimaryQlClass() { result = "JsxQualifiedName" } override string getAPrimaryQlClass() { result = "JsxQualifiedName" }
@@ -271,16 +273,16 @@ deprecated class JSXEmptyExpr = JsxEmptyExpr;
* ``` * ```
*/ */
class JsxPragma extends JSDocTag { class JsxPragma extends JSDocTag {
JsxPragma() { getTitle() = "jsx" } JsxPragma() { this.getTitle() = "jsx" }
/** /**
* Gets the DOM name specified by the pragma; for `@jsx React.DOM`, * Gets the DOM name specified by the pragma; for `@jsx React.DOM`,
* the result is `React.DOM`. * the result is `React.DOM`.
*/ */
string getDomName() { result = getDescription().trim() } string getDomName() { result = this.getDescription().trim() }
/** DEPRECATED: Alias for getDomName */ /** DEPRECATED: Alias for getDomName */
deprecated string getDOMName() { result = getDomName() } deprecated string getDOMName() { result = this.getDomName() }
} }
/** DEPRECATED: Alias for JsxPragma */ /** DEPRECATED: Alias for JsxPragma */

View File

@@ -32,7 +32,7 @@ class JsonStringifyCall extends DataFlow::CallNode {
/** /**
* Gets the data flow node holding the input object to be stringified. * Gets the data flow node holding the input object to be stringified.
*/ */
DataFlow::Node getInput() { result = getArgument(0) } DataFlow::Node getInput() { result = this.getArgument(0) }
/** /**
* Gets the data flow node holding the resulting string. * Gets the data flow node holding the resulting string.

View File

@@ -46,7 +46,7 @@ class Line extends @line, Locatable {
* If the line does not start with a whitespace character, or with a mixture of * If the line does not start with a whitespace character, or with a mixture of
* different whitespace characters, its indentation character is undefined. * different whitespace characters, its indentation character is undefined.
*/ */
string getIndentChar() { result = getText().regexpCapture("(\\s)\\1*\\S.*", 1) } string getIndentChar() { result = this.getText().regexpCapture("(\\s)\\1*\\S.*", 1) }
override string toString() { result = getText() } override string toString() { result = this.getText() }
} }

View File

@@ -198,7 +198,7 @@ class MainModulePath extends PathExpr, @json_string {
} }
/** DEPRECATED: Alias for getPackageJson */ /** DEPRECATED: Alias for getPackageJson */
deprecated PackageJSON getPackageJSON() { result = getPackageJson() } deprecated PackageJSON getPackageJSON() { result = this.getPackageJson() }
override string getValue() { result = this.(JsonString).getValue() } override string getValue() { result = this.(JsonString).getValue() }
@@ -259,7 +259,7 @@ private class FilesPath extends PathExpr, @json_string {
PackageJson getPackageJson() { result = pkg } PackageJson getPackageJson() { result = pkg }
/** DEPRECATED: Alias for getPackageJson */ /** DEPRECATED: Alias for getPackageJson */
deprecated PackageJSON getPackageJSON() { result = getPackageJson() } deprecated PackageJSON getPackageJSON() { result = this.getPackageJson() }
override string getValue() { result = this.(JsonString).getValue() } override string getValue() { result = this.(JsonString).getValue() }

View File

@@ -20,7 +20,7 @@ class FirstLineOf extends Locatable {
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
exists(int xl, int xc | exists(int xl, int xc |
getLocation().hasLocationInfo(filepath, startline, startcolumn, xl, xc) and this.getLocation().hasLocationInfo(filepath, startline, startcolumn, xl, xc) and
startline = endline and startline = endline and
if xl = startline if xl = startline
then endcolumn = xc then endcolumn = xc
@@ -49,7 +49,7 @@ class LastLineOf extends Locatable {
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
exists(int xl, int xc | exists(int xl, int xc |
getLocation().hasLocationInfo(filepath, xl, xc, endline, endcolumn) and this.getLocation().hasLocationInfo(filepath, xl, xc, endline, endcolumn) and
startline = endline and startline = endline and
if xl = endline then startcolumn = xc else startcolumn = 1 if xl = endline then startcolumn = xc else startcolumn = 1
) )

View File

@@ -401,16 +401,16 @@ class SsaVariable extends TSsaDefinition {
/** Gets a use in basic block `bb` that refers to this SSA variable. */ /** Gets a use in basic block `bb` that refers to this SSA variable. */
VarUse getAUseIn(ReachableBasicBlock bb) { VarUse getAUseIn(ReachableBasicBlock bb) {
exists(int i, SsaSourceVariable v | v = getSourceVariable() | exists(int i, SsaSourceVariable v | v = this.getSourceVariable() |
bb.useAt(i, v, result) and this = getDefinition(bb, i, v) bb.useAt(i, v, result) and this = getDefinition(bb, i, v)
) )
} }
/** Gets a use that refers to this SSA variable. */ /** Gets a use that refers to this SSA variable. */
VarUse getAUse() { result = getAUseIn(_) } VarUse getAUse() { result = this.getAUseIn(_) }
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
string toString() { result = getDefinition().prettyPrintRef() } string toString() { result = this.getDefinition().prettyPrintRef() }
/** /**
* Holds if this element is at the specified location. * Holds if this element is at the specified location.
@@ -422,7 +422,7 @@ class SsaVariable extends TSsaDefinition {
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getDefinition().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) this.getDefinition().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
} }
} }
@@ -475,7 +475,7 @@ class SsaDefinition extends TSsaDefinition {
abstract string prettyPrintRef(); abstract string prettyPrintRef();
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
string toString() { result = prettyPrintDef() } string toString() { result = this.prettyPrintDef() }
/** /**
* Holds if this element is at the specified location. * Holds if this element is at the specified location.
@@ -489,7 +489,7 @@ class SsaDefinition extends TSsaDefinition {
); );
/** Gets the function or toplevel to which this definition belongs. */ /** Gets the function or toplevel to which this definition belongs. */
StmtContainer getContainer() { result = getBasicBlock().getContainer() } StmtContainer getContainer() { result = this.getBasicBlock().getContainer() }
} }
/** /**
@@ -507,23 +507,23 @@ class SsaExplicitDefinition extends SsaDefinition, TExplicitDef {
VarDef getDef() { this = TExplicitDef(_, _, result, _) } VarDef getDef() { this = TExplicitDef(_, _, result, _) }
/** Gets the basic block to which this definition belongs. */ /** Gets the basic block to which this definition belongs. */
override ReachableBasicBlock getBasicBlock() { definesAt(result, _, _) } override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
override SsaSourceVariable getSourceVariable() { this = TExplicitDef(_, _, _, result) } override SsaSourceVariable getSourceVariable() { this = TExplicitDef(_, _, _, result) }
override VarDef getAContributingVarDef() { result = getDef() } override VarDef getAContributingVarDef() { result = this.getDef() }
override string prettyPrintRef() { override string prettyPrintRef() {
exists(int l, int c | hasLocationInfo(_, l, c, _, _) | result = "def@" + l + ":" + c) exists(int l, int c | this.hasLocationInfo(_, l, c, _, _) | result = "def@" + l + ":" + c)
} }
override string prettyPrintDef() { result = getDef().toString() } override string prettyPrintDef() { result = this.getDef().toString() }
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
exists(Location loc | exists(Location loc |
pragma[only_bind_into](loc) = pragma[only_bind_into](getDef()).getLocation() and pragma[only_bind_into](loc) = pragma[only_bind_into](this.getDef()).getLocation() and
loc.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) loc.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
) )
} }
@@ -549,7 +549,9 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
abstract string getKind(); abstract string getKind();
override string prettyPrintRef() { override string prettyPrintRef() {
exists(int l, int c | hasLocationInfo(_, l, c, _, _) | result = getKind() + "@" + l + ":" + c) exists(int l, int c | this.hasLocationInfo(_, l, c, _, _) |
result = this.getKind() + "@" + l + ":" + c
)
} }
override predicate hasLocationInfo( override predicate hasLocationInfo(
@@ -558,7 +560,7 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
endline = startline and endline = startline and
endcolumn = startcolumn and endcolumn = startcolumn and
exists(Location loc | exists(Location loc |
pragma[only_bind_into](loc) = pragma[only_bind_into](getBasicBlock()).getLocation() and pragma[only_bind_into](loc) = pragma[only_bind_into](this.getBasicBlock()).getLocation() and
loc.hasLocationInfo(filepath, startline, startcolumn, _, _) loc.hasLocationInfo(filepath, startline, startcolumn, _, _)
) )
} }
@@ -570,7 +572,7 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
*/ */
class SsaImplicitInit extends SsaImplicitDefinition, TImplicitInit { class SsaImplicitInit extends SsaImplicitDefinition, TImplicitInit {
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) { override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
bb = getBasicBlock() and v = getSourceVariable() and i = 0 bb = this.getBasicBlock() and v = this.getSourceVariable() and i = 0
} }
override ReachableBasicBlock getBasicBlock() { this = TImplicitInit(result, _) } override ReachableBasicBlock getBasicBlock() { this = TImplicitInit(result, _) }
@@ -581,7 +583,9 @@ class SsaImplicitInit extends SsaImplicitDefinition, TImplicitInit {
override VarDef getAContributingVarDef() { none() } override VarDef getAContributingVarDef() { none() }
override string prettyPrintDef() { result = "implicit initialization of " + getSourceVariable() } override string prettyPrintDef() {
result = "implicit initialization of " + this.getSourceVariable()
}
} }
/** /**
@@ -596,20 +600,20 @@ class SsaVariableCapture extends SsaImplicitDefinition, TCapture {
this = TCapture(bb, i, v) this = TCapture(bb, i, v)
} }
override ReachableBasicBlock getBasicBlock() { definesAt(result, _, _) } override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
override SsaSourceVariable getSourceVariable() { definesAt(_, _, result) } override SsaSourceVariable getSourceVariable() { this.definesAt(_, _, result) }
override VarDef getAContributingVarDef() { result.getAVariable() = getSourceVariable() } override VarDef getAContributingVarDef() { result.getAVariable() = this.getSourceVariable() }
override string getKind() { result = "capture" } override string getKind() { result = "capture" }
override string prettyPrintDef() { result = "capture variable " + getSourceVariable() } override string prettyPrintDef() { result = "capture variable " + this.getSourceVariable() }
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
exists(ReachableBasicBlock bb, int i | definesAt(bb, i, _) | exists(ReachableBasicBlock bb, int i | this.definesAt(bb, i, _) |
bb.getNode(i) bb.getNode(i)
.getLocation() .getLocation()
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -631,14 +635,14 @@ abstract class SsaPseudoDefinition extends SsaImplicitDefinition {
abstract SsaVariable getAnInput(); abstract SsaVariable getAnInput();
override VarDef getAContributingVarDef() { override VarDef getAContributingVarDef() {
result = getAnInput().getDefinition().getAContributingVarDef() result = this.getAnInput().getDefinition().getAContributingVarDef()
} }
/** /**
* Gets a textual representation of the inputs of this pseudo-definition * Gets a textual representation of the inputs of this pseudo-definition
* in lexicographical order. * in lexicographical order.
*/ */
string ppInputs() { result = concat(getAnInput().getDefinition().prettyPrintRef(), ", ") } string ppInputs() { result = concat(this.getAnInput().getDefinition().prettyPrintRef(), ", ") }
} }
/** /**
@@ -652,14 +656,14 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
*/ */
cached cached
SsaVariable getInputFromBlock(BasicBlock bb) { SsaVariable getInputFromBlock(BasicBlock bb) {
bb = getBasicBlock().getAPredecessor() and bb = this.getBasicBlock().getAPredecessor() and
result = getDefReachingEndOf(bb, getSourceVariable()) result = getDefReachingEndOf(bb, this.getSourceVariable())
} }
override SsaVariable getAnInput() { result = getInputFromBlock(_) } override SsaVariable getAnInput() { result = this.getInputFromBlock(_) }
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) { override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
bb = getBasicBlock() and v = getSourceVariable() and i = -1 bb = this.getBasicBlock() and v = this.getSourceVariable() and i = -1
} }
override ReachableBasicBlock getBasicBlock() { this = TPhi(result, _) } override ReachableBasicBlock getBasicBlock() { this = TPhi(result, _) }
@@ -668,14 +672,16 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
override string getKind() { result = "phi" } override string getKind() { result = "phi" }
override string prettyPrintDef() { result = getSourceVariable() + " = phi(" + ppInputs() + ")" } override string prettyPrintDef() {
result = this.getSourceVariable() + " = phi(" + this.ppInputs() + ")"
}
/** /**
* If all inputs to this phi node are (transitive) refinements of the same variable, * If all inputs to this phi node are (transitive) refinements of the same variable,
* gets that variable. * gets that variable.
*/ */
SsaVariable getRephinedVariable() { SsaVariable getRephinedVariable() {
forex(SsaVariable input | input = getAnInput() | result = getRefinedVariable(input)) forex(SsaVariable input | input = this.getAnInput() | result = getRefinedVariable(input))
} }
} }
@@ -706,10 +712,12 @@ class SsaRefinementNode extends SsaPseudoDefinition, TRefinement {
/** /**
* Gets the refinement associated with this definition. * Gets the refinement associated with this definition.
*/ */
Refinement getRefinement() { result = getGuard().getTest() } Refinement getRefinement() { result = this.getGuard().getTest() }
override SsaVariable getAnInput() { override SsaVariable getAnInput() {
exists(SsaSourceVariable v, BasicBlock bb | v = getSourceVariable() and bb = getBasicBlock() | exists(SsaSourceVariable v, BasicBlock bb |
v = this.getSourceVariable() and bb = this.getBasicBlock()
|
if exists(SsaPhiNode phi | phi.definesAt(bb, _, v)) if exists(SsaPhiNode phi | phi.definesAt(bb, _, v))
then result.(SsaPhiNode).definesAt(bb, _, v) then result.(SsaPhiNode).definesAt(bb, _, v)
else result = getDefReachingEndOf(bb.getAPredecessor(), v) else result = getDefReachingEndOf(bb.getAPredecessor(), v)
@@ -724,16 +732,19 @@ class SsaRefinementNode extends SsaPseudoDefinition, TRefinement {
override SsaSourceVariable getSourceVariable() { this = TRefinement(_, _, _, result) } override SsaSourceVariable getSourceVariable() { this = TRefinement(_, _, _, result) }
override string getKind() { result = "refine[" + getGuard() + "]" } override string getKind() { result = "refine[" + this.getGuard() + "]" }
override string prettyPrintDef() { override string prettyPrintDef() {
result = getSourceVariable() + " = refine[" + getGuard() + "](" + ppInputs() + ")" result =
this.getSourceVariable() + " = refine[" + this.getGuard() + "](" + this.ppInputs() + ")"
} }
override predicate hasLocationInfo( override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getGuard().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) this.getGuard()
.getLocation()
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
} }
} }

View File

@@ -25,5 +25,5 @@ class SourceMappingComment extends Comment {
string getSourceMappingUrl() { result = url } string getSourceMappingUrl() { result = url }
/** DEPRECATED: Alias for getSourceMappingUrl */ /** DEPRECATED: Alias for getSourceMappingUrl */
deprecated string getSourceMappingURL() { result = getSourceMappingUrl() } deprecated string getSourceMappingURL() { result = this.getSourceMappingUrl() }
} }

View File

@@ -13,19 +13,19 @@ import javascript
*/ */
class TaggedTemplateExpr extends Expr, @tagged_template_expr { class TaggedTemplateExpr extends Expr, @tagged_template_expr {
/** Gets the tagging expression of this tagged template. */ /** Gets the tagging expression of this tagged template. */
Expr getTag() { result = getChildExpr(0) } Expr getTag() { result = this.getChildExpr(0) }
/** Gets the tagged template itself. */ /** Gets the tagged template itself. */
TemplateLiteral getTemplate() { result = getChildExpr(1) } TemplateLiteral getTemplate() { result = this.getChildExpr(1) }
/** Gets the `i`th type argument to the tag of this template literal. */ /** Gets the `i`th type argument to the tag of this template literal. */
TypeExpr getTypeArgument(int i) { i >= 0 and result = getChildTypeExpr(2 + i) } TypeExpr getTypeArgument(int i) { i >= 0 and result = this.getChildTypeExpr(2 + i) }
/** Gets a type argument of the tag of this template literal. */ /** Gets a type argument of the tag of this template literal. */
TypeExpr getATypeArgument() { result = getTypeArgument(_) } TypeExpr getATypeArgument() { result = this.getTypeArgument(_) }
/** Gets the number of type arguments appearing on the tag of this template literal. */ /** Gets the number of type arguments appearing on the tag of this template literal. */
int getNumTypeArgument() { result = count(getATypeArgument()) } int getNumTypeArgument() { result = count(this.getATypeArgument()) }
override predicate isImpure() { any() } override predicate isImpure() { any() }
@@ -46,19 +46,19 @@ class TemplateLiteral extends Expr, @template_literal {
* Gets the `i`th element of this template literal, which may either * Gets the `i`th element of this template literal, which may either
* be an interpolated expression or a constant template element. * be an interpolated expression or a constant template element.
*/ */
Expr getElement(int i) { result = getChildExpr(i) } Expr getElement(int i) { result = this.getChildExpr(i) }
/** /**
* Gets an element of this template literal. * Gets an element of this template literal.
*/ */
Expr getAnElement() { result = getElement(_) } Expr getAnElement() { result = this.getElement(_) }
/** /**
* Gets the number of elements of this template literal. * Gets the number of elements of this template literal.
*/ */
int getNumElement() { result = count(getAnElement()) } int getNumElement() { result = count(this.getAnElement()) }
override predicate isImpure() { getAnElement().isImpure() } override predicate isImpure() { this.getAnElement().isImpure() }
override string getAPrimaryQlClass() { result = "TemplateLiteral" } override string getAPrimaryQlClass() { result = "TemplateLiteral" }
} }
@@ -80,7 +80,7 @@ class TemplateElement extends Expr, @template_element {
* elements with invalid escape sequences, which only have a raw value but * elements with invalid escape sequences, which only have a raw value but
* no cooked value. * no cooked value.
*/ */
predicate hasValue() { exists(getValue()) } predicate hasValue() { exists(this.getValue()) }
/** /**
* Gets the "cooked" value of this template element, if any. * Gets the "cooked" value of this template element, if any.

View File

@@ -21,31 +21,31 @@ class AbstractProperty extends TAbstractProperty {
* Gets an initial value that is implicitly assigned to this property. * Gets an initial value that is implicitly assigned to this property.
*/ */
AbstractValue getAnInitialValue() { AbstractValue getAnInitialValue() {
result = getAnInitialPropertyValue(getBase(), getPropertyName()) result = getAnInitialPropertyValue(this.getBase(), this.getPropertyName())
} }
/** /**
* Gets a value of this property for the purposes of `AnalyzedNode.getALocalValue`. * Gets a value of this property for the purposes of `AnalyzedNode.getALocalValue`.
*/ */
AbstractValue getALocalValue() { AbstractValue getALocalValue() {
result = getAnInitialPropertyValue(getBase(), getPropertyName()) result = getAnInitialPropertyValue(this.getBase(), this.getPropertyName())
or or
shouldAlwaysTrackProperties(getBase()) and shouldAlwaysTrackProperties(this.getBase()) and
result = getAnAssignedValue(getBase(), getPropertyName()) result = getAnAssignedValue(this.getBase(), this.getPropertyName())
} }
/** /**
* Gets a value of this property for the purposes of `AnalyzedNode.getAValue`. * Gets a value of this property for the purposes of `AnalyzedNode.getAValue`.
*/ */
AbstractValue getAValue() { AbstractValue getAValue() {
result = getALocalValue() or result = this.getALocalValue() or
result = getAnAssignedValue(getBase(), getPropertyName()) result = getAnAssignedValue(this.getBase(), this.getPropertyName())
} }
/** /**
* Gets a textual representation of this element. * Gets a textual representation of this element.
*/ */
string toString() { result = "property " + getPropertyName() + " of " + getBase() } string toString() { result = "property " + this.getPropertyName() + " of " + this.getBase() }
} }
/** /**
@@ -53,7 +53,7 @@ class AbstractProperty extends TAbstractProperty {
* class instance. * class instance.
*/ */
class AbstractProtoProperty extends AbstractProperty { class AbstractProtoProperty extends AbstractProperty {
AbstractProtoProperty() { getPropertyName() = "__proto__" } AbstractProtoProperty() { this.getPropertyName() = "__proto__" }
override AbstractValue getAValue() { override AbstractValue getAValue() {
result = super.getAValue() and result = super.getAValue() and
@@ -62,7 +62,7 @@ class AbstractProtoProperty extends AbstractProperty {
result instanceof AbstractNull result instanceof AbstractNull
) )
or or
exists(AbstractCallable ctor | getBase() = TAbstractInstance(ctor) | exists(AbstractCallable ctor | this.getBase() = TAbstractInstance(ctor) |
// the value of `ctor.prototype` // the value of `ctor.prototype`
exists(AbstractProperty prototype | exists(AbstractProperty prototype |
prototype = MkAbstractProperty(ctor.(AbstractFunction), "prototype") and prototype = MkAbstractProperty(ctor.(AbstractFunction), "prototype") and

View File

@@ -170,7 +170,7 @@ class AbstractBoolean extends PrimitiveAbstractValue, TAbstractBoolean {
override predicate isCoercibleToNumber() { any() } override predicate isCoercibleToNumber() { any() }
override string toString() { result = getBooleanValue().toString() } override string toString() { result = this.getBooleanValue().toString() }
} }
/** /**
@@ -280,7 +280,7 @@ abstract class AbstractCallable extends DefiniteAbstractValue {
class AbstractFunction extends AbstractCallable, TAbstractFunction { class AbstractFunction extends AbstractCallable, TAbstractFunction {
override Function getFunction() { this = TAbstractFunction(result) } override Function getFunction() { this = TAbstractFunction(result) }
override AST::ValueNode getDefinition() { result = getFunction() } override AST::ValueNode getDefinition() { result = this.getFunction() }
override boolean getBooleanValue() { result = true } override boolean getBooleanValue() { result = true }
@@ -293,10 +293,12 @@ class AbstractFunction extends AbstractCallable, TAbstractFunction {
override predicate hasLocationInfo( override predicate hasLocationInfo(
string path, int startline, int startcolumn, int endline, int endcolumn string path, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getFunction().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn) this.getFunction()
.getLocation()
.hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
} }
override string toString() { result = getFunction().describe() } override string toString() { result = this.getFunction().describe() }
} }
/** /**
@@ -308,9 +310,9 @@ class AbstractClass extends AbstractCallable, TAbstractClass {
*/ */
ClassDefinition getClass() { this = TAbstractClass(result) } ClassDefinition getClass() { this = TAbstractClass(result) }
override Function getFunction() { result = getClass().getConstructor().getBody() } override Function getFunction() { result = this.getClass().getConstructor().getBody() }
override AST::ValueNode getDefinition() { result = getClass() } override AST::ValueNode getDefinition() { result = this.getClass() }
override boolean getBooleanValue() { result = true } override boolean getBooleanValue() { result = true }
@@ -323,10 +325,10 @@ class AbstractClass extends AbstractCallable, TAbstractClass {
override predicate hasLocationInfo( override predicate hasLocationInfo(
string path, int startline, int startcolumn, int endline, int endcolumn string path, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getClass().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn) this.getClass().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
} }
override string toString() { result = getClass().describe() } override string toString() { result = this.getClass().describe() }
} }
/** /**
@@ -362,10 +364,12 @@ class AbstractArguments extends DefiniteAbstractValue, TAbstractArguments {
override predicate hasLocationInfo( override predicate hasLocationInfo(
string path, int startline, int startcolumn, int endline, int endcolumn string path, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getFunction().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn) this.getFunction()
.getLocation()
.hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
} }
override string toString() { result = "arguments object of " + getFunction().describe() } override string toString() { result = "arguments object of " + this.getFunction().describe() }
} }
/** /**
@@ -401,10 +405,10 @@ class AbstractModuleObject extends DefiniteAbstractValue, TAbstractModuleObject
override predicate hasLocationInfo( override predicate hasLocationInfo(
string path, int startline, int startcolumn, int endline, int endcolumn string path, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getModule().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn) this.getModule().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
} }
override string toString() { result = "module object of module " + getModule().getName() } override string toString() { result = "module object of module " + this.getModule().getName() }
} }
/** /**
@@ -425,10 +429,10 @@ class AbstractExportsObject extends DefiniteAbstractValue, TAbstractExportsObjec
override predicate hasLocationInfo( override predicate hasLocationInfo(
string path, int startline, int startcolumn, int endline, int endcolumn string path, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getModule().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn) this.getModule().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
} }
override string toString() { result = "exports object of module " + getModule().getName() } override string toString() { result = "exports object of module " + this.getModule().getName() }
} }
/** /**
@@ -450,7 +454,9 @@ class AbstractObjectLiteral extends DefiniteAbstractValue, TAbstractObjectLitera
override predicate hasLocationInfo( override predicate hasLocationInfo(
string path, int startline, int startcolumn, int endline, int endcolumn string path, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getObjectExpr().getLocation().hasLocationInfo(path, startline, startcolumn, endline, endcolumn) this.getObjectExpr()
.getLocation()
.hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
} }
override string toString() { result = "object literal" } override string toString() { result = "object literal" }
@@ -476,10 +482,10 @@ class AbstractInstance extends DefiniteAbstractValue, TAbstractInstance {
override predicate hasLocationInfo( override predicate hasLocationInfo(
string path, int startline, int startcolumn, int endline, int endcolumn string path, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getConstructor().hasLocationInfo(path, startline, startcolumn, endline, endcolumn) this.getConstructor().hasLocationInfo(path, startline, startcolumn, endline, endcolumn)
} }
override string toString() { result = "instance of " + getConstructor() } override string toString() { result = "instance of " + this.getConstructor() }
} }
module AbstractInstance { module AbstractInstance {
@@ -526,7 +532,7 @@ class IndefiniteFunctionOrClass extends AbstractValue, TIndefiniteFunctionOrClas
} }
override string toString() { override string toString() {
exists(DataFlow::Incompleteness cause | isIndefinite(cause) | exists(DataFlow::Incompleteness cause | this.isIndefinite(cause) |
result = "indefinite function or class (" + cause + ")" result = "indefinite function or class (" + cause + ")"
) )
} }
@@ -553,7 +559,7 @@ class IndefiniteObject extends AbstractValue, TIndefiniteObject {
} }
override string toString() { override string toString() {
exists(DataFlow::Incompleteness cause | isIndefinite(cause) | exists(DataFlow::Incompleteness cause | this.isIndefinite(cause) |
result = "indefinite object (" + cause + ")" result = "indefinite object (" + cause + ")"
) )
} }
@@ -576,7 +582,7 @@ class IndefiniteAbstractValue extends AbstractValue, TIndefiniteAbstractValue {
} }
override string toString() { override string toString() {
exists(DataFlow::Incompleteness cause | isIndefinite(cause) | exists(DataFlow::Incompleteness cause | this.isIndefinite(cause) |
result = "indefinite value (" + cause + ")" result = "indefinite value (" + cause + ")"
) )
} }
@@ -589,7 +595,7 @@ class IndefiniteAbstractValue extends AbstractValue, TIndefiniteAbstractValue {
* set of concrete values represented by this abstract value. * set of concrete values represented by this abstract value.
*/ */
AbstractValue split() { AbstractValue split() {
exists(string cause | isIndefinite(cause) | exists(string cause | this.isIndefinite(cause) |
result = TIndefiniteFunctionOrClass(cause) or result = TIndefiniteFunctionOrClass(cause) or
result = TIndefiniteObject(cause) or result = TIndefiniteObject(cause) or
result = abstractValueOfType(any(PrimitiveType pt)) result = abstractValueOfType(any(PrimitiveType pt))

View File

@@ -63,7 +63,7 @@ class LocalObject extends DataFlow::SourceNode {
LocalObject() { LocalObject() {
// pragmatic limitation: object literals only // pragmatic limitation: object literals only
this instanceof DataFlow::ObjectLiteralNode and this instanceof DataFlow::ObjectLiteralNode and
not flowsTo(getAnEscape()) and not this.flowsTo(getAnEscape()) and
not exposedAsReceiver(this) not exposedAsReceiver(this)
} }
@@ -72,16 +72,16 @@ class LocalObject extends DataFlow::SourceNode {
// the property is defined in the initializer, // the property is defined in the initializer,
any(DataFlow::PropWrite write).writes(this, name, _) and any(DataFlow::PropWrite write).writes(this, name, _) and
// and it is never deleted // and it is never deleted
not hasDeleteWithName(name) and not this.hasDeleteWithName(name) and
// and there is no deleted property with computed name // and there is no deleted property with computed name
not hasDeleteWithComputedProperty() not this.hasDeleteWithComputedProperty()
} }
pragma[noinline] pragma[noinline]
private predicate hasDeleteWithName(string name) { private predicate hasDeleteWithName(string name) {
exists(DeleteExpr del, DataFlow::PropRef ref | exists(DeleteExpr del, DataFlow::PropRef ref |
del.getOperand().flow() = ref and del.getOperand().flow() = ref and
flowsTo(ref.getBase()) and this.flowsTo(ref.getBase()) and
ref.getPropertyName() = name ref.getPropertyName() = name
) )
} }
@@ -90,7 +90,7 @@ class LocalObject extends DataFlow::SourceNode {
private predicate hasDeleteWithComputedProperty() { private predicate hasDeleteWithComputedProperty() {
exists(DeleteExpr del, DataFlow::PropRef ref | exists(DeleteExpr del, DataFlow::PropRef ref |
del.getOperand().flow() = ref and del.getOperand().flow() = ref and
flowsTo(ref.getBase()) and this.flowsTo(ref.getBase()) and
not exists(ref.getPropertyName()) not exists(ref.getPropertyName())
) )
} }

View File

@@ -71,7 +71,9 @@ class Refinement extends Expr instanceof RefinementCandidate {
abstract private class LiteralRefinement extends RefinementCandidate, Literal { abstract private class LiteralRefinement extends RefinementCandidate, Literal {
override SsaSourceVariable getARefinedVar() { none() } override SsaSourceVariable getARefinedVar() { none() }
override RefinementValue eval(RefinementContext ctxt) { ctxt.appliesTo(this) and result = eval() } override RefinementValue eval(RefinementContext ctxt) {
ctxt.appliesTo(this) and result = this.eval()
}
/** /**
* Gets the refinement value that represents this literal. * Gets the refinement value that represents this literal.
@@ -87,13 +89,13 @@ private class NullLiteralRefinement extends LiteralRefinement, NullLiteral {
/** A Boolean literal, viewed as a refinement expression. */ /** A Boolean literal, viewed as a refinement expression. */
private class BoolRefinement extends LiteralRefinement, BooleanLiteral { private class BoolRefinement extends LiteralRefinement, BooleanLiteral {
override RefinementValue eval() { override RefinementValue eval() {
exists(boolean b | b.toString() = getValue() | result = TBoolConstant(b)) exists(boolean b | b.toString() = this.getValue() | result = TBoolConstant(b))
} }
} }
/** A constant string, viewed as a refinement expression. */ /** A constant string, viewed as a refinement expression. */
private class StringRefinement extends LiteralRefinement, ConstantString { private class StringRefinement extends LiteralRefinement, ConstantString {
override RefinementValue eval() { result = TStringConstant(getStringValue()) } override RefinementValue eval() { result = TStringConstant(this.getStringValue()) }
} }
/** A numeric literal, viewed as a refinement expression. */ /** A numeric literal, viewed as a refinement expression. */
@@ -108,9 +110,9 @@ abstract private class NumberRefinement extends LiteralRefinement, NumberLiteral
* other integer values. * other integer values.
*/ */
private class IntRefinement extends NumberRefinement, NumberLiteral { private class IntRefinement extends NumberRefinement, NumberLiteral {
IntRefinement() { getValue().toInt() = 0 } IntRefinement() { this.getValue().toInt() = 0 }
override RefinementValue eval() { result = TIntConstant(getValue().toInt()) } override RefinementValue eval() { result = TIntConstant(this.getValue().toInt()) }
} }
/** /**
@@ -129,9 +131,9 @@ private class UndefinedInRefinement extends RefinementCandidate,
/** A variable use, viewed as a refinement expression. */ /** A variable use, viewed as a refinement expression. */
private class VariableRefinement extends RefinementCandidate, VarUse { private class VariableRefinement extends RefinementCandidate, VarUse {
VariableRefinement() { getVariable() instanceof SsaSourceVariable } VariableRefinement() { this.getVariable() instanceof SsaSourceVariable }
override SsaSourceVariable getARefinedVar() { result = getVariable() } override SsaSourceVariable getARefinedVar() { result = this.getVariable() }
override RefinementValue eval(RefinementContext ctxt) { override RefinementValue eval(RefinementContext ctxt) {
ctxt.appliesTo(this) and ctxt.appliesTo(this) and
@@ -141,28 +143,28 @@ private class VariableRefinement extends RefinementCandidate, VarUse {
/** A parenthesized refinement expression. */ /** A parenthesized refinement expression. */
private class ParRefinement extends RefinementCandidate, ParExpr { private class ParRefinement extends RefinementCandidate, ParExpr {
ParRefinement() { getExpression() instanceof RefinementCandidate } ParRefinement() { this.getExpression() instanceof RefinementCandidate }
override SsaSourceVariable getARefinedVar() { override SsaSourceVariable getARefinedVar() {
result = getExpression().(RefinementCandidate).getARefinedVar() result = this.getExpression().(RefinementCandidate).getARefinedVar()
} }
override RefinementValue eval(RefinementContext ctxt) { override RefinementValue eval(RefinementContext ctxt) {
result = getExpression().(RefinementCandidate).eval(ctxt) result = this.getExpression().(RefinementCandidate).eval(ctxt)
} }
} }
/** A `typeof` refinement expression. */ /** A `typeof` refinement expression. */
private class TypeofRefinement extends RefinementCandidate, TypeofExpr { private class TypeofRefinement extends RefinementCandidate, TypeofExpr {
TypeofRefinement() { getOperand() instanceof RefinementCandidate } TypeofRefinement() { this.getOperand() instanceof RefinementCandidate }
override SsaSourceVariable getARefinedVar() { override SsaSourceVariable getARefinedVar() {
result = getOperand().(RefinementCandidate).getARefinedVar() result = this.getOperand().(RefinementCandidate).getARefinedVar()
} }
override RefinementValue eval(RefinementContext ctxt) { override RefinementValue eval(RefinementContext ctxt) {
exists(RefinementValue opVal | exists(RefinementValue opVal |
opVal = getOperand().(RefinementCandidate).eval(ctxt) and opVal = this.getOperand().(RefinementCandidate).eval(ctxt) and
result = TStringConstant(opVal.typeof()) result = TStringConstant(opVal.typeof())
) )
} }
@@ -171,26 +173,26 @@ private class TypeofRefinement extends RefinementCandidate, TypeofExpr {
/** An equality test that can be used as a refinement expression. */ /** An equality test that can be used as a refinement expression. */
private class EqRefinement extends RefinementCandidate, EqualityTest { private class EqRefinement extends RefinementCandidate, EqualityTest {
EqRefinement() { EqRefinement() {
getLeftOperand() instanceof RefinementCandidate and this.getLeftOperand() instanceof RefinementCandidate and
getRightOperand() instanceof RefinementCandidate this.getRightOperand() instanceof RefinementCandidate
} }
override SsaSourceVariable getARefinedVar() { override SsaSourceVariable getARefinedVar() {
result = getLeftOperand().(RefinementCandidate).getARefinedVar() or result = this.getLeftOperand().(RefinementCandidate).getARefinedVar() or
result = getRightOperand().(RefinementCandidate).getARefinedVar() result = this.getRightOperand().(RefinementCandidate).getARefinedVar()
} }
override RefinementValue eval(RefinementContext ctxt) { override RefinementValue eval(RefinementContext ctxt) {
exists(RefinementCandidate l, RefinementValue lv, RefinementCandidate r, RefinementValue rv | exists(RefinementCandidate l, RefinementValue lv, RefinementCandidate r, RefinementValue rv |
l = getLeftOperand() and l = this.getLeftOperand() and
r = getRightOperand() and r = this.getRightOperand() and
lv = l.eval(ctxt) and lv = l.eval(ctxt) and
rv = r.eval(ctxt) rv = r.eval(ctxt)
| |
// if both sides evaluate to a constant, compare them // if both sides evaluate to a constant, compare them
if lv instanceof SingletonRefinementValue and rv instanceof SingletonRefinementValue if lv instanceof SingletonRefinementValue and rv instanceof SingletonRefinementValue
then then
exists(boolean s, boolean p | s = getStrictness() and p = getPolarity() | exists(boolean s, boolean p | s = this.getStrictness() and p = this.getPolarity() |
if lv.(SingletonRefinementValue).equals(rv, s) if lv.(SingletonRefinementValue).equals(rv, s)
then result = TBoolConstant(p) then result = TBoolConstant(p)
else result = TBoolConstant(p.booleanNot()) else result = TBoolConstant(p.booleanNot())
@@ -209,13 +211,13 @@ private class EqRefinement extends RefinementCandidate, EqualityTest {
/** An index expression that can be used as a refinement expression. */ /** An index expression that can be used as a refinement expression. */
private class IndexRefinement extends RefinementCandidate, IndexExpr { private class IndexRefinement extends RefinementCandidate, IndexExpr {
IndexRefinement() { IndexRefinement() {
getBase() instanceof RefinementCandidate and this.getBase() instanceof RefinementCandidate and
getIndex() instanceof RefinementCandidate this.getIndex() instanceof RefinementCandidate
} }
override SsaSourceVariable getARefinedVar() { override SsaSourceVariable getARefinedVar() {
result = getBase().(RefinementCandidate).getARefinedVar() or result = this.getBase().(RefinementCandidate).getARefinedVar() or
result = getIndex().(RefinementCandidate).getARefinedVar() result = this.getIndex().(RefinementCandidate).getARefinedVar()
} }
override RefinementValue eval(RefinementContext ctxt) { override RefinementValue eval(RefinementContext ctxt) {
@@ -223,8 +225,8 @@ private class IndexRefinement extends RefinementCandidate, IndexExpr {
RefinementCandidate base, RefinementValue baseVal, RefinementCandidate index, RefinementCandidate base, RefinementValue baseVal, RefinementCandidate index,
RefinementValue indexVal RefinementValue indexVal
| |
base = getBase() and base = this.getBase() and
index = getIndex() and index = this.getIndex() and
baseVal = base.eval(ctxt) and baseVal = base.eval(ctxt) and
indexVal = index.eval(ctxt) indexVal = index.eval(ctxt)
| |
@@ -424,21 +426,21 @@ private class AnyValue extends RefinementValue, TAny {
private class ValueWithType extends RefinementValue, TValueWithType { private class ValueWithType extends RefinementValue, TValueWithType {
InferredType getType() { this = TValueWithType(result) } InferredType getType() { this = TValueWithType(result) }
override string toString() { result = "any " + getType() } override string toString() { result = "any " + this.getType() }
override string typeof() { result = getType().getTypeofTag() } override string typeof() { result = this.getType().getTypeofTag() }
override boolean getABooleanValue() { override boolean getABooleanValue() {
result = true result = true
or or
// only primitive types can be falsy // only primitive types can be falsy
getType() instanceof PrimitiveType and result = false this.getType() instanceof PrimitiveType and result = false
} }
} }
/** An abstract value representing `null` or `undefined`. */ /** An abstract value representing `null` or `undefined`. */
private class NullOrUndefined extends ValueWithType, SingletonRefinementValue { private class NullOrUndefined extends ValueWithType, SingletonRefinementValue {
NullOrUndefined() { getType() instanceof TTNull or getType() instanceof TTUndefined } NullOrUndefined() { this.getType() instanceof TTNull or this.getType() instanceof TTUndefined }
override boolean getABooleanValue() { result = false } override boolean getABooleanValue() { result = false }
@@ -501,7 +503,7 @@ private class StringConstant extends SingletonRefinementValue, TStringConstant {
or or
isStrict = false and isStrict = false and
( (
isEmptyOrZero() and that = TBoolConstant(false) this.isEmptyOrZero() and that = TBoolConstant(false)
or or
value = "1" and that = TBoolConstant(true) value = "1" and that = TBoolConstant(true)
or or

View File

@@ -49,12 +49,12 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
* Holds if this node flows into `sink` in zero or more local (that is, * Holds if this node flows into `sink` in zero or more local (that is,
* intra-procedural) steps. * intra-procedural) steps.
*/ */
predicate flowsToExpr(Expr sink) { flowsTo(DataFlow::valueNode(sink)) } predicate flowsToExpr(Expr sink) { this.flowsTo(DataFlow::valueNode(sink)) }
/** /**
* Gets a node into which data may flow from this node in zero or more local steps. * Gets a node into which data may flow from this node in zero or more local steps.
*/ */
DataFlow::Node getALocalUse() { flowsTo(result) } DataFlow::Node getALocalUse() { this.flowsTo(result) }
/** /**
* Gets a reference (read or write) of property `propName` on this node. * Gets a reference (read or write) of property `propName` on this node.
@@ -66,13 +66,15 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
/** /**
* Gets a read of property `propName` on this node. * Gets a read of property `propName` on this node.
*/ */
DataFlow::PropRead getAPropertyRead(string propName) { result = getAPropertyReference(propName) } DataFlow::PropRead getAPropertyRead(string propName) {
result = this.getAPropertyReference(propName)
}
/** /**
* Gets a write of property `propName` on this node. * Gets a write of property `propName` on this node.
*/ */
DataFlow::PropWrite getAPropertyWrite(string propName) { DataFlow::PropWrite getAPropertyWrite(string propName) {
result = getAPropertyReference(propName) result = this.getAPropertyReference(propName)
} }
/** /**
@@ -81,7 +83,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
*/ */
pragma[nomagic] pragma[nomagic]
predicate hasPropertyWrite(string propName, DataFlow::Node rhs) { predicate hasPropertyWrite(string propName, DataFlow::Node rhs) {
rhs = getAPropertyWrite(propName).getRhs() rhs = this.getAPropertyWrite(propName).getRhs()
} }
/** /**
@@ -96,18 +98,18 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
/** /**
* Gets a read of any property on this node. * Gets a read of any property on this node.
*/ */
DataFlow::PropRead getAPropertyRead() { result = getAPropertyReference() } DataFlow::PropRead getAPropertyRead() { result = this.getAPropertyReference() }
/** /**
* Gets a write of any property on this node. * Gets a write of any property on this node.
*/ */
DataFlow::PropWrite getAPropertyWrite() { result = getAPropertyReference() } DataFlow::PropWrite getAPropertyWrite() { result = this.getAPropertyReference() }
/** /**
* Gets an invocation of the method or constructor named `memberName` on this node. * Gets an invocation of the method or constructor named `memberName` on this node.
*/ */
DataFlow::InvokeNode getAMemberInvocation(string memberName) { DataFlow::InvokeNode getAMemberInvocation(string memberName) {
result = getAPropertyRead(memberName).getAnInvocation() result = this.getAPropertyRead(memberName).getAnInvocation()
} }
/** /**
@@ -117,7 +119,9 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
* (as in `o.m(...)`), and calls where the callee undergoes some additional * (as in `o.m(...)`), and calls where the callee undergoes some additional
* data flow (as in `tmp = o.m; tmp(...)`). * data flow (as in `tmp = o.m; tmp(...)`).
*/ */
DataFlow::CallNode getAMemberCall(string memberName) { result = getAMemberInvocation(memberName) } DataFlow::CallNode getAMemberCall(string memberName) {
result = this.getAMemberInvocation(memberName)
}
/** /**
* Gets a method call that invokes method `methodName` on this node. * Gets a method call that invokes method `methodName` on this node.
@@ -126,7 +130,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
* that is, `o.m(...)` or `o[p](...)`. * that is, `o.m(...)` or `o[p](...)`.
*/ */
DataFlow::CallNode getAMethodCall(string methodName) { DataFlow::CallNode getAMethodCall(string methodName) {
result = getAMemberInvocation(methodName) and result = this.getAMemberInvocation(methodName) and
Cached::isSyntacticMethodCall(result) Cached::isSyntacticMethodCall(result)
} }
@@ -136,7 +140,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
* This includes only calls that have the syntactic shape of a method call, * This includes only calls that have the syntactic shape of a method call,
* that is, `o.m(...)` or `o[p](...)`. * that is, `o.m(...)` or `o[p](...)`.
*/ */
DataFlow::CallNode getAMethodCall() { result = getAMethodCall(_) } DataFlow::CallNode getAMethodCall() { result = this.getAMethodCall(_) }
/** /**
* Gets a chained method call that invokes `methodName` last. * Gets a chained method call that invokes `methodName` last.
@@ -146,14 +150,14 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
*/ */
DataFlow::CallNode getAChainedMethodCall(string methodName) { DataFlow::CallNode getAChainedMethodCall(string methodName) {
// the direct call to `getAMethodCall` is needed in case the base is not a `DataFlow::CallNode`. // the direct call to `getAMethodCall` is needed in case the base is not a `DataFlow::CallNode`.
result = [getAMethodCall+().getAMethodCall(methodName), getAMethodCall(methodName)] result = [this.getAMethodCall+().getAMethodCall(methodName), this.getAMethodCall(methodName)]
} }
/** /**
* Gets a `new` call that invokes constructor `constructorName` on this node. * Gets a `new` call that invokes constructor `constructorName` on this node.
*/ */
DataFlow::NewNode getAConstructorInvocation(string constructorName) { DataFlow::NewNode getAConstructorInvocation(string constructorName) {
result = getAMemberInvocation(constructorName) result = this.getAMemberInvocation(constructorName)
} }
/** /**
@@ -164,24 +168,24 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range {
/** /**
* Gets a function call to this node. * Gets a function call to this node.
*/ */
DataFlow::CallNode getACall() { result = getAnInvocation() } DataFlow::CallNode getACall() { result = this.getAnInvocation() }
/** /**
* Gets a `new` call to this node. * Gets a `new` call to this node.
*/ */
DataFlow::NewNode getAnInstantiation() { result = getAnInvocation() } DataFlow::NewNode getAnInstantiation() { result = this.getAnInvocation() }
/** /**
* Gets a source node whose value is stored in property `prop` of this node. * Gets a source node whose value is stored in property `prop` of this node.
*/ */
DataFlow::SourceNode getAPropertySource(string prop) { DataFlow::SourceNode getAPropertySource(string prop) {
result.flowsTo(getAPropertyWrite(prop).getRhs()) result.flowsTo(this.getAPropertyWrite(prop).getRhs())
} }
/** /**
* Gets a source node whose value is stored in a property of this node. * Gets a source node whose value is stored in a property of this node.
*/ */
DataFlow::SourceNode getAPropertySource() { result.flowsTo(getAPropertyWrite().getRhs()) } DataFlow::SourceNode getAPropertySource() { result.flowsTo(this.getAPropertyWrite().getRhs()) }
/** /**
* Gets a node that this node may flow to using one heap and/or interprocedural step. * Gets a node that this node may flow to using one heap and/or interprocedural step.

View File

@@ -45,7 +45,7 @@ class AnalyzedNode extends DataFlow::Node {
* Gets another data flow node whose value flows into this node in one local step * Gets another data flow node whose value flows into this node in one local step
* (that is, not involving global variables). * (that is, not involving global variables).
*/ */
AnalyzedNode localFlowPred() { result = getAPredecessor() } AnalyzedNode localFlowPred() { result = this.getAPredecessor() }
/** /**
* Gets an abstract value that this node may evaluate to at runtime. * Gets an abstract value that this node may evaluate to at runtime.
@@ -57,7 +57,7 @@ class AnalyzedNode extends DataFlow::Node {
* instances is also performed. * instances is also performed.
*/ */
cached cached
AbstractValue getAValue() { result = getALocalValue() } AbstractValue getAValue() { result = this.getALocalValue() }
/** /**
* INTERNAL: Do not use. * INTERNAL: Do not use.
@@ -76,31 +76,31 @@ class AnalyzedNode extends DataFlow::Node {
// feed back the results from the (value) flow analysis into // feed back the results from the (value) flow analysis into
// the control flow analysis, so all flow predecessors are // the control flow analysis, so all flow predecessors are
// considered as sources // considered as sources
result = localFlowPred().getALocalValue() result = this.localFlowPred().getALocalValue()
or or
// model flow that isn't captured by the data flow graph // model flow that isn't captured by the data flow graph
exists(DataFlow::Incompleteness cause | exists(DataFlow::Incompleteness cause |
isIncomplete(cause) and result = TIndefiniteAbstractValue(cause) this.isIncomplete(cause) and result = TIndefiniteAbstractValue(cause)
) )
} }
/** Gets a type inferred for this node. */ /** Gets a type inferred for this node. */
cached cached
InferredType getAType() { result = getAValue().getType() } InferredType getAType() { result = this.getAValue().getType() }
/** /**
* Gets a primitive type to which the value of this node can be coerced. * Gets a primitive type to which the value of this node can be coerced.
*/ */
PrimitiveType getAPrimitiveType() { result = getAValue().toPrimitive().getType() } PrimitiveType getAPrimitiveType() { result = this.getAValue().toPrimitive().getType() }
/** Gets a Boolean value that this node evaluates to. */ /** Gets a Boolean value that this node evaluates to. */
boolean getABooleanValue() { result = getAValue().getBooleanValue() } boolean getABooleanValue() { result = this.getAValue().getBooleanValue() }
/** Gets the unique Boolean value that this node evaluates to, if any. */ /** Gets the unique Boolean value that this node evaluates to, if any. */
boolean getTheBooleanValue() { forex(boolean bv | bv = getABooleanValue() | result = bv) } boolean getTheBooleanValue() { forex(boolean bv | bv = this.getABooleanValue() | result = bv) }
/** Gets the unique type inferred for this node, if any. */ /** Gets the unique type inferred for this node, if any. */
InferredType getTheType() { result = unique(InferredType t | t = getAType()) } InferredType getTheType() { result = unique(InferredType t | t = this.getAType()) }
/** /**
* Gets a pretty-printed representation of all types inferred for this node * Gets a pretty-printed representation of all types inferred for this node
@@ -110,19 +110,19 @@ class AnalyzedNode extends DataFlow::Node {
* particular addition) may have more than one inferred type. * particular addition) may have more than one inferred type.
*/ */
string ppTypes() { string ppTypes() {
exists(int n | n = getNumTypes() | exists(int n | n = this.getNumTypes() |
// inferred no types // inferred no types
n = 0 and result = "" n = 0 and result = ""
or or
// inferred a single type // inferred a single type
n = 1 and result = getAType().toString() n = 1 and result = this.getAType().toString()
or or
// inferred all types // inferred all types
n = count(InferredType it) and result = ppAllTypeTags() n = count(InferredType it) and result = ppAllTypeTags()
or or
// the general case: more than one type, but not all types // the general case: more than one type, but not all types
// first pretty-print as a comma separated list, then replace last comma by "or" // first pretty-print as a comma separated list, then replace last comma by "or"
result = (getType(1) + ", " + ppTypes(2)).regexpReplaceAll(", ([^,]++)$", " or $1") result = (this.getType(1) + ", " + this.ppTypes(2)).regexpReplaceAll(", ([^,]++)$", " or $1")
) )
} }
@@ -133,12 +133,12 @@ class AnalyzedNode extends DataFlow::Node {
* and one less than the total number of types. * and one less than the total number of types.
*/ */
private string getType(int i) { private string getType(int i) {
getNumTypes() in [2 .. count(InferredType it) - 1] and this.getNumTypes() in [2 .. count(InferredType it) - 1] and
result = rank[i](InferredType tp | tp = getAType() | tp.toString()) result = rank[i](InferredType tp | tp = this.getAType() | tp.toString())
} }
/** Gets the number of types inferred for this node. */ /** Gets the number of types inferred for this node. */
private int getNumTypes() { result = count(getAType()) } private int getNumTypes() { result = count(this.getAType()) }
/** /**
* Gets a pretty-printed comma-separated list of all types inferred for this node, * Gets a pretty-printed comma-separated list of all types inferred for this node,
@@ -147,15 +147,15 @@ class AnalyzedNode extends DataFlow::Node {
* the all-types case are handled specially above. * the all-types case are handled specially above.
*/ */
private string ppTypes(int i) { private string ppTypes(int i) {
exists(int n | n = getNumTypes() and n in [2 .. count(InferredType it) - 1] | exists(int n | n = this.getNumTypes() and n in [2 .. count(InferredType it) - 1] |
i = n and result = getType(i) i = n and result = this.getType(i)
or or
i in [2 .. n - 1] and result = getType(i) + ", " + ppTypes(i + 1) i in [2 .. n - 1] and result = this.getType(i) + ", " + this.ppTypes(i + 1)
) )
} }
/** Holds if the flow analysis can infer at least one abstract value for this node. */ /** Holds if the flow analysis can infer at least one abstract value for this node. */
predicate hasFlow() { exists(getAValue()) } predicate hasFlow() { exists(this.getAValue()) }
/** /**
* INTERNAL. Use `isIncomplete()` instead. * INTERNAL. Use `isIncomplete()` instead.
@@ -194,7 +194,7 @@ class AnalyzedModule extends TopLevel instanceof Module {
* property. * property.
*/ */
AbstractProperty getExportsProperty() { AbstractProperty getExportsProperty() {
result.getBase() = getModuleObject() and result.getBase() = this.getModuleObject() and
result.getPropertyName() = "exports" result.getPropertyName() = "exports"
} }
@@ -202,14 +202,14 @@ class AnalyzedModule extends TopLevel instanceof Module {
* Gets an abstract value inferred for this module's `module.exports` * Gets an abstract value inferred for this module's `module.exports`
* property. * property.
*/ */
AbstractValue getAnExportsValue() { result = getExportsProperty().getAValue() } AbstractValue getAnExportsValue() { result = this.getExportsProperty().getAValue() }
/** /**
* Gets an abstract value representing a value exported by this module * Gets an abstract value representing a value exported by this module
* under the given `name`. * under the given `name`.
*/ */
AbstractValue getAnExportedValue(string name) { AbstractValue getAnExportedValue(string name) {
exists(AbstractValue exports | exports = getAnExportsValue() | exists(AbstractValue exports | exports = this.getAnExportsValue() |
// CommonJS modules export `module.exports` as their `default` // CommonJS modules export `module.exports` as their `default`
// export in an ES2015 setting // export in an ES2015 setting
not this instanceof ES2015Module and not this instanceof ES2015Module and
@@ -243,7 +243,7 @@ class AnalyzedFunction extends DataFlow::AnalyzedValueNode {
// implicit return value // implicit return value
( (
// either because execution of the function may terminate normally // either because execution of the function may terminate normally
mayReturnImplicitly() this.mayReturnImplicitly()
or or
// or because there is a bare `return;` statement // or because there is a bare `return;` statement
exists(ReturnStmt ret | ret = astNode.getAReturnStmt() | not exists(ret.getExpr())) exists(ReturnStmt ret | ret = astNode.getAReturnStmt() | not exists(ret.getExpr()))

View File

@@ -120,7 +120,7 @@ class AccessPath extends TAccessPath {
/** /**
* Gets an expression represented by this access path. * Gets an expression represented by this access path.
*/ */
Expr getAnInstance() { result = getAnInstanceIn(_) } Expr getAnInstance() { result = this.getAnInstanceIn(_) }
/** /**
* Gets a textual representation of this access path. * Gets a textual representation of this access path.

View File

@@ -24,21 +24,21 @@ class AnalyzedParameter extends AnalyzedValueNode {
override AbstractValue getALocalValue() { override AbstractValue getALocalValue() {
exists(DataFlow::AnalyzedNode pred | exists(DataFlow::AnalyzedNode pred |
getFunction().argumentPassing(astNode, pred.asExpr()) and this.getFunction().argumentPassing(astNode, pred.asExpr()) and
result = pred.getALocalValue() result = pred.getALocalValue()
) )
or or
not getFunction().mayReceiveArgument(astNode) and not this.getFunction().mayReceiveArgument(astNode) and
result = TAbstractUndefined() result = TAbstractUndefined()
or or
result = astNode.getDefault().analyze().getALocalValue() result = astNode.getDefault().analyze().getALocalValue()
} }
override predicate hasAdditionalIncompleteness(DataFlow::Incompleteness cause) { override predicate hasAdditionalIncompleteness(DataFlow::Incompleteness cause) {
getFunction().isIncomplete(cause) this.getFunction().isIncomplete(cause)
or or
not getFunction().argumentPassing(astNode, _) and not this.getFunction().argumentPassing(astNode, _) and
getFunction().mayReceiveArgument(astNode) and this.getFunction().mayReceiveArgument(astNode) and
cause = "call" cause = "call"
} }
} }

View File

@@ -104,9 +104,9 @@ private class AnalyzedNamespaceDeclaration extends DataFlow::AnalyzedValueNode {
override NamespaceDeclaration astNode; override NamespaceDeclaration astNode;
override AbstractValue getALocalValue() { override AbstractValue getALocalValue() {
result = TAbstractOtherObject() and getPreviousValue().getBooleanValue() = false result = TAbstractOtherObject() and this.getPreviousValue().getBooleanValue() = false
or or
result = getPreviousValue() and result.getBooleanValue() = true result = this.getPreviousValue() and result.getBooleanValue() = true
} }
AbstractValue getPreviousValue() { AbstractValue getPreviousValue() {
@@ -161,7 +161,7 @@ private class AnalyzedSuperCall extends DataFlow::AnalyzedValueNode {
override AbstractValue getALocalValue() { override AbstractValue getALocalValue() {
exists(MethodDefinition md, DataFlow::AnalyzedNode sup, AbstractValue supVal | exists(MethodDefinition md, DataFlow::AnalyzedNode sup, AbstractValue supVal |
md.getBody() = asExpr().getEnclosingFunction() and md.getBody() = this.asExpr().getEnclosingFunction() and
sup = md.getDeclaringClass().getSuperClass().analyze() and sup = md.getDeclaringClass().getSuperClass().analyze() and
supVal = sup.getALocalValue() supVal = sup.getALocalValue()
| |
@@ -183,7 +183,7 @@ private class AnalyzedNewExpr extends DataFlow::AnalyzedValueNode {
override NewExpr astNode; override NewExpr astNode;
override AbstractValue getALocalValue() { override AbstractValue getALocalValue() {
isIndefinite() and this.isIndefinite() and
( (
result = TIndefiniteFunctionOrClass("call") or result = TIndefiniteFunctionOrClass("call") or
result = TIndefiniteObject("call") result = TIndefiniteObject("call")

View File

@@ -426,7 +426,7 @@ private class AnalyzedExportNamespaceSpecifier extends AnalyzedPropertyWrite, Da
} }
override predicate writesValue(AbstractValue baseVal, string propName, AbstractValue value) { override predicate writesValue(AbstractValue baseVal, string propName, AbstractValue value) {
baseVal = TAbstractExportsObject(getTopLevel()) and baseVal = TAbstractExportsObject(this.getTopLevel()) and
propName = astNode.getExportedName() and propName = astNode.getExportedName() and
value = TAbstractExportsObject(decl.getReExportedModule()) value = TAbstractExportsObject(decl.getReExportedModule())
} }

View File

@@ -14,7 +14,7 @@ private import semmle.javascript.dataflow.LocalObjects
abstract private class AnalyzedThisExpr extends DataFlow::AnalyzedNode, DataFlow::ThisNode { abstract private class AnalyzedThisExpr extends DataFlow::AnalyzedNode, DataFlow::ThisNode {
DataFlow::FunctionNode binder; DataFlow::FunctionNode binder;
AnalyzedThisExpr() { binder = getBinder() } AnalyzedThisExpr() { binder = this.getBinder() }
} }
/** /**
@@ -53,7 +53,7 @@ private class AnalyzedThisInBoundFunction extends AnalyzedThisExpr {
private class AnalyzedThisAsModuleExports extends DataFlow::AnalyzedNode, DataFlow::ThisNode { private class AnalyzedThisAsModuleExports extends DataFlow::AnalyzedNode, DataFlow::ThisNode {
NodeModule m; NodeModule m;
AnalyzedThisAsModuleExports() { m = getBindingContainer() } AnalyzedThisAsModuleExports() { m = this.getBindingContainer() }
override AbstractValue getALocalValue() { result = TAbstractExportsObject(m) } override AbstractValue getALocalValue() { result = TAbstractExportsObject(m) }
} }
@@ -143,7 +143,7 @@ abstract class CallWithAnalyzedReturnFlow extends DataFlow::AnalyzedValueNode {
abstract AnalyzedFunction getACallee(); abstract AnalyzedFunction getACallee();
override AbstractValue getALocalValue() { override AbstractValue getALocalValue() {
result = getACallee().getAReturnValue() and result = this.getACallee().getAReturnValue() and
not this instanceof DataFlow::NewNode not this instanceof DataFlow::NewNode
} }
} }
@@ -160,7 +160,7 @@ abstract class CallWithNonLocalAnalyzedReturnFlow extends DataFlow::AnalyzedValu
abstract AnalyzedFunction getACallee(); abstract AnalyzedFunction getACallee();
override AbstractValue getAValue() { override AbstractValue getAValue() {
result = getACallee().getAReturnValue() result = this.getACallee().getAReturnValue()
or or
// special case from the local layer (could be more precise if it is inferred that the callee is not `null`/`undefined`) // special case from the local layer (could be more precise if it is inferred that the callee is not `null`/`undefined`)
astNode instanceof OptionalChainRoot and astNode instanceof OptionalChainRoot and
@@ -213,7 +213,7 @@ class LocalFunction extends Function {
) and ) and
// if the function is non-strict and its `arguments` object is accessed, we // if the function is non-strict and its `arguments` object is accessed, we
// also assume that there may be other calls (through `arguments.callee`) // also assume that there may be other calls (through `arguments.callee`)
(isStrict() or not usesArgumentsObject()) (this.isStrict() or not this.usesArgumentsObject())
} }
/** Gets an invocation of this function. */ /** Gets an invocation of this function. */
@@ -307,7 +307,7 @@ private class AnalyzedThisInPartialInvokeCallback extends AnalyzedNode, DataFlow
AnalyzedThisInPartialInvokeCallback() { AnalyzedThisInPartialInvokeCallback() {
exists(DataFlow::Node callbackArg | exists(DataFlow::Node callbackArg |
receiver = any(DataFlow::PartialInvokeNode call).getBoundReceiver(callbackArg) and receiver = any(DataFlow::PartialInvokeNode call).getBoundReceiver(callbackArg) and
getBinder().flowsTo(callbackArg) this.getBinder().flowsTo(callbackArg)
) )
} }

View File

@@ -22,12 +22,12 @@ abstract class AnalyzedPropertyRead extends DataFlow::AnalyzedNode {
abstract predicate reads(AbstractValue base, string propName); abstract predicate reads(AbstractValue base, string propName);
override AbstractValue getAValue() { override AbstractValue getAValue() {
result = getASourceProperty().getAValue() or result = this.getASourceProperty().getAValue() or
result = DataFlow::AnalyzedNode.super.getAValue() result = DataFlow::AnalyzedNode.super.getAValue()
} }
override AbstractValue getALocalValue() { override AbstractValue getALocalValue() {
result = getASourceProperty().getALocalValue() or result = this.getASourceProperty().getALocalValue() or
result = DataFlow::AnalyzedNode.super.getALocalValue() result = DataFlow::AnalyzedNode.super.getALocalValue()
} }
@@ -37,7 +37,7 @@ abstract class AnalyzedPropertyRead extends DataFlow::AnalyzedNode {
*/ */
pragma[noinline] pragma[noinline]
private AbstractProperty getASourceProperty() { private AbstractProperty getASourceProperty() {
exists(AbstractValue base, string prop | reads(base, prop) | exists(AbstractValue base, string prop | this.reads(base, prop) |
result = MkAbstractProperty(base, prop) result = MkAbstractProperty(base, prop)
) )
} }
@@ -45,7 +45,7 @@ abstract class AnalyzedPropertyRead extends DataFlow::AnalyzedNode {
override predicate isIncomplete(DataFlow::Incompleteness cause) { override predicate isIncomplete(DataFlow::Incompleteness cause) {
super.isIncomplete(cause) super.isIncomplete(cause)
or or
exists(AbstractValue base | reads(base, _) | base.isIndefinite(cause)) exists(AbstractValue base | this.reads(base, _) | base.isIndefinite(cause))
} }
} }
@@ -105,7 +105,7 @@ abstract class AnalyzedPropertyWrite extends DataFlow::Node {
*/ */
predicate writesValue(AbstractValue baseVal, string propName, AbstractValue val) { predicate writesValue(AbstractValue baseVal, string propName, AbstractValue val) {
exists(AnalyzedNode source | exists(AnalyzedNode source |
writes(baseVal, propName, source) and this.writes(baseVal, propName, source) and
val = source.getALocalValue() val = source.getALocalValue()
) )
} }
@@ -151,7 +151,7 @@ private class AnalyzedArgumentsCallee extends AnalyzedNonNumericPropertyRead {
AnalyzedArgumentsCallee() { propName = "callee" } AnalyzedArgumentsCallee() { propName = "callee" }
override AbstractValue getALocalValue() { override AbstractValue getALocalValue() {
exists(AbstractArguments baseVal | reads(baseVal, _) | exists(AbstractArguments baseVal | this.reads(baseVal, _) |
result = TAbstractFunction(baseVal.getFunction()) result = TAbstractFunction(baseVal.getFunction())
) )
or or

View File

@@ -20,7 +20,7 @@ private class AnalyzedCapturedVariable extends @variable {
* Gets an abstract value that may be assigned to this variable. * Gets an abstract value that may be assigned to this variable.
*/ */
pragma[nomagic] pragma[nomagic]
AbstractValue getALocalValue() { result = getADef().getAnAssignedValue() } AbstractValue getALocalValue() { result = this.getADef().getAnAssignedValue() }
/** /**
* Gets a definition of this variable. * Gets a definition of this variable.
@@ -44,7 +44,7 @@ private class AnalyzedSsaDefinitionNode extends AnalyzedNode, DataFlow::SsaDefin
private class SsaDefinitionWithNonLocalFlow extends SsaExplicitDefinition { private class SsaDefinitionWithNonLocalFlow extends SsaExplicitDefinition {
CallWithNonLocalAnalyzedReturnFlow source; CallWithNonLocalAnalyzedReturnFlow source;
SsaDefinitionWithNonLocalFlow() { source = getDef().getSource().flow() } SsaDefinitionWithNonLocalFlow() { source = this.getDef().getSource().flow() }
CallWithNonLocalAnalyzedReturnFlow getSource() { result = source } CallWithNonLocalAnalyzedReturnFlow getSource() { result = source }
} }
@@ -84,10 +84,10 @@ class AnalyzedVarDef extends VarDef {
* cannot be analyzed completely. * cannot be analyzed completely.
*/ */
AbstractValue getAnAssignedValue() { AbstractValue getAnAssignedValue() {
result = getAnRhsValue() result = this.getAnRhsValue()
or or
exists(DataFlow::Incompleteness cause | exists(DataFlow::Incompleteness cause |
isIncomplete(cause) and result = TIndefiniteAbstractValue(cause) this.isIncomplete(cause) and result = TIndefiniteAbstractValue(cause)
) )
} }
@@ -96,7 +96,7 @@ class AnalyzedVarDef extends VarDef {
* may evaluate to. * may evaluate to.
*/ */
AbstractValue getAnRhsValue() { AbstractValue getAnRhsValue() {
result = getRhs().getALocalValue() result = this.getRhs().getALocalValue()
or or
this = any(ForInStmt fis).getIteratorExpr() and result = abstractValueOfType(TTString()) this = any(ForInStmt fis).getIteratorExpr() and result = abstractValueOfType(TTString())
or or
@@ -109,7 +109,7 @@ class AnalyzedVarDef extends VarDef {
* this `VarDef`. * this `VarDef`.
*/ */
DataFlow::AnalyzedNode getRhs() { DataFlow::AnalyzedNode getRhs() {
result = getSource().analyze() and getTarget() instanceof VarRef result = this.getSource().analyze() and this.getTarget() instanceof VarRef
or or
result.asExpr() = this.(CompoundAssignExpr) result.asExpr() = this.(CompoundAssignExpr)
or or
@@ -132,7 +132,7 @@ class AnalyzedVarDef extends VarDef {
or or
exists(ComprehensionBlock cb | this = cb.getIterator()) and cause = "yield" exists(ComprehensionBlock cb | this = cb.getIterator()) and cause = "yield"
or or
getTarget() instanceof DestructuringPattern and cause = "heap" this.getTarget() instanceof DestructuringPattern and cause = "heap"
} }
/** /**
@@ -197,9 +197,9 @@ abstract class AnalyzedSsaDefinition extends SsaDefinition {
*/ */
private class AnalyzedExplicitDefinition extends AnalyzedSsaDefinition, SsaExplicitDefinition { private class AnalyzedExplicitDefinition extends AnalyzedSsaDefinition, SsaExplicitDefinition {
override AbstractValue getAnRhsValue() { override AbstractValue getAnRhsValue() {
result = getDef().(AnalyzedVarDef).getAnAssignedValue() result = this.getDef().(AnalyzedVarDef).getAnAssignedValue()
or or
result = getRhsNode().analyze().getALocalValue() result = this.getRhsNode().analyze().getALocalValue()
} }
} }
@@ -207,7 +207,7 @@ private class AnalyzedExplicitDefinition extends AnalyzedSsaDefinition, SsaExpli
* Flow analysis for SSA definitions corresponding to implicit variable initialization. * Flow analysis for SSA definitions corresponding to implicit variable initialization.
*/ */
private class AnalyzedImplicitInit extends AnalyzedSsaDefinition, SsaImplicitInit { private class AnalyzedImplicitInit extends AnalyzedSsaDefinition, SsaImplicitInit {
override AbstractValue getAnRhsValue() { result = getImplicitInitValue(getSourceVariable()) } override AbstractValue getAnRhsValue() { result = getImplicitInitValue(this.getSourceVariable()) }
} }
/** /**
@@ -215,7 +215,7 @@ private class AnalyzedImplicitInit extends AnalyzedSsaDefinition, SsaImplicitIni
*/ */
private class AnalyzedVariableCapture extends AnalyzedSsaDefinition, SsaVariableCapture { private class AnalyzedVariableCapture extends AnalyzedSsaDefinition, SsaVariableCapture {
override AbstractValue getAnRhsValue() { override AbstractValue getAnRhsValue() {
exists(LocalVariable v | v = getSourceVariable() | exists(LocalVariable v | v = this.getSourceVariable() |
result = v.(AnalyzedCapturedVariable).getALocalValue() result = v.(AnalyzedCapturedVariable).getALocalValue()
or or
result = any(AnalyzedExplicitDefinition def | def.getSourceVariable() = v).getAnRhsValue() result = any(AnalyzedExplicitDefinition def | def.getSourceVariable() = v).getAnRhsValue()
@@ -230,7 +230,7 @@ private class AnalyzedVariableCapture extends AnalyzedSsaDefinition, SsaVariable
*/ */
private class AnalyzedPhiNode extends AnalyzedSsaDefinition, SsaPhiNode { private class AnalyzedPhiNode extends AnalyzedSsaDefinition, SsaPhiNode {
override AbstractValue getAnRhsValue() { override AbstractValue getAnRhsValue() {
result = getAnInput().(AnalyzedSsaDefinition).getAnRhsValue() result = this.getAnInput().(AnalyzedSsaDefinition).getAnRhsValue()
} }
} }
@@ -240,14 +240,14 @@ private class AnalyzedPhiNode extends AnalyzedSsaDefinition, SsaPhiNode {
class AnalyzedRefinement extends AnalyzedSsaDefinition, SsaRefinementNode { class AnalyzedRefinement extends AnalyzedSsaDefinition, SsaRefinementNode {
override AbstractValue getAnRhsValue() { override AbstractValue getAnRhsValue() {
// default implementation: don't refine // default implementation: don't refine
result = getAnInputRhsValue() result = this.getAnInputRhsValue()
} }
/** /**
* Gets an abstract value that one of the inputs of this refinement may evaluate to. * Gets an abstract value that one of the inputs of this refinement may evaluate to.
*/ */
AbstractValue getAnInputRhsValue() { AbstractValue getAnInputRhsValue() {
result = getAnInput().(AnalyzedSsaDefinition).getAnRhsValue() result = this.getAnInput().(AnalyzedSsaDefinition).getAnRhsValue()
} }
} }
@@ -258,7 +258,7 @@ class AnalyzedRefinement extends AnalyzedSsaDefinition, SsaRefinementNode {
* into sets of more precise abstract values to enable them to be refined. * into sets of more precise abstract values to enable them to be refined.
*/ */
class AnalyzedConditionGuard extends AnalyzedRefinement { class AnalyzedConditionGuard extends AnalyzedRefinement {
AnalyzedConditionGuard() { getGuard() instanceof ConditionGuardNode } AnalyzedConditionGuard() { this.getGuard() instanceof ConditionGuardNode }
override AbstractValue getAnInputRhsValue() { override AbstractValue getAnInputRhsValue() {
exists(AbstractValue input | input = super.getAnInputRhsValue() | exists(AbstractValue input | input = super.getAnInputRhsValue() |
@@ -276,13 +276,13 @@ class AnalyzedConditionGuard extends AnalyzedRefinement {
* the beginning of `s` to those that are truthy. * the beginning of `s` to those that are truthy.
*/ */
class AnalyzedPositiveConditionGuard extends AnalyzedRefinement { class AnalyzedPositiveConditionGuard extends AnalyzedRefinement {
AnalyzedPositiveConditionGuard() { getGuard().(ConditionGuardNode).getOutcome() = true } AnalyzedPositiveConditionGuard() { this.getGuard().(ConditionGuardNode).getOutcome() = true }
override AbstractValue getAnRhsValue() { override AbstractValue getAnRhsValue() {
result = getAnInputRhsValue() and result = this.getAnInputRhsValue() and
exists(RefinementContext ctxt | exists(RefinementContext ctxt |
ctxt = TVarRefinementContext(this, getSourceVariable(), result) and ctxt = TVarRefinementContext(this, this.getSourceVariable(), result) and
getRefinement().eval(ctxt).getABooleanValue() = true this.getRefinement().eval(ctxt).getABooleanValue() = true
) )
} }
} }
@@ -294,13 +294,13 @@ class AnalyzedPositiveConditionGuard extends AnalyzedRefinement {
* the beginning of `t` to those that are falsy. * the beginning of `t` to those that are falsy.
*/ */
class AnalyzedNegativeConditionGuard extends AnalyzedRefinement { class AnalyzedNegativeConditionGuard extends AnalyzedRefinement {
AnalyzedNegativeConditionGuard() { getGuard().(ConditionGuardNode).getOutcome() = false } AnalyzedNegativeConditionGuard() { this.getGuard().(ConditionGuardNode).getOutcome() = false }
override AbstractValue getAnRhsValue() { override AbstractValue getAnRhsValue() {
result = getAnInputRhsValue() and result = this.getAnInputRhsValue() and
exists(RefinementContext ctxt | exists(RefinementContext ctxt |
ctxt = TVarRefinementContext(this, getSourceVariable(), result) and ctxt = TVarRefinementContext(this, this.getSourceVariable(), result) and
getRefinement().eval(ctxt).getABooleanValue() = false this.getRefinement().eval(ctxt).getABooleanValue() = false
) )
} }
} }
@@ -389,7 +389,7 @@ private class AnalyzedGlobalVarUse extends DataFlow::AnalyzedValueNode {
* of the global object. * of the global object.
*/ */
private DataFlow::PropWrite getAnAssigningPropWrite() { private DataFlow::PropWrite getAnAssigningPropWrite() {
result.getPropertyName() = getVariableName() and result.getPropertyName() = this.getVariableName() and
result.getBase().analyze().getALocalValue() instanceof AbstractGlobalObject result.getBase().analyze().getALocalValue() instanceof AbstractGlobalObject
} }
@@ -400,7 +400,7 @@ private class AnalyzedGlobalVarUse extends DataFlow::AnalyzedValueNode {
override AbstractValue getALocalValue() { override AbstractValue getALocalValue() {
result = super.getALocalValue() result = super.getALocalValue()
or or
result = getAnAssigningPropWrite().getRhs().analyze().getALocalValue() result = this.getAnAssigningPropWrite().getRhs().analyze().getALocalValue()
or or
result = agv.getAnAssignedValue() result = agv.getAnAssignedValue()
} }
@@ -668,8 +668,8 @@ abstract private class CallWithAnalyzedParameters extends FunctionWithAnalyzedPa
abstract DataFlow::InvokeNode getAnInvocation(); abstract DataFlow::InvokeNode getAnInvocation();
override predicate argumentPassing(Parameter p, Expr arg) { override predicate argumentPassing(Parameter p, Expr arg) {
exists(DataFlow::InvokeNode invk, int argIdx | invk = getAnInvocation() | exists(DataFlow::InvokeNode invk, int argIdx | invk = this.getAnInvocation() |
p = getParameter(argIdx) and p = this.getParameter(argIdx) and
not p.isRestParameter() and not p.isRestParameter() and
arg = invk.getArgument(argIdx).asExpr() arg = invk.getArgument(argIdx).asExpr()
) )
@@ -677,13 +677,13 @@ abstract private class CallWithAnalyzedParameters extends FunctionWithAnalyzedPa
override predicate mayReceiveArgument(Parameter p) { override predicate mayReceiveArgument(Parameter p) {
exists(int argIdx | exists(int argIdx |
p = getParameter(argIdx) and p = this.getParameter(argIdx) and
getAnInvocation().getNumArgument() > argIdx this.getAnInvocation().getNumArgument() > argIdx
) )
or or
// All parameters may receive an argument if invoked with a spread argument // All parameters may receive an argument if invoked with a spread argument
p = getAParameter() and p = this.getAParameter() and
getAnInvocation().asExpr().(InvokeExpr).isSpreadArgument(_) this.getAnInvocation().asExpr().(InvokeExpr).isSpreadArgument(_)
} }
} }

View File

@@ -23,7 +23,7 @@ private class BackwardExploringConfiguration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() } override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() }
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) | exists(DataFlow::PathNode src, DataFlow::PathNode snk | this.hasFlowPath(src, snk) |
source = src.getNode() and source = src.getNode() and
sink = snk.getNode() sink = snk.getNode()
) )

View File

@@ -21,7 +21,7 @@ private class ForwardExploringConfiguration extends DataFlow::Configuration {
override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() } override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() }
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) | exists(DataFlow::PathNode src, DataFlow::PathNode snk | this.hasFlowPath(src, snk) |
source = src.getNode() and source = src.getNode() and
sink = snk.getNode() sink = snk.getNode()
) )

View File

@@ -196,19 +196,19 @@ module Angular2 {
this = httpClient().getAMethodCall("request") and argumentOffset = 1 this = httpClient().getAMethodCall("request") and argumentOffset = 1
or or
this = httpClient().getAMethodCall() and this = httpClient().getAMethodCall() and
not getMethodName() = "request" and not this.getMethodName() = "request" and
argumentOffset = 0 argumentOffset = 0
} }
override DataFlow::Node getUrl() { result = getArgument(argumentOffset) } override DataFlow::Node getUrl() { result = this.getArgument(argumentOffset) }
override DataFlow::Node getHost() { none() } override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() { override DataFlow::Node getADataNode() {
getMethodName() = ["patch", "post", "put"] and this.getMethodName() = ["patch", "post", "put"] and
result = getArgument(argumentOffset + 1) result = this.getArgument(argumentOffset + 1)
or or
result = getOptionArgument(argumentOffset + 1, "body") result = this.getOptionArgument(argumentOffset + 1, "body")
} }
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) { override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
@@ -268,7 +268,7 @@ module Angular2 {
DataFlow::CallNode decorator; DataFlow::CallNode decorator;
ComponentClass() { ComponentClass() {
decorator = getADecorator() and decorator = this.getADecorator() and
decorator = DataFlow::moduleMember("@angular/core", "Component").getACall() decorator = DataFlow::moduleMember("@angular/core", "Component").getACall()
} }
@@ -289,9 +289,9 @@ module Angular2 {
* this component. * this component.
*/ */
DataFlow::Node getFieldInputNode(string name) { DataFlow::Node getFieldInputNode(string name) {
result = getFieldNode(name) result = this.getFieldNode(name)
or or
result = getInstanceMember(name, DataFlow::MemberKind::setter()).getParameter(0) result = this.getInstanceMember(name, DataFlow::MemberKind::setter()).getParameter(0)
} }
/** /**
@@ -299,11 +299,11 @@ module Angular2 {
* of this component. * of this component.
*/ */
DataFlow::Node getFieldOutputNode(string name) { DataFlow::Node getFieldOutputNode(string name) {
result = getFieldNode(name) result = this.getFieldNode(name)
or or
result = getInstanceMember(name, DataFlow::MemberKind::getter()).getReturnNode() result = this.getInstanceMember(name, DataFlow::MemberKind::getter()).getReturnNode()
or or
result = getInstanceMethod(name) result = this.getInstanceMethod(name)
} }
/** /**
@@ -312,7 +312,7 @@ module Angular2 {
string getSelector() { decorator.getOptionArgument(0, "selector").mayHaveStringValue(result) } string getSelector() { decorator.getOptionArgument(0, "selector").mayHaveStringValue(result) }
/** Gets an HTML element that instantiates this component. */ /** Gets an HTML element that instantiates this component. */
HTML::Element getATemplateInstantiation() { result.getName() = getSelector() } HTML::Element getATemplateInstantiation() { result.getName() = this.getSelector() }
/** /**
* Gets an argument that flows into the `name` field of this component. * Gets an argument that flows into the `name` field of this component.
@@ -323,7 +323,8 @@ module Angular2 {
*/ */
DataFlow::Node getATemplateArgument(string name) { DataFlow::Node getATemplateArgument(string name) {
result = result =
getAttributeValueAsNode(getATemplateInstantiation().getAttributeByName("[" + name + "]")) getAttributeValueAsNode(this.getATemplateInstantiation()
.getAttributeByName("[" + name + "]"))
} }
/** /**
@@ -338,7 +339,7 @@ module Angular2 {
/** Gets an element in the HTML template of this component. */ /** Gets an element in the HTML template of this component. */
HTML::Element getATemplateElement() { HTML::Element getATemplateElement() {
result.getFile() = getTemplateFile() result.getFile() = this.getTemplateFile()
or or
result.getParent*() = result.getParent*() =
HTML::getHtmlElementFromExpr(decorator.getOptionArgument(0, "template").asExpr(), _) HTML::getHtmlElementFromExpr(decorator.getOptionArgument(0, "template").asExpr(), _)
@@ -349,7 +350,7 @@ module Angular2 {
*/ */
DataFlow::SourceNode getATemplateVarAccess(string name) { DataFlow::SourceNode getATemplateVarAccess(string name) {
result = result =
getATemplateElement() this.getATemplateElement()
.getAnAttribute() .getAnAttribute()
.getCodeInAttribute() .getCodeInAttribute()
.(TemplateTopLevel) .(TemplateTopLevel)
@@ -363,14 +364,14 @@ module Angular2 {
PipeClass() { PipeClass() {
decorator = DataFlow::moduleMember("@angular/core", "Pipe").getACall() and decorator = DataFlow::moduleMember("@angular/core", "Pipe").getACall() and
decorator = getADecorator() decorator = this.getADecorator()
} }
/** Gets the value of the `name` option passed to the `@Pipe` decorator. */ /** Gets the value of the `name` option passed to the `@Pipe` decorator. */
string getPipeName() { decorator.getOptionArgument(0, "name").mayHaveStringValue(result) } string getPipeName() { decorator.getOptionArgument(0, "name").mayHaveStringValue(result) }
/** Gets a reference to this pipe. */ /** Gets a reference to this pipe. */
DataFlow::Node getAPipeRef() { result.asExpr().(PipeRefExpr).getName() = getPipeName() } DataFlow::Node getAPipeRef() { result.asExpr().(PipeRefExpr).getName() = this.getPipeName() }
} }
private class ComponentSteps extends PreCallGraphStep { private class ComponentSteps extends PreCallGraphStep {
@@ -413,25 +414,25 @@ module Angular2 {
* attribute. There is no AST node for the implied for-of loop. * attribute. There is no AST node for the implied for-of loop.
*/ */
private class ForLoopAttribute extends HTML::Attribute { private class ForLoopAttribute extends HTML::Attribute {
ForLoopAttribute() { getName() = "*ngFor" } ForLoopAttribute() { this.getName() = "*ngFor" }
/** Gets a data-flow node holding the value being iterated over. */ /** Gets a data-flow node holding the value being iterated over. */
DataFlow::Node getIterationDomain() { result = getAttributeValueAsNode(this) } DataFlow::Node getIterationDomain() { result = getAttributeValueAsNode(this) }
/** Gets the name of the variable holding the element of the current iteration. */ /** Gets the name of the variable holding the element of the current iteration. */
string getIteratorName() { result = getValue().regexpCapture(" *let +(\\w+).*", 1) } string getIteratorName() { result = this.getValue().regexpCapture(" *let +(\\w+).*", 1) }
/** Gets an HTML element in which the iterator variable is in scope. */ /** Gets an HTML element in which the iterator variable is in scope. */
HTML::Element getAnElementInScope() { result.getParent*() = getElement() } HTML::Element getAnElementInScope() { result.getParent*() = this.getElement() }
/** Gets a reference to the iterator variable. */ /** Gets a reference to the iterator variable. */
DataFlow::Node getAnIteratorAccess() { DataFlow::Node getAnIteratorAccess() {
result = result =
getAnElementInScope() this.getAnElementInScope()
.getAnAttribute() .getAnAttribute()
.getCodeInAttribute() .getCodeInAttribute()
.(TemplateTopLevel) .(TemplateTopLevel)
.getAVariableUse(getIteratorName()) .getAVariableUse(this.getIteratorName())
} }
} }
@@ -485,11 +486,11 @@ module Angular2 {
* A `<mat-table>` element. * A `<mat-table>` element.
*/ */
class MatTableElement extends HTML::Element { class MatTableElement extends HTML::Element {
MatTableElement() { getName() = "mat-table" } MatTableElement() { this.getName() = "mat-table" }
/** Gets the data flow node corresponding to the `[dataSource]` attribute. */ /** Gets the data flow node corresponding to the `[dataSource]` attribute. */
DataFlow::Node getDataSourceNode() { DataFlow::Node getDataSourceNode() {
result = getAttributeValueAsNode(getAttributeByName("[dataSource]")) result = getAttributeValueAsNode(this.getAttributeByName("[dataSource]"))
} }
/** /**
@@ -506,7 +507,7 @@ module Angular2 {
DataFlow::Node getARowRef() { DataFlow::Node getARowRef() {
exists(string rowBinding | exists(string rowBinding |
result = result =
getATableCell(rowBinding) this.getATableCell(rowBinding)
.getChild*() .getChild*()
.getAnAttribute() .getAnAttribute()
.getCodeInAttribute() .getCodeInAttribute()

View File

@@ -22,7 +22,7 @@ private DataFlow::CallNode angularInjector() { result = angular().getAMemberCall
class InjectorInvokeCall extends DataFlow::CallNode, DependencyInjection { class InjectorInvokeCall extends DataFlow::CallNode, DependencyInjection {
InjectorInvokeCall() { this = angularInjector().getAMemberCall("invoke") } InjectorInvokeCall() { this = angularInjector().getAMemberCall("invoke") }
override DataFlow::Node getAnInjectableFunction() { result = getArgument(0) } override DataFlow::Node getAnInjectableFunction() { result = this.getArgument(0) }
} }
/** /**
@@ -52,13 +52,13 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
* Gets a node for the `name` dependency declaration. * Gets a node for the `name` dependency declaration.
*/ */
DataFlow::Node getADependencyDeclaration(string name) { DataFlow::Node getADependencyDeclaration(string name) {
result = getDependencyDeclaration(_, name) result = this.getDependencyDeclaration(_, name)
} }
/** /**
* Gets the dataflow node for the `i`th dependency declaration. * Gets the dataflow node for the `i`th dependency declaration.
*/ */
DataFlow::Node getDependencyDeclaration(int i) { result = getDependencyDeclaration(i, _) } DataFlow::Node getDependencyDeclaration(int i) { result = this.getDependencyDeclaration(i, _) }
/** Gets the function underlying this injectable function. */ /** Gets the function underlying this injectable function. */
abstract DataFlow::FunctionNode asFunction(); abstract DataFlow::FunctionNode asFunction();
@@ -72,7 +72,7 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
ServiceReference getAResolvedDependency(DataFlow::ParameterNode parameter) { ServiceReference getAResolvedDependency(DataFlow::ParameterNode parameter) {
exists(string name, InjectableFunctionServiceRequest request | exists(string name, InjectableFunctionServiceRequest request |
this = request.getAnInjectedFunction() and this = request.getAnInjectedFunction() and
parameter = getDependencyParameter(name) and parameter = this.getDependencyParameter(name) and
result = request.getAServiceDefinition(name) result = request.getAServiceDefinition(name)
) )
} }
@@ -83,7 +83,7 @@ abstract class InjectableFunction extends DataFlow::ValueNode {
*/ */
DataFlow::Node getCustomServiceDependency(DataFlow::ParameterNode parameter) { DataFlow::Node getCustomServiceDependency(DataFlow::ParameterNode parameter) {
exists(CustomServiceDefinition custom | exists(CustomServiceDefinition custom |
custom.getServiceReference() = getAResolvedDependency(parameter) and custom.getServiceReference() = this.getAResolvedDependency(parameter) and
result = custom.getAService() result = custom.getAService()
) )
} }
@@ -138,7 +138,7 @@ private class FunctionWithInjectProperty extends InjectableFunction instanceof D
} }
override DataFlow::ParameterNode getDependencyParameter(string name) { override DataFlow::ParameterNode getDependencyParameter(string name) {
exists(int i | exists(getDependencyDeclaration(i, name)) | result = super.getParameter(i)) exists(int i | exists(this.getDependencyDeclaration(i, name)) | result = super.getParameter(i))
} }
override DataFlow::Node getDependencyDeclaration(int i, string name) { override DataFlow::Node getDependencyDeclaration(int i, string name) {

View File

@@ -37,22 +37,22 @@ module AsyncPackage {
/** /**
* Gets the array of tasks, if it can be found. * Gets the array of tasks, if it can be found.
*/ */
DataFlow::ArrayCreationNode getTaskArray() { result.flowsTo(getArgument(0)) } DataFlow::ArrayCreationNode getTaskArray() { result.flowsTo(this.getArgument(0)) }
/** /**
* Gets the callback to invoke after the last task in the array completes. * Gets the callback to invoke after the last task in the array completes.
*/ */
DataFlow::FunctionNode getFinalCallback() { result.flowsTo(getArgument(1)) } DataFlow::FunctionNode getFinalCallback() { result.flowsTo(this.getArgument(1)) }
/** /**
* Gets the `n`th task, if it can be found. * Gets the `n`th task, if it can be found.
*/ */
DataFlow::FunctionNode getTask(int n) { result.flowsTo(getTaskArray().getElement(n)) } DataFlow::FunctionNode getTask(int n) { result.flowsTo(this.getTaskArray().getElement(n)) }
/** /**
* Gets the number of tasks. * Gets the number of tasks.
*/ */
int getNumTasks() { result = strictcount(getTaskArray().getAnElement()) } int getNumTasks() { result = strictcount(this.getTaskArray().getAnElement()) }
} }
/** /**
@@ -80,18 +80,18 @@ module AsyncPackage {
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) { override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
// Pass results to next task // Pass results to next task
index >= 0 and index >= 0 and
argument = getArgument(index + 1) and argument = this.getArgument(index + 1) and
callback = waterfall.getTask(n + 1) callback = waterfall.getTask(n + 1)
or or
// For the last task, pass results to the final callback // For the last task, pass results to the final callback
index >= 1 and index >= 1 and
n = waterfall.getNumTasks() - 1 and n = waterfall.getNumTasks() - 1 and
argument = getArgument(index) and argument = this.getArgument(index) and
callback = waterfall.getFinalCallback() callback = waterfall.getFinalCallback()
or or
// Always pass error to the final callback // Always pass error to the final callback
index = 0 and index = 0 and
argument = getArgument(0) and argument = this.getArgument(0) and
callback = waterfall.getFinalCallback() callback = waterfall.getFinalCallback()
} }
} }
@@ -120,17 +120,17 @@ module AsyncPackage {
/** /**
* Gets the node holding the collection being iterated over. * Gets the node holding the collection being iterated over.
*/ */
DataFlow::Node getCollection() { result = getArgument(0) } DataFlow::Node getCollection() { result = this.getArgument(0) }
/** /**
* Gets the node holding the function being called for each element in the collection. * Gets the node holding the function being called for each element in the collection.
*/ */
DataFlow::Node getIteratorCallback() { result = getArgument(getNumArgument() - 2) } DataFlow::Node getIteratorCallback() { result = this.getArgument(this.getNumArgument() - 2) }
/** /**
* Gets the node holding the function being invoked after iteration is complete. * Gets the node holding the function being invoked after iteration is complete.
*/ */
DataFlow::Node getFinalCallback() { result = getArgument(getNumArgument() - 1) } DataFlow::Node getFinalCallback() { result = this.getArgument(this.getNumArgument() - 1) }
} }
/** /**

View File

@@ -11,7 +11,7 @@ module Babel {
*/ */
class Config extends JsonObject { class Config extends JsonObject {
Config() { Config() {
isTopLevel() and getJsonFile().getBaseName().matches(".babelrc%") this.isTopLevel() and this.getJsonFile().getBaseName().matches(".babelrc%")
or or
this = any(PackageJson pkg).getPropValue("babel") this = any(PackageJson pkg).getPropValue("babel")
} }
@@ -21,7 +21,7 @@ module Babel {
*/ */
JsonValue getPluginConfig(string pluginName) { JsonValue getPluginConfig(string pluginName) {
exists(JsonArray plugins | exists(JsonArray plugins |
plugins = getPropValue("plugins") and plugins = this.getPropValue("plugins") and
result = plugins.getElementValue(_) result = plugins.getElementValue(_)
| |
result.getStringValue() = pluginName result.getStringValue() = pluginName
@@ -34,9 +34,9 @@ module Babel {
* Gets a file affected by this Babel configuration. * Gets a file affected by this Babel configuration.
*/ */
Container getAContainerInScope() { Container getAContainerInScope() {
result = getJsonFile().getParentContainer() result = this.getJsonFile().getParentContainer()
or or
result = getAContainerInScope().getAChildContainer() and result = this.getAContainerInScope().getAChildContainer() and
// File-relative .babelrc search stops at any package.json or .babelrc file. // File-relative .babelrc search stops at any package.json or .babelrc file.
not result.getAChildContainer() = any(PackageJson pkg).getJsonFile() and not result.getAChildContainer() = any(PackageJson pkg).getJsonFile() and
not result.getAChildContainer() = any(Config pkg).getJsonFile() not result.getAChildContainer() = any(Config pkg).getJsonFile()
@@ -45,7 +45,7 @@ module Babel {
/** /**
* Holds if this configuration applies to `tl`. * Holds if this configuration applies to `tl`.
*/ */
predicate appliesTo(TopLevel tl) { tl.getFile() = getAContainerInScope() } predicate appliesTo(TopLevel tl) { tl.getFile() = this.getAContainerInScope() }
} }
/** /**
@@ -67,7 +67,7 @@ module Babel {
JsonValue getOptions() { result = this.(JsonArray).getElementValue(1) } JsonValue getOptions() { result = this.(JsonArray).getElementValue(1) }
/** Gets a named option from the option object, if present. */ /** Gets a named option from the option object, if present. */
JsonValue getOption(string name) { result = getOptions().getPropValue(name) } JsonValue getOption(string name) { result = this.getOptions().getPropValue(name) }
/** Holds if this plugin applies to `tl`. */ /** Holds if this plugin applies to `tl`. */
predicate appliesTo(TopLevel tl) { cfg.appliesTo(tl) } predicate appliesTo(TopLevel tl) { cfg.appliesTo(tl) }
@@ -88,11 +88,11 @@ module Babel {
* Gets the root specified for the given prefix. * Gets the root specified for the given prefix.
*/ */
string getRoot(string prefix) { string getRoot(string prefix) {
result = getExplicitRoot(prefix) result = this.getExplicitRoot(prefix)
or or
// by default, `~` is mapped to the folder containing the configuration // by default, `~` is mapped to the folder containing the configuration
prefix = "~" and prefix = "~" and
not exists(getExplicitRoot(prefix)) and not exists(this.getExplicitRoot(prefix)) and
result = "." result = "."
} }
@@ -101,15 +101,15 @@ module Babel {
*/ */
private JsonObject getARootPathSpec() { private JsonObject getARootPathSpec() {
// ["babel-plugin-root-import", <spec>] // ["babel-plugin-root-import", <spec>]
result = getOptions() and result = this.getOptions() and
exists(result.getPropValue("rootPathSuffix")) exists(result.getPropValue("rootPathSuffix"))
or or
exists(JsonArray pathSpecs | exists(JsonArray pathSpecs |
// ["babel-plugin-root-import", [ <spec>... ] ] // ["babel-plugin-root-import", [ <spec>... ] ]
pathSpecs = getOptions() pathSpecs = this.getOptions()
or or
// ["babel-plugin-root-import", { "paths": [ <spec> ... ] }] // ["babel-plugin-root-import", { "paths": [ <spec> ... ] }]
pathSpecs = getOption("paths") pathSpecs = this.getOption("paths")
| |
result = pathSpecs.getElementValue(_) result = pathSpecs.getElementValue(_)
) )
@@ -120,7 +120,7 @@ module Babel {
*/ */
private string getExplicitRoot(string prefix) { private string getExplicitRoot(string prefix) {
exists(JsonObject rootPathSpec | exists(JsonObject rootPathSpec |
rootPathSpec = getARootPathSpec() and rootPathSpec = this.getARootPathSpec() and
result = rootPathSpec.getPropStringValue("rootPathSuffix") result = rootPathSpec.getPropStringValue("rootPathSuffix")
| |
if exists(rootPathSpec.getPropStringValue("rootPathPrefix")) if exists(rootPathSpec.getPropStringValue("rootPathPrefix"))
@@ -132,7 +132,7 @@ module Babel {
/** /**
* Gets the folder in which this configuration is located. * Gets the folder in which this configuration is located.
*/ */
Folder getFolder() { result = getJsonFile().getParentContainer() } Folder getFolder() { result = this.getJsonFile().getParentContainer() }
} }
/** /**
@@ -146,9 +146,9 @@ module Babel {
BabelRootTransformedPathExpr() { BabelRootTransformedPathExpr() {
this instanceof PathExpr and this instanceof PathExpr and
plugin.appliesTo(getTopLevel()) and plugin.appliesTo(this.getTopLevel()) and
prefix = getStringValue().regexpCapture("(.)/(.*)", 1) and prefix = this.getStringValue().regexpCapture("(.)/(.*)", 1) and
suffix = getStringValue().regexpCapture("(.)/(.*)", 2) and suffix = this.getStringValue().regexpCapture("(.)/(.*)", 2) and
mappedPrefix = plugin.getRoot(prefix) mappedPrefix = plugin.getRoot(prefix)
} }
@@ -184,7 +184,7 @@ module Babel {
TransformReactJsxConfig() { pluginName = "transform-react-jsx" } TransformReactJsxConfig() { pluginName = "transform-react-jsx" }
/** Gets the name of the variable used to create JSX elements. */ /** Gets the name of the variable used to create JSX elements. */
string getJsxFactoryVariableName() { result = getOption("pragma").getStringValue() } string getJsxFactoryVariableName() { result = this.getOption("pragma").getStringValue() }
} }
/** /**

View File

@@ -194,7 +194,7 @@ predicate isMultiPartBundle(TopLevel tl) {
* A comment that starts with '!'. Minifiers avoid removing such comments. * A comment that starts with '!'. Minifiers avoid removing such comments.
*/ */
class ExclamationPointComment extends Comment { class ExclamationPointComment extends Comment {
ExclamationPointComment() { getLine(0).matches("!%") } ExclamationPointComment() { this.getLine(0).matches("!%") }
} }
/** /**

View File

@@ -18,7 +18,7 @@ class FunctionCompositionCall extends DataFlow::CallNode instanceof FunctionComp
DataFlow::Node getOperandNode(int i) { result = super.getOperandNode(i) } DataFlow::Node getOperandNode(int i) { result = super.getOperandNode(i) }
/** Gets a node holding one of the functions to be composed. */ /** Gets a node holding one of the functions to be composed. */
final DataFlow::Node getAnOperandNode() { result = getOperandNode(_) } final DataFlow::Node getAnOperandNode() { result = this.getOperandNode(_) }
/** /**
* Gets the function flowing into the `i`th function in the composition `f(g(h(...)))`. * Gets the function flowing into the `i`th function in the composition `f(g(h(...)))`.
@@ -27,11 +27,11 @@ class FunctionCompositionCall extends DataFlow::CallNode instanceof FunctionComp
* that is, `g` occurs later than `f` in `f(g(...))` but is invoked before `f`. * that is, `g` occurs later than `f` in `f(g(...))` but is invoked before `f`.
*/ */
final DataFlow::FunctionNode getOperandFunction(int i) { final DataFlow::FunctionNode getOperandFunction(int i) {
result = getOperandNode(i).getALocalSource() result = this.getOperandNode(i).getALocalSource()
} }
/** Gets any of the functions being composed. */ /** Gets any of the functions being composed. */
final DataFlow::FunctionNode getAnOperandFunction() { result = getOperandFunction(_) } final DataFlow::FunctionNode getAnOperandFunction() { result = this.getOperandFunction(_) }
/** Gets the number of functions being composed. */ /** Gets the number of functions being composed. */
int getNumOperand() { result = super.getNumOperand() } int getNumOperand() { result = super.getNumOperand() }
@@ -65,17 +65,17 @@ module FunctionCompositionCall {
abstract private class WithArrayOverloading extends Range { abstract private class WithArrayOverloading extends Range {
/** Gets the `i`th argument to the call or the `i`th array element passed into the call. */ /** Gets the `i`th argument to the call or the `i`th array element passed into the call. */
DataFlow::Node getEffectiveArgument(int i) { DataFlow::Node getEffectiveArgument(int i) {
result = getArgument(0).(DataFlow::ArrayCreationNode).getElement(i) result = this.getArgument(0).(DataFlow::ArrayCreationNode).getElement(i)
or or
not getArgument(0) instanceof DataFlow::ArrayCreationNode and not this.getArgument(0) instanceof DataFlow::ArrayCreationNode and
result = getArgument(i) result = this.getArgument(i)
} }
override int getNumOperand() { override int getNumOperand() {
result = getArgument(0).(DataFlow::ArrayCreationNode).getSize() result = this.getArgument(0).(DataFlow::ArrayCreationNode).getSize()
or or
not getArgument(0) instanceof DataFlow::ArrayCreationNode and not this.getArgument(0) instanceof DataFlow::ArrayCreationNode and
result = getNumArgument() result = this.getNumArgument()
} }
} }
@@ -91,7 +91,7 @@ module FunctionCompositionCall {
this = LodashUnderscore::member("flowRight").getACall() this = LodashUnderscore::member("flowRight").getACall()
} }
override DataFlow::Node getOperandNode(int i) { result = getEffectiveArgument(i) } override DataFlow::Node getOperandNode(int i) { result = this.getEffectiveArgument(i) }
} }
/** A call whose arguments are functions `f,g,h` which are composed into `h(g(f(...))` */ /** A call whose arguments are functions `f,g,h` which are composed into `h(g(f(...))` */
@@ -103,7 +103,7 @@ module FunctionCompositionCall {
} }
override DataFlow::Node getOperandNode(int i) { override DataFlow::Node getOperandNode(int i) {
result = getEffectiveArgument(getNumOperand() - i - 1) result = this.getEffectiveArgument(this.getNumOperand() - i - 1)
} }
} }
} }

View File

@@ -36,14 +36,14 @@ module Connect {
* Gets the parameter of the route handler that contains the request object. * Gets the parameter of the route handler that contains the request object.
*/ */
override DataFlow::ParameterNode getRequestParameter() { override DataFlow::ParameterNode getRequestParameter() {
result = getRouteHandlerParameter("request") result = this.getRouteHandlerParameter("request")
} }
/** /**
* Gets the parameter of the route handler that contains the response object. * Gets the parameter of the route handler that contains the response object.
*/ */
override DataFlow::ParameterNode getResponseParameter() { override DataFlow::ParameterNode getResponseParameter() {
result = getRouteHandlerParameter("response") result = this.getRouteHandlerParameter("response")
} }
} }
@@ -65,7 +65,7 @@ module Connect {
ServerDefinition server; ServerDefinition server;
RouteSetup() { RouteSetup() {
getMethodName() = "use" and this.getMethodName() = "use" and
( (
// app.use(fun) // app.use(fun)
server.ref().getAMethodCall() = this server.ref().getAMethodCall() = this
@@ -76,14 +76,14 @@ module Connect {
} }
override DataFlow::SourceNode getARouteHandler() { override DataFlow::SourceNode getARouteHandler() {
result = getARouteHandler(DataFlow::TypeBackTracker::end()) result = this.getARouteHandler(DataFlow::TypeBackTracker::end())
} }
private DataFlow::SourceNode getARouteHandler(DataFlow::TypeBackTracker t) { private DataFlow::SourceNode getARouteHandler(DataFlow::TypeBackTracker t) {
t.start() and t.start() and
result = getARouteHandlerNode().getALocalSource() result = this.getARouteHandlerNode().getALocalSource()
or or
exists(DataFlow::TypeBackTracker t2 | result = getARouteHandler(t2).backtrack(t2, t)) exists(DataFlow::TypeBackTracker t2 | result = this.getARouteHandler(t2).backtrack(t2, t))
} }
override DataFlow::Node getServer() { result = server } override DataFlow::Node getServer() { result = server }
@@ -92,12 +92,12 @@ module Connect {
* DEPRECATED: Use `getARouteHandlerNode` instead. * DEPRECATED: Use `getARouteHandlerNode` instead.
* Gets an argument that represents a route handler being registered. * Gets an argument that represents a route handler being registered.
*/ */
deprecated Expr getARouteHandlerExpr() { result = getARouteHandlerNode().asExpr() } deprecated Expr getARouteHandlerExpr() { result = this.getARouteHandlerNode().asExpr() }
/** /**
* Gets an argument that represents a route handler being registered. * Gets an argument that represents a route handler being registered.
*/ */
DataFlow::Node getARouteHandlerNode() { result = getAnArgument() } DataFlow::Node getARouteHandlerNode() { result = this.getAnArgument() }
} }
/** An expression that is passed as `basicAuthConnect(<user>, <password>)`. */ /** An expression that is passed as `basicAuthConnect(<user>, <password>)`. */

View File

@@ -14,7 +14,7 @@ abstract class EmscriptenMarkerComment extends GeneratedCodeMarkerComment { }
* An `EMSCRIPTEN_START_ASM` marker comment. * An `EMSCRIPTEN_START_ASM` marker comment.
*/ */
class EmscriptenStartAsmComment extends EmscriptenMarkerComment { class EmscriptenStartAsmComment extends EmscriptenMarkerComment {
EmscriptenStartAsmComment() { getText().trim() = "EMSCRIPTEN_START_ASM" } EmscriptenStartAsmComment() { this.getText().trim() = "EMSCRIPTEN_START_ASM" }
} }
/** DEPRECATED: Alias for EmscriptenStartAsmComment */ /** DEPRECATED: Alias for EmscriptenStartAsmComment */
@@ -24,14 +24,14 @@ deprecated class EmscriptenStartASMComment = EmscriptenStartAsmComment;
* An `EMSCRIPTEN_START_FUNCS` marker comment. * An `EMSCRIPTEN_START_FUNCS` marker comment.
*/ */
class EmscriptenStartFuncsComment extends EmscriptenMarkerComment { class EmscriptenStartFuncsComment extends EmscriptenMarkerComment {
EmscriptenStartFuncsComment() { getText().trim() = "EMSCRIPTEN_START_FUNCS" } EmscriptenStartFuncsComment() { this.getText().trim() = "EMSCRIPTEN_START_FUNCS" }
} }
/** /**
* An `EMSCRIPTEN_END_ASM` marker comment. * An `EMSCRIPTEN_END_ASM` marker comment.
*/ */
class EmscriptenEndAsmComment extends EmscriptenMarkerComment { class EmscriptenEndAsmComment extends EmscriptenMarkerComment {
EmscriptenEndAsmComment() { getText().trim() = "EMSCRIPTEN_END_ASM" } EmscriptenEndAsmComment() { this.getText().trim() = "EMSCRIPTEN_END_ASM" }
} }
/** DEPRECATED: Alias for EmscriptenEndAsmComment */ /** DEPRECATED: Alias for EmscriptenEndAsmComment */
@@ -41,7 +41,7 @@ deprecated class EmscriptenEndASMComment = EmscriptenEndAsmComment;
* An `EMSCRIPTEN_END_FUNCS` marker comment. * An `EMSCRIPTEN_END_FUNCS` marker comment.
*/ */
class EmscriptenEndFuncsComment extends EmscriptenMarkerComment { class EmscriptenEndFuncsComment extends EmscriptenMarkerComment {
EmscriptenEndFuncsComment() { getText().trim() = "EMSCRIPTEN_END_FUNCS" } EmscriptenEndFuncsComment() { this.getText().trim() = "EMSCRIPTEN_END_FUNCS" }
} }
/** /**

View File

@@ -111,10 +111,10 @@ module ExpressLibraries {
/** /**
* Gets the expression for property `name` of the options object of this call. * Gets the expression for property `name` of the options object of this call.
*/ */
DataFlow::Node getOption(string name) { result = getOptionArgument(0, name) } DataFlow::Node getOption(string name) { result = this.getOptionArgument(0, name) }
override DataFlow::Node getASecretKey() { override DataFlow::Node getASecretKey() {
exists(DataFlow::Node secret | secret = getOption("secret") | exists(DataFlow::Node secret | secret = this.getOption("secret") |
if exists(DataFlow::ArrayCreationNode arr | arr.flowsTo(secret)) if exists(DataFlow::ArrayCreationNode arr | arr.flowsTo(secret))
then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(secret)).getAnElement() then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(secret)).getAnElement()
else result = secret else result = secret
@@ -138,10 +138,10 @@ module ExpressLibraries {
/** /**
* Gets the expression for property `name` of the options object of this call. * Gets the expression for property `name` of the options object of this call.
*/ */
DataFlow::Node getOption(string name) { result = getOptionArgument(1, name) } DataFlow::Node getOption(string name) { result = this.getOptionArgument(1, name) }
override DataFlow::Node getASecretKey() { override DataFlow::Node getASecretKey() {
exists(DataFlow::Node arg0 | arg0 = getArgument(0) | exists(DataFlow::Node arg0 | arg0 = this.getArgument(0) |
if exists(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0)) if exists(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0))
then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0)).getAnElement() then result = any(DataFlow::ArrayCreationNode arr | arr.flowsTo(arg0)).getAnElement()
else result = arg0 else result = arg0
@@ -167,13 +167,13 @@ module ExpressLibraries {
/** /**
* Gets the expression for property `name` of the options object of this call. * Gets the expression for property `name` of the options object of this call.
*/ */
DataFlow::Node getOption(string name) { result = getOptionArgument(0, name) } DataFlow::Node getOption(string name) { result = this.getOptionArgument(0, name) }
override DataFlow::Node getASecretKey() { override DataFlow::Node getASecretKey() {
result = getOption("secret") result = this.getOption("secret")
or or
exists(DataFlow::ArrayCreationNode keys | exists(DataFlow::ArrayCreationNode keys |
keys.flowsTo(getOption("keys")) and keys.flowsTo(this.getOption("keys")) and
result = keys.getAnElement() result = keys.getAnElement()
) )
} }
@@ -213,14 +213,14 @@ module ExpressLibraries {
*/ */
predicate isExtendedUrlEncoded() { predicate isExtendedUrlEncoded() {
kind = "urlencoded" and kind = "urlencoded" and
not getOptionArgument(0, "extended").mayHaveBooleanValue(false) not this.getOptionArgument(0, "extended").mayHaveBooleanValue(false)
} }
/** /**
* Holds if this parses the input as JSON or extended URL-encoding, resulting * Holds if this parses the input as JSON or extended URL-encoding, resulting
* in user-controlled objects (as opposed to user-controlled strings). * in user-controlled objects (as opposed to user-controlled strings).
*/ */
predicate producesUserControlledObjects() { isJson() or isExtendedUrlEncoded() } predicate producesUserControlledObjects() { this.isJson() or this.isExtendedUrlEncoded() }
} }
} }
@@ -245,7 +245,7 @@ module FileUpload {
this = filesRef(_, DataFlow::TypeTracker::end()).getAPropertyRead().getAMethodCall("mv") this = filesRef(_, DataFlow::TypeTracker::end()).getAPropertyRead().getAMethodCall("mv")
} }
override DataFlow::Node getAPathArgument() { result = getArgument(0) } override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getADataNode() { none() } override DataFlow::Node getADataNode() { none() }
} }

View File

@@ -8,7 +8,7 @@ import javascript
* A `$gwt_version` variable. * A `$gwt_version` variable.
*/ */
class GwtVersionVariable extends GlobalVariable { class GwtVersionVariable extends GlobalVariable {
GwtVersionVariable() { getName() = "$gwt_version" } GwtVersionVariable() { this.getName() = "$gwt_version" }
} }
/** DEPRECATED: Alias for GwtVersionVariable */ /** DEPRECATED: Alias for GwtVersionVariable */
@@ -33,7 +33,7 @@ class GwtHeader extends InlineScript {
} }
/** DEPRECATED: Alias for getGwtVersion */ /** DEPRECATED: Alias for getGwtVersion */
deprecated string getGWTVersion() { result = getGwtVersion() } deprecated string getGWTVersion() { result = this.getGwtVersion() }
} }
/** DEPRECATED: Alias for GwtHeader */ /** DEPRECATED: Alias for GwtHeader */
@@ -43,7 +43,7 @@ deprecated class GWTHeader = GwtHeader;
* A toplevel in a file that appears to be GWT-generated. * A toplevel in a file that appears to be GWT-generated.
*/ */
class GwtGeneratedTopLevel extends TopLevel { class GwtGeneratedTopLevel extends TopLevel {
GwtGeneratedTopLevel() { exists(GwtHeader h | getFile() = h.getFile()) } GwtGeneratedTopLevel() { exists(GwtHeader h | this.getFile() = h.getFile()) }
} }
/** DEPRECATED: Alias for GwtGeneratedTopLevel */ /** DEPRECATED: Alias for GwtGeneratedTopLevel */

View File

@@ -19,10 +19,10 @@ private module HttpProxy {
.getACall() .getACall()
} }
override DataFlow::Node getUrl() { result = getParameter(0).getMember("target").asSink() } override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("target").asSink() }
override DataFlow::Node getHost() { override DataFlow::Node getHost() {
result = getParameter(0).getMember("target").getMember("host").asSink() result = this.getParameter(0).getMember("target").getMember("host").asSink()
} }
override DataFlow::Node getADataNode() { none() } override DataFlow::Node getADataNode() { none() }
@@ -45,14 +45,16 @@ private module HttpProxy {
or or
method = "ws" and optionsIndex = 3 method = "ws" and optionsIndex = 3
| |
result = getParameter(optionsIndex) result = this.getParameter(optionsIndex)
) )
} }
override DataFlow::Node getUrl() { result = getOptionsObject().getMember("target").asSink() } override DataFlow::Node getUrl() {
result = this.getOptionsObject().getMember("target").asSink()
}
override DataFlow::Node getHost() { override DataFlow::Node getHost() {
result = getOptionsObject().getMember("target").getMember("host").asSink() result = this.getOptionsObject().getMember("target").getMember("host").asSink()
} }
override DataFlow::Node getADataNode() { none() } override DataFlow::Node getADataNode() { none() }
@@ -84,11 +86,11 @@ private module HttpProxy {
} }
override DataFlow::ParameterNode getRequestParameter() { override DataFlow::ParameterNode getRequestParameter() {
exists(int req | routeHandlingEventHandler(event, req, _) | result = getParameter(req)) exists(int req | routeHandlingEventHandler(event, req, _) | result = this.getParameter(req))
} }
override DataFlow::ParameterNode getResponseParameter() { override DataFlow::ParameterNode getResponseParameter() {
exists(int res | routeHandlingEventHandler(event, _, res) | result = getParameter(res)) exists(int res | routeHandlingEventHandler(event, _, res) | result = this.getParameter(res))
} }
} }
} }

View File

@@ -186,7 +186,7 @@ private class LodashCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode:
LodashCallbackAsPartialInvoke() { LodashCallbackAsPartialInvoke() {
exists(string name, int argumentCount | exists(string name, int argumentCount |
this = LodashUnderscore::member(name).getACall() and this = LodashUnderscore::member(name).getACall() and
getNumArgument() = argumentCount this.getNumArgument() = argumentCount
| |
name = ["bind", "callback", "iteratee"] and name = ["bind", "callback", "iteratee"] and
callbackIndex = 0 and callbackIndex = 0 and
@@ -219,7 +219,7 @@ private class LodashCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode:
} }
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) { override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
callback = getArgument(callbackIndex) and callback = this.getArgument(callbackIndex) and
result = getArgument(contextIndex) result = this.getArgument(contextIndex)
} }
} }

View File

@@ -63,11 +63,11 @@ private module Console {
override DataFlow::Node getAMessageComponent() { override DataFlow::Node getAMessageComponent() {
( (
if name = "assert" if name = "assert"
then result = getArgument([1 .. getNumArgument()]) then result = this.getArgument([1 .. this.getNumArgument()])
else result = getAnArgument() else result = this.getAnArgument()
) )
or or
result = getASpreadArgument() result = this.getASpreadArgument()
} }
/** /**
@@ -89,7 +89,7 @@ private module Loglevel {
this = API::moduleImport("loglevel").getMember(getAStandardLoggerMethodName()).getACall() this = API::moduleImport("loglevel").getMember(getAStandardLoggerMethodName()).getACall()
} }
override DataFlow::Node getAMessageComponent() { result = getAnArgument() } override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
} }
} }
@@ -111,9 +111,9 @@ private module Winston {
} }
override DataFlow::Node getAMessageComponent() { override DataFlow::Node getAMessageComponent() {
if getMethodName() = "log" if this.getMethodName() = "log"
then result = getOptionArgument(0, "message") then result = this.getOptionArgument(0, "message")
else result = getAnArgument() else result = this.getAnArgument()
} }
} }
} }
@@ -135,7 +135,7 @@ private module Log4js {
.getACall() .getACall()
} }
override DataFlow::Node getAMessageComponent() { result = getAnArgument() } override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
} }
} }
@@ -157,11 +157,11 @@ private module Npmlog {
override DataFlow::Node getAMessageComponent() { override DataFlow::Node getAMessageComponent() {
( (
if name = "log" if name = "log"
then result = getArgument([1 .. getNumArgument()]) then result = this.getArgument([1 .. this.getNumArgument()])
else result = getAnArgument() else result = this.getAnArgument()
) )
or or
result = getASpreadArgument() result = this.getASpreadArgument()
} }
} }
} }
@@ -179,7 +179,7 @@ private module Fancylog {
this = API::moduleImport("fancy-log").getACall() this = API::moduleImport("fancy-log").getACall()
} }
override DataFlow::Node getAMessageComponent() { result = getAnArgument() } override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
} }
} }
@@ -189,7 +189,7 @@ private module Fancylog {
private class DebugLoggerCall extends LoggerCall, API::CallNode { private class DebugLoggerCall extends LoggerCall, API::CallNode {
DebugLoggerCall() { this = API::moduleImport("debug").getReturn().getACall() } DebugLoggerCall() { this = API::moduleImport("debug").getReturn().getACall() }
override DataFlow::Node getAMessageComponent() { result = getAnArgument() } override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
} }
/** /**
@@ -293,11 +293,11 @@ class KleurStep extends TaintTracking::SharedTaintStep {
private API::Node kleurInstance() { private API::Node kleurInstance() {
result = API::moduleImport("kleur") result = API::moduleImport("kleur")
or or
result = kleurInstance().getAMember().getReturn() result = this.kleurInstance().getAMember().getReturn()
} }
override predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) { override predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(API::CallNode call | call = kleurInstance().getAMember().getACall() | exists(API::CallNode call | call = this.kleurInstance().getAMember().getACall() |
pred = call.getArgument(0) and pred = call.getArgument(0) and
succ = call succ = call
) )
@@ -363,7 +363,7 @@ private module Pino {
this = pino().getMember(["trace", "debug", "info", "warn", "error", "fatal"]).getACall() this = pino().getMember(["trace", "debug", "info", "warn", "error", "fatal"]).getACall()
} }
override DataFlow::Node getAMessageComponent() { result = getAnArgument() } override DataFlow::Node getAMessageComponent() { result = this.getAnArgument() }
} }
} }

View File

@@ -101,7 +101,7 @@ private module Micro {
override string getKind() { result = "body" } override string getKind() { result = "body" }
override Http::RouteHandler getRouteHandler() { override Http::RouteHandler getRouteHandler() {
result = getRouteHandlerFromReqRes(getArgument(0)) result = getRouteHandlerFromReqRes(this.getArgument(0))
} }
override predicate isUserControlledObject() { name = "json" } override predicate isUserControlledObject() { name = "json" }

View File

@@ -114,9 +114,9 @@ private class SimplePropertyProjection extends PropertyProjection::Range {
this = getASimplePropertyProjectionCallee(singleton, selectorIndex, objectIndex).getACall() this = getASimplePropertyProjectionCallee(singleton, selectorIndex, objectIndex).getACall()
} }
override DataFlow::Node getObject() { result = getArgument(objectIndex) } override DataFlow::Node getObject() { result = this.getArgument(objectIndex) }
override DataFlow::Node getASelector() { result = getArgument(selectorIndex) } override DataFlow::Node getASelector() { result = this.getArgument(selectorIndex) }
override predicate isSingletonProjection() { singleton = true } override predicate isSingletonProjection() { singleton = true }
} }
@@ -127,9 +127,9 @@ private class SimplePropertyProjection extends PropertyProjection::Range {
private class VarArgsPropertyProjection extends PropertyProjection::Range { private class VarArgsPropertyProjection extends PropertyProjection::Range {
VarArgsPropertyProjection() { this = LodashUnderscore::member("pick").getACall() } VarArgsPropertyProjection() { this = LodashUnderscore::member("pick").getACall() }
override DataFlow::Node getObject() { result = getArgument(0) } override DataFlow::Node getObject() { result = this.getArgument(0) }
override DataFlow::Node getASelector() { result = getArgument(any(int i | i > 0)) } override DataFlow::Node getASelector() { result = this.getArgument(any(int i | i > 0)) }
override predicate isSingletonProjection() { none() } override predicate isSingletonProjection() { none() }
} }

View File

@@ -71,7 +71,7 @@ module Puppeteer {
private class PuppeteerGotoCall extends ClientRequest::Range, API::InvokeNode { private class PuppeteerGotoCall extends ClientRequest::Range, API::InvokeNode {
PuppeteerGotoCall() { this = page().getMember("goto").getACall() } PuppeteerGotoCall() { this = page().getMember("goto").getACall() }
override DataFlow::Node getUrl() { result = getArgument(0) } override DataFlow::Node getUrl() { result = this.getArgument(0) }
override DataFlow::Node getHost() { none() } override DataFlow::Node getHost() { none() }
@@ -86,7 +86,7 @@ module Puppeteer {
this = page().getMember(["addStyleTag", "addScriptTag"]).getACall() this = page().getMember(["addStyleTag", "addScriptTag"]).getACall()
} }
override DataFlow::Node getUrl() { result = getParameter(0).getMember("url").asSink() } override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("url").asSink() }
override DataFlow::Node getHost() { none() } override DataFlow::Node getHost() { none() }

View File

@@ -53,18 +53,18 @@ abstract class ReactComponent extends AstNode {
* Gets a reference to an instance of this component. * Gets a reference to an instance of this component.
*/ */
pragma[noinline] pragma[noinline]
DataFlow::SourceNode getAnInstanceReference() { result = ref() } DataFlow::SourceNode getAnInstanceReference() { result = this.ref() }
/** /**
* Gets a reference to this component. * Gets a reference to this component.
*/ */
DataFlow::Node ref() { result.analyze().getAValue() = getAbstractComponent() } DataFlow::Node ref() { result.analyze().getAValue() = this.getAbstractComponent() }
/** /**
* Gets the `this` node in an instance method of this component. * Gets the `this` node in an instance method of this component.
*/ */
DataFlow::SourceNode getAThisNode() { DataFlow::SourceNode getAThisNode() {
result.(DataFlow::ThisNode).getBinder().getFunction() = getInstanceMethod(_) result.(DataFlow::ThisNode).getBinder().getFunction() = this.getInstanceMethod(_)
} }
/** /**
@@ -76,19 +76,19 @@ abstract class ReactComponent extends AstNode {
* Gets an access to the `state` object of this component. * Gets an access to the `state` object of this component.
*/ */
DataFlow::SourceNode getADirectStateAccess() { DataFlow::SourceNode getADirectStateAccess() {
result = getAnInstanceReference().getAPropertyReference("state") result = this.getAnInstanceReference().getAPropertyReference("state")
} }
/** /**
* Gets a data flow node that reads a prop of this component. * Gets a data flow node that reads a prop of this component.
*/ */
DataFlow::PropRead getAPropRead() { result = getADirectPropsAccess().getAPropertyRead() } DataFlow::PropRead getAPropRead() { result = this.getADirectPropsAccess().getAPropertyRead() }
/** /**
* Gets a data flow node that reads prop `name` of this component. * Gets a data flow node that reads prop `name` of this component.
*/ */
DataFlow::PropRead getAPropRead(string name) { DataFlow::PropRead getAPropRead(string name) {
result = getADirectPropsAccess().getAPropertyRead(name) result = this.getADirectPropsAccess().getAPropertyRead(name)
} }
/** /**
@@ -96,16 +96,16 @@ abstract class ReactComponent extends AstNode {
* of the state object of this component. * of the state object of this component.
*/ */
DataFlow::SourceNode getAStateAccess() { DataFlow::SourceNode getAStateAccess() {
result = getADirectStateAccess() result = this.getADirectStateAccess()
or or
result = getAStateAccess().getAPropertyReference() result = this.getAStateAccess().getAPropertyReference()
} }
/** /**
* Holds if this component specifies default values for (some of) its * Holds if this component specifies default values for (some of) its
* props. * props.
*/ */
predicate hasDefaultProps() { exists(getADefaultPropsSource()) } predicate hasDefaultProps() { exists(this.getADefaultPropsSource()) }
/** /**
* Gets the object that specifies default values for (some of) this * Gets the object that specifies default values for (some of) this
@@ -116,13 +116,13 @@ abstract class ReactComponent extends AstNode {
/** /**
* Gets the render method of this component. * Gets the render method of this component.
*/ */
Function getRenderMethod() { result = getInstanceMethod("render") } Function getRenderMethod() { result = this.getInstanceMethod("render") }
/** /**
* Gets a call to method `name` on this component. * Gets a call to method `name` on this component.
*/ */
DataFlow::MethodCallNode getAMethodCall(string name) { DataFlow::MethodCallNode getAMethodCall(string name) {
result = getAnInstanceReference().getAMethodCall(name) result = this.getAnInstanceReference().getAMethodCall(name)
} }
/** /**
@@ -131,11 +131,11 @@ abstract class ReactComponent extends AstNode {
*/ */
DataFlow::SourceNode getACandidateStateSource() { DataFlow::SourceNode getACandidateStateSource() {
// a direct definition: `this.state = o` // a direct definition: `this.state = o`
result = getAnInstanceReference().getAPropertySource("state") result = this.getAnInstanceReference().getAPropertySource("state")
or or
exists(DataFlow::MethodCallNode mce, DataFlow::SourceNode arg0 | exists(DataFlow::MethodCallNode mce, DataFlow::SourceNode arg0 |
mce = getAMethodCall("setState") or mce = this.getAMethodCall("setState") or
mce = getAMethodCall("forceUpdate") mce = this.getAMethodCall("forceUpdate")
| |
arg0.flowsTo(mce.getArgument(0)) and arg0.flowsTo(mce.getArgument(0)) and
if arg0 instanceof DataFlow::FunctionNode if arg0 instanceof DataFlow::FunctionNode
@@ -151,11 +151,12 @@ abstract class ReactComponent extends AstNode {
staticMember = "getDerivedStateFromProps" or staticMember = "getDerivedStateFromProps" or
staticMember = "getDerivedStateFromError" staticMember = "getDerivedStateFromError"
| |
result.flowsToExpr(getStaticMethod(staticMember).getAReturnedExpr()) result.flowsToExpr(this.getStaticMethod(staticMember).getAReturnedExpr())
) )
or or
// shouldComponentUpdate: (nextProps, nextState) // shouldComponentUpdate: (nextProps, nextState)
result = DataFlow::parameterNode(getInstanceMethod("shouldComponentUpdate").getParameter(1)) result =
DataFlow::parameterNode(this.getInstanceMethod("shouldComponentUpdate").getParameter(1))
} }
/** /**
@@ -169,19 +170,19 @@ abstract class ReactComponent extends AstNode {
callback.getParameter(stateParameterIndex).flowsTo(result) callback.getParameter(stateParameterIndex).flowsTo(result)
| |
// setState: (prevState, props) // setState: (prevState, props)
callback = getAMethodCall("setState").getCallback(0) and callback = this.getAMethodCall("setState").getCallback(0) and
stateParameterIndex = 0 stateParameterIndex = 0
or or
stateParameterIndex = 1 and stateParameterIndex = 1 and
( (
// componentDidUpdate: (prevProps, prevState) // componentDidUpdate: (prevProps, prevState)
callback = getInstanceMethod("componentDidUpdate").flow() callback = this.getInstanceMethod("componentDidUpdate").flow()
or or
// getDerivedStateFromProps: (props, state) // getDerivedStateFromProps: (props, state)
callback = getStaticMethod("getDerivedStateFromProps").flow() callback = this.getStaticMethod("getDerivedStateFromProps").flow()
or or
// getSnapshotBeforeUpdate: (prevProps, prevState) // getSnapshotBeforeUpdate: (prevProps, prevState)
callback = getInstanceMethod("getSnapshotBeforeUpdate").flow() callback = this.getInstanceMethod("getSnapshotBeforeUpdate").flow()
) )
) )
} }
@@ -192,12 +193,13 @@ abstract class ReactComponent extends AstNode {
* constructor of this component. * constructor of this component.
*/ */
DataFlow::SourceNode getACandidatePropsSource() { DataFlow::SourceNode getACandidatePropsSource() {
result.flowsTo(getAComponentCreatorReference().getAnInvocation().getArgument(0)) result.flowsTo(this.getAComponentCreatorReference().getAnInvocation().getArgument(0))
or or
result = getADefaultPropsSource() result = this.getADefaultPropsSource()
or or
// shouldComponentUpdate: (nextProps, nextState) // shouldComponentUpdate: (nextProps, nextState)
result = DataFlow::parameterNode(getInstanceMethod("shouldComponentUpdate").getParameter(0)) result =
DataFlow::parameterNode(this.getInstanceMethod("shouldComponentUpdate").getParameter(0))
} }
/** /**
@@ -206,7 +208,7 @@ abstract class ReactComponent extends AstNode {
* element that instantiates this component. * element that instantiates this component.
*/ */
DataFlow::Node getACandidatePropsValue(string name) { DataFlow::Node getACandidatePropsValue(string name) {
getACandidatePropsSource().hasPropertyWrite(name, result) this.getACandidatePropsSource().hasPropertyWrite(name, result)
or or
exists(ReactJsxElement e, JsxAttribute attr | exists(ReactJsxElement e, JsxAttribute attr |
this = e.getComponent() and this = e.getComponent() and
@@ -226,19 +228,19 @@ abstract class ReactComponent extends AstNode {
callback.getParameter(propsParameterIndex).flowsTo(result) callback.getParameter(propsParameterIndex).flowsTo(result)
| |
// setState: (prevState, props) // setState: (prevState, props)
callback = getAMethodCall("setState").getCallback(0) and callback = this.getAMethodCall("setState").getCallback(0) and
propsParameterIndex = 1 propsParameterIndex = 1
or or
propsParameterIndex = 0 and propsParameterIndex = 0 and
( (
// componentDidUpdate: (prevProps, prevState) // componentDidUpdate: (prevProps, prevState)
callback = getInstanceMethod("componentDidUpdate").flow() callback = this.getInstanceMethod("componentDidUpdate").flow()
or or
// getDerivedStateFromProps: (props, state) // getDerivedStateFromProps: (props, state)
callback = getStaticMethod("getDerivedStateFromProps").flow() callback = this.getStaticMethod("getDerivedStateFromProps").flow()
or or
// getSnapshotBeforeUpdate: (prevProps, prevState) // getSnapshotBeforeUpdate: (prevProps, prevState)
callback = getInstanceMethod("getSnapshotBeforeUpdate").flow() callback = this.getInstanceMethod("getSnapshotBeforeUpdate").flow()
) )
) )
} }
@@ -266,8 +268,8 @@ class FunctionalComponent extends ReactComponent, Function {
// heuristic: a function with a single parameter named `props` // heuristic: a function with a single parameter named `props`
// that always returns a JSX element or fragment, or a React // that always returns a JSX element or fragment, or a React
// element is probably a component // element is probably a component
getNumParameter() = 1 and this.getNumParameter() = 1 and
exists(Parameter p | p = getParameter(0) | exists(Parameter p | p = this.getParameter(0) |
p.getName().regexpMatch("(?i).*props.*") or p.getName().regexpMatch("(?i).*props.*") or
p instanceof ObjectPattern p instanceof ObjectPattern
) and ) and
@@ -279,7 +281,7 @@ class FunctionalComponent extends ReactComponent, Function {
override Function getStaticMethod(string name) { none() } override Function getStaticMethod(string name) { none() }
override DataFlow::SourceNode getADirectPropsAccess() { override DataFlow::SourceNode getADirectPropsAccess() {
result = DataFlow::parameterNode(getParameter(0)) result = DataFlow::parameterNode(this.getParameter(0))
} }
override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) } override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) }
@@ -288,11 +290,11 @@ class FunctionalComponent extends ReactComponent, Function {
t.start() and t.start() and
result = DataFlow::valueNode(this) result = DataFlow::valueNode(this)
or or
exists(DataFlow::TypeTracker t2 | result = getAComponentCreatorReference(t2).track(t2, t)) exists(DataFlow::TypeTracker t2 | result = this.getAComponentCreatorReference(t2).track(t2, t))
} }
override DataFlow::SourceNode getAComponentCreatorReference() { override DataFlow::SourceNode getAComponentCreatorReference() {
result = getAComponentCreatorReference(DataFlow::TypeTracker::end()) result = this.getAComponentCreatorReference(DataFlow::TypeTracker::end())
} }
override DataFlow::SourceNode getComponentCreatorSource() { result = DataFlow::valueNode(this) } override DataFlow::SourceNode getComponentCreatorSource() { result = DataFlow::valueNode(this) }
@@ -315,16 +317,16 @@ abstract private class SharedReactPreactClassComponent extends ReactComponent, C
override Function getStaticMethod(string name) { override Function getStaticMethod(string name) {
exists(MethodDeclaration decl | exists(MethodDeclaration decl |
decl = getMethod(name) and decl = this.getMethod(name) and
decl.isStatic() and decl.isStatic() and
result = decl.getBody() result = decl.getBody()
) )
} }
override DataFlow::SourceNode getADirectPropsAccess() { override DataFlow::SourceNode getADirectPropsAccess() {
result = getAnInstanceReference().getAPropertyRead("props") result = this.getAnInstanceReference().getAPropertyRead("props")
or or
result = DataFlow::parameterNode(getConstructor().getBody().getParameter(0)) result = DataFlow::parameterNode(this.getConstructor().getBody().getParameter(0))
} }
override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) } override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) }
@@ -337,7 +339,7 @@ abstract private class SharedReactPreactClassComponent extends ReactComponent, C
override DataFlow::SourceNode getACandidateStateSource() { override DataFlow::SourceNode getACandidateStateSource() {
result = ReactComponent.super.getACandidateStateSource() or result = ReactComponent.super.getACandidateStateSource() or
result.flowsToExpr(getField("state").getInit()) result.flowsToExpr(this.getField("state").getInit())
} }
override DataFlow::SourceNode getADefaultPropsSource() { override DataFlow::SourceNode getADefaultPropsSource() {
@@ -359,7 +361,7 @@ abstract class ES2015Component extends SharedReactPreactClassComponent { }
*/ */
private class DefiniteES2015Component extends ES2015Component { private class DefiniteES2015Component extends ES2015Component {
DefiniteES2015Component() { DefiniteES2015Component() {
exists(DataFlow::SourceNode sup | sup.flowsToExpr(getSuperClass()) | exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.getSuperClass()) |
exists(PropAccess access, string globalReactName | exists(PropAccess access, string globalReactName |
(globalReactName = "react" or globalReactName = "React") and (globalReactName = "react" or globalReactName = "React") and
access = sup.asExpr() access = sup.asExpr()
@@ -383,12 +385,12 @@ private class DefiniteES2015Component extends ES2015Component {
abstract class PreactComponent extends SharedReactPreactClassComponent { abstract class PreactComponent extends SharedReactPreactClassComponent {
override DataFlow::SourceNode getADirectPropsAccess() { override DataFlow::SourceNode getADirectPropsAccess() {
result = super.getADirectPropsAccess() or result = super.getADirectPropsAccess() or
result = DataFlow::parameterNode(getInstanceMethod("render").getParameter(0)) result = DataFlow::parameterNode(this.getInstanceMethod("render").getParameter(0))
} }
override DataFlow::SourceNode getADirectStateAccess() { override DataFlow::SourceNode getADirectStateAccess() {
result = super.getADirectStateAccess() or result = super.getADirectStateAccess() or
result = DataFlow::parameterNode(getInstanceMethod("render").getParameter(1)) result = DataFlow::parameterNode(this.getInstanceMethod("render").getParameter(1))
} }
} }
@@ -397,7 +399,7 @@ abstract class PreactComponent extends SharedReactPreactClassComponent {
*/ */
private class DefinitePreactComponent extends PreactComponent { private class DefinitePreactComponent extends PreactComponent {
DefinitePreactComponent() { DefinitePreactComponent() {
exists(DataFlow::SourceNode sup | sup.flowsToExpr(getSuperClass()) | exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.getSuperClass()) |
exists(PropAccess access, string globalPreactName | exists(PropAccess access, string globalPreactName |
(globalPreactName = "preact" or globalPreactName = "Preact") and (globalPreactName = "preact" or globalPreactName = "Preact") and
access = sup.asExpr() access = sup.asExpr()
@@ -420,7 +422,7 @@ private class HeuristicReactPreactComponent extends ClassDefinition, PreactCompo
ES2015Component ES2015Component
{ {
HeuristicReactPreactComponent() { HeuristicReactPreactComponent() {
any(DataFlow::GlobalVarRefNode c | c.getName() = "Component").flowsToExpr(getSuperClass()) and any(DataFlow::GlobalVarRefNode c | c.getName() = "Component").flowsToExpr(this.getSuperClass()) and
alwaysReturnsJsxOrReactElements(ClassDefinition.super.getInstanceMethod("render")) alwaysReturnsJsxOrReactElements(ClassDefinition.super.getInstanceMethod("render"))
} }
} }
@@ -442,12 +444,14 @@ class ES5Component extends ReactComponent, ObjectExpr {
create.getArgument(0).getALocalSource().asExpr() = this create.getArgument(0).getALocalSource().asExpr() = this
} }
override Function getInstanceMethod(string name) { result = getPropertyByName(name).getInit() } override Function getInstanceMethod(string name) {
result = this.getPropertyByName(name).getInit()
}
override Function getStaticMethod(string name) { none() } override Function getStaticMethod(string name) { none() }
override DataFlow::SourceNode getADirectPropsAccess() { override DataFlow::SourceNode getADirectPropsAccess() {
result = getAnInstanceReference().getAPropertyRead("props") result = this.getAnInstanceReference().getAPropertyRead("props")
} }
override AbstractValue getAbstractComponent() { result = TAbstractObjectLiteral(this) } override AbstractValue getAbstractComponent() { result = TAbstractObjectLiteral(this) }
@@ -456,23 +460,23 @@ class ES5Component extends ReactComponent, ObjectExpr {
t.start() and t.start() and
result = create result = create
or or
exists(DataFlow::TypeTracker t2 | result = getAComponentCreatorReference(t2).track(t2, t)) exists(DataFlow::TypeTracker t2 | result = this.getAComponentCreatorReference(t2).track(t2, t))
} }
override DataFlow::SourceNode getAComponentCreatorReference() { override DataFlow::SourceNode getAComponentCreatorReference() {
result = getAComponentCreatorReference(DataFlow::TypeTracker::end()) result = this.getAComponentCreatorReference(DataFlow::TypeTracker::end())
} }
override DataFlow::SourceNode getComponentCreatorSource() { result = create } override DataFlow::SourceNode getComponentCreatorSource() { result = create }
override DataFlow::SourceNode getACandidateStateSource() { override DataFlow::SourceNode getACandidateStateSource() {
result = ReactComponent.super.getACandidateStateSource() or result = ReactComponent.super.getACandidateStateSource() or
result.flowsToExpr(getInstanceMethod("getInitialState").getAReturnedExpr()) result.flowsToExpr(this.getInstanceMethod("getInitialState").getAReturnedExpr())
} }
override DataFlow::SourceNode getADefaultPropsSource() { override DataFlow::SourceNode getADefaultPropsSource() {
exists(Function f | exists(Function f |
f = getInstanceMethod("getDefaultProps") and f = this.getInstanceMethod("getDefaultProps") and
result.flowsToExpr(f.getAReturnedExpr()) result.flowsToExpr(f.getAReturnedExpr())
) )
} }
@@ -538,13 +542,13 @@ private class ReactCallbackPartialInvoke extends DataFlow::PartialInvokeNode::Ra
name = "forEach" name = "forEach"
| |
this = react().getAPropertyRead("Children").getAMemberCall(name) and this = react().getAPropertyRead("Children").getAMemberCall(name) and
3 = getNumArgument() 3 = this.getNumArgument()
) )
} }
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) { override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
callback = getArgument(1) and callback = this.getArgument(1) and
result = getArgument(2) result = this.getArgument(2)
} }
} }
@@ -554,7 +558,7 @@ private class ReactCallbackPartialInvoke extends DataFlow::PartialInvokeNode::Ra
private class ReactJsxElement extends JsxElement { private class ReactJsxElement extends JsxElement {
ReactComponent component; ReactComponent component;
ReactJsxElement() { component.getAComponentCreatorReference().flowsToExpr(getNameExpr()) } ReactJsxElement() { component.getAComponentCreatorReference().flowsToExpr(this.getNameExpr()) }
/** /**
* Gets the component this element instantiates. * Gets the component this element instantiates.

View File

@@ -58,7 +58,7 @@ module Redux {
*/ */
class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range { class StoreCreation extends DataFlow::SourceNode instanceof StoreCreation::Range {
/** Gets a reference to the store. */ /** Gets a reference to the store. */
DataFlow::SourceNode ref() { result = asApiNode().getAValueReachableFromSource() } DataFlow::SourceNode ref() { result = this.asApiNode().getAValueReachableFromSource() }
/** Gets an API node that refers to this store creation. */ /** Gets an API node that refers to this store creation. */
API::Node asApiNode() { result.asSource() = this } API::Node asApiNode() { result.asSource() = this }
@@ -67,7 +67,9 @@ module Redux {
DataFlow::Node getReducerArg() { result = super.getReducerArg() } DataFlow::Node getReducerArg() { result = super.getReducerArg() }
/** Gets a data flow node referring to the root reducer. */ /** Gets a data flow node referring to the root reducer. */
DataFlow::SourceNode getAReducerSource() { result = getReducerArg().(ReducerArg).getASource() } DataFlow::SourceNode getAReducerSource() {
result = this.getReducerArg().(ReducerArg).getASource()
}
} }
/** Companion module to the `StoreCreation` class. */ /** Companion module to the `StoreCreation` class. */
@@ -85,7 +87,7 @@ module Redux {
this = API::moduleImport(["redux", "@reduxjs/toolkit"]).getMember("createStore").getACall() this = API::moduleImport(["redux", "@reduxjs/toolkit"]).getMember("createStore").getACall()
} }
override DataFlow::Node getReducerArg() { result = getArgument(0) } override DataFlow::Node getReducerArg() { result = this.getArgument(0) }
} }
private class ToolkitStore extends API::CallNode, Range { private class ToolkitStore extends API::CallNode, Range {
@@ -94,7 +96,7 @@ module Redux {
} }
override DataFlow::Node getReducerArg() { override DataFlow::Node getReducerArg() {
result = getParameter(0).getMember("reducer").asSink() result = this.getParameter(0).getMember("reducer").asSink()
} }
} }
} }
@@ -193,7 +195,7 @@ module Redux {
CombineReducers() { this = combineReducers().getACall() } CombineReducers() { this = combineReducers().getACall() }
override DataFlow::Node getStateHandlerArg(string prop) { override DataFlow::Node getStateHandlerArg(string prop) {
result = getParameter(0).getMember(prop).asSink() result = this.getParameter(0).getMember(prop).asSink()
} }
} }
@@ -211,7 +213,7 @@ module Redux {
} }
override DataFlow::Node getStateHandlerArg(string prop) { override DataFlow::Node getStateHandlerArg(string prop) {
result = getAPropertyWrite(prop).getRhs() result = this.getAPropertyWrite(prop).getRhs()
} }
} }
@@ -235,7 +237,7 @@ module Redux {
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) { override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
exists(DataFlow::PropWrite write | exists(DataFlow::PropWrite write |
result = getParameter(0).getAMember().asSink() and result = this.getParameter(0).getAMember().asSink() and
write.getRhs() = result and write.getRhs() = result and
actionType = write.getPropertyNameExpr().flow() actionType = write.getPropertyNameExpr().flow()
) )
@@ -258,8 +260,8 @@ module Redux {
} }
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) { override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
actionType = getArgument(0) and actionType = this.getArgument(0) and
result = getArgument(1) result = this.getArgument(1)
} }
} }
@@ -271,7 +273,7 @@ module Redux {
this = API::moduleImport("redux-persist").getMember("persistReducer").getACall() this = API::moduleImport("redux-persist").getMember("persistReducer").getACall()
} }
override DataFlow::Node getAPlainHandlerArg() { result = getArgument(1) } override DataFlow::Node getAPlainHandlerArg() { result = this.getArgument(1) }
} }
/** /**
@@ -284,7 +286,7 @@ module Redux {
this = API::moduleImport("immer").getMember("produce").getACall() this = API::moduleImport("immer").getMember("produce").getACall()
} }
override DataFlow::Node getAPlainHandlerArg() { result = getArgument(0) } override DataFlow::Node getAPlainHandlerArg() { result = this.getArgument(0) }
} }
/** /**
@@ -312,9 +314,9 @@ module Redux {
} }
override DataFlow::Node getAPlainHandlerArg() { override DataFlow::Node getAPlainHandlerArg() {
result = getAnArgument() result = this.getAnArgument()
or or
result = getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement() result = this.getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
} }
} }
@@ -335,14 +337,14 @@ module Redux {
} }
private API::Node getABuilderRef() { private API::Node getABuilderRef() {
result = getParameter(1).getParameter(0) result = this.getParameter(1).getParameter(0)
or or
result = getABuilderRef().getAMember().getReturn() result = this.getABuilderRef().getAMember().getReturn()
} }
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) { override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
exists(API::CallNode addCase | exists(API::CallNode addCase |
addCase = getABuilderRef().getMember("addCase").getACall() and addCase = this.getABuilderRef().getMember("addCase").getACall() and
actionType = addCase.getArgument(0) and actionType = addCase.getArgument(0) and
result = addCase.getArgument(1) result = addCase.getArgument(1)
) )
@@ -380,7 +382,7 @@ module Redux {
private API::Node getABuilderRef() { private API::Node getABuilderRef() {
result = call.getParameter(0).getMember("extraReducers").getParameter(0) result = call.getParameter(0).getMember("extraReducers").getParameter(0)
or or
result = getABuilderRef().getAMember().getReturn() result = this.getABuilderRef().getAMember().getReturn()
} }
override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) { override DataFlow::Node getActionHandlerArg(DataFlow::Node actionType) {
@@ -400,7 +402,7 @@ module Redux {
// Builder callback to 'extraReducers': // Builder callback to 'extraReducers':
// extraReducers: builder => builder.addCase(action, reducer) // extraReducers: builder => builder.addCase(action, reducer)
exists(API::CallNode addCase | exists(API::CallNode addCase |
addCase = getABuilderRef().getMember("addCase").getACall() and addCase = this.getABuilderRef().getMember("addCase").getACall() and
actionType = addCase.getArgument(0) and actionType = addCase.getArgument(0) and
result = addCase.getArgument(1) result = addCase.getArgument(1)
) )
@@ -444,7 +446,7 @@ module Redux {
or or
// x -> bindActionCreators({ x, ... }) // x -> bindActionCreators({ x, ... })
exists(BindActionCreatorsCall bind, string prop | exists(BindActionCreatorsCall bind, string prop |
ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).asSink()) and this.ref(t.continue()).flowsTo(bind.getParameter(0).getMember(prop).asSink()) and
result = bind.getReturn().getMember(prop).asSource() result = bind.getReturn().getMember(prop).asSource()
) )
or or
@@ -454,32 +456,32 @@ module Redux {
API::moduleImport(["redux-actions", "redux-ts-utils"]) API::moduleImport(["redux-actions", "redux-ts-utils"])
.getMember("combineActions") .getMember("combineActions")
.getACall() and .getACall() and
ref(t.continue()).flowsTo(combiner.getAnArgument()) and this.ref(t.continue()).flowsTo(combiner.getAnArgument()) and
result = combiner result = combiner
) )
or or
// x -> x.fulfilled, for async action creators // x -> x.fulfilled, for async action creators
result = ref(t.continue()).getAPropertyRead("fulfilled") result = this.ref(t.continue()).getAPropertyRead("fulfilled")
or or
// follow flow through mapDispatchToProps // follow flow through mapDispatchToProps
ReactRedux::dispatchToPropsStep(ref(t.continue()).getALocalUse(), result) ReactRedux::dispatchToPropsStep(this.ref(t.continue()).getALocalUse(), result)
or or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
} }
/** Gets a data flow node referring to this action creator. */ /** Gets a data flow node referring to this action creator. */
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) }
/** /**
* Gets a block that is executed when a check has determined that `action` originated from this action creator. * Gets a block that is executed when a check has determined that `action` originated from this action creator.
*/ */
private ReachableBasicBlock getASuccessfulTypeCheckBlock(DataFlow::SourceNode action) { private ReachableBasicBlock getASuccessfulTypeCheckBlock(DataFlow::SourceNode action) {
action = getAnUntypedActionInReducer() and action = getAnUntypedActionInReducer() and
result = getASuccessfulTypeCheckBlock(action, getTypeTag()) result = getASuccessfulTypeCheckBlock(action, this.getTypeTag())
or or
// some action creators implement a .match method for this purpose // some action creators implement a .match method for this purpose
exists(ConditionGuardNode guard, DataFlow::CallNode call | exists(ConditionGuardNode guard, DataFlow::CallNode call |
call = ref().getAMethodCall("match") and call = this.ref().getAMethodCall("match") and
guard.getTest() = call.asExpr() and guard.getTest() = call.asExpr() and
action.flowsTo(call.getArgument(0)) and action.flowsTo(call.getArgument(0)) and
guard.getOutcome() = true and guard.getOutcome() = true and
@@ -497,9 +499,9 @@ module Redux {
*/ */
DataFlow::FunctionNode getAReducerFunction() { DataFlow::FunctionNode getAReducerFunction() {
exists(ReducerArg reducer | exists(ReducerArg reducer |
reducer.isTypeTagHandler(getTypeTag()) reducer.isTypeTagHandler(this.getTypeTag())
or or
reducer.isActionTypeHandler(ref().getALocalUse()) reducer.isActionTypeHandler(this.ref().getALocalUse())
| |
result = reducer.getASource() result = reducer.getASource()
) )
@@ -511,16 +513,17 @@ module Redux {
exists(DataFlow::SourceNode actionSrc | exists(DataFlow::SourceNode actionSrc |
actionSrc = getAnUntypedActionInReducer() and actionSrc = getAnUntypedActionInReducer() and
result = actionSrc.getAPropertyRead("payload") and result = actionSrc.getAPropertyRead("payload") and
getASuccessfulTypeCheckBlock(actionSrc).dominates(result.getBasicBlock()) this.getASuccessfulTypeCheckBlock(actionSrc).dominates(result.getBasicBlock())
) )
or or
result = getAReducerFunction().getParameter(1).getAPropertyRead("payload") result = this.getAReducerFunction().getParameter(1).getAPropertyRead("payload")
} }
/** Gets a data flow node referring to the first argument of the action creator invocation. */ /** Gets a data flow node referring to the first argument of the action creator invocation. */
DataFlow::SourceNode getAMetaArgReference() { DataFlow::SourceNode getAMetaArgReference() {
exists(ReducerArg reducer | exists(ReducerArg reducer |
reducer.isActionTypeHandler(ref().getAPropertyRead(["fulfilled", "rejected", "pending"])) and reducer
.isActionTypeHandler(this.ref().getAPropertyRead(["fulfilled", "rejected", "pending"])) and
result = result =
reducer reducer
.getASource() .getASource()
@@ -558,10 +561,10 @@ module Redux {
.getACall() .getACall()
} }
override string getTypeTag() { getArgument(0).mayHaveStringValue(result) } override string getTypeTag() { this.getArgument(0).mayHaveStringValue(result) }
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) { override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
result = getCallback(1) and async = false result = this.getCallback(1) and async = false
} }
} }
@@ -584,7 +587,7 @@ module Redux {
} }
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) { override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
result.flowsTo(createActions.getParameter(0).getMember(getTypeTag()).asSink()) and result.flowsTo(createActions.getParameter(0).getMember(this.getTypeTag()).asSink()) and
async = false async = false
} }
@@ -640,10 +643,10 @@ module Redux {
override DataFlow::FunctionNode getMiddlewareFunction(boolean async) { override DataFlow::FunctionNode getMiddlewareFunction(boolean async) {
async = true and async = true and
result = getParameter(1).getAValueReachingSink() result = this.getParameter(1).getAValueReachingSink()
} }
override string getTypeTag() { getArgument(0).mayHaveStringValue(result) } override string getTypeTag() { this.getArgument(0).mayHaveStringValue(result) }
} }
} }
@@ -681,26 +684,27 @@ module Redux {
/** Gets a data flow node that flows to this reducer argument. */ /** Gets a data flow node that flows to this reducer argument. */
DataFlow::SourceNode getASource(DataFlow::TypeBackTracker t) { DataFlow::SourceNode getASource(DataFlow::TypeBackTracker t) {
t.start() and t.start() and
result = getALocalSource() result = this.getALocalSource()
or or
// Step through forwarding functions // Step through forwarding functions
DataFlow::functionForwardingStep(result.getALocalUse(), getASource(t.continue())) DataFlow::functionForwardingStep(result.getALocalUse(), this.getASource(t.continue()))
or or
// Step through library functions like `redux-persist` // Step through library functions like `redux-persist`
result.getALocalUse() = getASource(t.continue()).(DelegatingReducer).getAPlainHandlerArg() result.getALocalUse() =
this.getASource(t.continue()).(DelegatingReducer).getAPlainHandlerArg()
or or
// Step through function composition (usually composed with various state "enhancer" functions) // Step through function composition (usually composed with various state "enhancer" functions)
exists(FunctionCompositionCall compose, DataFlow::CallNode call | exists(FunctionCompositionCall compose, DataFlow::CallNode call |
getASource(t.continue()) = call and this.getASource(t.continue()) = call and
call = compose.getACall() and call = compose.getACall() and
result.getALocalUse() = [compose.getAnOperandNode(), call.getAnArgument()] result.getALocalUse() = [compose.getAnOperandNode(), call.getAnArgument()]
) )
or or
exists(DataFlow::TypeBackTracker t2 | result = getASource(t2).backtrack(t2, t)) exists(DataFlow::TypeBackTracker t2 | result = this.getASource(t2).backtrack(t2, t))
} }
/** Gets a data flow node that flows to this reducer argument. */ /** Gets a data flow node that flows to this reducer argument. */
DataFlow::SourceNode getASource() { result = getASource(DataFlow::TypeBackTracker::end()) } DataFlow::SourceNode getASource() { result = this.getASource(DataFlow::TypeBackTracker::end()) }
/** /**
* Holds if the actions dispatched to this reducer have the given type, that is, * Holds if the actions dispatched to this reducer have the given type, that is,
@@ -721,7 +725,7 @@ module Redux {
*/ */
predicate isTypeTagHandler(string actionType) { predicate isTypeTagHandler(string actionType) {
exists(DataFlow::Node node | exists(DataFlow::Node node |
isActionTypeHandler(node) and this.isActionTypeHandler(node) and
actionType = getATypeTagFromNode(node) actionType = getATypeTagFromNode(node)
) )
} }
@@ -1035,7 +1039,7 @@ module Redux {
result = this result = this
or or
exists(FunctionCompositionCall compose | exists(FunctionCompositionCall compose |
getAComponentTransformer().flowsTo(compose.getAnOperandNode()) and this.getAComponentTransformer().flowsTo(compose.getAnOperandNode()) and
result = compose result = compose
) )
} }
@@ -1048,19 +1052,19 @@ module Redux {
// //
// const mapDispatchToProps = { foo } // const mapDispatchToProps = { foo }
// //
result = getMapDispatchToProps().getMember(name).asSink() result = this.getMapDispatchToProps().getMember(name).asSink()
or or
// //
// const mapDispatchToProps = dispatch => ( { foo } ) // const mapDispatchToProps = dispatch => ( { foo } )
// //
result = getMapDispatchToProps().getReturn().getMember(name).asSink() result = this.getMapDispatchToProps().getReturn().getMember(name).asSink()
or or
// Explicitly bound by bindActionCreators: // Explicitly bound by bindActionCreators:
// //
// const mapDispatchToProps = dispatch => bindActionCreators({ foo }, dispatch); // const mapDispatchToProps = dispatch => bindActionCreators({ foo }, dispatch);
// //
exists(BindActionCreatorsCall bind | exists(BindActionCreatorsCall bind |
bind.flowsTo(getMapDispatchToProps().getReturn().asSink()) and bind.flowsTo(this.getMapDispatchToProps().getReturn().asSink()) and
result = bind.getOptionArgument(0, name) result = bind.getOptionArgument(0, name)
) )
} }
@@ -1070,9 +1074,9 @@ module Redux {
*/ */
ReactComponent getReactComponent() { ReactComponent getReactComponent() {
exists(DataFlow::SourceNode component | component = result.getAComponentCreatorReference() | exists(DataFlow::SourceNode component | component = result.getAComponentCreatorReference() |
component.flowsTo(getAComponentTransformer().getACall().getArgument(0)) component.flowsTo(this.getAComponentTransformer().getACall().getArgument(0))
or or
component.(DataFlow::ClassNode).getADecorator() = getAComponentTransformer() component.(DataFlow::ClassNode).getADecorator() = this.getAComponentTransformer()
) )
} }
} }
@@ -1083,9 +1087,9 @@ module Redux {
this = API::moduleImport("react-redux").getMember("connect").getACall() this = API::moduleImport("react-redux").getMember("connect").getACall()
} }
override API::Node getMapStateToProps() { result = getParameter(0) } override API::Node getMapStateToProps() { result = this.getParameter(0) }
override API::Node getMapDispatchToProps() { result = getParameter(1) } override API::Node getMapDispatchToProps() { result = this.getParameter(1) }
} }
/** /**
@@ -1114,12 +1118,12 @@ module Redux {
HeuristicConnectFunction() { this = any(HeuristicConnectEntryPoint e).getANode().getACall() } HeuristicConnectFunction() { this = any(HeuristicConnectEntryPoint e).getANode().getACall() }
override API::Node getMapStateToProps() { override API::Node getMapStateToProps() {
result = getAParameter() and result = this.getAParameter() and
result.asSink().asExpr().(Identifier).getName() = "mapStateToProps" result.asSink().asExpr().(Identifier).getName() = "mapStateToProps"
} }
override API::Node getMapDispatchToProps() { override API::Node getMapDispatchToProps() {
result = getAParameter() and result = this.getAParameter() and
result.asSink().asExpr().(Identifier).getName() = "mapDispatchToProps" result.asSink().asExpr().(Identifier).getName() = "mapDispatchToProps"
} }
} }
@@ -1199,12 +1203,12 @@ module Redux {
/** Gets the `i`th selector callback, that is, a callback other than the result function. */ /** Gets the `i`th selector callback, that is, a callback other than the result function. */
API::Node getSelectorFunction(int i) { API::Node getSelectorFunction(int i) {
// When there are multiple callbacks, exclude the last one // When there are multiple callbacks, exclude the last one
result = getParameter(i) and result = this.getParameter(i) and
(i = 0 or i < getNumArgument() - 1) (i = 0 or i < this.getNumArgument() - 1)
or or
// Selector functions may be given as an array // Selector functions may be given as an array
exists(DataFlow::ArrayCreationNode array | exists(DataFlow::ArrayCreationNode array |
array.flowsTo(getArgument(0)) and array.flowsTo(this.getArgument(0)) and
result.getAValueReachableFromSource() = array.getElement(i) result.getAValueReachableFromSource() = array.getElement(i)
) )
} }

View File

@@ -64,14 +64,16 @@ module ShellJS {
/** Holds if the first argument starts with a `-`, indicating it is an option. */ /** Holds if the first argument starts with a `-`, indicating it is an option. */
predicate hasOptionsArg() { predicate hasOptionsArg() {
exists(string val | exists(string val |
getArgument(0).mayHaveStringValue(val) and this.getArgument(0).mayHaveStringValue(val) and
val.matches("-%") val.matches("-%")
) )
} }
/** Gets the `n`th argument after the initial options argument, if any. */ /** Gets the `n`th argument after the initial options argument, if any. */
DataFlow::Node getTranslatedArgument(int n) { DataFlow::Node getTranslatedArgument(int n) {
if hasOptionsArg() then result = getArgument(n + 1) else result = getArgument(n) if this.hasOptionsArg()
then result = this.getArgument(n + 1)
else result = this.getArgument(n)
} }
} }
@@ -83,7 +85,7 @@ module ShellJS {
name = ["cd", "cp", "touch", "chmod", "pushd", "find", "ls", "ln", "mkdir", "mv", "rm"] name = ["cd", "cp", "touch", "chmod", "pushd", "find", "ls", "ln", "mkdir", "mv", "rm"]
} }
override DataFlow::Node getAPathArgument() { result = getAnArgument() } override DataFlow::Node getAPathArgument() { result = this.getAnArgument() }
} }
/** /**
@@ -102,7 +104,7 @@ module ShellJS {
private class ShellJSRead extends FileSystemReadAccess, ShellJSCall { private class ShellJSRead extends FileSystemReadAccess, ShellJSCall {
ShellJSRead() { name = ["cat", "head", "sort", "tail", "uniq"] } ShellJSRead() { name = ["cat", "head", "sort", "tail", "uniq"] }
override DataFlow::Node getAPathArgument() { result = getAnArgument() } override DataFlow::Node getAPathArgument() { result = this.getAnArgument() }
override DataFlow::Node getADataNode() { result = this } override DataFlow::Node getADataNode() { result = this }
} }
@@ -124,7 +126,7 @@ module ShellJS {
// Do not treat regex patterns as filenames. // Do not treat regex patterns as filenames.
exists(int arg | exists(int arg |
arg >= offset and arg >= offset and
result = getTranslatedArgument(arg) result = this.getTranslatedArgument(arg)
) )
} }
@@ -137,15 +139,15 @@ module ShellJS {
private class ShellJSExec extends SystemCommandExecution, ShellJSCall { private class ShellJSExec extends SystemCommandExecution, ShellJSCall {
ShellJSExec() { name = "exec" } ShellJSExec() { name = "exec" }
override DataFlow::Node getACommandArgument() { result = getArgument(0) } override DataFlow::Node getACommandArgument() { result = this.getArgument(0) }
override predicate isShellInterpreted(DataFlow::Node arg) { arg = getACommandArgument() } override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getACommandArgument() }
override predicate isSync() { none() } override predicate isSync() { none() }
override DataFlow::Node getOptionsArg() { override DataFlow::Node getOptionsArg() {
result = getLastArgument() and result = this.getLastArgument() and
not result = getArgument(0) and not result = this.getArgument(0) and
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode // looks like argumentlist not result.getALocalSource() instanceof DataFlow::ArrayCreationNode // looks like argumentlist
} }
@@ -163,8 +165,8 @@ module ShellJS {
) )
} }
override DataFlow::Node getAPathArgument() { result = getArgument(0) } override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getADataNode() { result = getReceiver() } override DataFlow::Node getADataNode() { result = this.getReceiver() }
} }
} }

View File

@@ -87,11 +87,11 @@ private class LibraryFormatter extends PrintfStyleCall {
) )
} }
override DataFlow::Node getFormatString() { result = getArgument(formatIndex) } override DataFlow::Node getFormatString() { result = this.getArgument(formatIndex) }
override DataFlow::Node getFormatArgument(int i) { override DataFlow::Node getFormatArgument(int i) {
i >= 0 and i >= 0 and
result = getArgument(formatIndex + 1 + i) result = this.getArgument(formatIndex + 1 + i)
} }
override predicate returnsFormatted() { returns = true } override predicate returnsFormatted() { returns = true }

View File

@@ -79,13 +79,13 @@ private class SystemCommandExecutors extends SystemCommandExecution, DataFlow::I
sync = true sync = true
} }
override DataFlow::Node getACommandArgument() { result = getArgument(cmdArg) } override DataFlow::Node getACommandArgument() { result = this.getArgument(cmdArg) }
override predicate isShellInterpreted(DataFlow::Node arg) { override predicate isShellInterpreted(DataFlow::Node arg) {
arg = getACommandArgument() and shell = true arg = this.getACommandArgument() and shell = true
} }
override DataFlow::Node getArgumentList() { shell = false and result = getArgument(1) } override DataFlow::Node getArgumentList() { shell = false and result = this.getArgument(1) }
override predicate isSync() { sync = true } override predicate isSync() { sync = true }
@@ -93,9 +93,9 @@ private class SystemCommandExecutors extends SystemCommandExecution, DataFlow::I
( (
if optionsArg < 0 if optionsArg < 0
then then
result = getArgument(getNumArgument() + optionsArg) and result = this.getArgument(this.getNumArgument() + optionsArg) and
getNumArgument() + optionsArg > cmdArg this.getNumArgument() + optionsArg > cmdArg
else result = getArgument(optionsArg) else result = this.getArgument(optionsArg)
) and ) and
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode // looks like argumentlist not result.getALocalSource() instanceof DataFlow::ArrayCreationNode // looks like argumentlist
@@ -131,9 +131,9 @@ private class RemoteCommandExecutor extends SystemCommandExecution, DataFlow::In
) )
} }
override DataFlow::Node getACommandArgument() { result = getArgument(cmdArg) } override DataFlow::Node getACommandArgument() { result = this.getArgument(cmdArg) }
override predicate isShellInterpreted(DataFlow::Node arg) { arg = getACommandArgument() } override predicate isShellInterpreted(DataFlow::Node arg) { arg = this.getACommandArgument() }
override predicate isSync() { none() } override predicate isSync() { none() }
@@ -143,7 +143,7 @@ private class RemoteCommandExecutor extends SystemCommandExecution, DataFlow::In
private class Opener extends SystemCommandExecution, DataFlow::InvokeNode { private class Opener extends SystemCommandExecution, DataFlow::InvokeNode {
Opener() { this = API::moduleImport("opener").getACall() } Opener() { this = API::moduleImport("opener").getACall() }
override DataFlow::Node getACommandArgument() { result = getOptionArgument(1, "command") } override DataFlow::Node getACommandArgument() { result = this.getOptionArgument(1, "command") }
override predicate isShellInterpreted(DataFlow::Node arg) { none() } override predicate isShellInterpreted(DataFlow::Node arg) { none() }

View File

@@ -66,7 +66,7 @@ class JestTest extends Test, @call_expr {
exists(call.getArgument(0).getStringValue()) and exists(call.getArgument(0).getStringValue()) and
exists(call.getArgument(1).flow().getAFunctionValue(0)) exists(call.getArgument(1).flow().getAFunctionValue(0))
) and ) and
getFile() = getTestFile(any(File f), "test") this.getFile() = getTestFile(any(File f), "test")
} }
} }

View File

@@ -25,7 +25,7 @@ module TrustedTypes {
/** Gets the function passed as the given option. */ /** Gets the function passed as the given option. */
DataFlow::FunctionNode getPolicyCallback(string method) { DataFlow::FunctionNode getPolicyCallback(string method) {
result = getParameter(1).getMember(method).getAValueReachingSink() result = this.getParameter(1).getMember(method).getAValueReachingSink()
} }
} }

View File

@@ -168,7 +168,7 @@ module Vue {
/** Gets a component which is extended by this one. */ /** Gets a component which is extended by this one. */
Component getABaseComponent() { Component getABaseComponent() {
result.getComponentRef().getAValueReachableFromSource() = result.getComponentRef().getAValueReachableFromSource() =
getOwnOptions().getMember(["extends", "mixins"]).asSink() this.getOwnOptions().getMember(["extends", "mixins"]).asSink()
} }
/** /**
@@ -176,13 +176,13 @@ module Vue {
* of its base component. * of its base component.
*/ */
API::Node getOptions() { API::Node getOptions() {
result = getOwnOptions() result = this.getOwnOptions()
or or
result = getOwnOptions().getMember(["extends", "mixins"]).getAMember() result = this.getOwnOptions().getMember(["extends", "mixins"]).getAMember()
or or
result = getABaseComponent().getOptions() result = this.getABaseComponent().getOptions()
or or
result = getAsClassComponent().getDecoratorOptions() result = this.getAsClassComponent().getDecoratorOptions()
} }
/** /**
@@ -191,7 +191,7 @@ module Vue {
* Gets the options passed to the Vue object, such as the object literal `{...}` in `new Vue{{...})` * Gets the options passed to the Vue object, such as the object literal `{...}` in `new Vue{{...})`
* or the default export of a single-file component. * or the default export of a single-file component.
*/ */
deprecated DataFlow::Node getOwnOptionsObject() { result = getOwnOptions().asSink() } deprecated DataFlow::Node getOwnOptionsObject() { result = this.getOwnOptions().asSink() }
/** /**
* Gets the class implementing this Vue component, if any. * Gets the class implementing this Vue component, if any.
@@ -199,19 +199,21 @@ module Vue {
* Specifically, this is a class annotated with `@Component` which flows to the options * Specifically, this is a class annotated with `@Component` which flows to the options
* object of this Vue component. * object of this Vue component.
*/ */
ClassComponent getAsClassComponent() { result = getOwnOptions().getAValueReachingSink() } ClassComponent getAsClassComponent() { result = this.getOwnOptions().getAValueReachingSink() }
/** /**
* Gets the node for option `name` for this component, not including * Gets the node for option `name` for this component, not including
* those from extended objects and mixins. * those from extended objects and mixins.
*/ */
DataFlow::Node getOwnOption(string name) { result = getOwnOptions().getMember(name).asSink() } DataFlow::Node getOwnOption(string name) {
result = this.getOwnOptions().getMember(name).asSink()
}
/** /**
* Gets the node for option `name` for this component, including those from * Gets the node for option `name` for this component, including those from
* extended objects and mixins. * extended objects and mixins.
*/ */
DataFlow::Node getOption(string name) { result = getOptions().getMember(name).asSink() } DataFlow::Node getOption(string name) { result = this.getOptions().getMember(name).asSink() }
/** /**
* Gets a source node flowing into the option `name` of this component, including those from * Gets a source node flowing into the option `name` of this component, including those from
@@ -219,7 +221,7 @@ module Vue {
*/ */
pragma[nomagic] pragma[nomagic]
DataFlow::SourceNode getOptionSource(string name) { DataFlow::SourceNode getOptionSource(string name) {
result = getOptions().getMember(name).getAValueReachingSink() result = this.getOptions().getMember(name).getAValueReachingSink()
} }
/** /**
@@ -231,55 +233,55 @@ module Vue {
* Gets the node for the `data` option object of this component. * Gets the node for the `data` option object of this component.
*/ */
DataFlow::Node getData() { DataFlow::Node getData() {
result = getOption("data") result = this.getOption("data")
or or
result = getOptionSource("data").(DataFlow::FunctionNode).getReturnNode() result = this.getOptionSource("data").(DataFlow::FunctionNode).getReturnNode()
or or
result = getAsClassComponent().getAReceiverNode() result = this.getAsClassComponent().getAReceiverNode()
or or
result = getAsClassComponent().getInstanceMethod("data").getAReturn() result = this.getAsClassComponent().getInstanceMethod("data").getAReturn()
} }
/** /**
* Gets the node for the `template` option of this component. * Gets the node for the `template` option of this component.
*/ */
pragma[nomagic] pragma[nomagic]
DataFlow::SourceNode getTemplate() { result = getOptionSource("template") } DataFlow::SourceNode getTemplate() { result = this.getOptionSource("template") }
/** /**
* Gets the node for the `render` option of this component. * Gets the node for the `render` option of this component.
*/ */
pragma[nomagic] pragma[nomagic]
DataFlow::SourceNode getRender() { DataFlow::SourceNode getRender() {
result = getOptionSource("render") result = this.getOptionSource("render")
or or
result = getAsClassComponent().getInstanceMethod("render") result = this.getAsClassComponent().getInstanceMethod("render")
} }
/** /**
* Gets the node for the `methods` option of this component. * Gets the node for the `methods` option of this component.
*/ */
pragma[nomagic] pragma[nomagic]
DataFlow::SourceNode getMethods() { result = getOptionSource("methods") } DataFlow::SourceNode getMethods() { result = this.getOptionSource("methods") }
/** /**
* Gets the node for the `computed` option of this component. * Gets the node for the `computed` option of this component.
*/ */
pragma[nomagic] pragma[nomagic]
DataFlow::SourceNode getComputed() { result = getOptionSource("computed") } DataFlow::SourceNode getComputed() { result = this.getOptionSource("computed") }
/** /**
* Gets the node for the `watch` option of this component. * Gets the node for the `watch` option of this component.
*/ */
pragma[nomagic] pragma[nomagic]
DataFlow::SourceNode getWatch() { result = getOptionSource("watch") } DataFlow::SourceNode getWatch() { result = this.getOptionSource("watch") }
/** /**
* Gets the function responding to changes to the given `propName`. * Gets the function responding to changes to the given `propName`.
*/ */
DataFlow::FunctionNode getWatchHandler(string propName) { DataFlow::FunctionNode getWatchHandler(string propName) {
exists(API::Node propWatch | exists(API::Node propWatch |
propWatch = getOptions().getMember("watch").getMember(propName) and propWatch = this.getOptions().getMember("watch").getMember(propName) and
result = [propWatch, propWatch.getMember("handler")].getAValueReachingSink() result = [propWatch, propWatch.getMember("handler")].getAValueReachingSink()
) )
} }
@@ -288,11 +290,11 @@ module Vue {
* Gets a node for a member `name` of the `computed` option of this component that matches `kind`. * Gets a node for a member `name` of the `computed` option of this component that matches `kind`.
*/ */
private DataFlow::SourceNode getAccessor(string name, DataFlow::MemberKind kind) { private DataFlow::SourceNode getAccessor(string name, DataFlow::MemberKind kind) {
result = getComputed().getAPropertySource(name) and kind = DataFlow::MemberKind::getter() result = this.getComputed().getAPropertySource(name) and kind = DataFlow::MemberKind::getter()
or or
result = getComputed().getAPropertySource(name).getAPropertySource(memberKindVerb(kind)) result = this.getComputed().getAPropertySource(name).getAPropertySource(memberKindVerb(kind))
or or
result = getAsClassComponent().getInstanceMember(name, kind) and result = this.getAsClassComponent().getInstanceMember(name, kind) and
kind.isAccessor() kind.isAccessor()
} }
@@ -303,9 +305,9 @@ module Vue {
DataFlow::SourceNode getALifecycleHook(string hookName) { DataFlow::SourceNode getALifecycleHook(string hookName) {
hookName = lifecycleHookName() and hookName = lifecycleHookName() and
( (
result = getOptionSource(hookName) result = this.getOptionSource(hookName)
or or
result = getAsClassComponent().getInstanceMethod(hookName) result = this.getAsClassComponent().getInstanceMethod(hookName)
) )
} }
@@ -313,22 +315,22 @@ module Vue {
* Gets a node for a function that will be invoked with `this` bound to this component. * Gets a node for a function that will be invoked with `this` bound to this component.
*/ */
DataFlow::FunctionNode getABoundFunction() { DataFlow::FunctionNode getABoundFunction() {
result = getOptions().getAMember+().getAValueReachingSink() result = this.getOptions().getAMember+().getAValueReachingSink()
or or
result = getAsClassComponent().getAnInstanceMember() result = this.getAsClassComponent().getAnInstanceMember()
} }
/** Gets an API node referring to an instance of this component. */ /** Gets an API node referring to an instance of this component. */
API::Node getInstance() { result.asSource() = getABoundFunction().getReceiver() } API::Node getInstance() { result.asSource() = this.getABoundFunction().getReceiver() }
/** Gets a data flow node referring to an instance of this component. */ /** Gets a data flow node referring to an instance of this component. */
DataFlow::SourceNode getAnInstanceRef() { result = getInstance().asSource() } DataFlow::SourceNode getAnInstanceRef() { result = this.getInstance().asSource() }
pragma[noinline] pragma[noinline]
private DataFlow::PropWrite getAPropertyValueWrite(string name) { private DataFlow::PropWrite getAPropertyValueWrite(string name) {
result = getData().getALocalSource().getAPropertyWrite(name) result = this.getData().getALocalSource().getAPropertyWrite(name)
or or
result = getAnInstanceRef().getAPropertyWrite(name) result = this.getAnInstanceRef().getAPropertyWrite(name)
} }
/** /**
@@ -336,10 +338,10 @@ module Vue {
* returned form a getter defining that property. * returned form a getter defining that property.
*/ */
DataFlow::Node getAPropertyValue(string name) { DataFlow::Node getAPropertyValue(string name) {
result = getAPropertyValueWrite(name).getRhs() result = this.getAPropertyValueWrite(name).getRhs()
or or
exists(DataFlow::FunctionNode getter | exists(DataFlow::FunctionNode getter |
getter.flowsTo(getAccessor(name, DataFlow::MemberKind::getter())) and getter.flowsTo(this.getAccessor(name, DataFlow::MemberKind::getter())) and
result = getter.getAReturn() result = getter.getAReturn()
) )
} }
@@ -498,7 +500,7 @@ module Vue {
override API::Node getOwnOptions() { override API::Node getOwnOptions() {
// Use the entry point generated by `VueExportEntryPoint` // Use the entry point generated by `VueExportEntryPoint`
result.asSink() = getModule().getDefaultOrBulkExport() result.asSink() = this.getModule().getDefaultOrBulkExport()
} }
override string toString() { result = file.toString() } override string toString() { result = file.toString() }
@@ -508,7 +510,7 @@ module Vue {
* A `.vue` file. * A `.vue` file.
*/ */
class VueFile extends File { class VueFile extends File {
VueFile() { getExtension() = "vue" } VueFile() { this.getExtension() = "vue" }
} }
pragma[nomagic] pragma[nomagic]
@@ -584,7 +586,7 @@ module Vue {
*/ */
abstract class Element extends TElement { abstract class Element extends TElement {
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
string toString() { result = "<" + getName() + ">...</>" } string toString() { result = "<" + this.getName() + ">...</>" }
/** /**
* Holds if this element is at the specified location. * Holds if this element is at the specified location.

View File

@@ -87,11 +87,11 @@ module Vuex {
/** Gets the namespace prefix to use, or an empty string if no namespace was given. */ /** Gets the namespace prefix to use, or an empty string if no namespace was given. */
pragma[noinline] pragma[noinline]
string getNamespace() { string getNamespace() {
getNumArgument() = 2 and this.getNumArgument() = 2 and
result = result =
appendToNamespace(namespace, getParameter(0).getAValueReachingSink().getStringValue()) appendToNamespace(namespace, this.getParameter(0).getAValueReachingSink().getStringValue())
or or
getNumArgument() = 1 and this.getNumArgument() = 1 and
result = namespace result = namespace
} }
@@ -100,24 +100,25 @@ module Vuex {
*/ */
predicate hasMapping(string localName, string storeName) { predicate hasMapping(string localName, string storeName) {
// mapGetters('foo') // mapGetters('foo')
getLastParameter().getAValueReachingSink().getStringValue() = localName and this.getLastParameter().getAValueReachingSink().getStringValue() = localName and
storeName = getNamespace() + localName storeName = this.getNamespace() + localName
or or
// mapGetters(['foo', 'bar']) // mapGetters(['foo', 'bar'])
getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() = localName and this.getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() =
storeName = getNamespace() + localName localName and
storeName = this.getNamespace() + localName
or or
// mapGetters({foo: 'bar'}) // mapGetters({foo: 'bar'})
storeName = storeName =
getNamespace() + this.getNamespace() +
getLastParameter().getMember(localName).getAValueReachingSink().getStringValue() and this.getLastParameter().getMember(localName).getAValueReachingSink().getStringValue() and
localName != "*" // ignore special API graph member named "*" localName != "*" // ignore special API graph member named "*"
} }
/** Gets the Vue component in which the generated functions are installed. */ /** Gets the Vue component in which the generated functions are installed. */
Vue::Component getVueComponent() { Vue::Component getVueComponent() {
exists(DataFlow::ObjectLiteralNode obj | exists(DataFlow::ObjectLiteralNode obj |
obj.getASpreadProperty() = getReturn().getAValueReachableFromSource() and obj.getASpreadProperty() = this.getReturn().getAValueReachableFromSource() and
result.getOwnOptions().getAMember().asSink() = obj result.getOwnOptions().getAMember().asSink() = obj
) )
or or

View File

@@ -46,7 +46,7 @@ module XML {
) )
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(EntityKind kind) { override predicate resolvesEntities(EntityKind kind) {
// internal entities are always resolved // internal entities are always resolved
@@ -54,7 +54,7 @@ module XML {
or or
// other entities are only resolved if the configuration option `noent` is set to `true` // other entities are only resolved if the configuration option `noent` is set to `true`
exists(JS::Expr noent | exists(JS::Expr noent |
hasOptionArgument(1, "noent", noent) and this.hasOptionArgument(1, "noent", noent) and
noent.mayHaveBooleanValue(true) noent.mayHaveBooleanValue(true)
) )
} }
@@ -66,23 +66,24 @@ module XML {
private API::Node doc() { private API::Node doc() {
result = call.getReturn() result = call.getReturn()
or or
result = doc().getMember("encoding").getReturn() result = this.doc().getMember("encoding").getReturn()
or or
result = element().getMember("doc").getReturn() result = this.element().getMember("doc").getReturn()
or or
result = element().getMember("parent").getReturn() result = this.element().getMember("parent").getReturn()
} }
/** /**
* Gets an `Element` from the `libxmljs` library. * Gets an `Element` from the `libxmljs` library.
*/ */
private API::Node element() { private API::Node element() {
result = doc().getMember(["child", "get", "node", "root"]).getReturn() result = this.doc().getMember(["child", "get", "node", "root"]).getReturn()
or
result = [doc(), element()].getMember(["childNodes", "find"]).getReturn().getAMember()
or or
result = result =
element() [this.doc(), this.element()].getMember(["childNodes", "find"]).getReturn().getAMember()
or
result =
this.element()
.getMember([ .getMember([
"parent", "prevSibling", "nextSibling", "remove", "clone", "node", "child", "parent", "prevSibling", "nextSibling", "remove", "clone", "node", "child",
"prevElement", "nextElement" "prevElement", "nextElement"
@@ -94,19 +95,20 @@ module XML {
* Gets an `Attr` from the `libxmljs` library. * Gets an `Attr` from the `libxmljs` library.
*/ */
private API::Node attr() { private API::Node attr() {
result = element().getMember("attr").getReturn() result = this.element().getMember("attr").getReturn()
or or
result = element().getMember("attrs").getReturn().getAMember() result = this.element().getMember("attrs").getReturn().getAMember()
} }
override DataFlow::Node getAResult() { override DataFlow::Node getAResult() {
result = [doc(), element(), attr()].asSource() result = [this.doc(), this.element(), this.attr()].asSource()
or or
result = element().getMember(["name", "text"]).getACall() result = this.element().getMember(["name", "text"]).getACall()
or or
result = attr().getMember(["name", "value"]).getACall() result = this.attr().getMember(["name", "value"]).getACall()
or or
result = element().getMember("namespace").getReturn().getMember(["href", "prefix"]).getACall() result =
this.element().getMember("namespace").getReturn().getMember(["href", "prefix"]).getACall()
} }
} }
@@ -121,7 +123,7 @@ module XML {
this = parser.getMember("parseString").getACall().asExpr() this = parser.getMember("parseString").getACall().asExpr()
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(EntityKind kind) { override predicate resolvesEntities(EntityKind kind) {
// entities are resolved by default // entities are resolved by default
@@ -144,7 +146,7 @@ module XML {
this = parser.getMember("push").getACall().asExpr() this = parser.getMember("push").getACall().asExpr()
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(EntityKind kind) { override predicate resolvesEntities(EntityKind kind) {
// entities are resolved by default // entities are resolved by default
@@ -167,7 +169,7 @@ module XML {
this = parser.getMember(["parse", "write"]).getACall().asExpr() this = parser.getMember(["parse", "write"]).getACall().asExpr()
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(EntityKind kind) { override predicate resolvesEntities(EntityKind kind) {
// only internal entities are resolved by default // only internal entities are resolved by default
@@ -190,10 +192,10 @@ module XML {
.getAMethodCall("parseFromString") .getAMethodCall("parseFromString")
.asExpr() and .asExpr() and
// type contains the string `xml`, that is, it's not `text/html` // type contains the string `xml`, that is, it's not `text/html`
getArgument(1).mayHaveStringValue(any(string tp | tp.matches("%xml%"))) this.getArgument(1).mayHaveStringValue(any(string tp | tp.matches("%xml%")))
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() } override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
@@ -215,7 +217,7 @@ module XML {
) )
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { any() } override predicate resolvesEntities(XML::EntityKind kind) { any() }
} }
@@ -228,7 +230,7 @@ module XML {
this.getCallee().(JS::PropAccess).getQualifiedName() = "goog.dom.xml.loadXml" this.getCallee().(JS::PropAccess).getQualifiedName() = "goog.dom.xml.loadXml"
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() } override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
} }
@@ -246,7 +248,7 @@ module XML {
) )
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { override predicate resolvesEntities(XML::EntityKind kind) {
// sax-js (the parser used) does not expand entities. // sax-js (the parser used) does not expand entities.
@@ -273,7 +275,7 @@ module XML {
this = parser.getAMemberCall("write").asExpr() this = parser.getAMemberCall("write").asExpr()
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { override predicate resolvesEntities(XML::EntityKind kind) {
// sax-js does not expand entities. // sax-js does not expand entities.
@@ -298,7 +300,7 @@ module XML {
.asExpr() .asExpr()
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { override predicate resolvesEntities(XML::EntityKind kind) {
// xml-js does not expand custom entities. // xml-js does not expand custom entities.
@@ -319,7 +321,7 @@ module XML {
this = parser.getReturn().getMember("write").getACall().asExpr() this = parser.getReturn().getMember("write").getACall().asExpr()
} }
override JS::Expr getSourceArgument() { result = getArgument(0) } override JS::Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { override predicate resolvesEntities(XML::EntityKind kind) {
// htmlparser2 does not expand entities. // htmlparser2 does not expand entities.

View File

@@ -119,10 +119,10 @@ class XUnitAnnotation extends Expr {
Expr getAttribute(int i) { result = this.(BracketedListOfExpressions).getElement(i) } Expr getAttribute(int i) { result = this.(BracketedListOfExpressions).getElement(i) }
/** Gets an attribute of this annotation. */ /** Gets an attribute of this annotation. */
Expr getAnAttribute() { result = getAttribute(_) } Expr getAnAttribute() { result = this.getAttribute(_) }
/** Gets the number of attributes of this annotation. */ /** Gets the number of attributes of this annotation. */
int getNumAttribute() { result = strictcount(getAnAttribute()) } int getNumAttribute() { result = strictcount(this.getAnAttribute()) }
/** /**
* Holds if this element is at the specified location. * Holds if this element is at the specified location.
@@ -136,8 +136,8 @@ class XUnitAnnotation extends Expr {
) { ) {
// extend location to cover brackets // extend location to cover brackets
exists(Location l1, Location l2 | exists(Location l1, Location l2 |
l1 = getFirstToken().getLocation() and l1 = this.getFirstToken().getLocation() and
l2 = getLastToken().getLocation() l2 = this.getLastToken().getLocation()
| |
filepath = l1.getFile().getAbsolutePath() and filepath = l1.getFile().getAbsolutePath() and
startline = l1.getStartLine() and startline = l1.getStartLine() and
@@ -176,10 +176,10 @@ class XUnitAttribute extends Expr {
Expr getParameter(int i) { result = this.(CallExpr).getArgument(i) } Expr getParameter(int i) { result = this.(CallExpr).getArgument(i) }
/** Gets a parameter of this attribute. */ /** Gets a parameter of this attribute. */
Expr getAParameter() { result = getParameter(_) } Expr getAParameter() { result = this.getParameter(_) }
/** Gets the number of parameters of this attribute. */ /** Gets the number of parameters of this attribute. */
int getNumParameter() { result = count(getAParameter()) } int getNumParameter() { result = count(this.getAParameter()) }
} }
/** /**
@@ -205,26 +205,26 @@ private class XUnitAnnotatedFunction extends Function {
* An xUnit.js `Fixture` annotation. * An xUnit.js `Fixture` annotation.
*/ */
class XUnitFixtureAnnotation extends XUnitAnnotation { class XUnitFixtureAnnotation extends XUnitAnnotation {
XUnitFixtureAnnotation() { getAnAttribute().accessesGlobal("Fixture") } XUnitFixtureAnnotation() { this.getAnAttribute().accessesGlobal("Fixture") }
} }
/** /**
* An xUnit.js fixture. * An xUnit.js fixture.
*/ */
class XUnitFixture extends XUnitAnnotatedFunction { class XUnitFixture extends XUnitAnnotatedFunction {
XUnitFixture() { getAnAnnotation() instanceof XUnitFixtureAnnotation } XUnitFixture() { this.getAnAnnotation() instanceof XUnitFixtureAnnotation }
} }
/** /**
* An xUnit.js `Fact` annotation. * An xUnit.js `Fact` annotation.
*/ */
class XUnitFactAnnotation extends XUnitAnnotation { class XUnitFactAnnotation extends XUnitAnnotation {
XUnitFactAnnotation() { getAnAttribute().accessesGlobal("Fact") } XUnitFactAnnotation() { this.getAnAttribute().accessesGlobal("Fact") }
} }
/** /**
* An xUnit.js fact. * An xUnit.js fact.
*/ */
class XUnitFact extends XUnitAnnotatedFunction { class XUnitFact extends XUnitAnnotatedFunction {
XUnitFact() { getAnAnnotation() instanceof XUnitFactAnnotation } XUnitFact() { this.getAnAnnotation() instanceof XUnitFactAnnotation }
} }

View File

@@ -7,5 +7,5 @@
import javascript import javascript
private class PromotedPromiseCandidate extends PromiseDefinition, PromiseCandidate { private class PromotedPromiseCandidate extends PromiseDefinition, PromiseCandidate {
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
} }

View File

@@ -25,7 +25,7 @@ module Linting {
* Holds if this directive applies to `gva` and declares the variable it references. * Holds if this directive applies to `gva` and declares the variable it references.
*/ */
predicate declaresGlobalForAccess(GlobalVarAccess gva) { predicate declaresGlobalForAccess(GlobalVarAccess gva) {
appliesTo(gva) and declaresGlobal(gva.getName(), _) this.appliesTo(gva) and this.declaresGlobal(gva.getName(), _)
} }
} }
} }

View File

@@ -50,14 +50,14 @@ class StringReplaceCallSequence extends DataFlow::CallNode instanceof StringRepl
/** Gets a string that is the replacement of this call. */ /** Gets a string that is the replacement of this call. */
string getAReplacementString() { string getAReplacementString() {
getAMember().replaces(_, result) this.getAMember().replaces(_, result)
or or
// StringReplaceCall::replaces/2 can't always find the `old` string, so this is added as a fallback. // StringReplaceCall::replaces/2 can't always find the `old` string, so this is added as a fallback.
getAMember().getRawReplacement().getStringValue() = result this.getAMember().getRawReplacement().getStringValue() = result
} }
/** Gets a string that is being replaced by this call. */ /** Gets a string that is being replaced by this call. */
string getAReplacedString() { getAMember().getAReplacedString() = result } string getAReplacedString() { this.getAMember().getAReplacedString() = result }
} }
/** /**

View File

@@ -29,7 +29,7 @@ class Configuration extends TaintTracking::Configuration {
isIndirectCommandArgument(sink, highlight) isIndirectCommandArgument(sink, highlight)
} }
override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) } override predicate isSink(DataFlow::Node sink) { this.isSinkWithHighlight(sink, _) }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }

View File

@@ -61,7 +61,7 @@ class SensitiveActionGuardComparison extends Comparison {
class SensitiveActionGuardComparisonOperand extends Sink { class SensitiveActionGuardComparisonOperand extends Sink {
SensitiveActionGuardComparison comparison; SensitiveActionGuardComparison comparison;
SensitiveActionGuardComparisonOperand() { asExpr() = comparison.getAnOperand() } SensitiveActionGuardComparisonOperand() { this.asExpr() = comparison.getAnOperand() }
override SensitiveAction getAction() { result = comparison.getGuard().getAction() } override SensitiveAction getAction() { result = comparison.getGuard().getAction() }
} }

View File

@@ -45,6 +45,6 @@ module DifferentKindsComparisonBypass {
* A data flow sink for a potential suspicious comparisons. * A data flow sink for a potential suspicious comparisons.
*/ */
private class ComparisonOperandSink extends Sink { private class ComparisonOperandSink extends Sink {
ComparisonOperandSink() { asExpr() = any(Comparison c).getAnOperand() } ComparisonOperandSink() { this.asExpr() = any(Comparison c).getAnOperand() }
} }
} }

View File

@@ -36,8 +36,8 @@ class DifferentKindsComparison extends Comparison {
DifferentKindsComparison() { DifferentKindsComparison() {
exists(Configuration cfg | exists(Configuration cfg |
cfg.hasFlow(lSource, DataFlow::valueNode(getLeftOperand())) and cfg.hasFlow(lSource, DataFlow::valueNode(this.getLeftOperand())) and
cfg.hasFlow(rSource, DataFlow::valueNode(getRightOperand())) and cfg.hasFlow(rSource, DataFlow::valueNode(this.getRightOperand())) and
lSource.isSuspiciousToCompareWith(rSource) lSource.isSuspiciousToCompareWith(rSource)
) )
} }

View File

@@ -96,7 +96,7 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
/** Gets the number of untrusted sources used with this external API. */ /** Gets the number of untrusted sources used with this external API. */
int getNumberOfUntrustedSources() { int getNumberOfUntrustedSources() {
result = count(getUntrustedDataNode().getAnUntrustedSource()) result = count(this.getUntrustedDataNode().getAnUntrustedSource())
} }
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */

View File

@@ -45,7 +45,7 @@ class Configuration extends TaintTracking::Configuration {
override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) { override predicate isLabeledBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) {
lbl = Label::characterToLabel(node.(StringReplaceCall).getAReplacedString()) or lbl = Label::characterToLabel(node.(StringReplaceCall).getAReplacedString()) or
isSanitizer(node) this.isSanitizer(node)
} }
override predicate isSanitizer(DataFlow::Node n) { override predicate isSanitizer(DataFlow::Node n) {

View File

@@ -25,7 +25,7 @@ class Configuration extends TaintTracking::Configuration {
isIndirectCommandArgument(sink, highlight) isIndirectCommandArgument(sink, highlight)
} }
override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) } override predicate isSink(DataFlow::Node sink) { this.isSinkWithHighlight(sink, _) }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }

View File

@@ -72,12 +72,12 @@ module RegExpInjection {
*/ */
class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall { class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall {
MetacharEscapeSanitizer() { MetacharEscapeSanitizer() {
isGlobal() and this.isGlobal() and
( (
RegExp::alwaysMatchesMetaCharacter(getRegExp().getRoot(), ["{", "[", "+"]) RegExp::alwaysMatchesMetaCharacter(this.getRegExp().getRoot(), ["{", "[", "+"])
or or
// or it's like a wild-card. // or it's like a wild-card.
RegExp::isWildcardLike(getRegExp().getRoot()) RegExp::isWildcardLike(this.getRegExp().getRoot())
) )
} }
} }

View File

@@ -26,7 +26,7 @@ class Configuration extends TaintTracking::Configuration {
isIndirectCommandArgument(sink, highlight) isIndirectCommandArgument(sink, highlight)
} }
override predicate isSink(DataFlow::Node sink) { isSinkWithHighlight(sink, _) } override predicate isSink(DataFlow::Node sink) { this.isSinkWithHighlight(sink, _) }
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
} }

View File

@@ -47,7 +47,7 @@ module TemplateObjectInjection {
exists( exists(
Express::RouteSetup setup, Express::RouterDefinition router, Express::RouterDefinition top Express::RouteSetup setup, Express::RouterDefinition router, Express::RouterDefinition top
| |
setup.getARouteHandler() = getRouteHandler() and setup.getARouteHandler() = this.getRouteHandler() and
setup.getRouter() = router and setup.getRouter() = router and
top.getASubRouter*() = router and top.getASubRouter*() = router and
usesVulnerableTemplateEngine(top) usesVulnerableTemplateEngine(top)

View File

@@ -57,7 +57,7 @@ private class IsArrayBarrier extends DataFlow::BarrierGuardNode, DataFlow::CallN
IsArrayBarrier() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") } IsArrayBarrier() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") }
override predicate blocks(boolean outcome, Expr e) { override predicate blocks(boolean outcome, Expr e) {
e = getArgument(0).asExpr() and e = this.getArgument(0).asExpr() and
outcome = [true, false] // separation between string/array removes type confusion in both branches outcome = [true, false] // separation between string/array removes type confusion in both branches
} }
} }

View File

@@ -53,7 +53,7 @@ class Configuration extends TaintTracking::Configuration {
) { ) {
// Reading a property of the global object or of a function // Reading a property of the global object or of a function
exists(DataFlow::PropRead read | exists(DataFlow::PropRead read |
hasUnsafeMethods(read.getBase().getALocalSource()) and this.hasUnsafeMethods(read.getBase().getALocalSource()) and
src = read.getPropertyNameExpr().flow() and src = read.getPropertyNameExpr().flow() and
dst = read and dst = read and
srclabel.isTaint() and srclabel.isTaint() and

View File

@@ -46,7 +46,7 @@ module UnsafeJQueryPlugin {
{ {
AmbiguousHtmlOrSelectorArgument() { AmbiguousHtmlOrSelectorArgument() {
// any fixed prefix makes the call unambiguous // any fixed prefix makes the call unambiguous
not exists(getAPrefix()) not exists(this.getAPrefix())
} }
} }
@@ -91,12 +91,12 @@ module UnsafeJQueryPlugin {
if method.getAParameter().getName().regexpMatch(optionsPattern) if method.getAParameter().getName().regexpMatch(optionsPattern)
then ( then (
// use the last parameter named something like "options" if it exists ... // use the last parameter named something like "options" if it exists ...
getName().regexpMatch(optionsPattern) and this.getName().regexpMatch(optionsPattern) and
this = method.getAParameter() this = method.getAParameter()
) else ( ) else (
// ... otherwise, use the last parameter, unless it looks like a DOM node // ... otherwise, use the last parameter, unless it looks like a DOM node
this = method.getLastParameter() and this = method.getLastParameter() and
not getName().regexpMatch("(?i)(e(l(em(ent(s)?)?)?)?)") not this.getName().regexpMatch("(?i)(e(l(em(ent(s)?)?)?)?)")
) )
) )
} }
@@ -113,13 +113,13 @@ module UnsafeJQueryPlugin {
class IsElementSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode { class IsElementSanitizer extends TaintTracking::SanitizerGuardNode, DataFlow::CallNode {
IsElementSanitizer() { IsElementSanitizer() {
// common ad hoc sanitizing calls // common ad hoc sanitizing calls
exists(string name | getCalleeName() = name | exists(string name | this.getCalleeName() = name |
name = "isElement" or name = "isDocument" or name = "isWindow" name = "isElement" or name = "isDocument" or name = "isWindow"
) )
} }
override predicate sanitizes(boolean outcome, Expr e) { override predicate sanitizes(boolean outcome, Expr e) {
outcome = true and e = getArgument(0).asExpr() outcome = true and e = this.getArgument(0).asExpr()
} }
} }

View File

@@ -101,10 +101,10 @@ predicate hostnameSanitizingPrefixEdge(DataFlow::Node source, DataFlow::Node sin
* A check that sanitizes the hostname of a URL. * A check that sanitizes the hostname of a URL.
*/ */
class HostnameSanitizerGuard extends TaintTracking::SanitizerGuardNode, StringOps::StartsWith { class HostnameSanitizerGuard extends TaintTracking::SanitizerGuardNode, StringOps::StartsWith {
HostnameSanitizerGuard() { hasHostnameSanitizingSubstring(getSubstring()) } HostnameSanitizerGuard() { hasHostnameSanitizingSubstring(this.getSubstring()) }
override predicate sanitizes(boolean outcome, Expr e) { override predicate sanitizes(boolean outcome, Expr e) {
outcome = getPolarity() and outcome = this.getPolarity() and
e = getBaseString().asExpr() e = this.getBaseString().asExpr()
} }
} }

View File

@@ -10,7 +10,7 @@ class TopLevel extends @toplevel {
Location getLocation() { hasLocation(this, result) } Location getLocation() { hasLocation(this, result) }
pragma[nomagic] pragma[nomagic]
predicate startsAtLine(@file file, int line) { getLocation().startsAtLine(file, line) } predicate startsAtLine(@file file, int line) { this.getLocation().startsAtLine(file, line) }
} }
class XmlNode extends @xmllocatable { class XmlNode extends @xmllocatable {
@@ -19,7 +19,7 @@ class XmlNode extends @xmllocatable {
Location getLocation() { xmllocations(this, result) } Location getLocation() { xmllocations(this, result) }
pragma[nomagic] pragma[nomagic]
predicate startsAtLine(@file file, int line) { getLocation().startsAtLine(file, line) } predicate startsAtLine(@file file, int line) { this.getLocation().startsAtLine(file, line) }
} }
// Based on previous implementation on HTMLNode.getCodeInAttribute and getInlineScript, // Based on previous implementation on HTMLNode.getCodeInAttribute and getInlineScript,

View File

@@ -127,7 +127,7 @@ class CommentedOutCode extends Comment {
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
exists(Location loc, File f | loc = getLocation() and f = loc.getFile() | exists(Location loc, File f | loc = this.getLocation() and f = loc.getFile() |
filepath = f.getAbsolutePath() and filepath = f.getAbsolutePath() and
startline = loc.getStartLine() and startline = loc.getStartLine() and
startcolumn = loc.getStartColumn() and startcolumn = loc.getStartColumn() and

View File

@@ -20,7 +20,7 @@ class EvilTwin extends DataFlow::CallNode {
EvilTwin() { EvilTwin() {
exists(string fn | fn = "setTimeout" or fn = "setInterval" | exists(string fn | fn = "setTimeout" or fn = "setInterval" |
this = DataFlow::globalVarRef(fn).getACall() and this = DataFlow::globalVarRef(fn).getACall() and
getArgument(0).asExpr() instanceof ConstantString this.getArgument(0).asExpr() instanceof ConstantString
) )
} }
} }

View File

@@ -26,7 +26,7 @@ predicate isCommonPredefinedTypeName(string name) {
*/ */
class DefiniteTypeDecl extends TypeDecl { class DefiniteTypeDecl extends TypeDecl {
DefiniteTypeDecl() { DefiniteTypeDecl() {
this = any(ImportSpecifier im).getLocal() implies exists(getLocalTypeName().getAnAccess()) this = any(ImportSpecifier im).getLocal() implies exists(this.getLocalTypeName().getAnAccess())
} }
} }

View File

@@ -63,7 +63,7 @@ predicate isImportedAtRuntime(Module source, Module destination) {
*/ */
class CandidateVarAccess extends VarAccess { class CandidateVarAccess extends VarAccess {
CandidateVarAccess() { CandidateVarAccess() {
isImmediatelyExecutedContainer(getContainer()) and isImmediatelyExecutedContainer(this.getContainer()) and
not exists(ExportSpecifier spec | spec.getLocal() = this) not exists(ExportSpecifier spec | spec.getLocal() = this)
} }
} }

View File

@@ -132,7 +132,7 @@ class ImportVarDeclProvider extends Stmt {
* Gets an unacceptable unused variable declared by this import. * Gets an unacceptable unused variable declared by this import.
*/ */
UnusedLocal getAnUnacceptableUnusedLocal() { UnusedLocal getAnUnacceptableUnusedLocal() {
result = getAVarDecl().getVariable() and result = this.getAVarDecl().getVariable() and
not whitelisted(result) not whitelisted(result)
} }
} }

View File

@@ -21,10 +21,10 @@ import Clones
abstract class RedundantOperand extends StructurallyCompared { abstract class RedundantOperand extends StructurallyCompared {
RedundantOperand() { exists(BinaryExpr parent | this = parent.getLeftOperand()) } RedundantOperand() { exists(BinaryExpr parent | this = parent.getLeftOperand()) }
override Expr candidate() { result = getParent().(BinaryExpr).getRightOperand() } override Expr candidate() { result = this.getParent().(BinaryExpr).getRightOperand() }
/** Gets the expression to report when a pair of clones is found. */ /** Gets the expression to report when a pair of clones is found. */
Expr toReport() { result = getParent() } Expr toReport() { result = this.getParent() }
} }
/** /**
@@ -50,7 +50,7 @@ class IdemnecantExpr extends BinaryExpr {
class RedundantIdemnecantOperand extends RedundantOperand { class RedundantIdemnecantOperand extends RedundantOperand {
RedundantIdemnecantOperand() { RedundantIdemnecantOperand() {
exists(IdemnecantExpr parent | exists(IdemnecantExpr parent |
parent = getParent() and parent = this.getParent() and
// exclude trivial cases like `1-1` // exclude trivial cases like `1-1`
not parent.getRightOperand().getUnderlyingValue() instanceof Literal not parent.getRightOperand().getUnderlyingValue() instanceof Literal
) )
@@ -65,7 +65,7 @@ class RedundantIdemnecantOperand extends RedundantOperand {
*/ */
class RedundantIdempotentOperand extends RedundantOperand { class RedundantIdempotentOperand extends RedundantOperand {
RedundantIdempotentOperand() { RedundantIdempotentOperand() {
getParent() instanceof LogicalBinaryExpr and this.getParent() instanceof LogicalBinaryExpr and
not exists(UpdateExpr e | e.getParentExpr+() = this) not exists(UpdateExpr e | e.getParentExpr+() = this)
} }
} }
@@ -75,8 +75,8 @@ class RedundantIdempotentOperand extends RedundantOperand {
*/ */
class AverageExpr extends DivExpr { class AverageExpr extends DivExpr {
AverageExpr() { AverageExpr() {
getLeftOperand().getUnderlyingValue() instanceof AddExpr and this.getLeftOperand().getUnderlyingValue() instanceof AddExpr and
getRightOperand().getIntValue() = 2 this.getRightOperand().getIntValue() = 2
} }
} }
@@ -85,10 +85,14 @@ class AverageExpr extends DivExpr {
*/ */
class RedundantAverageOperand extends RedundantOperand { class RedundantAverageOperand extends RedundantOperand {
RedundantAverageOperand() { RedundantAverageOperand() {
exists(AverageExpr aver | getParent().(AddExpr) = aver.getLeftOperand().getUnderlyingValue()) exists(AverageExpr aver |
this.getParent().(AddExpr) = aver.getLeftOperand().getUnderlyingValue()
)
} }
override AverageExpr toReport() { getParent() = result.getLeftOperand().getUnderlyingValue() } override AverageExpr toReport() {
this.getParent() = result.getLeftOperand().getUnderlyingValue()
}
} }
from RedundantOperand e, Expr f from RedundantOperand e, Expr f

View File

@@ -22,7 +22,7 @@ import javascript
class OmittedArrayElement extends ArrayExpr { class OmittedArrayElement extends ArrayExpr {
int idx; int idx;
OmittedArrayElement() { idx = min(int i | elementIsOmitted(i)) } OmittedArrayElement() { idx = min(int i | this.elementIsOmitted(i)) }
/** /**
* Holds if this element is at the specified location. * Holds if this element is at the specified location.
@@ -35,9 +35,9 @@ class OmittedArrayElement extends ArrayExpr {
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
exists(Token pre, Location before, Location after | exists(Token pre, Location before, Location after |
idx = 0 and pre = getFirstToken() idx = 0 and pre = this.getFirstToken()
or or
pre = getElement(idx - 1).getLastToken().getNextToken() pre = this.getElement(idx - 1).getLastToken().getNextToken()
| |
before = pre.getLocation() and before = pre.getLocation() and
after = pre.getNextToken().getLocation() and after = pre.getNextToken().getLocation() and

View File

@@ -23,8 +23,8 @@ class RootDestructuringPattern extends DestructuringPattern {
/** Holds if this pattern has multiple bindings for `name`. */ /** Holds if this pattern has multiple bindings for `name`. */
predicate hasConflictingBindings(string name) { predicate hasConflictingBindings(string name) {
exists(VarRef v, VarRef w | exists(VarRef v, VarRef w |
v = getABindingVarRef() and v = this.getABindingVarRef() and
w = getABindingVarRef() and w = this.getABindingVarRef() and
name = v.getName() and name = v.getName() and
name = w.getName() and name = w.getName() and
v != w v != w
@@ -33,10 +33,10 @@ class RootDestructuringPattern extends DestructuringPattern {
/** Gets the first occurrence of the conflicting binding `name`. */ /** Gets the first occurrence of the conflicting binding `name`. */
VarDecl getFirstClobberedVarDecl(string name) { VarDecl getFirstClobberedVarDecl(string name) {
hasConflictingBindings(name) and this.hasConflictingBindings(name) and
result = result =
min(VarDecl decl | min(VarDecl decl |
decl = getABindingVarRef() and decl.getName() = name decl = this.getABindingVarRef() and decl.getName() = name
| |
decl order by decl.getLocation().getStartLine(), decl.getLocation().getStartColumn() decl order by decl.getLocation().getStartLine(), decl.getLocation().getStartColumn()
) )
@@ -44,11 +44,11 @@ class RootDestructuringPattern extends DestructuringPattern {
/** Holds if variables in this pattern may resemble type annotations. */ /** Holds if variables in this pattern may resemble type annotations. */
predicate resemblesTypeAnnotation() { predicate resemblesTypeAnnotation() {
hasConflictingBindings(_) and // Restrict size of predicate. this.hasConflictingBindings(_) and // Restrict size of predicate.
this instanceof Parameter and this instanceof Parameter and
this instanceof ObjectPattern and this instanceof ObjectPattern and
not exists(getTypeAnnotation()) and not exists(this.getTypeAnnotation()) and
getFile().getFileType().isTypeScript() this.getFile().getFileType().isTypeScript()
} }
} }

View File

@@ -60,7 +60,7 @@ class SpuriousArguments extends Expr {
* expected by any potential callee. * expected by any potential callee.
*/ */
int getCount() { int getCount() {
result = count(int i | exists(invk.getArgument(i)) and i >= maxArity(getCall())) result = count(int i | exists(invk.getArgument(i)) and i >= maxArity(this.getCall()))
} }
/** /**
@@ -73,7 +73,7 @@ class SpuriousArguments extends Expr {
predicate hasLocationInfo( predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and this.getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
exists(DataFlow::Node lastArg | exists(DataFlow::Node lastArg |
lastArg = max(DataFlow::Node arg, int i | arg = invk.getArgument(i) | arg order by i) lastArg = max(DataFlow::Node arg, int i | arg = invk.getArgument(i) | arg order by i)
| |

View File

@@ -87,8 +87,8 @@ class RegExpSearchCall extends DataFlow::MethodCallNode, RegExpQuery {
DataFlow::RegExpCreationNode regexp; DataFlow::RegExpCreationNode regexp;
RegExpSearchCall() { RegExpSearchCall() {
getMethodName() = "search" and this.getMethodName() = "search" and
regexp.getAReference().flowsTo(getArgument(0)) regexp.getAReference().flowsTo(this.getArgument(0))
} }
override RegExpTerm getRegExp() { result = regexp.getRoot() } override RegExpTerm getRegExp() { result = regexp.getRoot() }

View File

@@ -73,8 +73,8 @@ class RegExpPatternMistake extends TRegExpPatternMistake {
string filepath, int startline, int startcolumn, int endline, int endcolumn string filepath, int startline, int startcolumn, int endline, int endcolumn
) { ) {
exists(int srcStartcolumn, int srcEndcolumn, int index | exists(int srcStartcolumn, int srcEndcolumn, int index |
index = getIndex() and index = this.getIndex() and
getRawStringNode() this.getRawStringNode()
.getLocation() .getLocation()
.hasLocationInfo(filepath, startline, srcStartcolumn, endline, srcEndcolumn) .hasLocationInfo(filepath, startline, srcStartcolumn, endline, srcEndcolumn)
| |
@@ -89,7 +89,7 @@ class RegExpPatternMistake extends TRegExpPatternMistake {
} }
/** Gets a textual representation of this element. */ /** Gets a textual representation of this element. */
string toString() { result = getMessage() } string toString() { result = this.getMessage() }
abstract AstNode getRawStringNode(); abstract AstNode getRawStringNode();

View File

@@ -29,8 +29,8 @@ private import semmle.javascript.dataflow.InferredTypes
*/ */
class SplitCall extends StringSplitCall { class SplitCall extends StringSplitCall {
SplitCall() { SplitCall() {
getSeparator() = "." and this.getSeparator() = "." and
getBaseString().getALocalSource() instanceof ParameterNode this.getBaseString().getALocalSource() instanceof ParameterNode
} }
} }
@@ -93,7 +93,7 @@ class SplitPropName extends SourceNode {
SourceNode getArray() { result = array } SourceNode getArray() { result = array }
/** Gets an element accessed on the same underlying array. */ /** Gets an element accessed on the same underlying array. */
SplitPropName getAnAlias() { result.getArray() = getArray() } SplitPropName getAnAlias() { result.getArray() = this.getArray() }
} }
/** /**
@@ -434,13 +434,13 @@ class DenyListInclusionGuard extends DataFlow::LabeledBarrierGuardNode, Inclusio
DenyListInclusionGuard() { DenyListInclusionGuard() {
exists(DataFlow::ArrayCreationNode array | exists(DataFlow::ArrayCreationNode array |
array.getAnElement().getStringValue() = label and array.getAnElement().getStringValue() = label and
array.flowsTo(getContainerNode()) array.flowsTo(this.getContainerNode())
) )
} }
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) { override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
outcome = getPolarity().booleanNot() and outcome = this.getPolarity().booleanNot() and
e = getContainedNode().asExpr() and e = this.getContainedNode().asExpr() and
label = lbl label = lbl
} }
} }
@@ -475,7 +475,7 @@ class IsPlainObjectGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::Ca
} }
override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) { override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) {
e = getArgument(0).asExpr() and e = this.getArgument(0).asExpr() and
outcome = true and outcome = true and
lbl = "constructor" lbl = "constructor"
} }
@@ -561,7 +561,7 @@ DataFlow::SourceNode getANodeLeadingToBaseBase(Node base) {
class ObjectCreateNullCall extends CallNode { class ObjectCreateNullCall extends CallNode {
ObjectCreateNullCall() { ObjectCreateNullCall() {
this = globalVarRef("Object").getAMemberCall("create") and this = globalVarRef("Object").getAMemberCall("create") and
getArgument(0).asExpr() instanceof NullLiteral this.getArgument(0).asExpr() instanceof NullLiteral
} }
} }

Some files were not shown because too many files have changed in this diff Show More