add explicit this to all member calls

This commit is contained in:
Erik Krogh Kristensen
2021-11-01 09:51:15 +01:00
parent 1c78c792ff
commit db40ccae81
85 changed files with 2063 additions and 1937 deletions

View File

@@ -26,7 +26,7 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
override Location getLocation() { hasLocation(this, result) }
override File getFile() {
result = getLocation().getFile() // Specialized for performance reasons
result = this.getLocation().getFile() // Specialized for performance reasons
}
/** Gets the first token belonging to this element. */
@@ -76,7 +76,7 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
/** Gets the toplevel syntactic unit to which this element belongs. */
cached
TopLevel getTopLevel() { Stages::Ast::ref() and result = getParent().getTopLevel() }
TopLevel getTopLevel() { Stages::Ast::ref() and result = this.getParent().getTopLevel() }
/**
* Gets the `i`th child node of this node.
@@ -85,10 +85,10 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
* change between versions of the extractor.
*/
ASTNode getChild(int i) {
result = getChildExpr(i) or
result = getChildStmt(i) or
result = this.getChildExpr(i) or
result = this.getChildStmt(i) or
properties(result, this, i, _, _) or
result = getChildTypeExpr(i)
result = this.getChildTypeExpr(i)
}
/** Gets the `i`th child statement of this node. */
@@ -101,22 +101,22 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
TypeExpr getChildTypeExpr(int i) { typeexprs(result, _, this, i, _) }
/** Gets a child node of this node. */
ASTNode getAChild() { result = getChild(_) }
ASTNode getAChild() { result = this.getChild(_) }
/** Gets a child expression of this node. */
Expr getAChildExpr() { result = getChildExpr(_) }
Expr getAChildExpr() { result = this.getChildExpr(_) }
/** Gets a child statement of this node. */
Stmt getAChildStmt() { result = getChildStmt(_) }
Stmt getAChildStmt() { result = this.getChildStmt(_) }
/** Gets the number of child nodes of this node. */
int getNumChild() { result = count(getAChild()) }
int getNumChild() { result = count(this.getAChild()) }
/** Gets the number of child expressions of this node. */
int getNumChildExpr() { result = count(getAChildExpr()) }
int getNumChildExpr() { result = count(this.getAChildExpr()) }
/** Gets the number of child statements of this node. */
int getNumChildStmt() { result = count(getAChildStmt()) }
int getNumChildStmt() { result = count(this.getAChildStmt()) }
/** Gets the parent node of this node, if any. */
cached
@@ -126,7 +126,7 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
ControlFlowNode getFirstControlFlowNode() { result = this }
/** Holds if this syntactic entity belongs to an externs file. */
predicate inExternsFile() { getTopLevel().isExterns() }
predicate inExternsFile() { this.getTopLevel().isExterns() }
/**
* Holds if this is an ambient node that is not a `TypeExpr` and is not inside a `.d.ts` file
@@ -137,9 +137,9 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
cached
private predicate isAmbientInternal() {
Stages::Ast::ref() and
getParent().isAmbientInternal()
this.getParent().isAmbientInternal()
or
not isAmbientTopLevel(getTopLevel()) and
not isAmbientTopLevel(this.getTopLevel()) and
(
this instanceof ExternalModuleDeclaration
or
@@ -176,9 +176,9 @@ class ASTNode extends @ast_node, NodeInStmtContainer {
*/
pragma[inline]
predicate isAmbient() {
isAmbientInternal()
this.isAmbientInternal()
or
isAmbientTopLevel(getTopLevel())
isAmbientTopLevel(this.getTopLevel())
or
this instanceof TypeExpr
}
@@ -209,11 +209,11 @@ class TopLevel extends @toplevel, StmtContainer {
/** Holds if this toplevel is minified. */
predicate isMinified() {
// file name contains 'min' (not as part of a longer word)
getFile().getBaseName().regexpMatch(".*[^-._]*[-._]min([-._].*)?\\.\\w+")
this.getFile().getBaseName().regexpMatch(".*[^-._]*[-._]min([-._].*)?\\.\\w+")
or
exists(int numstmt | numstmt = strictcount(Stmt s | s.getTopLevel() = this) |
// there are more than two statements per line on average
numstmt.(float) / getNumberOfLines() > 2 and
numstmt.(float) / this.getNumberOfLines() > 2 and
// and there are at least ten statements overall
numstmt >= 10
)
@@ -247,9 +247,9 @@ class TopLevel extends @toplevel, StmtContainer {
/** Gets the number of lines containing comments in this toplevel. */
int getNumberOfLinesOfComments() { numlines(this, _, _, result) }
override predicate isStrict() { getAStmt() instanceof StrictModeDecl }
override predicate isStrict() { this.getAStmt() instanceof StrictModeDecl }
override ControlFlowNode getFirstControlFlowNode() { result = getEntry() }
override ControlFlowNode getFirstControlFlowNode() { result = this.getEntry() }
override string toString() { result = "<toplevel>" }
}
@@ -346,7 +346,7 @@ class JavaScriptURL extends @javascript_url, CodeInAttribute { }
* </pre>
*/
class Externs extends TopLevel {
Externs() { isExterns() }
Externs() { this.isExterns() }
}
/**
@@ -391,7 +391,7 @@ class StmtContainer extends @stmt_container, ASTNode {
StmtContainer getFunctionBoundary() {
if this instanceof Function or this instanceof TopLevel
then result = this
else result = getEnclosingContainer().getFunctionBoundary()
else result = this.getEnclosingContainer().getFunctionBoundary()
}
/** Gets a statement that belongs to this container. */
@@ -425,19 +425,19 @@ class StmtContainer extends @stmt_container, ASTNode {
*
* Empty toplevels do not have a start node.
*/
ConcreteControlFlowNode getStart() { successor(getEntry(), result) }
ConcreteControlFlowNode getStart() { successor(this.getEntry(), result) }
/**
* Gets the entry basic block of this function, that is, the basic block
* containing the entry node of its CFG.
*/
EntryBasicBlock getEntryBB() { result = getEntry() }
EntryBasicBlock getEntryBB() { result = this.getEntry() }
/**
* Gets the start basic block of this function, that is, the basic block
* containing the start node of its CFG.
*/
BasicBlock getStartBB() { result.getANode() = getStart() }
BasicBlock getStartBB() { result.getANode() = this.getStart() }
/** Gets the scope induced by this toplevel or function, if any. */
Scope getScope() { scopenodes(this, result) }
@@ -447,7 +447,7 @@ class StmtContainer extends @stmt_container, ASTNode {
*
* See Annex C of the ECMAScript language specification.
*/
predicate isStrict() { getEnclosingContainer().isStrict() }
predicate isStrict() { this.getEnclosingContainer().isStrict() }
}
/**

View File

@@ -55,14 +55,14 @@ module API {
/**
* Gets a call to the function represented by this API component.
*/
CallNode getACall() { result = getReturn().getAnImmediateUse() }
CallNode getACall() { result = this.getReturn().getAnImmediateUse() }
/**
* Gets a call to the function represented by this API component,
* or a promisified version of the function.
*/
CallNode getMaybePromisifiedCall() {
result = getACall()
result = this.getACall()
or
result = Impl::getAPromisifiedInvocation(this, _, _)
}
@@ -70,12 +70,12 @@ module API {
/**
* Gets a `new` call to the function represented by this API component.
*/
NewNode getAnInstantiation() { result = getInstance().getAnImmediateUse() }
NewNode getAnInstantiation() { result = this.getInstance().getAnImmediateUse() }
/**
* Gets an invocation (with our without `new`) to the function represented by this API component.
*/
InvokeNode getAnInvocation() { result = getACall() or result = getAnInstantiation() }
InvokeNode getAnInvocation() { result = this.getACall() or result = this.getAnInstantiation() }
/**
* Gets a data-flow node corresponding to the right-hand side of a definition of the API
@@ -97,7 +97,7 @@ module API {
* Gets a data-flow node that may interprocedurally flow to the right-hand side of a definition
* of the API component represented by this node.
*/
DataFlow::Node getAValueReachingRhs() { result = Impl::trackDefNode(getARhs()) }
DataFlow::Node getAValueReachingRhs() { result = Impl::trackDefNode(this.getARhs()) }
/**
* Gets a node representing member `m` of this API component.
@@ -107,21 +107,21 @@ module API {
*/
bindingset[m]
bindingset[result]
Node getMember(string m) { result = getASuccessor(Label::member(m)) }
Node getMember(string m) { result = this.getASuccessor(Label::member(m)) }
/**
* Gets a node representing a member of this API component where the name of the member is
* not known statically.
*/
Node getUnknownMember() { result = getASuccessor(Label::unknownMember()) }
Node getUnknownMember() { result = this.getASuccessor(Label::unknownMember()) }
/**
* Gets a node representing a member of this API component where the name of the member may
* or may not be known statically.
*/
Node getAMember() {
result = getASuccessor(Label::member(_)) or
result = getUnknownMember()
result = this.getASuccessor(Label::member(_)) or
result = this.getUnknownMember()
}
/**
@@ -135,7 +135,7 @@ module API {
* This predicate may have multiple results when there are multiple constructor calls invoking this API component.
* Consider using `getAnInstantiation()` if there is a need to distinguish between individual constructor calls.
*/
Node getInstance() { result = getASuccessor(Label::instance()) }
Node getInstance() { result = this.getASuccessor(Label::instance()) }
/**
* Gets a node representing the `i`th parameter of the function represented by this node.
@@ -144,14 +144,14 @@ module API {
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
*/
bindingset[i]
Node getParameter(int i) { result = getASuccessor(Label::parameter(i)) }
Node getParameter(int i) { result = this.getASuccessor(Label::parameter(i)) }
/**
* Gets the number of parameters of the function represented by this node.
*/
int getNumParameter() {
result =
max(string s | exists(getASuccessor(Label::parameterByStringIndex(s))) | s.toInt()) + 1
max(string s | exists(this.getASuccessor(Label::parameterByStringIndex(s))) | s.toInt()) + 1
}
/**
@@ -160,12 +160,12 @@ module API {
* This predicate may have multiple results when there are multiple invocations of this API component.
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
*/
Node getLastParameter() { result = getParameter(getNumParameter() - 1) }
Node getLastParameter() { result = this.getParameter(this.getNumParameter() - 1) }
/**
* Gets a node representing the receiver of the function represented by this node.
*/
Node getReceiver() { result = getASuccessor(Label::receiver()) }
Node getReceiver() { result = this.getASuccessor(Label::receiver()) }
/**
* Gets a node representing a parameter or the receiver of the function represented by this
@@ -176,8 +176,8 @@ module API {
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
*/
Node getAParameter() {
result = getASuccessor(Label::parameterByStringIndex(_)) or
result = getReceiver()
result = this.getASuccessor(Label::parameterByStringIndex(_)) or
result = this.getReceiver()
}
/**
@@ -186,24 +186,26 @@ module API {
* This predicate may have multiple results when there are multiple invocations of this API component.
* Consider using `getACall()` if there is a need to distingiush between individual calls.
*/
Node getReturn() { result = getASuccessor(Label::return()) }
Node getReturn() { result = this.getASuccessor(Label::return()) }
/**
* Gets a node representing the promised value wrapped in the `Promise` object represented by
* this node.
*/
Node getPromised() { result = getASuccessor(Label::promised()) }
Node getPromised() { result = this.getASuccessor(Label::promised()) }
/**
* Gets a node representing the error wrapped in the `Promise` object represented by this node.
*/
Node getPromisedError() { result = getASuccessor(Label::promisedError()) }
Node getPromisedError() { result = this.getASuccessor(Label::promisedError()) }
/**
* Gets a string representation of the lexicographically least among all shortest access paths
* from the root to this node.
*/
string getPath() { result = min(string p | p = getAPath(Impl::distanceFromRoot(this)) | p) }
string getPath() {
result = min(string p | p = this.getAPath(Impl::distanceFromRoot(this)) | p)
}
/**
* Gets a node such that there is an edge in the API graph between this node and the other
@@ -221,13 +223,13 @@ module API {
* Gets a node such that there is an edge in the API graph between this node and the other
* one.
*/
Node getAPredecessor() { result = getAPredecessor(_) }
Node getAPredecessor() { result = this.getAPredecessor(_) }
/**
* Gets a node such that there is an edge in the API graph between that other node and
* this one.
*/
Node getASuccessor() { result = getASuccessor(_) }
Node getASuccessor() { result = this.getASuccessor(_) }
/**
* Holds if this node may take its value from `that` node.
@@ -256,9 +258,9 @@ module API {
* parameters are zero.
*/
predicate hasLocationInfo(string path, int startline, int startcol, int endline, int endcol) {
getInducingNode().hasLocationInfo(path, startline, startcol, endline, endcol)
this.getInducingNode().hasLocationInfo(path, startline, startcol, endline, endcol)
or
not exists(getInducingNode()) and
not exists(this.getInducingNode()) and
path = "" and
startline = 0 and
startcol = 0 and
@@ -305,12 +307,12 @@ module API {
/** A node corresponding to a definition of an API component. */
class Definition extends Node, Impl::TDef {
override string toString() { result = "def " + getPath() }
override string toString() { result = "def " + this.getPath() }
}
/** A node corresponding to the use of an API component. */
class Use extends Node, Impl::TUse {
override string toString() { result = "use " + getPath() }
override string toString() { result = "use " + this.getPath() }
}
/** Gets the root node. */
@@ -917,19 +919,19 @@ module API {
pragma[nomagic]
Node getParameter(int i) {
result = callee.getParameter(i) and
result = getAParameterCandidate(i)
result = this.getAParameterCandidate(i)
}
/**
* Gets an API node where a RHS of the node is the `i`th argument to this call.
*/
private Node getAParameterCandidate(int i) { result.getARhs() = getArgument(i) }
private Node getAParameterCandidate(int i) { result.getARhs() = this.getArgument(i) }
/** Gets the API node for a parameter of this invocation. */
Node getAParameter() { result = getParameter(_) }
Node getAParameter() { result = this.getParameter(_) }
/** Gets the API node for the last parameter of this invocation. */
Node getLastParameter() { result = getParameter(getNumArgument() - 1) }
Node getLastParameter() { result = this.getParameter(this.getNumArgument() - 1) }
/** Gets the API node for the return value of this call. */
Node getReturn() {

View File

@@ -129,7 +129,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
BasicBlock getAPredecessor() { result.getASuccessor() = this }
/** Gets a node in this block. */
ControlFlowNode getANode() { result = getNode(_) }
ControlFlowNode getANode() { result = this.getNode(_) }
/** Gets the node at the given position in this block. */
ControlFlowNode getNode(int pos) { bbIndex(this, result, pos) }
@@ -138,7 +138,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
ControlFlowNode getFirstNode() { result = this }
/** Gets the last node in this block. */
ControlFlowNode getLastNode() { result = getNode(length() - 1) }
ControlFlowNode getLastNode() { result = this.getNode(this.length() - 1) }
/** Gets the length of this block. */
int length() { result = bbLength(this) }
@@ -160,13 +160,13 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
*/
predicate isLiveAtEntry(Variable v, VarUse u) {
// restrict `u` to be reachable from this basic block
u = getASuccessor*().getANode() and
u = this.getASuccessor*().getANode() and
(
// shortcut: if `v` is never defined, then it must be live
isDefinedInSameContainer(v)
this.isDefinedInSameContainer(v)
implies
// otherwise, do full liveness computation
isLiveAtEntryImpl(v, u)
this.isLiveAtEntryImpl(v, u)
)
}
@@ -176,11 +176,11 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* function or script.
*/
private predicate isLiveAtEntryImpl(Variable v, VarUse u) {
isLocallyLiveAtEntry(v, u)
this.isLocallyLiveAtEntry(v, u)
or
isDefinedInSameContainer(v) and
this.isDefinedInSameContainer(v) and
not this.defAt(_, v, _) and
getASuccessor().isLiveAtEntryImpl(v, u)
this.getASuccessor().isLiveAtEntryImpl(v, u)
}
/**
@@ -188,7 +188,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* this basic block belongs.
*/
private predicate isDefinedInSameContainer(Variable v) {
exists(VarDef def | def.getAVariable() = v and def.getContainer() = getContainer())
exists(VarDef def | def.getAVariable() = v and def.getContainer() = this.getContainer())
}
/**
@@ -198,9 +198,9 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* be more efficient on large databases.
*/
predicate isLiveAtEntry(Variable v) {
isLocallyLiveAtEntry(v, _)
this.isLocallyLiveAtEntry(v, _)
or
not this.defAt(_, v, _) and getASuccessor().isLiveAtEntry(v)
not this.defAt(_, v, _) and this.getASuccessor().isLiveAtEntry(v)
}
/**
@@ -208,18 +208,18 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* `u` is a use of `v` witnessing the liveness.
*/
predicate localIsLiveAtEntry(LocalVariable v, VarUse u) {
isLocallyLiveAtEntry(v, u)
this.isLocallyLiveAtEntry(v, u)
or
not this.defAt(_, v, _) and getASuccessor().localIsLiveAtEntry(v, u)
not this.defAt(_, v, _) and this.getASuccessor().localIsLiveAtEntry(v, u)
}
/**
* Holds if local variable `v` is live at entry to this basic block.
*/
predicate localIsLiveAtEntry(LocalVariable v) {
isLocallyLiveAtEntry(v, _)
this.isLocallyLiveAtEntry(v, _)
or
not this.defAt(_, v, _) and getASuccessor().localIsLiveAtEntry(v)
not this.defAt(_, v, _) and this.getASuccessor().localIsLiveAtEntry(v)
}
/**
@@ -227,9 +227,9 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* this basic block without going through a redefinition of `v`.
*/
predicate localMayBeOverwritten(LocalVariable v, VarDef d) {
isLocallyOverwritten(v, d)
this.isLocallyOverwritten(v, d)
or
not defAt(_, v, _) and getASuccessor().localMayBeOverwritten(v, d)
not this.defAt(_, v, _) and this.getASuccessor().localMayBeOverwritten(v, d)
}
/**
@@ -239,10 +239,10 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* result is the length of this basic block.
*/
private int nextDefOrUseAfter(PurelyLocalVariable v, int i, VarDef d) {
defAt(i, v, d) and
this.defAt(i, v, d) and
result =
min(int j |
(defAt(j, v, _) or useAt(j, v, _) or j = length()) and
(this.defAt(j, v, _) or this.useAt(j, v, _) or j = this.length()) and
j > i
)
}
@@ -253,10 +253,10 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* definition and before a re-definition.
*/
predicate localLiveDefAt(PurelyLocalVariable v, int i, VarDef d) {
exists(int j | j = nextDefOrUseAfter(v, i, d) |
useAt(j, v, _)
exists(int j | j = this.nextDefOrUseAfter(v, i, d) |
this.useAt(j, v, _)
or
j = length() and getASuccessor().localIsLiveAtEntry(v)
j = this.length() and this.getASuccessor().localIsLiveAtEntry(v)
)
}
@@ -265,7 +265,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* no definitions of `v` before it.
*/
private predicate isLocallyLiveAtEntry(Variable v, VarUse u) {
exists(int n | useAt(n, v, u) | not exists(int m | m < n | defAt(m, v, _)))
exists(int n | this.useAt(n, v, u) | not exists(int m | m < n | this.defAt(m, v, _)))
}
/**
@@ -273,7 +273,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* no other definitions of `v` before it.
*/
private predicate isLocallyOverwritten(Variable v, VarDef d) {
exists(int n | defAt(n, v, d) | not exists(int m | m < n | defAt(m, v, _)))
exists(int n | this.defAt(n, v, d) | not exists(int m | m < n | this.defAt(m, v, _)))
}
/**
@@ -287,7 +287,7 @@ class BasicBlock extends @cfg_node, NodeInStmtContainer {
* whose first node is unreachable.
*/
class UnreachableBlock extends BasicBlock {
UnreachableBlock() { getFirstNode().isUnreachable() }
UnreachableBlock() { this.getFirstNode().isUnreachable() }
}
/**
@@ -337,7 +337,7 @@ class ReachableBasicBlock extends BasicBlock {
* A reachable basic block with more than one predecessor.
*/
class ReachableJoinBlock extends ReachableBasicBlock {
ReachableJoinBlock() { getFirstNode().isJoin() }
ReachableJoinBlock() { this.getFirstNode().isJoin() }
/**
* Holds if this basic block belongs to the dominance frontier of `b`, that is
@@ -348,11 +348,11 @@ class ReachableJoinBlock extends ReachableBasicBlock {
* its use in optimization".
*/
predicate inDominanceFrontierOf(ReachableBasicBlock b) {
b = getAPredecessor() and not b = getImmediateDominator()
b = this.getAPredecessor() and not b = this.getImmediateDominator()
or
exists(ReachableBasicBlock prev | inDominanceFrontierOf(prev) |
exists(ReachableBasicBlock prev | this.inDominanceFrontierOf(prev) |
b = prev.getImmediateDominator() and
not b = getImmediateDominator()
not b = this.getImmediateDominator()
)
}
}

View File

@@ -39,7 +39,7 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized {
* Has no result if no name could be determined.
*/
string getName() {
result = getIdentifier().getName() // Overridden in ClassExpr
result = this.getIdentifier().getName() // Overridden in ClassExpr
}
/** Gets a member declared in this class or interface. */
@@ -50,37 +50,37 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized {
/** Gets the member with the given name declared in this class or interface. */
MemberDeclaration getMember(string name) {
result = getAMember() and
result = this.getAMember() and
result.getName() = name
}
/** Gets a method declared in this class or interface. */
MethodDeclaration getAMethod() { result = getAMember() }
MethodDeclaration getAMethod() { result = this.getAMember() }
/**
* Gets the method with the given name declared in this class or interface.
*
* Note that for overloaded method signatures in TypeScript files, this returns every overload.
*/
MethodDeclaration getMethod(string name) { result = getMember(name) }
MethodDeclaration getMethod(string name) { result = this.getMember(name) }
/** Gets an overloaded version of the method with the given name declared in this class or interface. */
MethodDeclaration getMethodOverload(string name, int overloadIndex) {
result = getMethod(name) and
result = this.getMethod(name) and
overloadIndex = result.getOverloadIndex()
}
/** Gets a field declared in this class or interface. */
FieldDeclaration getAField() { result = getAMember() }
FieldDeclaration getAField() { result = this.getAMember() }
/** Gets the field with the given name declared in this class or interface. */
FieldDeclaration getField(string name) { result = getMember(name) }
FieldDeclaration getField(string name) { result = this.getMember(name) }
/** Gets a call signature declared in this interface. */
CallSignature getACallSignature() { result = getAMember() }
CallSignature getACallSignature() { result = this.getAMember() }
/** Gets an index signature declared in this interface. */
IndexSignature getAnIndexSignature() { result = getAMember() }
IndexSignature getAnIndexSignature() { result = this.getAMember() }
/**
* Gets the expression denoting the super class of this class,
@@ -97,7 +97,7 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized {
/**
* Gets any type from the `implements` clause of this class or `extends` clause of this interface.
*/
TypeExpr getASuperInterface() { result = getSuperInterface(_) }
TypeExpr getASuperInterface() { result = this.getSuperInterface(_) }
/**
* Holds if this is an interface or a class declared with the `abstract` modifier.
@@ -157,10 +157,10 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized {
*/
class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNode {
/** Gets the variable holding this class. */
Variable getVariable() { result = getIdentifier().getVariable() }
Variable getVariable() { result = this.getIdentifier().getVariable() }
/** Gets the identifier naming the defined class, if any. */
override VarDecl getIdentifier() { result = getChildExpr(0) }
override VarDecl getIdentifier() { result = this.getChildExpr(0) }
override TypeParameter getTypeParameter(int i) {
// AST indices for type parameters: -3, -6, -9, ...
@@ -170,7 +170,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
}
/** Gets the expression denoting the super class of the defined class, if any. */
override Expr getSuperClass() { result = getChildExpr(1) }
override Expr getSuperClass() { result = this.getChildExpr(1) }
/** Gets the `n`th type from the `implements` clause of this class, starting at 0. */
override TypeExpr getSuperInterface(int i) {
@@ -189,7 +189,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
* Note that every class has a constructor: if no explicit constructor
* is declared, it has a synthetic default constructor.
*/
ConstructorDeclaration getConstructor() { result = getAMethod() }
ConstructorDeclaration getConstructor() { result = this.getAMethod() }
/**
* Gets the `i`th decorator applied to this class.
@@ -210,7 +210,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
* For example, the class `@A @B class C {}` has
* decorators `@A` and `@B`.
*/
Decorator getADecorator() { result = getDecorator(_) }
Decorator getADecorator() { result = this.getDecorator(_) }
/**
* Holds if this class has the `abstract` modifier.
@@ -218,8 +218,8 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
override predicate isAbstract() { is_abstract_class(this) }
override string describe() {
if exists(inferNameFromVarDef())
then result = inferNameFromVarDef()
if exists(this.inferNameFromVarDef())
then result = this.inferNameFromVarDef()
else result = "anonymous class"
}
@@ -229,8 +229,8 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
*/
private string inferNameFromVarDef() {
// in ambiguous cases like `let C = class D {}`, prefer `D` to `C`
if exists(getIdentifier())
then result = "class " + getIdentifier().getName()
if exists(this.getIdentifier())
then result = "class " + this.getIdentifier().getName()
else
exists(VarDef vd | this = vd.getSource() |
result = "class " + vd.getTarget().(VarRef).getName()
@@ -243,7 +243,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
* Note that constructors aren't considered instance methods.
*/
Function getInstanceMethod(string name) {
exists(MemberDefinition mem | mem = getMember(name) |
exists(MemberDefinition mem | mem = this.getMember(name) |
result = mem.getInit() and
not mem.isStatic() and
not mem instanceof ConstructorDefinition
@@ -254,7 +254,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
* Gets the definition of the super class of this class, if it can be determined.
*/
ClassDefinition getSuperClassDefinition() {
result = getSuperClass().analyze().getAValue().(AbstractClass).getClass()
result = this.getSuperClass().analyze().getAValue().(AbstractClass).getClass()
}
override string getAPrimaryQlClass() { result = "ClassDefinition" }
@@ -285,7 +285,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod
*/
class ClassDeclStmt extends @class_decl_stmt, ClassDefinition, Stmt {
override ControlFlowNode getFirstControlFlowNode() {
if has_declare_keyword(this) then result = this else result = getIdentifier()
if has_declare_keyword(this) then result = this else result = this.getIdentifier()
}
}
@@ -307,7 +307,7 @@ class ClassExpr extends @class_expr, ClassDefinition, Expr {
override string getName() {
result = ClassDefinition.super.getName()
or
not exists(getIdentifier()) and
not exists(this.getIdentifier()) and
(
exists(VarDef vd | this = vd.getSource() | result = vd.getTarget().(VarRef).getName())
or
@@ -327,21 +327,25 @@ class ClassExpr extends @class_expr, ClassDefinition, Expr {
override predicate isImpure() { none() }
override ControlFlowNode getFirstControlFlowNode() {
if exists(getIdentifier())
then result = getIdentifier()
if exists(this.getIdentifier())
then result = this.getIdentifier()
else
if exists(getSuperClass())
then result = getSuperClass().getFirstControlFlowNode()
if exists(this.getSuperClass())
then result = this.getSuperClass().getFirstControlFlowNode()
else
if exists(getClassInitializedMember())
if exists(this.getClassInitializedMember())
then
result =
min(ClassInitializedMember m | m = getClassInitializedMember() | m order by m.getIndex())
min(ClassInitializedMember m |
m = this.getClassInitializedMember()
|
m order by m.getIndex()
)
else result = this
}
/** Returns a member that is initialized during the creation of this class. */
private ClassInitializedMember getClassInitializedMember() { result = getAMember() }
private ClassInitializedMember getClassInitializedMember() { result = this.getAMember() }
}
/**
@@ -371,7 +375,7 @@ class SuperExpr extends @super_expr, Expr {
* Gets the function whose `super` binding this expression refers to,
* which is the nearest enclosing non-arrow function.
*/
Function getBinder() { result = getEnclosingFunction().getThisBinder() }
Function getBinder() { result = this.getEnclosingFunction().getThisBinder() }
override string getAPrimaryQlClass() { result = "SuperExpr" }
}
@@ -386,13 +390,13 @@ class SuperExpr extends @super_expr, Expr {
* ```
*/
class SuperCall extends CallExpr {
SuperCall() { getCallee().getUnderlyingValue() instanceof SuperExpr }
SuperCall() { this.getCallee().getUnderlyingValue() instanceof SuperExpr }
/**
* Gets the function whose `super` binding this call refers to,
* which is the nearest enclosing non-arrow function.
*/
Function getBinder() { result = getCallee().getUnderlyingValue().(SuperExpr).getBinder() }
Function getBinder() { result = this.getCallee().getUnderlyingValue().(SuperExpr).getBinder() }
}
/**
@@ -405,7 +409,7 @@ class SuperCall extends CallExpr {
* ```
*/
class SuperPropAccess extends PropAccess {
SuperPropAccess() { getBase().getUnderlyingValue() instanceof SuperExpr }
SuperPropAccess() { this.getBase().getUnderlyingValue() instanceof SuperExpr }
}
/**
@@ -502,7 +506,7 @@ class MemberDeclaration extends @property, Documentable {
*
* Class members not declared in a TypeScript file are always considered public.
*/
predicate isPublic() { not isPrivate() and not isProtected() }
predicate isPublic() { not this.isPrivate() and not this.isProtected() }
/**
* Holds if this is a TypeScript member explicitly annotated with the `public` keyword.
@@ -523,20 +527,20 @@ class MemberDeclaration extends @property, Documentable {
* Gets the expression specifying the name of this member,
* or nothing if this is a call signature.
*/
Expr getNameExpr() { result = getChildExpr(0) }
Expr getNameExpr() { result = this.getChildExpr(0) }
/**
* Gets the expression specifying the initial value of the member;
* for methods and constructors this is always a function, for fields
* it may not be defined.
*/
Expr getInit() { result = getChildExpr(1) }
Expr getInit() { result = this.getChildExpr(1) }
/** Gets the name of this member. */
string getName() {
result = getNameExpr().(Literal).getValue()
result = this.getNameExpr().(Literal).getValue()
or
not isComputed() and result = getNameExpr().(Identifier).getName()
not this.isComputed() and result = this.getNameExpr().(Identifier).getName()
}
/** Holds if the name of this member is computed. */
@@ -552,7 +556,7 @@ class MemberDeclaration extends @property, Documentable {
int getMemberIndex() { properties(this, _, result, _, _) }
/** Holds if the name of this member is computed by an impure expression. */
predicate hasImpureNameExpr() { isComputed() and getNameExpr().isImpure() }
predicate hasImpureNameExpr() { this.isComputed() and this.getNameExpr().isImpure() }
/**
* Gets the `i`th decorator applied to this member.
@@ -560,7 +564,7 @@ class MemberDeclaration extends @property, Documentable {
* For example, a method of the form `@A @B m() { ... }` has
* `@A` as its 0th decorator and `@B` as its first decorator.
*/
Decorator getDecorator(int i) { result = getChildExpr(-(i + 1)) }
Decorator getDecorator(int i) { result = this.getChildExpr(-(i + 1)) }
/**
* Gets a decorator applied to this member.
@@ -568,27 +572,27 @@ class MemberDeclaration extends @property, Documentable {
* For example, a method of the form `@A @B m() { ... }` has
* decorators `@A` and `@B`.
*/
Decorator getADecorator() { result = getDecorator(_) }
Decorator getADecorator() { result = this.getDecorator(_) }
override string toString() { properties(this, _, _, _, result) }
override ControlFlowNode getFirstControlFlowNode() {
result = getNameExpr().getFirstControlFlowNode()
result = this.getNameExpr().getFirstControlFlowNode()
}
/**
* True if this is neither abstract, ambient, nor part of an overloaded method signature.
*/
predicate isConcrete() {
not isAbstract() and
not isAmbient() and
not this.isAbstract() and
not this.isAmbient() and
(this instanceof MethodDeclaration implies this.(MethodDeclaration).getBody().hasBody())
}
/**
* True if this is abstract, ambient, or an overload signature.
*/
predicate isSignature() { not isConcrete() }
predicate isSignature() { not this.isConcrete() }
override string getAPrimaryQlClass() { result = "MemberDeclaration" }
}
@@ -615,7 +619,7 @@ class MemberDeclaration extends @property, Documentable {
* ```
*/
class MemberDefinition extends MemberDeclaration {
MemberDefinition() { isConcrete() }
MemberDefinition() { this.isConcrete() }
}
/**
@@ -631,7 +635,7 @@ class MemberDefinition extends MemberDeclaration {
* ```
*/
class MemberSignature extends MemberDeclaration {
MemberSignature() { isSignature() }
MemberSignature() { this.isSignature() }
}
/**
@@ -668,7 +672,7 @@ class MethodDeclaration extends MemberDeclaration {
/**
* Gets the body of this method.
*/
FunctionExpr getBody() { result = getChildExpr(1) }
FunctionExpr getBody() { result = this.getChildExpr(1) }
/**
* Holds if this method is overloaded, that is, there are multiple method
@@ -676,10 +680,10 @@ class MethodDeclaration extends MemberDeclaration {
*/
predicate isOverloaded() {
not this instanceof ConstructorDeclaration and
hasOverloadedMethod(getDeclaringType(), getName())
hasOverloadedMethod(this.getDeclaringType(), this.getName())
or
this instanceof ConstructorDeclaration and
hasOverloadedConstructor(getDeclaringClass())
hasOverloadedConstructor(this.getDeclaringClass())
}
/**
@@ -806,13 +810,13 @@ class MethodSignature extends MethodDeclaration, MemberSignature {
*/
class ConstructorDeclaration extends MethodDeclaration {
ConstructorDeclaration() {
not isComputed() and
not isStatic() and
getName() = "constructor"
not this.isComputed() and
not this.isStatic() and
this.getName() = "constructor"
}
/** Holds if this is a synthetic default constructor. */
predicate isSynthetic() { getLocation().isEmpty() }
predicate isSynthetic() { this.getLocation().isEmpty() }
override string getAPrimaryQlClass() { result = "ConstructorDeclaration" }
}
@@ -1073,9 +1077,9 @@ class SetterMethodSignature extends SetterMethodDeclaration, AccessorMethodSigna
class FieldDeclaration extends MemberDeclaration, @field {
/** Gets the type annotation of this field, if any, such as `T` in `{ x: T }`. */
TypeAnnotation getTypeAnnotation() {
result = getChildTypeExpr(2)
result = this.getChildTypeExpr(2)
or
result = getDocumentation().getATagByTitle("type").getType()
result = this.getDocumentation().getATagByTitle("type").getType()
}
/** Holds if this is a TypeScript field annotated with the `readonly` keyword. */
@@ -1136,9 +1140,9 @@ class ParameterField extends FieldDeclaration, @parameter_field {
)
}
override Expr getNameExpr() { result = getParameter() }
override Expr getNameExpr() { result = this.getParameter() }
override TypeAnnotation getTypeAnnotation() { result = getParameter().getTypeAnnotation() }
override TypeAnnotation getTypeAnnotation() { result = this.getParameter().getTypeAnnotation() }
}
/**
@@ -1168,7 +1172,7 @@ class StaticInitializer extends MemberDefinition, @static_initializer {
* Call signatures are either function call signatures or constructor call signatures.
*/
class CallSignature extends @call_signature, MemberSignature {
FunctionExpr getBody() { result = getChildExpr(1) }
FunctionExpr getBody() { result = this.getChildExpr(1) }
/** Gets the interface or function type that declares this call signature. */
override InterfaceDefinition getDeclaringType() {
@@ -1190,7 +1194,7 @@ class CallSignature extends @call_signature, MemberSignature {
class FunctionCallSignature extends @function_call_signature, CallSignature {
/** Gets the index of this function call signature among the function call signatures in the enclosing type. */
int getOverloadIndex() {
exists(ClassOrInterface type | type = getDeclaringType() |
exists(ClassOrInterface type | type = this.getDeclaringType() |
this =
rank[result + 1](FunctionCallSignature sig, int i |
sig = type.getMemberByIndex(i)
@@ -1204,7 +1208,7 @@ class FunctionCallSignature extends @function_call_signature, CallSignature {
* Holds if this function call signature is overloaded, that is, there are multiple function call
* signatures declared in the enclosing type.
*/
predicate isOverloaded() { hasOverloadedFunctionCallSignature(getDeclaringType()) }
predicate isOverloaded() { hasOverloadedFunctionCallSignature(this.getDeclaringType()) }
}
/**
@@ -1221,7 +1225,7 @@ class FunctionCallSignature extends @function_call_signature, CallSignature {
class ConstructorCallSignature extends @constructor_call_signature, CallSignature {
/** Gets the index of this constructor call signature among the constructor call signatures in the enclosing type. */
int getOverloadIndex() {
exists(ClassOrInterface type | type = getDeclaringType() |
exists(ClassOrInterface type | type = this.getDeclaringType() |
this =
rank[result + 1](ConstructorCallSignature sig, int i |
sig = type.getMemberByIndex(i)
@@ -1235,7 +1239,7 @@ class ConstructorCallSignature extends @constructor_call_signature, CallSignatur
* Holds if this constructor call signature is overloaded, that is, there are multiple constructor call
* signatures declared in the enclosing type.
*/
predicate isOverloaded() { hasOverloadedConstructorCallSignature(getDeclaringType()) }
predicate isOverloaded() { hasOverloadedConstructorCallSignature(this.getDeclaringType()) }
}
/**
@@ -1250,7 +1254,7 @@ class ConstructorCallSignature extends @constructor_call_signature, CallSignatur
* ```
*/
class IndexSignature extends @index_signature, MemberSignature {
FunctionExpr getBody() { result = getChildExpr(1) }
FunctionExpr getBody() { result = this.getChildExpr(1) }
/** Gets the interface or function type that declares this index signature. */
override InterfaceDefinition getDeclaringType() {

View File

@@ -51,13 +51,13 @@ module DOM {
* Gets the root element (i.e. an element without a parent) in which this element is contained.
*/
ElementDefinition getRoot() {
if not exists(getParent()) then result = this else result = getParent().getRoot()
if not exists(this.getParent()) then result = this else result = this.getParent().getRoot()
}
/**
* Gets the document element to which this element belongs, if it can be determined.
*/
DocumentElementDefinition getDocument() { result = getRoot() }
DocumentElementDefinition getDocument() { result = this.getRoot() }
}
/**
@@ -112,7 +112,7 @@ module DOM {
/**
* Gets the value of this attribute, if it can be determined.
*/
string getStringValue() { result = getValueNode().getStringValue() }
string getStringValue() { result = this.getValueNode().getStringValue() }
/**
* Gets the DOM element this attribute belongs to.
@@ -124,7 +124,7 @@ module DOM {
* such as `{{window.location.url}}`.
*/
predicate mayHaveTemplateValue() {
getStringValue().regexpMatch(Templating::getDelimiterMatchingRegexp())
this.getStringValue().regexpMatch(Templating::getDelimiterMatchingRegexp())
}
}

View File

@@ -45,7 +45,7 @@ module DefensiveExpressionTest {
)
}
override boolean getTheTestResult() { result = analyze().getTheBooleanValue() }
override boolean getTheTestResult() { result = this.analyze().getTheBooleanValue() }
}
/**
@@ -153,7 +153,7 @@ module DefensiveExpressionTest {
InferredType op2type;
NullUndefinedComparison() {
exists(Expr op2 | hasOperands(operand, op2) |
exists(Expr op2 | this.hasOperands(operand, op2) |
op2type = TTNull() and SyntacticConstants::isNull(op2)
or
op2type = TTUndefined() and SyntacticConstants::isUndefined(op2)
@@ -161,7 +161,7 @@ module DefensiveExpressionTest {
}
override boolean getTheTestResult() {
result = getPolarity() and
result = this.getPolarity() and
(
if this instanceof StrictEqualityTest
then
@@ -172,7 +172,7 @@ module DefensiveExpressionTest {
not isNotNullOrUndefined(operand.analyze().getAType())
)
or
result = getPolarity().booleanNot() and
result = this.getPolarity().booleanNot() and
(
if this instanceof StrictEqualityTest
then
@@ -336,7 +336,7 @@ module DefensiveExpressionTest {
or
testResult = false and not operand.analyze().getAType().getTypeofTag() = tag
|
if getPolarity() = true then result = testResult else result = testResult.booleanNot()
if this.getPolarity() = true then result = testResult else result = testResult.booleanNot()
)
}

View File

@@ -20,22 +20,22 @@ class ExprOrType extends @expr_or_type, Documentable {
Stmt getEnclosingStmt() { enclosing_stmt(this, result) }
/** Gets the function in which this expression or type appears, if any. */
Function getEnclosingFunction() { result = getContainer() }
Function getEnclosingFunction() { result = this.getContainer() }
/**
* Gets the JSDoc comment associated with this expression or type or its parent statement, if any.
*/
override JSDoc getDocumentation() {
result = getOwnDocumentation()
result = this.getOwnDocumentation()
or
// if there is no JSDoc for the expression itself, check the enclosing property or statement
not exists(getOwnDocumentation()) and
not exists(this.getOwnDocumentation()) and
(
exists(Property prop | prop = getParent() | result = prop.getDocumentation())
exists(Property prop | prop = this.getParent() | result = prop.getDocumentation())
or
exists(MethodDeclaration decl | decl = getParent() | result = decl.getDocumentation())
exists(MethodDeclaration decl | decl = this.getParent() | result = decl.getDocumentation())
or
exists(VariableDeclarator decl | decl = getParent() | result = decl.getDocumentation())
exists(VariableDeclarator decl | decl = this.getParent() | result = decl.getDocumentation())
or
exists(DeclStmt stmt | this = stmt.getDecl(0) | result = stmt.getDocumentation())
or
@@ -119,7 +119,7 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode {
* Holds if this expression is pure, that is, its evaluation is guaranteed
* to be side-effect free.
*/
predicate isPure() { not isImpure() }
predicate isPure() { not this.isImpure() }
/**
* Gets the kind of this expression, which is an integer value representing the expression's
@@ -151,22 +151,22 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode {
* Holds if this expression accesses the global variable `g`, either directly
* or through the `window` object.
*/
predicate accessesGlobal(string g) { flow().accessesGlobal(g) }
predicate accessesGlobal(string g) { this.flow().accessesGlobal(g) }
/**
* Holds if this expression may evaluate to `s`.
*/
predicate mayHaveStringValue(string s) { flow().mayHaveStringValue(s) }
predicate mayHaveStringValue(string s) { this.flow().mayHaveStringValue(s) }
/**
* Holds if this expression may evaluate to `b`.
*/
predicate mayHaveBooleanValue(boolean b) { flow().mayHaveBooleanValue(b) }
predicate mayHaveBooleanValue(boolean b) { this.flow().mayHaveBooleanValue(b) }
/**
* Holds if this expression may refer to the initial value of parameter `p`.
*/
predicate mayReferToParameter(Parameter p) { flow().mayReferToParameter(p) }
predicate mayReferToParameter(Parameter p) { this.flow().mayReferToParameter(p) }
/**
* Gets the static type of this expression, as determined by the TypeScript type system.
@@ -248,9 +248,9 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode {
*/
pragma[inline]
DataFlow::Node getExceptionTarget() {
result = getCatchParameterFromStmt(getRawEnclosingStmt(this))
result = getCatchParameterFromStmt(this.getRawEnclosingStmt(this))
or
not exists(getCatchParameterFromStmt(getRawEnclosingStmt(this))) and
not exists(getCatchParameterFromStmt(this.getRawEnclosingStmt(this))) and
result =
any(DataFlow::FunctionNode f | f.getFunction() = this.getContainer()).getExceptionalReturn()
}
@@ -340,15 +340,15 @@ class ParExpr extends @par_expr, Expr {
/** Gets the expression within parentheses. */
Expr getExpression() { result = this.getChildExpr(0) }
override Expr stripParens() { result = getExpression().stripParens() }
override Expr stripParens() { result = this.getExpression().stripParens() }
override int getIntValue() { result = getExpression().getIntValue() }
override int getIntValue() { result = this.getExpression().getIntValue() }
override predicate isImpure() { getExpression().isImpure() }
override predicate isImpure() { this.getExpression().isImpure() }
override Expr getUnderlyingValue() { result = getExpression().getUnderlyingValue() }
override Expr getUnderlyingValue() { result = this.getExpression().getUnderlyingValue() }
override Expr getUnderlyingReference() { result = getExpression().getUnderlyingReference() }
override Expr getUnderlyingReference() { result = this.getExpression().getUnderlyingReference() }
override string getAPrimaryQlClass() { result = "ParExpr" }
}
@@ -391,10 +391,10 @@ class BooleanLiteral extends @boolean_literal, Literal { }
*/
class NumberLiteral extends @number_literal, Literal {
/** Gets the integer value of this literal. */
override int getIntValue() { result = getValue().toInt() }
override int getIntValue() { result = this.getValue().toInt() }
/** Gets the floating point value of this literal. */
float getFloatValue() { result = getValue().toFloat() }
float getFloatValue() { result = this.getValue().toFloat() }
}
/**
@@ -411,13 +411,13 @@ class BigIntLiteral extends @bigint_literal, Literal {
* Gets the integer value of this literal if it can be represented
* as a QL integer value.
*/
override int getIntValue() { result = getValue().toInt() }
override int getIntValue() { result = this.getValue().toInt() }
/**
* Gets the floating point value of this literal if it can be represented
* as a QL floating point value.
*/
float getFloatValue() { result = getValue().toFloat() }
float getFloatValue() { result = this.getValue().toFloat() }
}
/**
@@ -459,19 +459,19 @@ class RegExpLiteral extends @regexp_literal, Literal, RegExpParent {
RegExpTerm getRoot() { this = result.getParent() }
/** Gets the flags of this regular expression. */
string getFlags() { result = getValue().regexpCapture(".*/(\\w*)$", 1) }
string getFlags() { result = this.getValue().regexpCapture(".*/(\\w*)$", 1) }
/** Holds if this regular expression has an `m` flag. */
predicate isMultiline() { RegExp::isMultiline(getFlags()) }
predicate isMultiline() { RegExp::isMultiline(this.getFlags()) }
/** Holds if this regular expression has a `g` flag. */
predicate isGlobal() { RegExp::isGlobal(getFlags()) }
predicate isGlobal() { RegExp::isGlobal(this.getFlags()) }
/** Holds if this regular expression has an `i` flag. */
predicate isIgnoreCase() { RegExp::isIgnoreCase(getFlags()) }
predicate isIgnoreCase() { RegExp::isIgnoreCase(this.getFlags()) }
/** Holds if this regular expression has an `s` flag. */
predicate isDotAll() { RegExp::isDotAll(getFlags()) }
predicate isDotAll() { RegExp::isDotAll(this.getFlags()) }
override string getAPrimaryQlClass() { result = "RegExpLiteral" }
}
@@ -492,16 +492,16 @@ class ThisExpr extends @this_expr, Expr {
* Gets the function whose `this` binding this expression refers to,
* which is the nearest enclosing non-arrow function.
*/
Function getBinder() { result = getEnclosingFunction().getThisBinder() }
Function getBinder() { result = this.getEnclosingFunction().getThisBinder() }
/**
* Gets the function or top-level whose `this` binding this expression refers to,
* which is the nearest enclosing non-arrow function or top-level.
*/
StmtContainer getBindingContainer() {
result = getContainer().(Function).getThisBindingContainer()
result = this.getContainer().(Function).getThisBindingContainer()
or
result = getContainer().(TopLevel)
result = this.getContainer().(TopLevel)
}
override string getAPrimaryQlClass() { result = "ThisExpr" }
@@ -534,14 +534,14 @@ class ArrayExpr extends @array_expr, Expr {
/** Holds if the `i`th element of this array literal is omitted. */
predicate elementIsOmitted(int i) {
i in [0 .. getSize() - 1] and
not exists(getElement(i))
i in [0 .. this.getSize() - 1] and
not exists(this.getElement(i))
}
/** Holds if this array literal has an omitted element. */
predicate hasOmittedElement() { elementIsOmitted(_) }
predicate hasOmittedElement() { this.elementIsOmitted(_) }
override predicate isImpure() { getAnElement().isImpure() }
override predicate isImpure() { this.getAnElement().isImpure() }
override string getAPrimaryQlClass() { result = "ArrayExpr" }
}
@@ -583,7 +583,7 @@ class ObjectExpr extends @obj_expr, Expr {
*/
predicate hasTrailingComma() { this.getLastToken().getPreviousToken().getValue() = "," }
override predicate isImpure() { getAProperty().isImpure() }
override predicate isImpure() { this.getAProperty().isImpure() }
override string getAPrimaryQlClass() { result = "ObjectExpr" }
}
@@ -626,9 +626,9 @@ class Property extends @property, Documentable {
/** Gets the name of this property. */
string getName() {
not isComputed() and result = getNameExpr().(Identifier).getName()
not this.isComputed() and result = this.getNameExpr().(Identifier).getName()
or
result = getNameExpr().(Literal).getValue()
result = this.getNameExpr().(Literal).getValue()
}
/** Holds if the name of this property is computed. */
@@ -638,30 +638,30 @@ class Property extends @property, Documentable {
predicate isMethod() { is_method(this) }
/** Holds if this property is defined using shorthand syntax. */
predicate isShorthand() { getNameExpr().getLocation() = getInit().getLocation() }
predicate isShorthand() { this.getNameExpr().getLocation() = this.getInit().getLocation() }
/** Gets the object literal this property belongs to. */
ObjectExpr getObjectExpr() { properties(this, result, _, _, _) }
/** Gets the (0-based) index at which this property appears in its enclosing literal. */
int getIndex() { this = getObjectExpr().getProperty(result) }
int getIndex() { this = this.getObjectExpr().getProperty(result) }
/**
* Holds if this property is impure, that is, the evaluation of its name or
* its initializer expression could have side effects.
*/
predicate isImpure() {
isComputed() and getNameExpr().isImpure()
this.isComputed() and this.getNameExpr().isImpure()
or
getInit().isImpure()
this.getInit().isImpure()
}
override string toString() { properties(this, _, _, _, result) }
override ControlFlowNode getFirstControlFlowNode() {
result = getNameExpr().getFirstControlFlowNode()
result = this.getNameExpr().getFirstControlFlowNode()
or
not exists(getNameExpr()) and result = getInit().getFirstControlFlowNode()
not exists(this.getNameExpr()) and result = this.getInit().getFirstControlFlowNode()
}
/**
@@ -677,7 +677,7 @@ class Property extends @property, Documentable {
* For example, the property `@A @B x: 42` has
* `@A` as its 0th decorator, and `@B` as its first decorator.
*/
Decorator getDecorator(int i) { result = getChildExpr(-(i + 1)) }
Decorator getDecorator(int i) { result = this.getChildExpr(-(i + 1)) }
/**
* Gets a decorator applied to this property.
@@ -685,7 +685,7 @@ class Property extends @property, Documentable {
* For example, the property `@A @B x: 42` has
* decorators `@A` and `@B`.
*/
Decorator getADecorator() { result = getDecorator(_) }
Decorator getADecorator() { result = this.getDecorator(_) }
override string getAPrimaryQlClass() { result = "Property" }
}
@@ -774,7 +774,7 @@ class PropertySetter extends PropertyAccessor, @property_setter { }
* ```
*/
class SpreadProperty extends Property {
SpreadProperty() { not exists(getNameExpr()) }
SpreadProperty() { not exists(this.getNameExpr()) }
}
/**
@@ -834,7 +834,9 @@ class ArrowFunctionExpr extends @arrow_function_expr, Expr, Function {
override predicate isImpure() { none() }
override Function getThisBinder() { result = getEnclosingContainer().(Function).getThisBinder() }
override Function getThisBinder() {
result = this.getEnclosingContainer().(Function).getThisBinder()
}
override string getAPrimaryQlClass() { result = "ArrowFunctionExpr" }
}
@@ -850,20 +852,20 @@ class ArrowFunctionExpr extends @arrow_function_expr, Expr, Function {
*/
class SeqExpr extends @seq_expr, Expr {
/** Gets the `i`th expression in this sequence. */
Expr getOperand(int i) { result = getChildExpr(i) }
Expr getOperand(int i) { result = this.getChildExpr(i) }
/** Gets an expression in this sequence. */
Expr getAnOperand() { result = getOperand(_) }
Expr getAnOperand() { result = this.getOperand(_) }
/** Gets the number of expressions in this sequence. */
int getNumOperands() { result = count(getOperand(_)) }
int getNumOperands() { result = count(this.getOperand(_)) }
/** Gets the last expression in this sequence. */
Expr getLastOperand() { result = getOperand(getNumOperands() - 1) }
Expr getLastOperand() { result = this.getOperand(this.getNumOperands() - 1) }
override predicate isImpure() { getAnOperand().isImpure() }
override predicate isImpure() { this.getAnOperand().isImpure() }
override Expr getUnderlyingValue() { result = getLastOperand().getUnderlyingValue() }
override Expr getUnderlyingValue() { result = this.getLastOperand().getUnderlyingValue() }
override string getAPrimaryQlClass() { result = "SeqExpr" }
}
@@ -879,20 +881,20 @@ class SeqExpr extends @seq_expr, Expr {
*/
class ConditionalExpr extends @conditional_expr, Expr {
/** Gets the condition expression of this conditional. */
Expr getCondition() { result = getChildExpr(0) }
Expr getCondition() { result = this.getChildExpr(0) }
/** Gets the 'then' expression of this conditional. */
Expr getConsequent() { result = getChildExpr(1) }
Expr getConsequent() { result = this.getChildExpr(1) }
/** Gets the 'else' expression of this conditional. */
Expr getAlternate() { result = getChildExpr(2) }
Expr getAlternate() { result = this.getChildExpr(2) }
/** Gets either the 'then' or the 'else' expression of this conditional. */
Expr getABranch() { result = getConsequent() or result = getAlternate() }
Expr getABranch() { result = this.getConsequent() or result = this.getAlternate() }
override predicate isImpure() {
getCondition().isImpure() or
getABranch().isImpure()
this.getCondition().isImpure() or
this.getABranch().isImpure()
}
override string getAPrimaryQlClass() { result = "ConditionalExpr" }
@@ -917,7 +919,7 @@ class InvokeExpr extends @invokeexpr, Expr {
/** Gets the name of the function or method being invoked, if it can be determined. */
string getCalleeName() {
exists(Expr callee | callee = getCallee().getUnderlyingValue() |
exists(Expr callee | callee = this.getCallee().getUnderlyingValue() |
result = callee.(Identifier).getName() or
result = callee.(PropAccess).getPropertyName()
)
@@ -927,25 +929,25 @@ class InvokeExpr extends @invokeexpr, Expr {
Expr getArgument(int i) { i >= 0 and result = this.getChildExpr(i) }
/** Gets an argument of this invocation. */
Expr getAnArgument() { result = getArgument(_) }
Expr getAnArgument() { result = this.getArgument(_) }
/** Gets the last argument of this invocation, if any. */
Expr getLastArgument() { result = getArgument(getNumArgument() - 1) }
Expr getLastArgument() { result = this.getArgument(this.getNumArgument() - 1) }
/** Gets the number of arguments of this invocation. */
int getNumArgument() { result = count(getAnArgument()) }
int getNumArgument() { result = count(this.getAnArgument()) }
/** Gets the `i`th type argument of this invocation. */
TypeExpr getTypeArgument(int i) { i >= 0 and result = this.getChildTypeExpr(-i - 2) }
/** Gets a type argument of this invocation. */
TypeExpr getATypeArgument() { result = getTypeArgument(_) }
TypeExpr getATypeArgument() { result = this.getTypeArgument(_) }
/** Gets the number of type arguments of this invocation. */
int getNumTypeArgument() { result = count(getATypeArgument()) }
int getNumTypeArgument() { result = count(this.getATypeArgument()) }
override ControlFlowNode getFirstControlFlowNode() {
result = getCallee().getFirstControlFlowNode()
result = this.getCallee().getFirstControlFlowNode()
}
/** Holds if the argument list of this function has a trailing comma. */
@@ -953,7 +955,7 @@ class InvokeExpr extends @invokeexpr, Expr {
// check whether the last token of this invocation is a closing
// parenthesis, which itself is preceded by a comma
exists(PunctuatorToken rparen | rparen.getValue() = ")" |
rparen = getLastToken() and
rparen = this.getLastToken() and
rparen.getPreviousToken().getValue() = ","
)
}
@@ -961,7 +963,7 @@ class InvokeExpr extends @invokeexpr, Expr {
/**
* Holds if the `i`th argument of this invocation is a spread element.
*/
predicate isSpreadArgument(int i) { getArgument(i).stripParens() instanceof SpreadElement }
predicate isSpreadArgument(int i) { this.getArgument(i).stripParens() instanceof SpreadElement }
/**
* Holds if the `i`th argument of this invocation is an object literal whose property
@@ -970,7 +972,7 @@ class InvokeExpr extends @invokeexpr, Expr {
* This predicate is an approximation, computed using only local data flow.
*/
predicate hasOptionArgument(int i, string name, Expr value) {
value = flow().(DataFlow::InvokeNode).getOptionArgument(i, name).asExpr()
value = this.flow().(DataFlow::InvokeNode).getOptionArgument(i, name).asExpr()
}
/**
@@ -1004,7 +1006,7 @@ class InvokeExpr extends @invokeexpr, Expr {
* Note that the resolved function may be overridden in a subclass and thus is not
* necessarily the actual target of this invocation at runtime.
*/
Function getResolvedCallee() { result = getResolvedCalleeName().getImplementation() }
Function getResolvedCallee() { result = this.getResolvedCalleeName().getImplementation() }
}
/**
@@ -1036,7 +1038,7 @@ class CallExpr extends @call_expr, InvokeExpr {
* Gets the expression specifying the receiver on which the function
* is invoked, if any.
*/
Expr getReceiver() { result = getCallee().(PropAccess).getBase() }
Expr getReceiver() { result = this.getCallee().(PropAccess).getBase() }
override string getAPrimaryQlClass() { result = "CallExpr" }
}
@@ -1052,25 +1054,25 @@ class CallExpr extends @call_expr, InvokeExpr {
* ```
*/
class MethodCallExpr extends CallExpr {
MethodCallExpr() { getCallee().stripParens() instanceof PropAccess }
MethodCallExpr() { this.getCallee().stripParens() instanceof PropAccess }
/**
* Gets the property access referencing the method to be invoked.
*/
private PropAccess getMethodRef() { result = getCallee().stripParens() }
private PropAccess getMethodRef() { result = this.getCallee().stripParens() }
/**
* Gets the receiver expression of this method call.
*/
override Expr getReceiver() { result = getMethodRef().getBase() }
override Expr getReceiver() { result = this.getMethodRef().getBase() }
/**
* Gets the name of the invoked method, if it can be determined.
*/
string getMethodName() { result = getMethodRef().getPropertyName() }
string getMethodName() { result = this.getMethodRef().getPropertyName() }
/** Holds if this invocation calls method `m` on expression `base`. */
predicate calls(Expr base, string m) { getMethodRef().accesses(base, m) }
predicate calls(Expr base, string m) { this.getMethodRef().accesses(base, m) }
override string getAPrimaryQlClass() { result = "MethodCallExpr" }
}
@@ -1088,14 +1090,14 @@ class MethodCallExpr extends CallExpr {
*/
class PropAccess extends @propaccess, Expr {
/** Gets the base expression on which the property is accessed. */
Expr getBase() { result = getChildExpr(0) }
Expr getBase() { result = this.getChildExpr(0) }
/**
* Gets the expression specifying the name of the property being
* read or written. For dot expressions, this is an identifier; for
* index expressions it can be an arbitrary expression.
*/
Expr getPropertyNameExpr() { result = getChildExpr(1) }
Expr getPropertyNameExpr() { result = this.getChildExpr(1) }
/** Gets the name of the accessed property, if it can be determined. */
string getPropertyName() { none() }
@@ -1103,21 +1105,21 @@ class PropAccess extends @propaccess, Expr {
/** Gets the qualified name of the accessed property, if it can be determined. */
string getQualifiedName() {
exists(string basename |
basename = getBase().(Identifier).getName() or
basename = getBase().(PropAccess).getQualifiedName()
basename = this.getBase().(Identifier).getName() or
basename = this.getBase().(PropAccess).getQualifiedName()
|
result = basename + "." + getPropertyName()
result = basename + "." + this.getPropertyName()
)
}
/** Holds if this property name accesses property `p` on expression `base`. */
predicate accesses(Expr base, string p) {
base = getBase() and
p = getPropertyName()
base = this.getBase() and
p = this.getPropertyName()
}
override ControlFlowNode getFirstControlFlowNode() {
result = getBase().getFirstControlFlowNode()
result = this.getBase().getFirstControlFlowNode()
}
override Expr getUnderlyingReference() { result = this }
@@ -1133,12 +1135,12 @@ class PropAccess extends @propaccess, Expr {
* ```
*/
class DotExpr extends @dot_expr, PropAccess {
override string getPropertyName() { result = getProperty().getName() }
override string getPropertyName() { result = this.getProperty().getName() }
/** Gets the identifier specifying the name of the accessed property. */
Identifier getProperty() { result = getChildExpr(1) }
Identifier getProperty() { result = this.getChildExpr(1) }
override predicate isImpure() { getBase().isImpure() }
override predicate isImpure() { this.getBase().isImpure() }
override string getAPrimaryQlClass() { result = "DotExpr" }
}
@@ -1154,13 +1156,13 @@ class DotExpr extends @dot_expr, PropAccess {
*/
class IndexExpr extends @index_expr, PropAccess {
/** Gets the expression specifying the name of the accessed property. */
Expr getIndex() { result = getChildExpr(1) }
Expr getIndex() { result = this.getChildExpr(1) }
override string getPropertyName() { result = getIndex().(Literal).getValue() }
override string getPropertyName() { result = this.getIndex().(Literal).getValue() }
override predicate isImpure() {
getBase().isImpure() or
getIndex().isImpure()
this.getBase().isImpure() or
this.getIndex().isImpure()
}
override string getAPrimaryQlClass() { result = "IndexExpr" }
@@ -1178,15 +1180,15 @@ class IndexExpr extends @index_expr, PropAccess {
*/
class UnaryExpr extends @unaryexpr, Expr {
/** Gets the operand of this unary operator. */
Expr getOperand() { result = getChildExpr(0) }
Expr getOperand() { result = this.getChildExpr(0) }
/** Gets the operator of this expression. */
string getOperator() { none() }
override predicate isImpure() { getOperand().isImpure() }
override predicate isImpure() { this.getOperand().isImpure() }
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
result = this.getOperand().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "UnaryExpr" }
@@ -1204,7 +1206,7 @@ class UnaryExpr extends @unaryexpr, Expr {
class NegExpr extends @neg_expr, UnaryExpr {
override string getOperator() { result = "-" }
override int getIntValue() { result = -getOperand().getIntValue() }
override int getIntValue() { result = -this.getOperand().getIntValue() }
}
/**
@@ -1316,28 +1318,28 @@ class SpreadElement extends @spread_element, UnaryExpr {
*/
class BinaryExpr extends @binaryexpr, Expr {
/** Gets the left operand of this binary operator. */
Expr getLeftOperand() { result = getChildExpr(0) }
Expr getLeftOperand() { result = this.getChildExpr(0) }
/** Gets the right operand of this binary operator. */
Expr getRightOperand() { result = getChildExpr(1) }
Expr getRightOperand() { result = this.getChildExpr(1) }
/** Gets an operand of this binary operator. */
Expr getAnOperand() { result = getAChildExpr() }
Expr getAnOperand() { result = this.getAChildExpr() }
/** Holds if `e` and `f` (in either order) are the two operands of this expression. */
predicate hasOperands(Expr e, Expr f) {
e = getAnOperand() and
f = getAnOperand() and
e = this.getAnOperand() and
f = this.getAnOperand() and
e != f
}
/** Gets the operator of this expression. */
string getOperator() { none() }
override predicate isImpure() { getAnOperand().isImpure() }
override predicate isImpure() { this.getAnOperand().isImpure() }
override ControlFlowNode getFirstControlFlowNode() {
result = getLeftOperand().getFirstControlFlowNode()
result = this.getLeftOperand().getFirstControlFlowNode()
}
/**
@@ -1348,7 +1350,7 @@ class BinaryExpr extends @binaryexpr, Expr {
*/
int getWhitespaceAroundOperator() {
exists(Token lastLeft, Token operator, Token firstRight, int l, int c1, int c2, int c3, int c4 |
lastLeft = getLeftOperand().getLastToken() and
lastLeft = this.getLeftOperand().getLastToken() and
operator = lastLeft.getNextToken() and
firstRight = operator.getNextToken() and
lastLeft.getLocation().hasLocationInfo(_, _, _, l, c1) and
@@ -1881,15 +1883,17 @@ class ShiftExpr extends BinaryExpr {
*/
class Assignment extends @assignment, Expr {
/** Gets the left hand side of this assignment. */
Expr getLhs() { result = getChildExpr(0) }
Expr getLhs() { result = this.getChildExpr(0) }
/** Gets the right hand side of this assignment. */
Expr getRhs() { result = getChildExpr(1) }
Expr getRhs() { result = this.getChildExpr(1) }
/** Gets the variable or property this assignment writes to, if any. */
Expr getTarget() { result = getLhs().stripParens() }
Expr getTarget() { result = this.getLhs().stripParens() }
override ControlFlowNode getFirstControlFlowNode() { result = getLhs().getFirstControlFlowNode() }
override ControlFlowNode getFirstControlFlowNode() {
result = this.getLhs().getFirstControlFlowNode()
}
}
/**
@@ -1902,7 +1906,7 @@ class Assignment extends @assignment, Expr {
* ```
*/
class AssignExpr extends @assign_expr, Assignment {
override Expr getUnderlyingValue() { result = getRhs().getUnderlyingValue() }
override Expr getUnderlyingValue() { result = this.getRhs().getUnderlyingValue() }
override string getAPrimaryQlClass() { result = "AssignExpr" }
}
@@ -2118,7 +2122,7 @@ class AssignNullishCoalescingExpr extends @assignnullishcoalescingexpr, Compound
*/
class UpdateExpr extends @updateexpr, Expr {
/** Gets the operand of this update. */
Expr getOperand() { result = getChildExpr(0) }
Expr getOperand() { result = this.getChildExpr(0) }
/** Holds if this is a prefix increment or prefix decrement expression. */
predicate isPrefix() { none() }
@@ -2127,7 +2131,7 @@ class UpdateExpr extends @updateexpr, Expr {
string getOperator() { none() }
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
result = this.getOperand().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "UpdateExpr" }
@@ -2200,7 +2204,7 @@ class PostDecExpr extends @postdec_expr, UpdateExpr {
*/
class YieldExpr extends @yield_expr, Expr {
/** Gets the operand of this `yield` expression. */
Expr getOperand() { result = getChildExpr(0) }
Expr getOperand() { result = this.getChildExpr(0) }
/** Holds if this is a `yield*` expression. */
predicate isDelegating() { is_delegating(this) }
@@ -2208,9 +2212,9 @@ class YieldExpr extends @yield_expr, Expr {
override predicate isImpure() { any() }
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
result = this.getOperand().getFirstControlFlowNode()
or
not exists(getOperand()) and result = this
not exists(this.getOperand()) and result = this
}
override string getAPrimaryQlClass() { result = "YieldExpr" }
@@ -2231,45 +2235,47 @@ class ComprehensionExpr extends @comprehension_expr, Expr {
/** Gets the `n`th comprehension block in this comprehension. */
ComprehensionBlock getBlock(int n) {
exists(int idx |
result = getChildExpr(idx) and
result = this.getChildExpr(idx) and
idx > 0 and
n = idx - 1
)
}
/** Gets a comprehension block in this comprehension. */
ComprehensionBlock getABlock() { result = getBlock(_) }
ComprehensionBlock getABlock() { result = this.getBlock(_) }
/** Gets the number of comprehension blocks in this comprehension. */
int getNumBlock() { result = count(getABlock()) }
int getNumBlock() { result = count(this.getABlock()) }
/** Gets the `n`th filter expression in this comprehension. */
Expr getFilter(int n) {
exists(int idx |
result = getChildExpr(idx) and
result = this.getChildExpr(idx) and
idx < 0 and
n = -idx - 1
)
}
/** Gets a filter expression in this comprehension. */
Expr getAFilter() { result = getFilter(_) }
Expr getAFilter() { result = this.getFilter(_) }
/** Gets the number of filter expressions in this comprehension. */
int getNumFilter() { result = count(getAFilter()) }
int getNumFilter() { result = count(this.getAFilter()) }
/** Gets the body expression of this comprehension. */
Expr getBody() { result = getChildExpr(0) }
Expr getBody() { result = this.getChildExpr(0) }
override predicate isImpure() {
getABlock().isImpure() or
getAFilter().isImpure() or
getBody().isImpure()
this.getABlock().isImpure() or
this.getAFilter().isImpure() or
this.getBody().isImpure()
}
/** Holds if this is a legacy postfix comprehension expression. */
predicate isPostfix() {
exists(Token tk | tk = getFirstToken().getNextToken() | not tk.getValue().regexpMatch("if|for"))
exists(Token tk | tk = this.getFirstToken().getNextToken() |
not tk.getValue().regexpMatch("if|for")
)
}
override string getAPrimaryQlClass() { result = "ComprehensionExpr" }
@@ -2316,14 +2322,14 @@ class GeneratorExpr extends @generator_expr, ComprehensionExpr { }
*/
class ComprehensionBlock extends @comprehension_block, Expr {
/** Gets the iterating variable or pattern of this comprehension block. */
BindingPattern getIterator() { result = getChildExpr(0) }
BindingPattern getIterator() { result = this.getChildExpr(0) }
/** Gets the domain over which this comprehension block iterates. */
Expr getDomain() { result = getChildExpr(1) }
Expr getDomain() { result = this.getChildExpr(1) }
override predicate isImpure() {
getIterator().isImpure() or
getDomain().isImpure()
this.getIterator().isImpure() or
this.getDomain().isImpure()
}
override string getAPrimaryQlClass() { result = "ComprehensionBlock" }
@@ -2482,17 +2488,17 @@ class RelationalComparison extends Comparison {
*/
Expr getLesserOperand() {
(this instanceof LTExpr or this instanceof LEExpr) and
result = getLeftOperand()
result = this.getLeftOperand()
or
(this instanceof GTExpr or this instanceof GEExpr) and
result = getRightOperand()
result = this.getRightOperand()
}
/**
* Gets the greater operand of this comparison, that is, the right operand for
* a `<` or `<=` comparison, and the left operand for `>=` or `>`.
*/
Expr getGreaterOperand() { result = getAnOperand() and result != getLesserOperand() }
Expr getGreaterOperand() { result = this.getAnOperand() and result != this.getLesserOperand() }
/**
* Holds if this is a comparison with `<=` or `>=`.
@@ -2542,13 +2548,13 @@ class DecExpr extends UpdateExpr {
*/
class LegacyLetExpr extends Expr, @legacy_letexpr {
/** Gets the `i`th declarator in this `let` expression. */
VariableDeclarator getDecl(int i) { result = getChildExpr(i) and i >= 0 }
VariableDeclarator getDecl(int i) { result = this.getChildExpr(i) and i >= 0 }
/** Gets a declarator in this declaration expression. */
VariableDeclarator getADecl() { result = getDecl(_) }
VariableDeclarator getADecl() { result = this.getDecl(_) }
/** Gets the expression this `let` expression scopes over. */
Expr getBody() { result = getChildExpr(-1) }
Expr getBody() { result = this.getChildExpr(-1) }
override string getAPrimaryQlClass() { result = "LegacyLetExpr" }
}
@@ -2625,11 +2631,11 @@ class ImmediatelyInvokedFunctionExpr extends Function {
*/
predicate argumentPassing(Parameter p, Expr arg) {
exists(int parmIdx, int argIdx |
p = getParameter(parmIdx) and
p = this.getParameter(parmIdx) and
not p.isRestParameter() and
argIdx = parmIdx + getArgumentOffset() and
arg = getArgument(argIdx) and
not isSpreadArgument([0 .. argIdx])
argIdx = parmIdx + this.getArgumentOffset() and
arg = this.getArgument(argIdx) and
not this.isSpreadArgument([0 .. argIdx])
)
}
}
@@ -2645,12 +2651,12 @@ class ImmediatelyInvokedFunctionExpr extends Function {
*/
class AwaitExpr extends @await_expr, Expr {
/** Gets the operand of this `await` expression. */
Expr getOperand() { result = getChildExpr(0) }
Expr getOperand() { result = this.getChildExpr(0) }
override predicate isImpure() { any() }
override ControlFlowNode getFirstControlFlowNode() {
result = getOperand().getFirstControlFlowNode()
result = this.getOperand().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "AwaitExpr" }
@@ -2703,10 +2709,10 @@ class Decorator extends @decorator, Expr {
* For example, the decorator `@A` has expression `A`,
* and `@testable(true)` has expression `testable(true)`.
*/
Expr getExpression() { result = getChildExpr(0) }
Expr getExpression() { result = this.getChildExpr(0) }
override ControlFlowNode getFirstControlFlowNode() {
result = getExpression().getFirstControlFlowNode()
result = this.getExpression().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "Decorator" }
@@ -2766,15 +2772,15 @@ class FunctionBindExpr extends @bind_expr, Expr {
* Gets the object of this function bind expression; undefined for
* expressions of the form `::b.f`.
*/
Expr getObject() { result = getChildExpr(0) }
Expr getObject() { result = this.getChildExpr(0) }
/** Gets the callee of this function bind expression. */
Expr getCallee() { result = getChildExpr(1) }
Expr getCallee() { result = this.getChildExpr(1) }
override ControlFlowNode getFirstControlFlowNode() {
result = getObject().getFirstControlFlowNode()
result = this.getObject().getFirstControlFlowNode()
or
not exists(getObject()) and result = getCallee().getFirstControlFlowNode()
not exists(this.getObject()) and result = this.getCallee().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "FunctionBindExpr" }
@@ -2791,15 +2797,15 @@ class FunctionBindExpr extends @bind_expr, Expr {
*/
class DynamicImportExpr extends @dynamic_import, Expr, Import {
/** Gets the expression specifying the path of the imported module. */
Expr getSource() { result = getChildExpr(0) }
Expr getSource() { result = this.getChildExpr(0) }
override ControlFlowNode getFirstControlFlowNode() {
result = getSource().getFirstControlFlowNode()
result = this.getSource().getFirstControlFlowNode()
}
override PathExpr getImportedPath() { result = getSource() }
override PathExpr getImportedPath() { result = this.getSource() }
override Module getEnclosingModule() { result = getTopLevel() }
override Module getEnclosingModule() { result = this.getTopLevel() }
override DataFlow::Node getImportedModuleNode() { result = DataFlow::valueNode(this) }
@@ -2812,7 +2818,7 @@ private class LiteralDynamicImportPath extends PathExpr, ConstantString {
exists(DynamicImportExpr di | this.getParentExpr*() = di.getSource())
}
override string getValue() { result = getStringValue() }
override string getValue() { result = this.getStringValue() }
}
/**
@@ -2850,7 +2856,7 @@ class OptionalChainRoot extends ChainElem {
OptionalUse optionalUse;
OptionalChainRoot() {
getChainBase*() = optionalUse and
this.getChainBase*() = optionalUse and
not exists(ChainElem other | this = other.getChainBase())
}

View File

@@ -80,14 +80,14 @@ private predicate hasTypedefAnnotation(Stmt s) {
/** A typedef declaration in an externs file. */
class ExternalTypedef extends ExternalDecl, VariableDeclarator {
ExternalTypedef() {
getBindingPattern() instanceof Identifier and
inExternsFile() and
hasTypedefAnnotation(getDeclStmt())
this.getBindingPattern() instanceof Identifier and
this.inExternsFile() and
hasTypedefAnnotation(this.getDeclStmt())
}
override string getName() { result = getBindingPattern().(Identifier).getName() }
override string getName() { result = this.getBindingPattern().(Identifier).getName() }
override string getQualifiedName() { result = getName() }
override string getQualifiedName() { result = this.getName() }
}
/**
@@ -135,7 +135,7 @@ abstract class ExternalVarDecl extends ExternalDecl {
/**
* Gets the `@type` tag associated with this declaration, if any.
*/
ExternalTypeTag getTypeTag() { result = getATag() }
ExternalTypeTag getTypeTag() { result = this.getATag() }
}
/**
@@ -157,7 +157,7 @@ abstract class ExternalVarDecl extends ExternalDecl {
* </pre>
*/
abstract class ExternalGlobalDecl extends ExternalVarDecl {
override string getQualifiedName() { result = getName() }
override string getQualifiedName() { result = this.getName() }
}
/**
@@ -174,7 +174,7 @@ abstract class ExternalGlobalDecl extends ExternalVarDecl {
* </pre>
*/
class ExternalGlobalFunctionDecl extends ExternalGlobalDecl, FunctionDeclStmt {
ExternalGlobalFunctionDecl() { inExternsFile() }
ExternalGlobalFunctionDecl() { this.inExternsFile() }
/** Gets the name of this declaration. */
override string getName() { result = FunctionDeclStmt.super.getName() }
@@ -196,13 +196,13 @@ class ExternalGlobalFunctionDecl extends ExternalGlobalDecl, FunctionDeclStmt {
*/
class ExternalGlobalVarDecl extends ExternalGlobalDecl, VariableDeclarator {
ExternalGlobalVarDecl() {
getBindingPattern() instanceof Identifier and
inExternsFile() and
this.getBindingPattern() instanceof Identifier and
this.inExternsFile() and
// exclude type aliases
not hasTypedefAnnotation(getDeclStmt())
not hasTypedefAnnotation(this.getDeclStmt())
}
override string getName() { result = getBindingPattern().(Identifier).getName() }
override string getName() { result = this.getBindingPattern().(Identifier).getName() }
/** Gets the initializer associated with this declaration, if any. */
override Expr getInit() { result = VariableDeclarator.super.getInit() }
@@ -226,10 +226,10 @@ class ExternalGlobalVarDecl extends ExternalGlobalDecl, VariableDeclarator {
*/
class ExternalMemberDecl extends ExternalVarDecl, ExprStmt {
ExternalMemberDecl() {
getParent() instanceof Externs and
this.getParent() instanceof Externs and
(
getExpr() instanceof PropAccess or
getExpr().(AssignExpr).getLhs() instanceof PropAccess
this.getExpr() instanceof PropAccess or
this.getExpr().(AssignExpr).getLhs() instanceof PropAccess
)
}
@@ -237,20 +237,22 @@ class ExternalMemberDecl extends ExternalVarDecl, ExprStmt {
* Gets the property access describing the declared member.
*/
PropAccess getProperty() {
result = getExpr() or
result = getExpr().(AssignExpr).getLhs()
result = this.getExpr() or
result = this.getExpr().(AssignExpr).getLhs()
}
override Expr getInit() { result = getExpr().(AssignExpr).getRhs() }
override Expr getInit() { result = this.getExpr().(AssignExpr).getRhs() }
override string getQualifiedName() { result = getBaseName() + "." + getName() }
override string getQualifiedName() { result = this.getBaseName() + "." + this.getName() }
/**
* Holds if this member belongs to type `base` and has name `name`.
*/
predicate hasQualifiedName(string base, string name) { base = getBaseName() and name = getName() }
predicate hasQualifiedName(string base, string name) {
base = this.getBaseName() and name = this.getName()
}
override string getName() { result = getProperty().getPropertyName() }
override string getName() { result = this.getProperty().getPropertyName() }
/**
* Gets the name of the base type to which the member declared by this declaration belongs.
@@ -260,7 +262,7 @@ class ExternalMemberDecl extends ExternalVarDecl, ExprStmt {
/**
* Gets the base type to which the member declared by this declaration belongs.
*/
ExternalType getDeclaringType() { result.getQualifiedName() = getBaseName() }
ExternalType getDeclaringType() { result.getQualifiedName() = this.getBaseName() }
}
/**
@@ -282,9 +284,9 @@ class ExternalMemberDecl extends ExternalVarDecl, ExprStmt {
* </pre>
*/
class ExternalStaticMemberDecl extends ExternalMemberDecl {
ExternalStaticMemberDecl() { getProperty().getBase() instanceof Identifier }
ExternalStaticMemberDecl() { this.getProperty().getBase() instanceof Identifier }
override string getBaseName() { result = getProperty().getBase().(Identifier).getName() }
override string getBaseName() { result = this.getProperty().getBase().(Identifier).getName() }
}
/**
@@ -307,14 +309,16 @@ class ExternalStaticMemberDecl extends ExternalMemberDecl {
*/
class ExternalInstanceMemberDecl extends ExternalMemberDecl {
ExternalInstanceMemberDecl() {
exists(PropAccess outer, PropAccess inner | outer = getProperty() and inner = outer.getBase() |
exists(PropAccess outer, PropAccess inner |
outer = this.getProperty() and inner = outer.getBase()
|
inner.getBase() instanceof Identifier and
inner.getPropertyName() = "prototype"
)
}
override string getBaseName() {
result = getProperty().getBase().(PropAccess).getBase().(Identifier).getName()
result = this.getProperty().getBase().(PropAccess).getBase().(Identifier).getName()
}
}
@@ -360,7 +364,7 @@ class ExternalFunction extends ExternalEntity, Function {
predicate isVarArgs() {
exists(SimpleParameter lastParm, JSDocParamTag pt |
lastParm = this.getParameter(this.getNumParameter() - 1) and
pt = getDecl().getATag() and
pt = this.getDecl().getATag() and
pt.getName() = lastParm.getName() and
pt.getType() instanceof JSDocRestParameterTypeExpr
)
@@ -380,7 +384,7 @@ class ExternalFunction extends ExternalEntity, Function {
* </pre>
*/
class ConstructorTag extends JSDocTag {
ConstructorTag() { getTitle() = "constructor" }
ConstructorTag() { this.getTitle() = "constructor" }
}
/**
@@ -396,8 +400,8 @@ class ConstructorTag extends JSDocTag {
abstract private class NamedTypeReferent extends JSDocTag {
/** Gets the name of the type to which this tag refers. */
string getTarget() {
result = getType().(JSDocNamedTypeExpr).getName() or
result = getType().(JSDocAppliedTypeExpr).getHead().(JSDocNamedTypeExpr).getName()
result = this.getType().(JSDocNamedTypeExpr).getName() or
result = this.getType().(JSDocAppliedTypeExpr).getHead().(JSDocNamedTypeExpr).getName()
}
/**
@@ -412,7 +416,7 @@ abstract private class NamedTypeReferent extends JSDocTag {
* type `Array`, which is also the source declaration of `!Array=`. Primitive types,
* union types, and other complex kinds of types do not have a source declaration.
*/
ExternalType getTypeDeclaration() { result = sourceDecl(getType()) }
ExternalType getTypeDeclaration() { result = sourceDecl(this.getType()) }
}
/**
@@ -437,7 +441,7 @@ private ExternalType sourceDecl(JSDocTypeExpr tp) {
* </pre>
*/
class ImplementsTag extends NamedTypeReferent {
ImplementsTag() { getTitle() = "implements" }
ImplementsTag() { this.getTitle() = "implements" }
}
/**
@@ -451,7 +455,7 @@ class ImplementsTag extends NamedTypeReferent {
* </pre>
*/
class ExtendsTag extends NamedTypeReferent {
ExtendsTag() { getTitle() = "extends" }
ExtendsTag() { this.getTitle() = "extends" }
}
/**
@@ -465,7 +469,7 @@ class ExtendsTag extends NamedTypeReferent {
* </pre>
*/
class ExternalTypeTag extends NamedTypeReferent {
ExternalTypeTag() { getTitle() = "type" }
ExternalTypeTag() { this.getTitle() = "type" }
}
/**
@@ -489,16 +493,18 @@ class ExternalTypeTag extends NamedTypeReferent {
abstract class ExternalType extends ExternalGlobalFunctionDecl {
/** Gets a type which this type extends. */
ExternalType getAnExtendedType() {
getDocumentation().getATag().(ExtendsTag).getTarget() = result.getQualifiedName()
this.getDocumentation().getATag().(ExtendsTag).getTarget() = result.getQualifiedName()
}
/** Gets a type which this type implements. */
ExternalType getAnImplementedType() {
getDocumentation().getATag().(ImplementsTag).getTarget() = result.getQualifiedName()
this.getDocumentation().getATag().(ImplementsTag).getTarget() = result.getQualifiedName()
}
/** Gets a supertype of this type. */
ExternalType getASupertype() { result = getAnExtendedType() or result = getAnImplementedType() }
ExternalType getASupertype() {
result = this.getAnExtendedType() or result = this.getAnImplementedType()
}
/** Gets a declaration of a member of this type. */
ExternalMemberDecl getAMember() { result.getDeclaringType() = this }
@@ -518,7 +524,7 @@ abstract class ExternalType extends ExternalGlobalFunctionDecl {
* </pre>
*/
class ExternalConstructor extends ExternalType {
ExternalConstructor() { getDocumentation().getATag() instanceof ConstructorTag }
ExternalConstructor() { this.getDocumentation().getATag() instanceof ConstructorTag }
}
/**
@@ -534,7 +540,7 @@ class ExternalConstructor extends ExternalType {
* </pre>
*/
class ExternalInterface extends ExternalType {
ExternalInterface() { getDocumentation().getATag().getTitle() = "interface" }
ExternalInterface() { this.getDocumentation().getATag().getTitle() = "interface" }
}
/**
@@ -551,7 +557,7 @@ class ExternalInterface extends ExternalType {
* </pre>
*/
class FunctionExternal extends ExternalConstructor {
FunctionExternal() { getName() = "Function" }
FunctionExternal() { this.getName() = "Function" }
}
/**
@@ -568,7 +574,7 @@ class FunctionExternal extends ExternalConstructor {
* </pre>
*/
class ObjectExternal extends ExternalConstructor {
ObjectExternal() { getName() = "Object" }
ObjectExternal() { this.getName() = "Object" }
}
/**
@@ -586,5 +592,5 @@ class ObjectExternal extends ExternalConstructor {
* </pre>
*/
class ArrayExternal extends ExternalConstructor {
ArrayExternal() { getName() = "Array" }
ArrayExternal() { this.getName() = "Array" }
}

View File

@@ -48,7 +48,7 @@ abstract class Container extends @container {
*/
string getRelativePath() {
exists(string absPath, string pref |
absPath = getAbsolutePath() and sourceLocationPrefix(pref)
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
absPath = pref and result = ""
or
@@ -74,7 +74,9 @@ abstract class Container extends @container {
* <tr><td>"//FileServer/"</td><td>""</td></tr>
* </table>
*/
string getBaseName() { result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 1) }
string getBaseName() {
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 1)
}
/**
* Gets the extension of this container, that is, the suffix of its base name
@@ -100,7 +102,7 @@ abstract class Container extends @container {
* </table>
*/
string getExtension() {
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 4)
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 4)
}
/**
@@ -120,7 +122,9 @@ abstract class Container extends @container {
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
* </table>
*/
string getStem() { result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 2) }
string getStem() {
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(\\.([^.]*))?)", 2)
}
/** Gets the parent container of this file or folder, if any. */
Container getParentContainer() { containerparent(result, this) }
@@ -129,20 +133,20 @@ abstract class Container extends @container {
Container getAChildContainer() { this = result.getParentContainer() }
/** Gets a file in this container. */
File getAFile() { result = getAChildContainer() }
File getAFile() { result = this.getAChildContainer() }
/** Gets the file in this container that has the given `baseName`, if any. */
File getFile(string baseName) {
result = getAFile() and
result = this.getAFile() and
result.getBaseName() = baseName
}
/** Gets a sub-folder in this container. */
Folder getAFolder() { result = getAChildContainer() }
Folder getAFolder() { result = this.getAChildContainer() }
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
Folder getFolder(string baseName) {
result = getAFolder() and
result = this.getAFolder() and
result.getBaseName() = baseName
}
@@ -151,7 +155,7 @@ abstract class Container extends @container {
*
* This is the absolute path of the container.
*/
string toString() { result = getAbsolutePath() }
string toString() { result = this.getAbsolutePath() }
}
/** A folder. */
@@ -160,13 +164,13 @@ class Folder extends Container, @folder {
/** Gets the file or subfolder in this folder that has the given `name`, if any. */
Container getChildContainer(string name) {
result = getAChildContainer() and
result = this.getAChildContainer() and
result.getBaseName() = name
}
/** Gets the file in this folder that has the given `stem` and `extension`, if any. */
File getFile(string stem, string extension) {
result = getAChildContainer() and
result = this.getAChildContainer() and
result.getStem() = stem and
result.getExtension() = extension
}
@@ -184,14 +188,14 @@ class Folder extends Container, @folder {
*/
File getJavaScriptFile(string stem) {
result =
min(int p, string ext | p = getFileExtensionPriority(ext) | getFile(stem, ext) order by p)
min(int p, string ext | p = getFileExtensionPriority(ext) | this.getFile(stem, ext) order by p)
}
/** Gets a subfolder contained in this folder. */
Folder getASubFolder() { result = getAChildContainer() }
Folder getASubFolder() { result = this.getAChildContainer() }
/** Gets the URL of this folder. */
override string getURL() { result = "folder://" + getAbsolutePath() }
override string getURL() { result = "folder://" + this.getAbsolutePath() }
}
/** A file. */

View File

@@ -39,14 +39,14 @@ import javascript
class Function extends @function, Parameterized, TypeParameterized, StmtContainer, Documentable,
AST::ValueNode {
/** Gets the `i`th parameter of this function. */
Parameter getParameter(int i) { result = getChildExpr(i) }
Parameter getParameter(int i) { result = this.getChildExpr(i) }
/** Gets a parameter of this function. */
override Parameter getAParameter() { exists(int idx | result = getParameter(idx)) }
override Parameter getAParameter() { exists(int idx | result = this.getParameter(idx)) }
/** Gets the parameter named `name` of this function, if any. */
SimpleParameter getParameterByName(string name) {
result = getAParameter() and
result = this.getAParameter() and
result.getName() = name
}
@@ -72,9 +72,9 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* `this` parameter types are specific to TypeScript.
*/
TypeAnnotation getThisTypeAnnotation() {
result = getChildTypeExpr(-4)
result = this.getChildTypeExpr(-4)
or
result = getDocumentation().getATagByTitle("this").getType()
result = this.getDocumentation().getATagByTitle("this").getType()
}
/**
@@ -82,10 +82,10 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*
* Gets the identifier specifying the name of this function, if any.
*/
deprecated VarDecl getId() { result = getIdentifier() }
deprecated VarDecl getId() { result = this.getIdentifier() }
/** Gets the identifier specifying the name of this function, if any. */
VarDecl getIdentifier() { result = getChildExpr(-1) }
VarDecl getIdentifier() { result = this.getChildExpr(-1) }
/**
* Gets the name of this function if it has one, or a name inferred from its context.
@@ -96,9 +96,9 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* can be inferred, there is no result.
*/
string getName() {
result = getIdentifier().getName()
result = this.getIdentifier().getName()
or
not exists(getIdentifier()) and
not exists(this.getIdentifier()) and
(
exists(VarDef vd | this = vd.getSource() | result = vd.getTarget().(VarRef).getName())
or
@@ -118,17 +118,17 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
}
/** Gets the variable holding this function. */
Variable getVariable() { result = getIdentifier().getVariable() }
Variable getVariable() { result = this.getIdentifier().getVariable() }
/** Gets the `arguments` variable of this function, if any. */
ArgumentsVariable getArgumentsVariable() { result.getFunction() = this }
/** Holds if the body of this function refers to the function's `arguments` variable. */
predicate usesArgumentsObject() {
exists(getArgumentsVariable().getAnAccess())
exists(this.getArgumentsVariable().getAnAccess())
or
exists(PropAccess read |
read.getBase() = getVariable().getAnAccess() and
read.getBase() = this.getVariable().getAnAccess() and
read.getPropertyName() = "arguments"
)
}
@@ -136,29 +136,31 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
/**
* Holds if this function declares a parameter or local variable named `arguments`.
*/
predicate declaresArguments() { exists(getScope().getVariable("arguments").getADeclaration()) }
predicate declaresArguments() {
exists(this.getScope().getVariable("arguments").getADeclaration())
}
/** Gets the statement enclosing this function, if any. */
Stmt getEnclosingStmt() { none() }
/** Gets the body of this function. */
override ExprOrStmt getBody() { result = getChild(-2) }
override ExprOrStmt getBody() { result = this.getChild(-2) }
/** Gets the `i`th statement in the body of this function. */
Stmt getBodyStmt(int i) { result = getBody().(BlockStmt).getStmt(i) }
Stmt getBodyStmt(int i) { result = this.getBody().(BlockStmt).getStmt(i) }
/** Gets a statement in the body of this function. */
Stmt getABodyStmt() { result = getBodyStmt(_) }
Stmt getABodyStmt() { result = this.getBodyStmt(_) }
/** Gets the number of statements in the body of this function. */
int getNumBodyStmt() { result = count(getABodyStmt()) }
int getNumBodyStmt() { result = count(this.getABodyStmt()) }
/** Gets the return type annotation on this function, if any. */
TypeAnnotation getReturnTypeAnnotation() {
typeexprs(result, _, this, -3, _)
or
exists(string title | title = "return" or title = "returns" |
result = getDocumentation().getATagByTitle(title).getType()
result = this.getDocumentation().getATagByTitle(title).getType()
)
}
@@ -179,7 +181,7 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*/
private Token lastTokenOfParameterList() {
// if there are any parameters, it's the last token of the last parameter
exists(Parameter lastParam | lastParam = getParameter(getNumParameter() - 1) |
exists(Parameter lastParam | lastParam = this.getParameter(this.getNumParameter() - 1) |
result = lastParam.getDefault().getLastToken()
or
not exists(lastParam.getDefault()) and result = lastParam.getLastToken()
@@ -187,32 +189,34 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
or
// otherwise we have an empty parameter list `()`, and
// we want to return the opening parenthesis
not exists(getAParameter()) and
not exists(this.getAParameter()) and
(
// if the function has a name, the opening parenthesis comes right after it
result = getIdentifier().getLastToken().getNextToken()
result = this.getIdentifier().getLastToken().getNextToken()
or
// otherwise this must be an arrow function with no parameters, so the opening
// parenthesis is the very first token of the function
not exists(getIdentifier()) and result = getFirstToken()
not exists(this.getIdentifier()) and result = this.getFirstToken()
)
}
/** Holds if the parameter list of this function has a trailing comma. */
predicate hasTrailingComma() { lastTokenOfParameterList().getNextToken().getValue() = "," }
predicate hasTrailingComma() { this.lastTokenOfParameterList().getNextToken().getValue() = "," }
/** Holds if this function is an asynchronous function. */
predicate isAsync() { is_async(this) }
/** Holds if this function is asynchronous or a generator. */
predicate isAsyncOrGenerator() { isAsync() or isGenerator() }
predicate isAsyncOrGenerator() { this.isAsync() or this.isGenerator() }
/** Gets the enclosing function or toplevel of this function. */
override StmtContainer getEnclosingContainer() { result = getEnclosingStmt().getContainer() }
override StmtContainer getEnclosingContainer() { result = this.getEnclosingStmt().getContainer() }
/** Gets the number of lines in this function. */
int getNumberOfLines() {
exists(int sl, int el | getLocation().hasLocationInfo(_, sl, _, el, _) | result = el - sl + 1)
exists(int sl, int el | this.getLocation().hasLocationInfo(_, sl, _, el, _) |
result = el - sl + 1
)
}
/** Gets the number of lines containing code in this function. */
@@ -247,8 +251,8 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
/** Gets an expression that could be returned by this function, if any. */
Expr getAReturnedExpr() {
result = getBody() or
result = getAReturnStmt().getExpr()
result = this.getBody() or
result = this.getAReturnStmt().getExpr()
}
/**
@@ -262,10 +266,10 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* which is the nearest enclosing non-arrow function or top-level.
*/
StmtContainer getThisBindingContainer() {
result = getThisBinder()
result = this.getThisBinder()
or
not exists(getThisBinder()) and
result = getTopLevel()
not exists(this.getThisBinder()) and
result = this.getTopLevel()
}
/**
@@ -276,12 +280,12 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* parameter, no parameter default values, and no destructuring parameters.
*/
predicate hasMappedArgumentsVariable() {
exists(getArgumentsVariable()) and
not isStrict() and
forall(Parameter p | p = getAParameter() |
exists(this.getArgumentsVariable()) and
not this.isStrict() and
forall(Parameter p | p = this.getAParameter() |
p instanceof SimpleParameter and not exists(p.getDefault())
) and
not hasRestParameter()
not this.hasRestParameter()
}
/**
@@ -293,23 +297,23 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
* can be inferred, the result is "anonymous function".
*/
override string describe() {
if exists(inferNameFromVarDef())
then result = inferNameFromVarDef()
if exists(this.inferNameFromVarDef())
then result = this.inferNameFromVarDef()
else
if exists(inferNameFromProp())
then result = inferNameFromProp()
if exists(this.inferNameFromProp())
then result = this.inferNameFromProp()
else
if exists(inferNameFromMemberDef())
then result = inferNameFromMemberDef()
if exists(this.inferNameFromMemberDef())
then result = this.inferNameFromMemberDef()
else
if exists(inferNameFromCallSig())
then result = inferNameFromCallSig()
if exists(this.inferNameFromCallSig())
then result = this.inferNameFromCallSig()
else
if exists(inferNameFromIndexSig())
then result = inferNameFromIndexSig()
if exists(this.inferNameFromIndexSig())
then result = this.inferNameFromIndexSig()
else
if exists(inferNameFromFunctionType())
then result = inferNameFromFunctionType()
if exists(this.inferNameFromFunctionType())
then result = this.inferNameFromFunctionType()
else result = "anonymous function"
}
@@ -319,8 +323,8 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*/
private string inferNameFromVarDef() {
// in ambiguous cases like `var f = function g() {}`, prefer `g` to `f`
if exists(getIdentifier())
then result = "function " + getIdentifier().getName()
if exists(this.getIdentifier())
then result = "function " + this.getIdentifier().getName()
else
exists(VarDef vd | this = vd.getSource() |
result = "function " + vd.getTarget().(VarRef).getName()
@@ -400,7 +404,7 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
*
* A JavaScript function always has a body.
*/
predicate hasBody() { exists(getBody()) }
predicate hasBody() { exists(this.getBody()) }
/**
* Holds if this function is part of an abstract class member.
@@ -419,10 +423,10 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
this instanceof ArrowFunctionExpr and
kind = "an arrow function"
or
isGenerator() and
this.isGenerator() and
kind = "a generator function"
or
isAsync() and
this.isAsync() and
kind = "an async function"
}

View File

@@ -80,7 +80,7 @@ module AccessPath {
SsaExplicitDefinition getSsaDefinition() { result.getSourceVariable() = this }
/** Gets the data flow node representing the value of this variable, if one exists. */
DataFlow::Node getValue() { result = getSsaDefinition().getRhsNode() }
DataFlow::Node getValue() { result = this.getSsaDefinition().getRhsNode() }
}
/**

View File

@@ -94,13 +94,13 @@ module InclusionTest {
*/
private class Includes_Native extends Range, DataFlow::MethodCallNode {
Includes_Native() {
getMethodName() = "includes" and
getNumArgument() = 1
this.getMethodName() = "includes" and
this.getNumArgument() = 1
}
override DataFlow::Node getContainerNode() { result = getReceiver() }
override DataFlow::Node getContainerNode() { result = this.getReceiver() }
override DataFlow::Node getContainedNode() { result = getArgument(0) }
override DataFlow::Node getContainedNode() { result = this.getArgument(0) }
}
/**
@@ -117,9 +117,9 @@ module InclusionTest {
)
}
override DataFlow::Node getContainerNode() { result = getArgument(0) }
override DataFlow::Node getContainerNode() { result = this.getArgument(0) }
override DataFlow::Node getContainedNode() { result = getArgument(1) }
override DataFlow::Node getContainedNode() { result = this.getArgument(1) }
}
/**

View File

@@ -38,7 +38,7 @@ private class PlainJsonParserCall extends JsonParserCall {
)
}
override DataFlow::Node getInput() { result = getArgument(0) }
override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::SourceNode getOutput() { result = this }
}
@@ -61,7 +61,7 @@ private class JsonParserCallWithWrapper extends JsonParserCall {
)
}
override DataFlow::Node getInput() { result = getArgument(0) }
override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::SourceNode getOutput() { result = this.getAPropertyRead(outputPropName) }
}
@@ -74,9 +74,9 @@ private class JsonParserCallWithCallback extends JsonParserCall {
this = DataFlow::moduleImport("safe-json-parse/callback").getACall()
}
override DataFlow::Node getInput() { result = getArgument(0) }
override DataFlow::Node getInput() { result = this.getArgument(0) }
override DataFlow::SourceNode getOutput() { result = getCallback(1).getParameter(1) }
override DataFlow::SourceNode getOutput() { result = this.getCallback(1).getParameter(1) }
}
/**

View File

@@ -25,7 +25,7 @@ module JsonSchema {
* Gets a value that indicates whether the validation was successful.
*/
DataFlow::Node getAValidationResultAccess(boolean polarity) {
result = this and polarity = getPolarity()
result = this and polarity = this.getPolarity()
}
}
@@ -35,7 +35,7 @@ module JsonSchema {
/** An object literal with a `$schema` property indicating it is the root of a JSON schema. */
private class SchemaNodeByTag extends SchemaRoot, DataFlow::ObjectLiteralNode {
SchemaNodeByTag() {
getAPropertyWrite("$schema").getRhs().getStringValue().matches("%//json-schema.org%")
this.getAPropertyWrite("$schema").getRhs().getStringValue().matches("%//json-schema.org%")
}
}
@@ -67,13 +67,13 @@ module JsonSchema {
Instance() { this = API::moduleImport("ajv").getAnInstantiation() }
/** Gets the data flow node holding the options passed to this `Ajv` instance. */
DataFlow::Node getOptionsArg() { result = getArgument(0) }
DataFlow::Node getOptionsArg() { result = this.getArgument(0) }
/** Gets an API node that refers to this object. */
API::Node ref() {
result = getReturn()
result = this.getReturn()
or
result = ref().getMember(chainedMethod()).getReturn()
result = this.ref().getMember(chainedMethod()).getReturn()
}
/**
@@ -83,16 +83,16 @@ module JsonSchema {
* signature is different.
*/
API::Node getAValidationFunction() {
result = ref().getMember(["compile", "getSchema"]).getReturn()
result = this.ref().getMember(["compile", "getSchema"]).getReturn()
or
result = ref().getMember("compileAsync").getPromised()
result = this.ref().getMember("compileAsync").getPromised()
}
/**
* Gets an API node that refers to an error produced by this Ajv instance.
*/
API::Node getAValidationError() {
exists(API::Node base | base = [ref(), getAValidationFunction()] |
exists(API::Node base | base = [this.ref(), this.getAValidationFunction()] |
result = base.getMember("errors")
or
result = base.getMember("errorsText").getReturn()
@@ -111,14 +111,14 @@ module JsonSchema {
this = instance.getAValidationFunction().getACall() and argIndex = 0
}
override DataFlow::Node getInput() { result = getArgument(argIndex) }
override DataFlow::Node getInput() { result = this.getArgument(argIndex) }
/** Gets the argument holding additional options to the call. */
DataFlow::Node getOwnOptionsArg() { result = getArgument(argIndex + 1) }
DataFlow::Node getOwnOptionsArg() { result = this.getArgument(argIndex + 1) }
/** Gets a data flow passed as the extra options to this validation call or to the underlying `Ajv` instance. */
DataFlow::Node getAnOptionsArg() {
result = getOwnOptionsArg()
result = this.getOwnOptionsArg()
or
result = instance.getOptionsArg()
}

View File

@@ -25,7 +25,7 @@ class Location extends @location {
int getEndColumn() { locations_default(this, _, _, _, _, result) }
/** Gets the number of lines covered by this location. */
int getNumLines() { result = getEndLine() - getStartLine() + 1 }
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
/** Holds if this location starts before location `that`. */
pragma[inline]
@@ -85,7 +85,7 @@ class Location extends @location {
/** A program element with a location. */
class Locatable extends @locatable {
/** Gets the file this program element comes from. */
File getFile() { result = getLocation().getFile() }
File getFile() { result = this.getLocation().getFile() }
/** Gets this element's location. */
Location getLocation() {
@@ -124,7 +124,7 @@ class Locatable extends @locatable {
}
/** Gets the number of lines covered by this element. */
int getNumLines() { result = getLocation().getNumLines() }
int getNumLines() { result = this.getLocation().getNumLines() }
/** Gets a textual representation of this element. */
string toString() {
@@ -135,7 +135,7 @@ class Locatable extends @locatable {
/**
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
*/
final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") }
final string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") }
/**
* Gets the primary QL class for the Locatable.

View File

@@ -13,19 +13,19 @@ private import semmle.javascript.internal.CachedStages
*/
abstract class Module extends TopLevel {
/** Gets the full path of the file containing this module. */
string getPath() { result = getFile().getAbsolutePath() }
string getPath() { result = this.getFile().getAbsolutePath() }
/** Gets the short name of this module without file extension. */
string getName() { result = getFile().getStem() }
string getName() { result = this.getFile().getStem() }
/** Gets an import appearing in this module. */
Import getAnImport() { result.getTopLevel() = this }
/** Gets a module from which this module imports. */
Module getAnImportedModule() { result = getAnImport().getImportedModule() }
Module getAnImportedModule() { result = this.getAnImport().getImportedModule() }
/** Gets a symbol exported by this module. */
string getAnExportedSymbol() { exists(getAnExportedValue(result)) }
string getAnExportedSymbol() { exists(this.getAnExportedValue(result)) }
/**
* DEPRECATED. Use `getAnExportedValue` instead.
@@ -86,7 +86,7 @@ abstract class Module extends TopLevel {
exists(PropAccess pacc | export = pacc |
pacc.getBase() = this.(NodeModule).getAModuleExportsNode().asExpr() and
name = pacc.getPropertyName() and
isExterns() and
this.isExterns() and
exists(pacc.getDocumentation())
)
)
@@ -125,7 +125,7 @@ abstract class Module extends TopLevel {
* as the interaction between different module types is not standardized.
*/
DataFlow::Node getDefaultOrBulkExport() {
result = [getAnExportedValue("default"), getABulkExportedNode()]
result = [this.getAnExportedValue("default"), this.getABulkExportedNode()]
}
/**
@@ -144,7 +144,7 @@ abstract class Module extends TopLevel {
exists(string v | v = path.getValue() |
// paths starting with a dot are resolved relative to the module's directory
if v.matches(".%")
then searchRoot = getFile().getParentContainer()
then searchRoot = this.getFile().getParentContainer()
else
// all other paths are resolved relative to the file system root
searchRoot.getBaseName() = ""
@@ -202,14 +202,14 @@ abstract class Import extends ASTNode {
* path is assumed to be a possible target of the import.
*/
Module resolveExternsImport() {
result.isExterns() and result.getName() = getImportedPath().getValue()
result.isExterns() and result.getName() = this.getImportedPath().getValue()
}
/**
* Gets the module the path of this import resolves to.
*/
Module resolveImportedPath() {
result.getFile() = getEnclosingModule().resolve(getImportedPath())
result.getFile() = this.getEnclosingModule().resolve(this.getImportedPath())
}
/**
@@ -220,7 +220,7 @@ abstract class Import extends ASTNode {
exists(JSDocTag tag |
tag.getTitle() = "providesModule" and
tag.getParent().getComment().getTopLevel() = result and
tag.getDescription().trim() = getImportedPath().getValue()
tag.getDescription().trim() = this.getImportedPath().getValue()
)
}
@@ -231,9 +231,9 @@ abstract class Import extends ASTNode {
result.getFile() =
min(TypeRootFolder typeRoot |
|
typeRoot.getModuleFile(getImportedPath().getValue())
typeRoot.getModuleFile(this.getImportedPath().getValue())
order by
typeRoot.getSearchPriority(getFile().getParentContainer())
typeRoot.getSearchPriority(this.getFile().getParentContainer())
)
}
@@ -258,13 +258,13 @@ abstract class Import extends ASTNode {
cached
Module getImportedModule() {
Stages::Imports::ref() and
if exists(resolveExternsImport())
then result = resolveExternsImport()
if exists(this.resolveExternsImport())
then result = this.resolveExternsImport()
else (
result = resolveAsProvidedModule() or
result = resolveImportedPath() or
result = resolveFromTypeRoot() or
result = resolveFromTypeScriptSymbol() or
result = this.resolveAsProvidedModule() or
result = this.resolveImportedPath() or
result = this.resolveFromTypeRoot() or
result = this.resolveFromTypeScriptSymbol() or
result = resolveNeighbourPackage(this.getImportedPath().getValue())
)
}

View File

@@ -8,91 +8,95 @@ private import NodeModuleResolutionImpl
/** A `package.json` configuration object. */
class PackageJSON extends JSONObject {
PackageJSON() {
getJsonFile().getBaseName() = "package.json" and
isTopLevel()
this.getJsonFile().getBaseName() = "package.json" and
this.isTopLevel()
}
/** Gets the name of this package. */
string getPackageName() { result = getPropStringValue("name") }
string getPackageName() { result = this.getPropStringValue("name") }
/** Gets the version of this package. */
string getVersion() { result = getPropStringValue("version") }
string getVersion() { result = this.getPropStringValue("version") }
/** Gets the description of this package. */
string getDescription() { result = getPropStringValue("description") }
string getDescription() { result = this.getPropStringValue("description") }
/** Gets the array of keywords for this package. */
JSONArray getKeywords() { result = getPropValue("keywords") }
JSONArray getKeywords() { result = this.getPropValue("keywords") }
/** Gets a keyword for this package. */
string getAKeyword() { result = getKeywords().getElementStringValue(_) }
string getAKeyword() { result = this.getKeywords().getElementStringValue(_) }
/** Gets the homepage URL of this package. */
string getHomepage() { result = getPropStringValue("homepage") }
string getHomepage() { result = this.getPropStringValue("homepage") }
/** Gets the bug tracker information of this package. */
BugTrackerInfo getBugs() { result = getPropValue("bugs") }
BugTrackerInfo getBugs() { result = this.getPropValue("bugs") }
/** Gets the license information of this package. */
string getLicense() { result = getPropStringValue("license") }
string getLicense() { result = this.getPropStringValue("license") }
/** Gets the author information of this package. */
ContributorInfo getAuthor() { result = getPropValue("author") }
ContributorInfo getAuthor() { result = this.getPropValue("author") }
/** Gets information for a contributor to this package. */
ContributorInfo getAContributor() { result = getPropValue("contributors").getElementValue(_) }
ContributorInfo getAContributor() {
result = this.getPropValue("contributors").getElementValue(_)
}
/** Gets the array of files for this package. */
JSONArray getFiles() { result = getPropValue("files") }
JSONArray getFiles() { result = this.getPropValue("files") }
/** Gets a file for this package. */
string getAFile() { result = getFiles().getElementStringValue(_) }
string getAFile() { result = this.getFiles().getElementStringValue(_) }
/** Gets the main module of this package. */
string getMain() { result = MainModulePath::of(this).getValue() }
/** Gets the path of a command defined for this package. */
string getBin(string cmd) {
cmd = getPackageName() and result = getPropStringValue("bin")
cmd = this.getPackageName() and result = this.getPropStringValue("bin")
or
result = getPropValue("bin").getPropValue(cmd).getStringValue()
result = this.getPropValue("bin").getPropValue(cmd).getStringValue()
}
/** Gets a manual page for this package. */
string getAManFile() {
result = getPropStringValue("man") or
result = getPropValue("man").getElementValue(_).getStringValue()
result = this.getPropStringValue("man") or
result = this.getPropValue("man").getElementValue(_).getStringValue()
}
/** Gets information about the directories of this package. */
JSONObject getDirectories() { result = getPropValue("directories") }
JSONObject getDirectories() { result = this.getPropValue("directories") }
/** Gets repository information for this package. */
RepositoryInfo getRepository() { result = getPropValue("repository") }
RepositoryInfo getRepository() { result = this.getPropValue("repository") }
/** Gets information about the scripts of this package. */
JSONObject getScripts() { result = getPropValue("scripts") }
JSONObject getScripts() { result = this.getPropValue("scripts") }
/** Gets configuration information for this package. */
JSONObject getConfig() { result = getPropValue("config") }
JSONObject getConfig() { result = this.getPropValue("config") }
/** Gets the dependencies of this package. */
PackageDependencies getDependencies() { result = getPropValue("dependencies") }
PackageDependencies getDependencies() { result = this.getPropValue("dependencies") }
/** Gets the development dependencies of this package. */
PackageDependencies getDevDependencies() { result = getPropValue("devDependencies") }
PackageDependencies getDevDependencies() { result = this.getPropValue("devDependencies") }
/** Gets the peer dependencies of this package. */
PackageDependencies getPeerDependencies() { result = getPropValue("peerDependencies") }
PackageDependencies getPeerDependencies() { result = this.getPropValue("peerDependencies") }
/** Gets the bundled dependencies of this package. */
PackageDependencies getBundledDependencies() {
result = getPropValue("bundledDependencies") or
result = getPropValue("bundleDependencies")
result = this.getPropValue("bundledDependencies") or
result = this.getPropValue("bundleDependencies")
}
/** Gets the optional dependencies of this package. */
PackageDependencies getOptionalDependencies() { result = getPropValue("optionalDependencies") }
PackageDependencies getOptionalDependencies() {
result = this.getPropValue("optionalDependencies")
}
/**
* Gets a JSON object describing a group of dependencies of
@@ -102,13 +106,13 @@ class PackageJSON extends JSONObject {
* `optionalDependencies`.
*/
PackageDependencies getADependenciesObject(string depkind) {
result = getDependencies() and depkind = ""
result = this.getDependencies() and depkind = ""
or
result = getDevDependencies() and depkind = "dev"
result = this.getDevDependencies() and depkind = "dev"
or
result = getBundledDependencies() and depkind = "bundled"
result = this.getBundledDependencies() and depkind = "bundled"
or
result = getOptionalDependencies() and depkind = "opt"
result = this.getOptionalDependencies() and depkind = "opt"
}
/**
@@ -120,55 +124,55 @@ class PackageJSON extends JSONObject {
* different from the other dependency types.
*/
predicate declaresDependency(string pkg, string version) {
getADependenciesObject(_).getADependency(pkg, version)
this.getADependenciesObject(_).getADependency(pkg, version)
}
/** Gets the engine dependencies of this package. */
PackageDependencies getEngines() { result = getPropValue("engines") }
PackageDependencies getEngines() { result = this.getPropValue("engines") }
/** Holds if this package has strict engine requirements. */
predicate isEngineStrict() { getPropValue("engineStrict").(JSONBoolean).getValue() = "true" }
predicate isEngineStrict() { this.getPropValue("engineStrict").(JSONBoolean).getValue() = "true" }
/** Gets information about operating systems supported by this package. */
JSONArray getOSs() { result = getPropValue("os") }
JSONArray getOSs() { result = this.getPropValue("os") }
/** Gets an operating system supported by this package. */
string getWhitelistedOS() {
result = getOSs().getElementStringValue(_) and
result = this.getOSs().getElementStringValue(_) and
not result.matches("!%")
}
/** Gets an operating system not supported by this package. */
string getBlacklistedOS() {
exists(string str | str = getOSs().getElementStringValue(_) |
exists(string str | str = this.getOSs().getElementStringValue(_) |
result = str.regexpCapture("!(.*)", 1)
)
}
/** Gets information about platforms supported by this package. */
JSONArray getCPUs() { result = getPropValue("cpu") }
JSONArray getCPUs() { result = this.getPropValue("cpu") }
/** Gets a platform supported by this package. */
string getWhitelistedCPU() {
result = getCPUs().getElementStringValue(_) and
result = this.getCPUs().getElementStringValue(_) and
not result.matches("!%")
}
/** Gets a platform not supported by this package. */
string getBlacklistedCPU() {
exists(string str | str = getCPUs().getElementStringValue(_) |
exists(string str | str = this.getCPUs().getElementStringValue(_) |
result = str.regexpCapture("!(.*)", 1)
)
}
/** Holds if this package prefers to be installed globally. */
predicate isPreferGlobal() { getPropValue("preferGlobal").(JSONBoolean).getValue() = "true" }
predicate isPreferGlobal() { this.getPropValue("preferGlobal").(JSONBoolean).getValue() = "true" }
/** Holds if this is a private package. */
predicate isPrivate() { getPropValue("private").(JSONBoolean).getValue() = "true" }
predicate isPrivate() { this.getPropValue("private").(JSONBoolean).getValue() = "true" }
/** Gets publishing configuration information about this package. */
JSONValue getPublishConfig() { result = getPropValue("publishConfig") }
JSONValue getPublishConfig() { result = this.getPropValue("publishConfig") }
/**
* Gets the main module of this package.
@@ -221,19 +225,19 @@ class ContributorInfo extends JSONValue {
/** Gets the contributor's name. */
string getName() {
result = this.getPropValue("name").getStringValue() or
result = parseInfo(1)
result = this.parseInfo(1)
}
/** Gets the contributor's email address. */
string getEmail() {
result = this.getPropValue("email").getStringValue() or
result = parseInfo(2)
result = this.parseInfo(2)
}
/** Gets the contributor's homepage URL. */
string getUrl() {
result = this.getPropValue("url").getStringValue() or
result = parseInfo(3)
result = this.parseInfo(3)
}
}
@@ -244,10 +248,10 @@ class RepositoryInfo extends JSONObject {
RepositoryInfo() { exists(PackageJSON pkg | this = pkg.getPropValue("repository")) }
/** Gets the repository type. */
string getType() { result = getPropStringValue("type") }
string getType() { result = this.getPropStringValue("type") }
/** Gets the repository URL. */
string getUrl() { result = getPropStringValue("url") }
string getUrl() { result = this.getPropStringValue("url") }
}
/**
@@ -262,7 +266,7 @@ class PackageDependencies extends JSONObject {
}
/** Holds if this package depends on version 'version' of package 'pkg'. */
predicate getADependency(string pkg, string version) { version = getPropStringValue(pkg) }
predicate getADependency(string pkg, string version) { version = this.getPropStringValue(pkg) }
}
/**
@@ -284,7 +288,7 @@ class NPMPackage extends @folder {
PackageJSON getPackageJSON() { result = pkg }
/** Gets the name of this package. */
string getPackageName() { result = getPackageJSON().getPackageName() }
string getPackageName() { result = this.getPackageJSON().getPackageName() }
/** Gets the `node_modules` folder of this package. */
Folder getNodeModulesFolder() {
@@ -308,7 +312,7 @@ class NPMPackage extends @folder {
* and modules inside the `node_modules` folder of a package are not
* considered to belong to that package.
*/
Module getAModule() { result.getFile() = getAFile() }
Module getAModule() { result.getFile() = this.getAFile() }
/**
* Gets the main module of this package.

View File

@@ -21,10 +21,10 @@ class NodeModule extends Module {
}
/** Gets the `module` variable of this module. */
Variable getModuleVariable() { result = getScope().getVariable("module") }
Variable getModuleVariable() { result = this.getScope().getVariable("module") }
/** Gets the `exports` variable of this module. */
Variable getExportsVariable() { result = getScope().getVariable("exports") }
Variable getExportsVariable() { result = this.getScope().getVariable("exports") }
/** Gets the scope induced by this module. */
override ModuleScope getScope() { result.getScopeElement() = this }
@@ -35,7 +35,7 @@ class NodeModule extends Module {
*/
pragma[noinline]
DefiniteAbstractValue getAModuleExportsValue() {
result = getAModuleExportsProperty().getAValue()
result = this.getAModuleExportsProperty().getAValue()
}
pragma[noinline]
@@ -51,14 +51,14 @@ class NodeModule extends Module {
*/
DataFlow::AnalyzedNode getAModuleExportsNode() {
result = getAModuleExportsCandidate() and
result.getAValue() = getAModuleExportsValue()
result.getAValue() = this.getAModuleExportsValue()
}
/** Gets a symbol exported by this module. */
override string getAnExportedSymbol() {
result = super.getAnExportedSymbol()
or
result = getAnImplicitlyExportedSymbol()
result = this.getAnImplicitlyExportedSymbol()
or
// getters and the like.
exists(DataFlow::PropWrite pwn |
@@ -70,12 +70,12 @@ class NodeModule extends Module {
override DataFlow::Node getAnExportedValue(string name) {
// a property write whose base is `exports` or `module.exports`
exists(DataFlow::PropWrite pwn | result = pwn.getRhs() |
pwn.getBase() = getAModuleExportsNode() and
pwn.getBase() = this.getAModuleExportsNode() and
name = pwn.getPropertyName()
)
or
// a re-export using spread-operator. E.g. `const foo = require("./foo"); module.exports = {bar: bar, ...foo};`
exists(ObjectExpr obj | obj = getAModuleExportsNode().asExpr() |
exists(ObjectExpr obj | obj = this.getAModuleExportsNode().asExpr() |
result =
obj.getAProperty()
.(SpreadProperty)
@@ -92,16 +92,16 @@ class NodeModule extends Module {
or
// an externs definition (where appropriate)
exists(PropAccess pacc | result = DataFlow::valueNode(pacc) |
pacc.getBase() = getAModuleExportsNode().asExpr() and
pacc.getBase() = this.getAModuleExportsNode().asExpr() and
name = pacc.getPropertyName() and
isExterns() and
this.isExterns() and
exists(pacc.getDocumentation())
)
}
override DataFlow::Node getABulkExportedNode() {
exists(DataFlow::PropWrite write |
write.getBase().asExpr() = getModuleVariable().getAnAccess() and
write.getBase().asExpr() = this.getModuleVariable().getAnAccess() and
write.getPropertyName() = "exports" and
result = write.getRhs()
)
@@ -109,7 +109,7 @@ class NodeModule extends Module {
/** Gets a symbol that the module object inherits from its prototypes. */
private string getAnImplicitlyExportedSymbol() {
exists(ExternalConstructor ec | ec = getPrototypeOfExportedExpr() |
exists(ExternalConstructor ec | ec = this.getPrototypeOfExportedExpr() |
result = ec.getAMember().getName()
or
ec instanceof FunctionExternal and result = "prototype"
@@ -121,7 +121,7 @@ class NodeModule extends Module {
/** Gets an externs declaration of the prototype object of a value exported by this module. */
private ExternalConstructor getPrototypeOfExportedExpr() {
exists(AbstractValue exported | exported = getAModuleExportsValue() |
exists(AbstractValue exported | exported = this.getAModuleExportsValue() |
result instanceof ObjectExternal
or
exported instanceof AbstractFunction and result instanceof FunctionExternal
@@ -136,7 +136,7 @@ class NodeModule extends Module {
// paths starting with `./` or `../` are resolved relative to the importing
// module's folder
pathval.regexpMatch("\\.\\.?(/.*)?") and
(searchRoot = getFile().getParentContainer() and priority = 0)
(searchRoot = this.getFile().getParentContainer() and priority = 0)
or
// paths starting with `/` are resolved relative to the file system root
pathval.matches("/%") and
@@ -145,7 +145,7 @@ class NodeModule extends Module {
// paths that do not start with `./`, `../` or `/` are resolved relative
// to `node_modules` folders
not pathval.regexpMatch("\\.\\.?(/.*)?|/.*") and
findNodeModulesFolder(getFile().getParentContainer(), searchRoot, priority)
findNodeModulesFolder(this.getFile().getParentContainer(), searchRoot, priority)
)
}
}
@@ -277,16 +277,16 @@ private predicate isRequire(DataFlow::Node nd) {
* ```
*/
class Require extends CallExpr, Import {
Require() { isRequire(getCallee().flow()) }
Require() { isRequire(this.getCallee().flow()) }
override PathExpr getImportedPath() { result = getArgument(0) }
override PathExpr getImportedPath() { result = this.getArgument(0) }
override Module getEnclosingModule() { this = result.getAnImport() }
override Module resolveImportedPath() {
moduleInFile(result, load(min(int prio | moduleInFile(_, load(prio)))))
moduleInFile(result, this.load(min(int prio | moduleInFile(_, this.load(prio)))))
or
not exists(Module mod | moduleInFile(mod, load(_))) and
not exists(Module mod | moduleInFile(mod, this.load(_))) and
result = Import.super.resolveImportedPath()
}
@@ -296,7 +296,7 @@ class Require extends CallExpr, Import {
* The result can be a JavaScript file, a JSON file or a `.node` file.
* Externs files are not treated differently from other files by this predicate.
*/
File getImportedFile() { result = load(min(int prio | exists(load(prio)))) }
File getImportedFile() { result = this.load(min(int prio | exists(this.load(prio)))) }
/**
* Gets the file that this `require` refers to (which may not be a JavaScript file),
@@ -354,7 +354,7 @@ class Require extends CallExpr, Import {
* `.js`, `.json` and `.node`.
*/
private File load(int priority) {
exists(int r | getEnclosingModule().searchRoot(getImportedPath(), _, r) |
exists(int r | this.getEnclosingModule().searchRoot(this.getImportedPath(), _, r) |
result = loadAsFile(this, r, priority - prioritiesPerCandidate() * r) or
result =
loadAsDirectory(this, r,
@@ -382,27 +382,27 @@ private class RequirePath extends PathExprCandidate {
private class ConstantRequirePathElement extends PathExpr, ConstantString {
ConstantRequirePathElement() { this = any(RequirePath rp).getAPart() }
override string getValue() { result = getStringValue() }
override string getValue() { result = this.getStringValue() }
}
/** A `__dirname` path expression. */
private class DirNamePath extends PathExpr, VarAccess {
DirNamePath() {
getName() = "__dirname" and
getVariable().getScope() instanceof ModuleScope
this.getName() = "__dirname" and
this.getVariable().getScope() instanceof ModuleScope
}
override string getValue() { result = getFile().getParentContainer().getAbsolutePath() }
override string getValue() { result = this.getFile().getParentContainer().getAbsolutePath() }
}
/** A `__filename` path expression. */
private class FileNamePath extends PathExpr, VarAccess {
FileNamePath() {
getName() = "__filename" and
getVariable().getScope() instanceof ModuleScope
this.getName() = "__filename" and
this.getVariable().getScope() instanceof ModuleScope
}
override string getValue() { result = getFile().getAbsolutePath() }
override string getValue() { result = this.getFile().getAbsolutePath() }
}
/**

View File

@@ -113,7 +113,7 @@ abstract class PathString extends string {
string getComponent(int i) { result = this.splitAt("/", i) }
/** Gets the number of components of this path. */
int getNumComponent() { result = count(int i | exists(getComponent(i))) }
int getNumComponent() { result = count(int i | exists(this.getComponent(i))) }
/** Gets the base name of the folder or file this path refers to. */
string getBaseName() { result = this.regexpCapture(pathRegex(), 2) }
@@ -147,7 +147,7 @@ abstract class PathString extends string {
* Gets the absolute path that this path refers to when resolved relative to
* `root`.
*/
Path resolve(Folder root) { result = resolveUpTo(getNumComponent(), root) }
Path resolve(Folder root) { result = this.resolveUpTo(this.getNumComponent(), root) }
}
/**
@@ -306,9 +306,9 @@ abstract class PathExpr extends Locatable {
/** Gets the root folder of priority `priority` associated with this path expression. */
Folder getSearchRoot(int priority) {
// We default to the enclosing module's search root, though this may be overridden.
getEnclosingModule().searchRoot(this, result, priority)
this.getEnclosingModule().searchRoot(this, result, priority)
or
result = getAdditionalSearchRoot(priority)
result = this.getAdditionalSearchRoot(priority)
}
/**
@@ -320,16 +320,16 @@ abstract class PathExpr extends Locatable {
Folder getAdditionalSearchRoot(int priority) { none() }
/** Gets the `i`th component of this path. */
string getComponent(int i) { result = getValue().(PathString).getComponent(i) }
string getComponent(int i) { result = this.getValue().(PathString).getComponent(i) }
/** Gets the number of components of this path. */
int getNumComponent() { result = getValue().(PathString).getNumComponent() }
int getNumComponent() { result = this.getValue().(PathString).getNumComponent() }
/** Gets the base name of the folder or file this path refers to. */
string getBaseName() { result = getValue().(PathString).getBaseName() }
string getBaseName() { result = this.getValue().(PathString).getBaseName() }
/** Gets the stem, that is, base name without extension, of the folder or file this path refers to. */
string getStem() { result = getValue().(PathString).getStem() }
string getStem() { result = this.getValue().(PathString).getStem() }
/**
* Gets the extension of the folder or file this path refers to, that is, the suffix of the base name
@@ -337,7 +337,7 @@ abstract class PathExpr extends Locatable {
*
* Has no result if the base name does not contain a dot.
*/
string getExtension() { result = getValue().(PathString).getExtension() }
string getExtension() { result = this.getValue().(PathString).getExtension() }
/**
* Gets the file or folder that the first `n` components of this path refer to
@@ -345,22 +345,25 @@ abstract class PathExpr extends Locatable {
*/
pragma[nomagic]
Container resolveUpTo(int n, int priority) {
result = getValue().(PathString).resolveUpTo(n, getSearchRoot(priority)).getContainer()
result =
this.getValue().(PathString).resolveUpTo(n, this.getSearchRoot(priority)).getContainer()
}
/**
* Gets the file or folder that this path refers to when resolved relative to
* the root folder of the given `priority`.
*/
Container resolve(int priority) { result = resolveUpTo(getNumComponent(), priority) }
Container resolve(int priority) { result = this.resolveUpTo(this.getNumComponent(), priority) }
/**
* Gets the file or folder that the first `n` components of this path refer to.
*/
Container resolveUpTo(int n) { result = resolveUpTo(n, min(int p | exists(resolveUpTo(n, p)))) }
Container resolveUpTo(int n) {
result = this.resolveUpTo(n, min(int p | exists(this.resolveUpTo(n, p))))
}
/** Gets the file or folder that this path refers to. */
Container resolve() { result = resolveUpTo(getNumComponent()) }
Container resolve() { result = this.resolveUpTo(this.getNumComponent()) }
/** Gets the module containing this path expression, if any. */
Module getEnclosingModule() {
@@ -418,5 +421,5 @@ abstract class PathExprCandidate extends Expr {
* `ConstantString`s).
*/
pragma[nomagic]
Expr getAPart() { result = this or result = getAPart().getAChildExpr() }
Expr getAPart() { result = this or result = this.getAPart().getAChildExpr() }
}

View File

@@ -98,7 +98,7 @@ class PrintAstNode extends TPrintAstNode {
/**
* Gets a child of this node.
*/
final PrintAstNode getAChild() { result = getChild(_) }
final PrintAstNode getAChild() { result = this.getChild(_) }
/**
* Gets the parent of this node, if any.
@@ -116,7 +116,7 @@ class PrintAstNode extends TPrintAstNode {
*/
string getProperty(string key) {
key = "semmle.label" and
result = toString()
result = this.toString()
}
/**
@@ -125,7 +125,7 @@ class PrintAstNode extends TPrintAstNode {
* this.
*/
string getChildEdgeLabel(int childIndex) {
exists(getChild(childIndex)) and
exists(this.getChild(childIndex)) and
result = childIndex.toString()
}
}

View File

@@ -13,14 +13,14 @@ abstract class PromiseDefinition extends DataFlow::SourceNode {
abstract DataFlow::FunctionNode getExecutor();
/** Gets the `resolve` parameter of the executor function. */
DataFlow::ParameterNode getResolveParameter() { result = getExecutor().getParameter(0) }
DataFlow::ParameterNode getResolveParameter() { result = this.getExecutor().getParameter(0) }
/** Gets the `reject` parameter of the executor function. */
DataFlow::ParameterNode getRejectParameter() { result = getExecutor().getParameter(1) }
DataFlow::ParameterNode getRejectParameter() { result = this.getExecutor().getParameter(1) }
/** Gets the `i`th callback handler installed by method `m`. */
private DataFlow::FunctionNode getAHandler(string m, int i) {
result = getAMethodCall(m).getCallback(i)
result = this.getAMethodCall(m).getCallback(i)
}
/**
@@ -28,8 +28,8 @@ abstract class PromiseDefinition extends DataFlow::SourceNode {
* `then` handlers and `finally` handlers.
*/
DataFlow::FunctionNode getAResolveHandler() {
result = getAHandler("then", 0) or
result = getAFinallyHandler()
result = this.getAHandler("then", 0) or
result = this.getAFinallyHandler()
}
/**
@@ -37,20 +37,20 @@ abstract class PromiseDefinition extends DataFlow::SourceNode {
* `then` handlers, `catch` handlers and `finally` handlers.
*/
DataFlow::FunctionNode getARejectHandler() {
result = getAHandler("then", 1) or
result = getACatchHandler() or
result = getAFinallyHandler()
result = this.getAHandler("then", 1) or
result = this.getACatchHandler() or
result = this.getAFinallyHandler()
}
/**
* Gets a `catch` handler of this promise.
*/
DataFlow::FunctionNode getACatchHandler() { result = getAHandler("catch", 0) }
DataFlow::FunctionNode getACatchHandler() { result = this.getAHandler("catch", 0) }
/**
* Gets a `finally` handler of this promise.
*/
DataFlow::FunctionNode getAFinallyHandler() { result = getAHandler("finally", 0) }
DataFlow::FunctionNode getAFinallyHandler() { result = this.getAHandler("finally", 0) }
}
/** Holds if the `i`th callback handler is installed by method `m`. */
@@ -115,7 +115,7 @@ class PromiseCandidate extends DataFlow::InvokeNode {
private class ES2015PromiseDefinition extends PromiseDefinition, DataFlow::InvokeNode {
ES2015PromiseDefinition() { this = getAPromiseObject().getAnInvocation() }
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
}
/**
@@ -149,7 +149,7 @@ abstract class PromiseAllCreation extends PromiseCreationCall {
class ResolvedES2015PromiseDefinition extends ResolvedPromiseDefinition {
ResolvedES2015PromiseDefinition() { this = getAPromiseObject().getAMemberCall("resolve") }
override DataFlow::Node getValue() { result = getArgument(0) }
override DataFlow::Node getValue() { result = this.getArgument(0) }
}
/**
@@ -165,7 +165,7 @@ class AggregateES2015PromiseDefinition extends PromiseCreationCall {
}
override DataFlow::Node getValue() {
result = getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
result = this.getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
}
}
@@ -175,7 +175,7 @@ class AggregateES2015PromiseDefinition extends PromiseCreationCall {
class ES2015PromiseAllDefinition extends AggregateES2015PromiseDefinition, PromiseAllCreation {
ES2015PromiseAllDefinition() { this.getCalleeName() = "all" }
override DataFlow::Node getArrayNode() { result = getArgument(0) }
override DataFlow::Node getArrayNode() { result = this.getArgument(0) }
}
/**
@@ -548,7 +548,7 @@ module Bluebird {
private class BluebirdPromiseDefinition extends PromiseDefinition, DataFlow::NewNode {
BluebirdPromiseDefinition() { this = bluebird().getAnInstantiation() }
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
}
/**
@@ -557,7 +557,7 @@ module Bluebird {
class ResolvedBluebidPromiseDefinition extends ResolvedPromiseDefinition {
ResolvedBluebidPromiseDefinition() { this = bluebird().getAMemberCall("resolve") }
override DataFlow::Node getValue() { result = getArgument(0) }
override DataFlow::Node getValue() { result = this.getArgument(0) }
}
/**
@@ -569,7 +569,7 @@ module Bluebird {
}
override DataFlow::Node getValue() {
result = getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
result = this.getArgument(0).getALocalSource().(DataFlow::ArrayCreationNode).getAnElement()
}
}
@@ -579,7 +579,7 @@ module Bluebird {
class BluebirdPromiseAllDefinition extends AggregateBluebirdPromiseDefinition, PromiseAllCreation {
BluebirdPromiseAllDefinition() { this.getCalleeName() = "all" }
override DataFlow::Node getArrayNode() { result = getArgument(0) }
override DataFlow::Node getArrayNode() { result = this.getArgument(0) }
}
/**
@@ -593,7 +593,7 @@ module Bluebird {
BluebirdCoroutineDefinition {
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
boundArgs = 0 and
callback = getArgument(0) and
callback = this.getArgument(0) and
result = this
}
}
@@ -609,7 +609,7 @@ module Q {
private class QPromiseDefinition extends PromiseDefinition, DataFlow::CallNode {
QPromiseDefinition() { this = DataFlow::moduleMember(["q", "kew"], "Promise").getACall() }
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
}
}
@@ -620,7 +620,7 @@ private module ClosurePromise {
private class ClosurePromiseDefinition extends PromiseDefinition, DataFlow::NewNode {
ClosurePromiseDefinition() { this = Closure::moduleImport("goog.Promise").getACall() }
override DataFlow::FunctionNode getExecutor() { result = getCallback(0) }
override DataFlow::FunctionNode getExecutor() { result = this.getCallback(0) }
}
/**
@@ -632,7 +632,7 @@ private module ClosurePromise {
this = Closure::moduleImport("goog.Promise.resolve").getACall()
}
override DataFlow::Node getValue() { result = getArgument(0) }
override DataFlow::Node getValue() { result = this.getArgument(0) }
}
/**

View File

@@ -48,13 +48,13 @@ class RegExpTerm extends Locatable, @regexpterm {
RegExpTerm getChild(int i) { regexpterm(result, _, this, i, _) }
/** Gets a child term of this term. */
RegExpTerm getAChild() { result = getChild(_) }
RegExpTerm getAChild() { result = this.getChild(_) }
/** Gets the number of child terms of this term. */
int getNumChild() { result = count(getAChild()) }
int getNumChild() { result = count(this.getAChild()) }
/** Gets the last child term of this term. */
RegExpTerm getLastChild() { result = getChild(getNumChild() - 1) }
RegExpTerm getLastChild() { result = this.getChild(this.getNumChild() - 1) }
/**
* Gets the parent term of this regular expression term, or the
@@ -63,7 +63,7 @@ class RegExpTerm extends Locatable, @regexpterm {
RegExpParent getParent() { regexpterm(this, _, result, _, _) }
/** Gets the regular expression literal this term belongs to, if any. */
RegExpLiteral getLiteral() { result = getRootTerm().getParent() }
RegExpLiteral getLiteral() { result = this.getRootTerm().getParent() }
override string toString() { regexpterm(this, _, _, _, result) }
@@ -75,7 +75,7 @@ class RegExpTerm extends Locatable, @regexpterm {
/** Gets the regular expression term that is matched (textually) before this one, if any. */
RegExpTerm getPredecessor() {
exists(RegExpTerm parent | parent = getParent() |
exists(RegExpTerm parent | parent = this.getParent() |
result = parent.(RegExpSequence).previousElement(this)
or
not exists(parent.(RegExpSequence).previousElement(this)) and
@@ -86,7 +86,7 @@ class RegExpTerm extends Locatable, @regexpterm {
/** Gets the regular expression term that is matched (textually) after this one, if any. */
RegExpTerm getSuccessor() {
exists(RegExpTerm parent | parent = getParent() |
exists(RegExpTerm parent | parent = this.getParent() |
result = parent.(RegExpSequence).nextElement(this)
or
not exists(parent.(RegExpSequence).nextElement(this)) and
@@ -99,7 +99,7 @@ class RegExpTerm extends Locatable, @regexpterm {
* Holds if this regular term is in a forward-matching context, that is,
* it has no enclosing lookbehind assertions.
*/
predicate isInForwardMatchingContext() { not isInBackwardMatchingContext() }
predicate isInForwardMatchingContext() { not this.isInBackwardMatchingContext() }
/**
* Holds if this regular term is in a backward-matching context, that is,
@@ -110,22 +110,22 @@ class RegExpTerm extends Locatable, @regexpterm {
/**
* Holds if this is the root term of a regular expression.
*/
predicate isRootTerm() { not getParent() instanceof RegExpTerm }
predicate isRootTerm() { not this.getParent() instanceof RegExpTerm }
/**
* Gets the outermost term of this regular expression.
*/
RegExpTerm getRootTerm() {
isRootTerm() and
this.isRootTerm() and
result = this
or
result = getParent().(RegExpTerm).getRootTerm()
result = this.getParent().(RegExpTerm).getRootTerm()
}
/**
* Holds if this term occurs as part of a regular expression literal.
*/
predicate isPartOfRegExpLiteral() { exists(getLiteral()) }
predicate isPartOfRegExpLiteral() { exists(this.getLiteral()) }
/**
* Holds if this term occurs as part of a string literal.
@@ -133,7 +133,7 @@ class RegExpTerm extends Locatable, @regexpterm {
* This predicate holds regardless of whether the string literal is actually
* used as a regular expression. See `isUsedAsRegExp`.
*/
predicate isPartOfStringLiteral() { getRootTerm().getParent() instanceof StringLiteral }
predicate isPartOfStringLiteral() { this.getRootTerm().getParent() instanceof StringLiteral }
/**
* Holds if this term is part of a regular expression literal, or a string literal
@@ -152,7 +152,7 @@ class RegExpTerm extends Locatable, @regexpterm {
* ```
*/
predicate isUsedAsRegExp() {
exists(RegExpParent parent | parent = getRootTerm().getParent() |
exists(RegExpParent parent | parent = this.getRootTerm().getParent() |
parent instanceof RegExpLiteral
or
parent.(StringLiteral).flow() instanceof RegExpPatternSource
@@ -174,7 +174,7 @@ class RegExpTerm extends Locatable, @regexpterm {
/**
* Gets a string that is matched by this regular-expression term.
*/
string getAMatchedString() { result = getConstantValue() }
string getAMatchedString() { result = this.getConstantValue() }
}
/**
@@ -241,7 +241,7 @@ class RegExpConstant extends RegExpTerm, @regexp_constant {
override predicate isNullable() { none() }
override string getConstantValue() { result = getValue() }
override string getConstantValue() { result = this.getValue() }
override string getAPrimaryQlClass() { result = "RegExpConstant" }
}
@@ -259,8 +259,8 @@ class RegExpCharEscape extends RegExpEscape, RegExpConstant, @regexp_char_escape
override predicate isCharacter() {
not (
// unencodable characters are represented as '?' or \uFFFD in the database
getValue() = ["?", 65533.toUnicode()] and
exists(string s | s = toString().toLowerCase() |
this.getValue() = ["?", 65533.toUnicode()] and
exists(string s | s = this.toString().toLowerCase() |
// only Unicode escapes give rise to unencodable characters
s.matches("\\\\u%") and
// but '\u003f' actually is the '?' character itself
@@ -283,14 +283,14 @@ class RegExpCharEscape extends RegExpEscape, RegExpConstant, @regexp_char_escape
*/
class RegExpAlt extends RegExpTerm, @regexp_alt {
/** Gets an alternative of this term. */
RegExpTerm getAlternative() { result = getAChild() }
RegExpTerm getAlternative() { result = this.getAChild() }
/** Gets the number of alternatives of this term. */
int getNumAlternative() { result = getNumChild() }
int getNumAlternative() { result = this.getNumChild() }
override predicate isNullable() { getAlternative().isNullable() }
override predicate isNullable() { this.getAlternative().isNullable() }
override string getAMatchedString() { result = getAlternative().getAMatchedString() }
override string getAMatchedString() { result = this.getAlternative().getAMatchedString() }
override string getAPrimaryQlClass() { result = "RegExpAlt" }
}
@@ -308,30 +308,30 @@ class RegExpAlt extends RegExpTerm, @regexp_alt {
*/
class RegExpSequence extends RegExpTerm, @regexp_seq {
/** Gets an element of this sequence. */
RegExpTerm getElement() { result = getAChild() }
RegExpTerm getElement() { result = this.getAChild() }
/** Gets the number of elements in this sequence. */
int getNumElement() { result = getNumChild() }
int getNumElement() { result = this.getNumChild() }
override predicate isNullable() {
forall(RegExpTerm child | child = getAChild() | child.isNullable())
forall(RegExpTerm child | child = this.getAChild() | child.isNullable())
}
override string getConstantValue() { result = getConstantValue(0) }
override string getConstantValue() { result = this.getConstantValue(0) }
/**
* Gets the single string matched by the `i`th child and all following children of
* this sequence, if any.
*/
private string getConstantValue(int i) {
i = getNumChild() and
i = this.getNumChild() and
result = ""
or
result = getChild(i).getConstantValue() + getConstantValue(i + 1)
result = this.getChild(i).getConstantValue() + this.getConstantValue(i + 1)
}
/** Gets the element preceding `element` in this sequence. */
RegExpTerm previousElement(RegExpTerm element) { element = nextElement(result) }
RegExpTerm previousElement(RegExpTerm element) { element = this.nextElement(result) }
/** Gets the element following `element` in this sequence. */
RegExpTerm nextElement(RegExpTerm element) {
@@ -430,7 +430,7 @@ class RegExpNonWordBoundary extends RegExpTerm, @regexp_nonwordboundary {
*/
class RegExpSubPattern extends RegExpTerm, @regexp_subpattern {
/** Gets the lookahead term. */
RegExpTerm getOperand() { result = getAChild() }
RegExpTerm getOperand() { result = this.getAChild() }
override predicate isNullable() { any() }
}
@@ -540,7 +540,7 @@ class RegExpStar extends RegExpQuantifier, @regexp_star {
* ```
*/
class RegExpPlus extends RegExpQuantifier, @regexp_plus {
override predicate isNullable() { getAChild().isNullable() }
override predicate isNullable() { this.getAChild().isNullable() }
override string getAPrimaryQlClass() { result = "RegExpPlus" }
}
@@ -585,8 +585,8 @@ class RegExpRange extends RegExpQuantifier, @regexp_range {
int getUpperBound() { range_quantifier_upper_bound(this, result) }
override predicate isNullable() {
getAChild().isNullable() or
getLowerBound() = 0
this.getAChild().isNullable() or
this.getLowerBound() = 0
}
override string getAPrimaryQlClass() { result = "RegExpRange" }
@@ -639,11 +639,11 @@ class RegExpGroup extends RegExpTerm, @regexp_group {
/** Gets the name of this capture group, if any. */
string getName() { is_named_capture(this, result) }
override predicate isNullable() { getAChild().isNullable() }
override predicate isNullable() { this.getAChild().isNullable() }
override string getConstantValue() { result = getAChild().getConstantValue() }
override string getConstantValue() { result = this.getAChild().getConstantValue() }
override string getAMatchedString() { result = getAChild().getAMatchedString() }
override string getAMatchedString() { result = this.getAChild().getAMatchedString() }
override string getAPrimaryQlClass() { result = "RegExpGroup" }
}
@@ -831,7 +831,7 @@ class RegExpBackRef extends RegExpTerm, @regexp_backref {
)
}
override predicate isNullable() { getGroup().isNullable() }
override predicate isNullable() { this.getGroup().isNullable() }
override string getAPrimaryQlClass() { result = "RegExpBackRef" }
}
@@ -853,7 +853,7 @@ class RegExpCharacterClass extends RegExpTerm, @regexp_char_class {
override predicate isNullable() { none() }
override string getAMatchedString() {
not isInverted() and result = getAChild().getAMatchedString()
not this.isInverted() and result = this.getAChild().getAMatchedString()
}
/**
@@ -861,13 +861,13 @@ class RegExpCharacterClass extends RegExpTerm, @regexp_char_class {
*/
predicate isUniversalClass() {
// [^]
isInverted() and not exists(getAChild())
this.isInverted() and not exists(this.getAChild())
or
// [\w\W] and similar
not isInverted() and
not this.isInverted() and
exists(string cce1, string cce2 |
cce1 = getAChild().(RegExpCharacterClassEscape).getValue() and
cce2 = getAChild().(RegExpCharacterClassEscape).getValue()
cce1 = this.getAChild().(RegExpCharacterClassEscape).getValue() and
cce2 = this.getAChild().(RegExpCharacterClassEscape).getValue()
|
cce1 != cce2 and cce1.toLowerCase() = cce2.toLowerCase()
)
@@ -890,8 +890,8 @@ class RegExpCharacterRange extends RegExpTerm, @regexp_char_range {
/** Holds if `lo` is the lower bound of this character range and `hi` the upper bound. */
predicate isRange(string lo, string hi) {
lo = getChild(0).(RegExpConstant).getValue() and
hi = getChild(1).(RegExpConstant).getValue()
lo = this.getChild(0).(RegExpConstant).getValue() and
hi = this.getChild(1).(RegExpConstant).getValue()
}
override string getAPrimaryQlClass() { result = "RegExpCharacterRange" }
@@ -903,11 +903,11 @@ class RegExpParseError extends Error, @regexp_parse_error {
RegExpTerm getTerm() { regexp_parse_errors(this, result, _) }
/** Gets the regular expression literal in which the parse error occurred. */
RegExpLiteral getLiteral() { result = getTerm().getLiteral() }
RegExpLiteral getLiteral() { result = this.getTerm().getLiteral() }
override string getMessage() { regexp_parse_errors(this, _, result) }
override string toString() { result = getMessage() }
override string toString() { result = this.getMessage() }
override predicate isFatal() { none() }
}
@@ -1099,9 +1099,9 @@ private class StringRegExpPatternSource extends RegExpPatternSource {
)
}
override string getPattern() { result = getStringValue() }
override string getPattern() { result = this.getStringValue() }
override RegExpTerm getRegExpTerm() { result = asExpr().(StringLiteral).asRegExp() }
override RegExpTerm getRegExpTerm() { result = this.asExpr().(StringLiteral).asRegExp() }
}
module RegExp {

View File

@@ -9,18 +9,18 @@ class CallToObjectDefineProperty extends DataFlow::MethodCallNode {
CallToObjectDefineProperty() {
exists(GlobalVariable obj |
obj.getName() = "Object" and
calls(DataFlow::valueNode(obj.getAnAccess()), "defineProperty")
this.calls(DataFlow::valueNode(obj.getAnAccess()), "defineProperty")
)
}
/** Gets the data flow node denoting the object on which the property is defined. */
DataFlow::Node getBaseObject() { result = getArgument(0) }
DataFlow::Node getBaseObject() { result = this.getArgument(0) }
/** Gets the name of the property being defined, if it can be determined. */
string getPropertyName() { result = getArgument(1).getStringValue() }
string getPropertyName() { result = this.getArgument(1).getStringValue() }
/** Gets the data flow node denoting the descriptor of the property being defined. */
DataFlow::Node getPropertyDescriptor() { result = getArgument(2) }
DataFlow::Node getPropertyDescriptor() { result = this.getArgument(2) }
/**
* Holds if there is an assignment to property `name` to the
@@ -29,7 +29,7 @@ class CallToObjectDefineProperty extends DataFlow::MethodCallNode {
*/
predicate hasPropertyAttributeWrite(string name, DataFlow::Node rhs) {
exists(DataFlow::SourceNode descriptor |
descriptor.flowsTo(getPropertyDescriptor()) and
descriptor.flowsTo(this.getPropertyDescriptor()) and
descriptor.hasPropertyWrite(name, rhs)
)
}
@@ -39,10 +39,10 @@ class CallToObjectDefineProperty extends DataFlow::MethodCallNode {
* A direct call to `eval`.
*/
class DirectEval extends CallExpr {
DirectEval() { getCallee().(GlobalVarAccess).getName() = "eval" }
DirectEval() { this.getCallee().(GlobalVarAccess).getName() = "eval" }
/** Holds if this call could affect the value of `lv`. */
predicate mayAffect(LocalVariable lv) { getParent+() = lv.getScope().getScopeElement() }
predicate mayAffect(LocalVariable lv) { this.getParent+() = lv.getScope().getScopeElement() }
}
/**
@@ -52,15 +52,15 @@ class DirectEval extends CallExpr {
private class ArrayIterationCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode::Range,
DataFlow::MethodCallNode {
ArrayIterationCallbackAsPartialInvoke() {
getNumArgument() = 2 and
this.getNumArgument() = 2 and
// Filter out library methods named 'forEach' etc
not DataFlow::moduleImport(_).flowsTo(getReceiver()) and
getMethodName() = ["filter", "forEach", "map", "some", "every"]
not DataFlow::moduleImport(_).flowsTo(this.getReceiver()) and
this.getMethodName() = ["filter", "forEach", "map", "some", "every"]
}
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
callback = getArgument(0) and
result = getArgument(1)
callback = this.getArgument(0) and
result = this.getArgument(1)
}
}
@@ -86,48 +86,48 @@ private class IteratorExceptionStep extends DataFlow::SharedFlowStep {
*/
class StringReplaceCall extends DataFlow::MethodCallNode {
StringReplaceCall() {
getMethodName() = ["replace", "replaceAll"] and
(getNumArgument() = 2 or getReceiver().mayHaveStringValue(_))
this.getMethodName() = ["replace", "replaceAll"] and
(this.getNumArgument() = 2 or this.getReceiver().mayHaveStringValue(_))
}
/** Gets the regular expression passed as the first argument to `replace`, if any. */
DataFlow::RegExpCreationNode getRegExp() { result.flowsTo(getArgument(0)) }
DataFlow::RegExpCreationNode getRegExp() { result.flowsTo(this.getArgument(0)) }
/** Gets a string that is being replaced by this call. */
string getAReplacedString() {
result = getRegExp().getRoot().getAMatchedString() or
getArgument(0).mayHaveStringValue(result)
result = this.getRegExp().getRoot().getAMatchedString() or
this.getArgument(0).mayHaveStringValue(result)
}
/**
* Gets the second argument of this call to `replace`, which is either a string
* or a callback.
*/
DataFlow::Node getRawReplacement() { result = getArgument(1) }
DataFlow::Node getRawReplacement() { result = this.getArgument(1) }
/**
* Gets a function flowing into the second argument of this call to `replace`.
*/
DataFlow::FunctionNode getReplacementCallback() { result = getCallback(1) }
DataFlow::FunctionNode getReplacementCallback() { result = this.getCallback(1) }
/**
* Holds if this is a global replacement, that is, the first argument is a regular expression
* with the `g` flag, or this is a call to `.replaceAll()`.
*/
predicate isGlobal() { getRegExp().isGlobal() or getMethodName() = "replaceAll" }
predicate isGlobal() { this.getRegExp().isGlobal() or this.getMethodName() = "replaceAll" }
/**
* Holds if this call to `replace` replaces `old` with `new`.
*/
predicate replaces(string old, string new) {
exists(string rawNew |
old = getAReplacedString() and
getRawReplacement().mayHaveStringValue(rawNew) and
old = this.getAReplacedString() and
this.getRawReplacement().mayHaveStringValue(rawNew) and
new = rawNew.replaceAll("$&", old)
)
or
exists(DataFlow::FunctionNode replacer, DataFlow::PropRead pr, DataFlow::ObjectLiteralNode map |
replacer = getCallback(1) and
replacer = this.getCallback(1) and
replacer.getParameter(0).flowsToExpr(pr.getPropertyNameExpr()) and
pr = map.getAPropertyRead() and
pr.flowsTo(replacer.getAReturn()) and
@@ -143,7 +143,7 @@ class StringReplaceCall extends DataFlow::MethodCallNode {
DataFlow::FunctionNode replacer, ConditionGuardNode guard, EqualityTest test,
DataFlow::Node ret
|
replacer = getCallback(1) and
replacer = this.getCallback(1) and
guard.getOutcome() = test.getPolarity() and
guard.getTest() = test and
replacer.getParameter(0).flowsToExpr(test.getAnOperand()) and
@@ -164,27 +164,31 @@ class StringReplaceCall extends DataFlow::MethodCallNode {
class StringSplitCall extends DataFlow::MethodCallNode {
StringSplitCall() {
this.getMethodName() = "split" and
(getNumArgument() = [1, 2] or getReceiver().mayHaveStringValue(_))
(this.getNumArgument() = [1, 2] or this.getReceiver().mayHaveStringValue(_))
}
/**
* Gets a string that determines where the string is split.
*/
string getSeparator() {
getArgument(0).mayHaveStringValue(result)
this.getArgument(0).mayHaveStringValue(result)
or
result =
getArgument(0).getALocalSource().(DataFlow::RegExpCreationNode).getRoot().getAMatchedString()
this.getArgument(0)
.getALocalSource()
.(DataFlow::RegExpCreationNode)
.getRoot()
.getAMatchedString()
}
/**
* Gets the DataFlow::Node for the base string that is split.
*/
DataFlow::Node getBaseString() { result = getReceiver() }
DataFlow::Node getBaseString() { result = this.getReceiver() }
/**
* Gets a read of the `i`th element from the split string.
*/
bindingset[i]
DataFlow::Node getASubstringRead(int i) { result = getAPropertyRead(i.toString()) }
DataFlow::Node getASubstringRead(int i) { result = this.getAPropertyRead(i.toString()) }
}

View File

@@ -20,8 +20,8 @@ import javascript
class Stmt extends @stmt, ExprOrStmt, Documentable {
/** Holds if this statement has an implicitly inserted semicolon. */
predicate hasSemicolonInserted() {
isSubjectToSemicolonInsertion() and
getLastToken().getValue() != ";"
this.isSubjectToSemicolonInsertion() and
this.getLastToken().getValue() != ";"
}
/** Holds if automatic semicolon insertion applies to this statement. */
@@ -47,8 +47,8 @@ class Stmt extends @stmt, ExprOrStmt, Documentable {
* Holds if this statement is lexically nested inside statement `outer`.
*/
predicate nestedIn(Stmt outer) {
outer = getParentStmt+() or
getContainer().(Expr).getEnclosingStmt().nestedIn(outer)
outer = this.getParentStmt+() or
this.getContainer().(Expr).getEnclosingStmt().nestedIn(outer)
}
/**
@@ -56,10 +56,10 @@ class Stmt extends @stmt, ExprOrStmt, Documentable {
* crossing function boundaries or other `try ` statements with catch blocks.
*/
TryStmt getEnclosingTryCatchStmt() {
getParentStmt+() = result.getBody() and
this.getParentStmt+() = result.getBody() and
exists(result.getACatchClause()) and
not exists(TryStmt mid | exists(mid.getACatchClause()) |
getParentStmt+() = mid.getBody() and mid.getParentStmt+() = result.getBody()
this.getParentStmt+() = mid.getBody() and mid.getParentStmt+() = result.getBody()
)
}
}
@@ -116,7 +116,7 @@ class LoopStmt extends TLoopStmt, ControlStmt {
/** Gets the loop test of this loop. */
abstract Expr getTest();
override Stmt getAControlledStmt() { result = getBody() }
override Stmt getAControlledStmt() { result = this.getBody() }
}
/**
@@ -145,13 +145,13 @@ class EmptyStmt extends @empty_stmt, Stmt {
*/
class BlockStmt extends @block_stmt, Stmt {
/** Gets the `i`th statement in this block. */
Stmt getStmt(int i) { result = getChildStmt(i) }
Stmt getStmt(int i) { result = this.getChildStmt(i) }
/** Gets a statement in this block. */
Stmt getAStmt() { result = getStmt(_) }
Stmt getAStmt() { result = this.getStmt(_) }
/** Gets the number of statements in this block. */
int getNumStmt() { result = count(getAStmt()) }
int getNumStmt() { result = count(this.getAStmt()) }
/** Holds if this block is a function body. */
predicate isFunctionBody() { this.getParent() instanceof Function }
@@ -171,9 +171,9 @@ class BlockStmt extends @block_stmt, Stmt {
*/
class ExprStmt extends @expr_stmt, Stmt {
/** Gets the expression of this expression statement. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
override predicate isSubjectToSemicolonInsertion() { not isDoubleColonMethod(_, _, _) }
override predicate isSubjectToSemicolonInsertion() { not this.isDoubleColonMethod(_, _, _) }
/**
* Holds if this expression statement is a JScript-style double colon method declaration.
@@ -182,7 +182,7 @@ class ExprStmt extends @expr_stmt, Stmt {
// the parser converts double colon method declarations into assignments, but we
// can consult token-level information to identify them
exists(Assignment assgn, DotExpr dot, Token tk |
assgn = getExpr() and
assgn = this.getExpr() and
dot = assgn.getLhs() and
interface = dot.getBase() and
// check if the interface name is followed by two colons
@@ -205,7 +205,7 @@ class ExprStmt extends @expr_stmt, Stmt {
* be a directive).
*/
private class MaybeDirective extends ExprStmt {
MaybeDirective() { getExpr() instanceof StringLiteral }
MaybeDirective() { this.getExpr() instanceof StringLiteral }
/**
* Gets the raw text of the string literal wrapped by this statement.
@@ -228,7 +228,7 @@ private class MaybeDirective extends ExprStmt {
* string literal is the same as in the former case.)
*/
string getDirectiveText() {
exists(string text | text = getExpr().(StringLiteral).getRawValue() |
exists(string text | text = this.getExpr().(StringLiteral).getRawValue() |
result = text.substring(1, text.length() - 1)
)
}
@@ -279,7 +279,7 @@ abstract class KnownDirective extends Directive { }
* ```
*/
class StrictModeDecl extends KnownDirective {
StrictModeDecl() { getDirectiveText() = "use strict" }
StrictModeDecl() { this.getDirectiveText() = "use strict" }
}
/**
@@ -292,7 +292,7 @@ class StrictModeDecl extends KnownDirective {
* ```
*/
class ASMJSDirective extends KnownDirective {
ASMJSDirective() { getDirectiveText() = "use asm" }
ASMJSDirective() { this.getDirectiveText() = "use asm" }
}
/**
@@ -305,7 +305,7 @@ class ASMJSDirective extends KnownDirective {
* ```
*/
class BabelDirective extends KnownDirective {
BabelDirective() { getDirectiveText() = "use babel" }
BabelDirective() { this.getDirectiveText() = "use babel" }
}
/**
@@ -318,7 +318,7 @@ class BabelDirective extends KnownDirective {
* ```
*/
class SixToFiveDirective extends KnownDirective {
SixToFiveDirective() { getDirectiveText() = "use 6to5" }
SixToFiveDirective() { this.getDirectiveText() = "use 6to5" }
}
/**
@@ -331,7 +331,9 @@ class SixToFiveDirective extends KnownDirective {
* ```
*/
class SystemJSFormatDirective extends KnownDirective {
SystemJSFormatDirective() { getDirectiveText().regexpMatch("format (cjs|esm|global|register)") }
SystemJSFormatDirective() {
this.getDirectiveText().regexpMatch("format (cjs|esm|global|register)")
}
}
/**
@@ -344,7 +346,7 @@ class SystemJSFormatDirective extends KnownDirective {
* ```
*/
class FormatRegisterDirective extends SystemJSFormatDirective {
FormatRegisterDirective() { getDirectiveText() = "format register" }
FormatRegisterDirective() { this.getDirectiveText() = "format register" }
}
/**
@@ -357,7 +359,7 @@ class FormatRegisterDirective extends SystemJSFormatDirective {
* ```
*/
class NgInjectDirective extends KnownDirective {
NgInjectDirective() { getDirectiveText().regexpMatch("ng(No)?Inject") }
NgInjectDirective() { this.getDirectiveText().regexpMatch("ng(No)?Inject") }
}
/**
@@ -370,7 +372,9 @@ class NgInjectDirective extends KnownDirective {
* ```
*/
class YuiDirective extends KnownDirective {
YuiDirective() { getDirectiveText().regexpMatch("([a-z0-9_]+:nomunge, ?)*([a-z0-9_]+:nomunge)") }
YuiDirective() {
this.getDirectiveText().regexpMatch("([a-z0-9_]+:nomunge, ?)*([a-z0-9_]+:nomunge)")
}
}
/**
@@ -383,7 +387,7 @@ class YuiDirective extends KnownDirective {
* ```
*/
class SystemJSDepsDirective extends KnownDirective {
SystemJSDepsDirective() { getDirectiveText().regexpMatch("deps [^ ]+") }
SystemJSDepsDirective() { this.getDirectiveText().regexpMatch("deps [^ ]+") }
}
/**
@@ -396,7 +400,7 @@ class SystemJSDepsDirective extends KnownDirective {
* ```
*/
class BundleDirective extends KnownDirective {
BundleDirective() { getDirectiveText() = "bundle" }
BundleDirective() { this.getDirectiveText() = "bundle" }
}
/**
@@ -414,26 +418,26 @@ class BundleDirective extends KnownDirective {
*/
class IfStmt extends @if_stmt, ControlStmt {
/** Gets the condition of this `if` statement. */
Expr getCondition() { result = getChildExpr(0) }
Expr getCondition() { result = this.getChildExpr(0) }
/** Gets the "then" branch of this `if` statement. */
Stmt getThen() { result = getChildStmt(1) }
Stmt getThen() { result = this.getChildStmt(1) }
/** Gets the "else" branch of this `if` statement, if any. */
Stmt getElse() { result = getChildStmt(2) }
Stmt getElse() { result = this.getChildStmt(2) }
/** Gets the `if` token of this `if` statement. */
KeywordToken getIfToken() { result = getFirstToken() }
KeywordToken getIfToken() { result = this.getFirstToken() }
/** Gets the `else` token of this `if` statement, if any. */
KeywordToken getElseToken() {
result = getThen().getLastToken().getNextToken() and
result.getIndex() < getLastToken().getIndex()
result = this.getThen().getLastToken().getNextToken() and
result.getIndex() < this.getLastToken().getIndex()
}
override Stmt getAControlledStmt() {
result = getThen() or
result = getElse()
result = this.getThen() or
result = this.getElse()
}
/** Holds if this `if` statement is an `else if` of an outer `if` statement. */
@@ -459,10 +463,10 @@ class IfStmt extends @if_stmt, ControlStmt {
*/
class LabeledStmt extends @labeled_stmt, Stmt {
/** Gets the label of this statement. */
string getLabel() { result = getChildExpr(0).(Identifier).getName() }
string getLabel() { result = this.getChildExpr(0).(Identifier).getName() }
/** Gets the labeled statement of this statement. */
Stmt getStmt() { result = getChildStmt(1) }
Stmt getStmt() { result = this.getChildStmt(1) }
override string getAPrimaryQlClass() { result = "LabeledStmt" }
}
@@ -513,10 +517,10 @@ class JumpStmt extends TJumpStmt, Stmt {
*/
class BreakOrContinueStmt extends TBreakOrContinueStmt, JumpStmt {
/** Gets the label this statement refers to, if any. */
string getTargetLabel() { result = getChildExpr(0).(Identifier).getName() }
string getTargetLabel() { result = this.getChildExpr(0).(Identifier).getName() }
/** Holds if this statement has an explicit target label. */
predicate hasTargetLabel() { exists(getTargetLabel()) }
predicate hasTargetLabel() { exists(this.getTargetLabel()) }
/** Gets the statement this statement breaks out of or continues with. */
override Stmt getTarget() { jump_targets(this, result) }
@@ -565,25 +569,27 @@ class ContinueStmt extends @continue_stmt, BreakOrContinueStmt {
*/
class WithStmt extends @with_stmt, ControlStmt {
/** Gets the controlling expression of this `with` statement. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
/** Gets the body of this `with` statement. */
Stmt getBody() { result = getChildStmt(1) }
Stmt getBody() { result = this.getChildStmt(1) }
/**
* Holds if `acc` could refer to a property of the scope object
* introduced by this `with` statement.
*/
predicate mayAffect(VarAccess acc) {
acc.getEnclosingStmt().nestedIn(getBody()) and
acc.getEnclosingStmt().nestedIn(this.getBody()) and
exists(Variable v | v = acc.getVariable() |
v instanceof GlobalVariable
or
exists(ASTNode scopeElt | scopeElt = v.getScope().getScopeElement() | scopeElt = getParent+())
exists(ASTNode scopeElt | scopeElt = v.getScope().getScopeElement() |
scopeElt = this.getParent+()
)
)
}
override Stmt getAControlledStmt() { result = getBody() }
override Stmt getAControlledStmt() { result = this.getBody() }
override string getAPrimaryQlClass() { result = "WithStmt" }
}
@@ -608,18 +614,18 @@ class WithStmt extends @with_stmt, ControlStmt {
*/
class SwitchStmt extends @switch_stmt, ControlStmt {
/** Gets the controlling expression of this `switch` statement. */
Expr getExpr() { result = getChildExpr(-1) }
Expr getExpr() { result = this.getChildExpr(-1) }
/** Gets the `i`th `case` clause of this `switch` statement. */
Case getCase(int i) { result = getChildStmt(i) }
Case getCase(int i) { result = this.getChildStmt(i) }
/** Gets a `case` clause of this `switch` statement. */
Case getACase() { result = getCase(_) }
Case getACase() { result = this.getCase(_) }
/** Gets the number of `case` clauses of this `switch` statement. */
int getNumCase() { result = count(getACase()) }
int getNumCase() { result = count(this.getACase()) }
override Case getAControlledStmt() { result = getACase() }
override Case getAControlledStmt() { result = this.getACase() }
override string getAPrimaryQlClass() { result = "SwitchStmt" }
}
@@ -636,13 +642,15 @@ class SwitchStmt extends @switch_stmt, ControlStmt {
*/
class ReturnStmt extends @return_stmt, JumpStmt {
/** Gets the expression specifying the returned value, if any. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
/** Gets the target of this `return` statement, which is the enclosing statement container. */
override Function getTarget() { result = getContainer() }
override Function getTarget() { result = this.getContainer() }
override ControlFlowNode getFirstControlFlowNode() {
if exists(getExpr()) then result = getExpr().getFirstControlFlowNode() else result = this
if exists(this.getExpr())
then result = this.getExpr().getFirstControlFlowNode()
else result = this
}
override predicate isSubjectToSemicolonInsertion() { any() }
@@ -661,7 +669,7 @@ class ReturnStmt extends @return_stmt, JumpStmt {
*/
class ThrowStmt extends @throw_stmt, JumpStmt {
/** Gets the expression specifying the value to throw. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
/**
* Gets the target of this `throw` statement, which is the closest surrounding
@@ -669,15 +677,17 @@ class ThrowStmt extends @throw_stmt, JumpStmt {
* `try` statement, the target defaults to the enclosing statement container.
*/
override ASTNode getTarget() {
if exists(TryStmt ts | getParentStmt+() = ts.getBody())
if exists(TryStmt ts | this.getParentStmt+() = ts.getBody())
then
getParentStmt+() = result.(TryStmt).getBody() and
not exists(TryStmt mid | getParentStmt+() = mid.getBody() and mid.getParentStmt+() = result)
else result = getContainer()
this.getParentStmt+() = result.(TryStmt).getBody() and
not exists(TryStmt mid |
this.getParentStmt+() = mid.getBody() and mid.getParentStmt+() = result
)
else result = this.getContainer()
}
override ControlFlowNode getFirstControlFlowNode() {
result = getExpr().getFirstControlFlowNode()
result = this.getExpr().getFirstControlFlowNode()
}
override predicate isSubjectToSemicolonInsertion() { any() }
@@ -701,37 +711,37 @@ class ThrowStmt extends @throw_stmt, JumpStmt {
*/
class TryStmt extends @try_stmt, ControlStmt {
/** Gets the body of this `try` statement. */
BlockStmt getBody() { result = getChildStmt(0) }
BlockStmt getBody() { result = this.getChildStmt(0) }
override Stmt getAControlledStmt() {
result = getBody() or
result = getACatchClause() or
result = getFinally()
result = this.getBody() or
result = this.getACatchClause() or
result = this.getFinally()
}
/** Gets the `i`th `catch` clause of this `try` statement, if any. */
CatchClause getCatchClause(int i) {
exists(int idx |
result = getChildStmt(idx) and
result = this.getChildStmt(idx) and
idx >= 1 and
i = idx - 1
)
}
/** Gets a `catch` clause of this `try` statement. */
CatchClause getACatchClause() { result = getCatchClause(_) }
CatchClause getACatchClause() { result = this.getCatchClause(_) }
/** Gets the (unique) unguarded `catch` clause of this `try` statement, if any. */
CatchClause getCatchClause() {
result = getACatchClause() and
result = this.getACatchClause() and
not exists(result.getGuard())
}
/** Gets the number of `catch` clauses of this `try` statement. */
int getNumCatchClause() { result = count(getACatchClause()) }
int getNumCatchClause() { result = count(this.getACatchClause()) }
/** Gets the `finally` block of this `try` statement, if any. */
BlockStmt getFinally() { result = getChildStmt(-1) }
BlockStmt getFinally() { result = this.getChildStmt(-1) }
override string getAPrimaryQlClass() { result = "TryStmt" }
}
@@ -749,11 +759,11 @@ class TryStmt extends @try_stmt, ControlStmt {
*/
class WhileStmt extends @while_stmt, LoopStmt {
/** Gets the loop condition of this `while` loop. */
Expr getExpr() { result = getChildExpr(0) }
Expr getExpr() { result = this.getChildExpr(0) }
override Expr getTest() { result = getExpr() }
override Expr getTest() { result = this.getExpr() }
override Stmt getBody() { result = getChildStmt(1) }
override Stmt getBody() { result = this.getChildStmt(1) }
override string getAPrimaryQlClass() { result = "WhileStmt" }
}
@@ -771,11 +781,11 @@ class WhileStmt extends @while_stmt, LoopStmt {
*/
class DoWhileStmt extends @do_while_stmt, LoopStmt {
/** Gets the loop condition of this `do`-`while` loop. */
Expr getExpr() { result = getChildExpr(1) }
Expr getExpr() { result = this.getChildExpr(1) }
override Expr getTest() { result = getExpr() }
override Expr getTest() { result = this.getExpr() }
override Stmt getBody() { result = getChildStmt(0) }
override Stmt getBody() { result = this.getChildStmt(0) }
override predicate isSubjectToSemicolonInsertion() { any() }
@@ -813,16 +823,16 @@ class ExprOrVarDecl extends ASTNode {
class ForStmt extends @for_stmt, LoopStmt {
/** Gets the init part of this `for` loop. */
ExprOrVarDecl getInit() {
result = getChildExpr(0) or
result = getChildStmt(0)
result = this.getChildExpr(0) or
result = this.getChildStmt(0)
}
override Expr getTest() { result = getChildExpr(1) }
override Expr getTest() { result = this.getChildExpr(1) }
/** Gets the update part of this `for` loop. */
Expr getUpdate() { result = getChildExpr(2) }
Expr getUpdate() { result = this.getChildExpr(2) }
override Stmt getBody() { result = getChildStmt(3) }
override Stmt getBody() { result = this.getChildStmt(3) }
override string getAPrimaryQlClass() { result = "ForStmt" }
}
@@ -848,22 +858,22 @@ class EnhancedForLoop extends TEnhancedForLoop, LoopStmt {
* pattern, a property reference, or a variable declaration statement.
*/
ExprOrVarDecl getIterator() {
result = getChildExpr(0) or
result = getChildStmt(0)
result = this.getChildExpr(0) or
result = this.getChildStmt(0)
}
/**
* Gets the default value of the loop's iterator, if any.
*/
Expr getDefault() { result = getChildExpr(-1) }
Expr getDefault() { result = this.getChildExpr(-1) }
/**
* Gets the iterator expression of this `for`-`in` or `for`-`of` loop; this can be
* either a variable access or a variable declarator.
*/
Expr getIteratorExpr() {
result = getIterator() or
result = getIterator().(DeclStmt).getADecl()
result = this.getIterator() or
result = this.getIterator().(DeclStmt).getADecl()
}
/**
@@ -871,29 +881,29 @@ class EnhancedForLoop extends TEnhancedForLoop, LoopStmt {
* expression in this `for`-`in` or `for`-`of` loop.
*/
Expr getLValue() {
result = getIterator() and
result = this.getIterator() and
(result instanceof BindingPattern or result instanceof PropAccess)
or
result = getIterator().(DeclStmt).getADecl().getBindingPattern()
result = this.getIterator().(DeclStmt).getADecl().getBindingPattern()
}
/**
* Gets an iterator variable of this `for`-`in` or `for`-`of` loop.
*/
Variable getAnIterationVariable() {
result = getIterator().(DeclStmt).getADecl().getBindingPattern().getAVariable() or
result = getIterator().(BindingPattern).getAVariable()
result = this.getIterator().(DeclStmt).getADecl().getBindingPattern().getAVariable() or
result = this.getIterator().(BindingPattern).getAVariable()
}
override Expr getTest() { none() }
/** Gets the expression this `for`-`in` or `for`-`of` loop iterates over. */
Expr getIterationDomain() { result = getChildExpr(1) }
Expr getIterationDomain() { result = this.getChildExpr(1) }
override Stmt getBody() { result = getChildStmt(2) }
override Stmt getBody() { result = this.getChildStmt(2) }
override ControlFlowNode getFirstControlFlowNode() {
result = getIteratorExpr().getFirstControlFlowNode()
result = this.getIteratorExpr().getFirstControlFlowNode()
}
}
@@ -993,10 +1003,10 @@ class FunctionDeclStmt extends @function_decl_stmt, Stmt, Function {
*/
class DeclStmt extends @decl_stmt, Stmt {
/** Gets the `i`th declarator in this declaration statement. */
VariableDeclarator getDecl(int i) { result = getChildExpr(i) and i >= 0 }
VariableDeclarator getDecl(int i) { result = this.getChildExpr(i) and i >= 0 }
/** Gets a declarator in this declaration statement. */
VariableDeclarator getADecl() { result = getDecl(_) }
VariableDeclarator getADecl() { result = this.getDecl(_) }
override predicate isSubjectToSemicolonInsertion() {
// exclude variable declarations in the init part of for/for-in/for-of loops
@@ -1052,7 +1062,7 @@ class LetStmt extends @let_stmt, DeclStmt { }
*/
class LegacyLetStmt extends @legacy_let_stmt, DeclStmt {
/** Gets the statement this let statement scopes over. */
Stmt getBody() { result = getChildStmt(-1) }
Stmt getBody() { result = this.getChildStmt(-1) }
override predicate isSubjectToSemicolonInsertion() { none() }
}
@@ -1069,22 +1079,22 @@ class LegacyLetStmt extends @legacy_let_stmt, DeclStmt {
*/
class Case extends @case, Stmt {
/** Gets the test expression of this `case` clause. */
Expr getExpr() { result = getChildExpr(-1) }
Expr getExpr() { result = this.getChildExpr(-1) }
/** Holds if this is a `default` clause. */
predicate isDefault() { not exists(getExpr()) }
predicate isDefault() { not exists(this.getExpr()) }
/** Gets the `i`th statement in this `case` clause. */
Stmt getBodyStmt(int i) { result = getChildStmt(i) }
Stmt getBodyStmt(int i) { result = this.getChildStmt(i) }
/** Gets a statement in this `case` clause. */
Stmt getABodyStmt() { result = getChildStmt(_) }
Stmt getABodyStmt() { result = this.getChildStmt(_) }
/** Gets the number of statements in this `case` clause. */
int getNumBodyStmt() { result = count(getABodyStmt()) }
int getNumBodyStmt() { result = count(this.getABodyStmt()) }
/** Gets the `switch` statement to which this clause belongs. */
SwitchStmt getSwitch() { result = getParent() }
SwitchStmt getSwitch() { result = this.getParent() }
override string getAPrimaryQlClass() { result = "Case" }
}
@@ -1102,12 +1112,12 @@ class Case extends @case, Stmt {
*/
class CatchClause extends @catch_clause, ControlStmt, Parameterized {
/** Gets the body of this `catch` clause. */
BlockStmt getBody() { result = getChildStmt(1) }
BlockStmt getBody() { result = this.getChildStmt(1) }
/** Gets the guard expression of this `catch` clause, if any. */
Expr getGuard() { result = getChildExpr(2) }
Expr getGuard() { result = this.getChildExpr(2) }
override Stmt getAControlledStmt() { result = getBody() }
override Stmt getAControlledStmt() { result = this.getBody() }
/** Gets the scope induced by this `catch` clause. */
CatchScope getScope() { result.getCatchClause() = this }

View File

@@ -89,13 +89,13 @@ module StringOps {
*/
private class StartsWith_Native extends Range, DataFlow::MethodCallNode {
StartsWith_Native() {
getMethodName() = "startsWith" and
getNumArgument() = 1
this.getMethodName() = "startsWith" and
this.getNumArgument() = 1
}
override DataFlow::Node getBaseString() { result = getReceiver() }
override DataFlow::Node getBaseString() { result = this.getReceiver() }
override DataFlow::Node getSubstring() { result = getArgument(0) }
override DataFlow::Node getSubstring() { result = this.getArgument(0) }
}
/**
@@ -126,14 +126,14 @@ module StringOps {
*/
private class StartsWith_IndexOfCoercion extends Range, DataFlow::MethodCallNode {
StartsWith_IndexOfCoercion() {
getMethodName() = "indexOf" and
getNumArgument() = 1 and
this.getMethodName() = "indexOf" and
this.getNumArgument() = 1 and
this.flowsToExpr(any(ConditionGuardNode guard).getTest()) // check for boolean coercion
}
override DataFlow::Node getBaseString() { result = getReceiver() }
override DataFlow::Node getBaseString() { result = this.getReceiver() }
override DataFlow::Node getSubstring() { result = getArgument(0) }
override DataFlow::Node getSubstring() { result = this.getArgument(0) }
override boolean getPolarity() { result = false }
}
@@ -143,7 +143,7 @@ module StringOps {
*/
private class StartsWith_Library extends Range, DataFlow::CallNode {
StartsWith_Library() {
getNumArgument() = 2 and
this.getNumArgument() = 2 and
exists(DataFlow::SourceNode callee | this = callee.getACall() |
callee = LodashUnderscore::member("startsWith")
or
@@ -156,9 +156,9 @@ module StringOps {
)
}
override DataFlow::Node getBaseString() { result = getArgument(0) }
override DataFlow::Node getBaseString() { result = this.getArgument(0) }
override DataFlow::Node getSubstring() { result = getArgument(1) }
override DataFlow::Node getSubstring() { result = this.getArgument(1) }
}
/**
@@ -224,10 +224,10 @@ module StringOps {
*/
class Includes extends InclusionTest {
/** Gets the `A` in `A.includes(B)`. */
DataFlow::Node getBaseString() { result = getContainerNode() }
DataFlow::Node getBaseString() { result = this.getContainerNode() }
/** Gets the `B` in `A.includes(B)`. */
DataFlow::Node getSubstring() { result = getContainedNode() }
DataFlow::Node getSubstring() { result = this.getContainedNode() }
}
/**
@@ -314,13 +314,13 @@ module StringOps {
*/
private class EndsWith_Native extends Range, DataFlow::MethodCallNode {
EndsWith_Native() {
getMethodName() = "endsWith" and
getNumArgument() = 1
this.getMethodName() = "endsWith" and
this.getNumArgument() = 1
}
override DataFlow::Node getBaseString() { result = getReceiver() }
override DataFlow::Node getBaseString() { result = this.getReceiver() }
override DataFlow::Node getSubstring() { result = getArgument(0) }
override DataFlow::Node getSubstring() { result = this.getArgument(0) }
}
/**
@@ -328,7 +328,7 @@ module StringOps {
*/
private class EndsWith_Library extends Range, DataFlow::CallNode {
EndsWith_Library() {
getNumArgument() = 2 and
this.getNumArgument() = 2 and
exists(DataFlow::SourceNode callee | this = callee.getACall() |
callee = LodashUnderscore::member("endsWith")
or
@@ -341,9 +341,9 @@ module StringOps {
)
}
override DataFlow::Node getBaseString() { result = getArgument(0) }
override DataFlow::Node getBaseString() { result = this.getArgument(0) }
override DataFlow::Node getSubstring() { result = getArgument(1) }
override DataFlow::Node getSubstring() { result = this.getArgument(1) }
}
}
@@ -542,7 +542,7 @@ module StringOps {
*/
class ConcatenationRoot extends Concatenation {
pragma[inline]
ConcatenationRoot() { isRoot() }
ConcatenationRoot() { this.isRoot() }
/**
* Gets a leaf in this concatenation tree that this node is the root of.
@@ -561,9 +561,9 @@ module StringOps {
* the result is `"Hello , how are you?"`
*/
string getConstantStringParts() {
result = getStringValue()
result = this.getStringValue()
or
not exists(getStringValue()) and
not exists(this.getStringValue()) and
result =
strictconcat(StringLiteralLike leaf |
leaf = this.(SmallConcatenationRoot).getALeaf().asExpr()
@@ -581,7 +581,7 @@ module StringOps {
*/
private class SmallConcatenationRoot extends ConcatenationRoot {
SmallConcatenationRoot() {
sum(StringLiteralLike leaf | leaf = getALeaf().asExpr() | leaf.getStringValue().length()) <
sum(StringLiteralLike leaf | leaf = this.getALeaf().asExpr() | leaf.getStringValue().length()) <
1000 * 1000
}
}
@@ -607,7 +607,7 @@ module StringOps {
*/
class ConcatenationLeaf extends ConcatenationOperand {
pragma[inline]
ConcatenationLeaf() { isLeaf() }
ConcatenationLeaf() { this.isLeaf() }
}
/**
@@ -616,7 +616,7 @@ module StringOps {
class HtmlConcatenationRoot extends ConcatenationRoot {
pragma[noinline]
HtmlConcatenationRoot() {
getConstantStringParts().regexpMatch("(?s).*</?[a-zA-Z][^\\r\\n<>/]*/?>.*")
this.getConstantStringParts().regexpMatch("(?s).*</?[a-zA-Z][^\\r\\n<>/]*/?>.*")
}
}
@@ -624,7 +624,7 @@ module StringOps {
* A data flow node that is part of an HTML string concatenation.
*/
class HtmlConcatenationNode extends ConcatenationNode {
HtmlConcatenationNode() { getRoot() instanceof HtmlConcatenationRoot }
HtmlConcatenationNode() { this.getRoot() instanceof HtmlConcatenationRoot }
}
/**
@@ -632,7 +632,7 @@ module StringOps {
* and is not itself a concatenation operator.
*/
class HtmlConcatenationLeaf extends ConcatenationLeaf {
HtmlConcatenationLeaf() { getRoot() instanceof HtmlConcatenationRoot }
HtmlConcatenationLeaf() { this.getRoot() instanceof HtmlConcatenationRoot }
}
/**
@@ -659,7 +659,7 @@ module StringOps {
* Gets the AST of the regular expression used in the test, if it can be seen locally.
*/
RegExpTerm getRegExp() {
result = getRegExpOperand().getALocalSource().(DataFlow::RegExpCreationNode).getRoot()
result = this.getRegExpOperand().getALocalSource().(DataFlow::RegExpCreationNode).getRoot()
or
result = super.getRegExpOperand(true).asExpr().(StringLiteral).asRegExp()
}
@@ -712,21 +712,21 @@ module StringOps {
}
private class TestCall extends Range, DataFlow::MethodCallNode {
TestCall() { getMethodName() = "test" }
TestCall() { this.getMethodName() = "test" }
override DataFlow::Node getRegExpOperand(boolean coerced) {
result = getReceiver() and coerced = false
result = this.getReceiver() and coerced = false
}
override DataFlow::Node getStringOperand() { result = getArgument(0) }
override DataFlow::Node getStringOperand() { result = this.getArgument(0) }
}
private class MatchCall extends DataFlow::MethodCallNode {
MatchCall() { getMethodName() = "match" }
MatchCall() { this.getMethodName() = "match" }
}
private class ExecCall extends DataFlow::MethodCallNode {
ExecCall() { getMethodName() = "exec" }
ExecCall() { this.getMethodName() = "exec" }
}
private predicate isCoercedToBoolean(Expr e) {

View File

@@ -37,7 +37,7 @@ class Token extends Locatable, @token {
/** Gets the token preceding this token inside the same toplevel structure, if any. */
Token getPreviousToken() { result.getNextToken() = this }
override string toString() { result = getValue() }
override string toString() { result = this.getValue() }
}
/** An end-of-file token. */

File diff suppressed because it is too large Load Diff

View File

@@ -17,14 +17,14 @@ class Scope extends @scope {
ASTNode getScopeElement() { scopenodes(result, this) }
/** Gets the location of the program element this scope is associated with, if any. */
Location getLocation() { result = getScopeElement().getLocation() }
Location getLocation() { result = this.getScopeElement().getLocation() }
/** Gets a variable declared in this scope. */
Variable getAVariable() { result.getScope() = this }
/** Gets the variable with the given name declared in this scope. */
Variable getVariable(string name) {
result = getAVariable() and
result = this.getAVariable() and
result.getName() = name
}
}
@@ -56,7 +56,7 @@ class LocalScope extends Scope {
*/
class ModuleScope extends Scope, @module_scope {
/** Gets the module that induces this scope. */
Module getModule() { result = getScopeElement() }
Module getModule() { result = this.getScopeElement() }
override string toString() { result = "module scope" }
}
@@ -64,7 +64,7 @@ class ModuleScope extends Scope, @module_scope {
/** A scope induced by a function. */
class FunctionScope extends Scope, @function_scope {
/** Gets the function that induces this scope. */
Function getFunction() { result = getScopeElement() }
Function getFunction() { result = this.getScopeElement() }
override string toString() { result = "function scope" }
}
@@ -72,7 +72,7 @@ class FunctionScope extends Scope, @function_scope {
/** A scope induced by a catch clause. */
class CatchScope extends Scope, @catch_scope {
/** Gets the catch clause that induces this scope. */
CatchClause getCatchClause() { result = getScopeElement() }
CatchClause getCatchClause() { result = this.getScopeElement() }
override string toString() { result = "catch scope" }
}
@@ -80,7 +80,7 @@ class CatchScope extends Scope, @catch_scope {
/** A scope induced by a block of statements. */
class BlockScope extends Scope, @block_scope {
/** Gets the block of statements that induces this scope. */
BlockStmt getBlock() { result = getScopeElement() }
BlockStmt getBlock() { result = this.getScopeElement() }
override string toString() { result = "block scope" }
}
@@ -88,7 +88,7 @@ class BlockScope extends Scope, @block_scope {
/** A scope induced by a `for` statement. */
class ForScope extends Scope, @for_scope {
/** Gets the `for` statement that induces this scope. */
ForStmt getLoop() { result = getScopeElement() }
ForStmt getLoop() { result = this.getScopeElement() }
override string toString() { result = "for scope" }
}
@@ -96,7 +96,7 @@ class ForScope extends Scope, @for_scope {
/** A scope induced by a `for`-`in` or `for`-`of` statement. */
class ForInScope extends Scope, @for_in_scope {
/** Gets the `for`-`in` or `for`-`of` statement that induces this scope. */
EnhancedForLoop getLoop() { result = getScopeElement() }
EnhancedForLoop getLoop() { result = this.getScopeElement() }
override string toString() { result = "for-in scope" }
}
@@ -104,7 +104,7 @@ class ForInScope extends Scope, @for_in_scope {
/** A scope induced by a comprehension block. */
class ComprehensionBlockScope extends Scope, @comprehension_block_scope {
/** Gets the comprehension block that induces this scope. */
ComprehensionBlock getComprehensionBlock() { result = getScopeElement() }
ComprehensionBlock getComprehensionBlock() { result = this.getScopeElement() }
override string toString() { result = "comprehension block scope" }
}
@@ -129,7 +129,7 @@ class Variable extends @variable, LexicalName {
override Scope getScope() { variables(this, _, result) }
/** Holds if this is a global variable. */
predicate isGlobal() { getScope() instanceof GlobalScope }
predicate isGlobal() { this.getScope() instanceof GlobalScope }
/**
* Holds if this is a variable exported from a TypeScript namespace.
@@ -137,7 +137,7 @@ class Variable extends @variable, LexicalName {
* Note that such variables are also considered local for the time being.
*/
predicate isNamespaceExport() {
getScope() instanceof NamespaceScope and
this.getScope() instanceof NamespaceScope and
exists(ExportNamedDeclaration decl | decl.getADecl().getVariable() = this)
}
@@ -146,7 +146,7 @@ class Variable extends @variable, LexicalName {
*
* Parameters and `arguments` variables are considered to be local.
*/
predicate isLocal() { not isGlobal() }
predicate isLocal() { not this.isGlobal() }
/** Holds if this variable is a parameter. */
predicate isParameter() { exists(Parameter p | p.getAVariable() = this) }
@@ -179,7 +179,7 @@ class Variable extends @variable, LexicalName {
exists(FunctionExpr fn | fn.getVariable() = this | result = fn)
or
// there is an assignment to this variable
exists(Assignment assgn | assgn.getLhs() = getAnAccess() and assgn.getRhs() = result)
exists(Assignment assgn | assgn.getLhs() = this.getAnAccess() and assgn.getRhs() = result)
}
/**
@@ -189,15 +189,15 @@ class Variable extends @variable, LexicalName {
*/
predicate isCaptured() {
this instanceof GlobalVariable or
getAnAccess().getContainer().getFunctionBoundary() !=
this.getAnAccess().getContainer().getFunctionBoundary() !=
this.(LocalVariable).getDeclaringContainer().getFunctionBoundary()
}
/** Holds if there is a declaration of this variable in `tl`. */
predicate declaredIn(TopLevel tl) { getADeclaration().getTopLevel() = tl }
predicate declaredIn(TopLevel tl) { this.getADeclaration().getTopLevel() = tl }
/** Gets a textual representation of this element. */
override string toString() { result = getName() }
override string toString() { result = this.getName() }
override DeclarationSpace getDeclarationSpace() { result = "variable" }
}
@@ -209,7 +209,7 @@ class ArgumentsVariable extends Variable {
override FunctionScope getScope() { result = Variable.super.getScope() }
/** Gets the function declaring this 'arguments' variable. */
Function getFunction() { result = getScope().getFunction() }
Function getFunction() { result = this.getScope().getFunction() }
}
/**
@@ -270,7 +270,7 @@ class VarAccess extends @varaccess, VarRef, LexicalAccess {
exists(BindingPattern p | this = p.getABindingVarRef() and p.isLValue())
}
override Variable getAVariable() { result = getVariable() }
override Variable getAVariable() { result = this.getVariable() }
}
/**
@@ -294,12 +294,12 @@ class ExportVarAccess extends VarAccess, @export_varaccess {
/** A global variable. */
class GlobalVariable extends Variable {
GlobalVariable() { isGlobal() }
GlobalVariable() { this.isGlobal() }
}
/** A local variable or a parameter. */
class LocalVariable extends Variable {
LocalVariable() { isLocal() }
LocalVariable() { this.isLocal() }
/**
* Gets the function or toplevel in which this variable is declared;
@@ -313,7 +313,7 @@ class LocalVariable extends Variable {
StmtContainer getDeclaringContainer() {
this = result.getScope().getAVariable()
or
exists(VarDecl d | d = getADeclaration() |
exists(VarDecl d | d = this.getADeclaration() |
if d = any(FunctionDeclStmt fds).getIdentifier()
then
exists(FunctionDeclStmt fds | d = fds.getIdentifier() |
@@ -332,19 +332,19 @@ class LocalVariable extends Variable {
Location getLocation() {
result =
min(Location loc |
loc = getADeclaration().getLocation()
loc = this.getADeclaration().getLocation()
|
loc order by loc.getStartLine(), loc.getStartColumn()
)
or
not exists(getADeclaration()) and
result = getDeclaringContainer().getEntry().getLocation()
not exists(this.getADeclaration()) and
result = this.getDeclaringContainer().getEntry().getLocation()
}
}
/** A local variable that is not captured. */
class PurelyLocalVariable extends LocalVariable {
PurelyLocalVariable() { not isCaptured() }
PurelyLocalVariable() { not this.isCaptured() }
}
/**
@@ -358,7 +358,7 @@ class PurelyLocalVariable extends LocalVariable {
* ```
*/
class GlobalVarAccess extends VarAccess {
GlobalVarAccess() { getVariable().isGlobal() }
GlobalVarAccess() { this.getVariable().isGlobal() }
}
/**
@@ -387,7 +387,7 @@ class BindingPattern extends @pattern, Expr {
VarRef getABindingVarRef() { none() }
/** Gets a variable bound by this pattern. */
Variable getAVariable() { result = getABindingVarRef().getVariable() }
Variable getAVariable() { result = this.getABindingVarRef().getVariable() }
/** Holds if this pattern appears in an l-value position. */
predicate isLValue() { any() }
@@ -467,7 +467,7 @@ class VarDecl extends @var_decl, VarRef, LexicalDecl {
* ```
*/
class GlobalVarDecl extends VarDecl {
GlobalVarDecl() { getVariable() instanceof GlobalVariable }
GlobalVarDecl() { this.getVariable() instanceof GlobalVariable }
}
/**
@@ -494,35 +494,35 @@ class ArrayPattern extends DestructuringPattern, @array_pattern {
/** Gets the default expression for the `i`th element of this array pattern, if any. */
Expr getDefault(int i) {
i in [0 .. getSize() - 1] and
result = getChildExpr(-2 - i)
i in [0 .. this.getSize() - 1] and
result = this.getChildExpr(-2 - i)
}
/** Holds if the `i`th element of this array pattern has a default expression. */
predicate hasDefault(int i) { exists(getDefault(i)) }
predicate hasDefault(int i) { exists(this.getDefault(i)) }
/** Gets the rest pattern of this array pattern, if any. */
override Expr getRest() { result = getChildExpr(-1) }
override Expr getRest() { result = this.getChildExpr(-1) }
/** Holds if this array pattern has a rest pattern. */
predicate hasRest() { exists(getRest()) }
predicate hasRest() { exists(this.getRest()) }
/** Gets the number of elements in this array pattern, not including any rest pattern. */
int getSize() { array_size(this, result) }
/** Holds if the `i`th element of this array pattern is omitted. */
predicate elementIsOmitted(int i) {
i in [0 .. getSize() - 1] and
not exists(getElement(i))
i in [0 .. this.getSize() - 1] and
not exists(this.getElement(i))
}
/** Holds if this array pattern has an omitted element. */
predicate hasOmittedElement() { elementIsOmitted(_) }
predicate hasOmittedElement() { this.elementIsOmitted(_) }
override predicate isImpure() { getAnElement().isImpure() }
override predicate isImpure() { this.getAnElement().isImpure() }
override VarRef getABindingVarRef() {
result = getAnElement().(BindingPattern).getABindingVarRef()
result = this.getAnElement().(BindingPattern).getABindingVarRef()
}
override string getAPrimaryQlClass() { result = "ArrayPattern" }
@@ -557,13 +557,13 @@ class ObjectPattern extends DestructuringPattern, @object_pattern {
}
/** Gets the rest property pattern of this object pattern, if any. */
override Expr getRest() { result = getChildExpr(-1) }
override Expr getRest() { result = this.getChildExpr(-1) }
override predicate isImpure() { getAPropertyPattern().isImpure() }
override predicate isImpure() { this.getAPropertyPattern().isImpure() }
override VarRef getABindingVarRef() {
result = getAPropertyPattern().getValuePattern().(BindingPattern).getABindingVarRef() or
result = getRest().(BindingPattern).getABindingVarRef()
result = this.getAPropertyPattern().getValuePattern().(BindingPattern).getABindingVarRef() or
result = this.getRest().(BindingPattern).getABindingVarRef()
}
override string getAPrimaryQlClass() { result = "ObjectPattern" }
@@ -600,14 +600,16 @@ class PropertyPattern extends @property, ASTNode {
Expr getDefault() { result = this.getChildExpr(2) }
/** Holds if this property pattern is a shorthand pattern. */
predicate isShorthand() { getNameExpr().getLocation() = getValuePattern().getLocation() }
predicate isShorthand() {
this.getNameExpr().getLocation() = this.getValuePattern().getLocation()
}
/** Gets the name of the property matched by this pattern. */
string getName() {
not isComputed() and
result = getNameExpr().(Identifier).getName()
not this.isComputed() and
result = this.getNameExpr().(Identifier).getName()
or
result = getNameExpr().(Literal).getValue()
result = this.getNameExpr().(Literal).getValue()
}
/** Gets the object pattern this property pattern belongs to. */
@@ -615,15 +617,15 @@ class PropertyPattern extends @property, ASTNode {
/** Holds if this pattern is impure, that is, if its evaluation could have side effects. */
predicate isImpure() {
isComputed() and getNameExpr().isImpure()
this.isComputed() and this.getNameExpr().isImpure()
or
getValuePattern().isImpure()
this.getValuePattern().isImpure()
}
override string toString() { properties(this, _, _, _, result) }
override ControlFlowNode getFirstControlFlowNode() {
result = getNameExpr().getFirstControlFlowNode()
result = this.getNameExpr().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "PropertyPattern" }
@@ -651,7 +653,7 @@ class VariableDeclarator extends Expr, @var_declarator {
TypeAnnotation getTypeAnnotation() {
result = this.getChildTypeExpr(2)
or
result = getDeclStmt().getDocumentation().getATagByTitle("type").getType()
result = this.getDeclStmt().getDocumentation().getATagByTitle("type").getType()
}
/** Holds if this is a TypeScript variable marked as definitely assigned with the `!` operator. */
@@ -661,7 +663,7 @@ class VariableDeclarator extends Expr, @var_declarator {
DeclStmt getDeclStmt() { this = result.getADecl() }
override ControlFlowNode getFirstControlFlowNode() {
result = getBindingPattern().getFirstControlFlowNode()
result = this.getBindingPattern().getFirstControlFlowNode()
}
override string getAPrimaryQlClass() { result = "VariableDeclarator" }
@@ -671,11 +673,11 @@ class VariableDeclarator extends Expr, @var_declarator {
* For internal use, holding the decorators of a function parameter.
*/
private class DecoratorList extends Expr, @decorator_list {
Decorator getDecorator(int i) { result = getChildExpr(i) }
Decorator getDecorator(int i) { result = this.getChildExpr(i) }
override ControlFlowNode getFirstControlFlowNode() {
if exists(getDecorator(0))
then result = getDecorator(0).getFirstControlFlowNode()
if exists(this.getDecorator(0))
then result = this.getDecorator(0).getFirstControlFlowNode()
else result = this
}
}
@@ -700,11 +702,11 @@ class Parameterized extends @parameterized, Documentable {
Parameter getAParameter() { this = result.getParent() }
/** Gets the number of parameters declared by this element. */
int getNumParameter() { result = count(getAParameter()) }
int getNumParameter() { result = count(this.getAParameter()) }
/** Gets a variable of the given name that is a parameter of this element. */
Variable getParameterVariable(string name) {
result = getAParameter().getAVariable() and
result = this.getAParameter().getAVariable() and
result.getName() = name
}
}
@@ -750,7 +752,7 @@ class Parameter extends BindingPattern {
override TypeAnnotation getTypeAnnotation() {
exists(Function f, int n | this = f.getParameter(n) | result = f.getChildTypeExpr(-(4 * n + 6)))
or
result = getJSDocTag().getType()
result = this.getJSDocTag().getType()
}
/** Holds if this parameter is a rest parameter. */
@@ -766,13 +768,13 @@ class Parameter extends BindingPattern {
}
/** Gets the `i`th decorator applied to this parameter. */
Decorator getDecorator(int i) { result = getDecoratorList().getDecorator(i) }
Decorator getDecorator(int i) { result = this.getDecoratorList().getDecorator(i) }
/** Gets a decorator applied to this parameter. */
Decorator getADecorator() { result = getDecorator(_) }
Decorator getADecorator() { result = this.getDecorator(_) }
/** Gets the number of decorators applied to this parameter. */
int getNumDecorator() { result = count(getADecorator()) }
int getNumDecorator() { result = count(this.getADecorator()) }
override predicate isLValue() { any() }

View File

@@ -39,22 +39,22 @@ class YAMLNode extends @yaml_node, Locatable {
/**
* Gets a child node of this node.
*/
YAMLNode getAChildNode() { result = getChildNode(_) }
YAMLNode getAChildNode() { result = this.getChildNode(_) }
/**
* Gets the number of child nodes of this node.
*/
int getNumChild() { result = count(getAChildNode()) }
int getNumChild() { result = count(this.getAChildNode()) }
/**
* Gets the `i`th child of this node, as a YAML value.
*/
YAMLValue getChild(int i) { result = getChildNode(i).eval() }
YAMLValue getChild(int i) { result = this.getChildNode(i).eval() }
/**
* Gets a child of this node, as a YAML value.
*/
YAMLValue getAChild() { result = getChild(_) }
YAMLValue getAChild() { result = this.getChild(_) }
/**
* Gets the tag of this node.
@@ -65,7 +65,9 @@ class YAMLNode extends @yaml_node, Locatable {
* Holds if this node is tagged with a standard type tag of the form
* `tag:yaml.org,2002:<t>`.
*/
predicate hasStandardTypeTag(string t) { t = getTag().regexpCapture("tag:yaml.org,2002:(.*)", 1) }
predicate hasStandardTypeTag(string t) {
t = this.getTag().regexpCapture("tag:yaml.org,2002:(.*)", 1)
}
override string toString() { yaml(this, _, _, _, _, result) }
@@ -77,7 +79,7 @@ class YAMLNode extends @yaml_node, Locatable {
/**
* Gets the toplevel document to which this node belongs.
*/
YAMLDocument getDocument() { result = getParentNode*() }
YAMLDocument getDocument() { result = this.getParentNode*() }
/**
* Gets the YAML value this node corresponds to after resolving aliases and includes.
@@ -159,12 +161,12 @@ class YAMLScalar extends YAMLValue, @yaml_scalar_node {
* ```
*/
class YAMLInteger extends YAMLScalar {
YAMLInteger() { hasStandardTypeTag("int") }
YAMLInteger() { this.hasStandardTypeTag("int") }
/**
* Gets the value of this scalar, as an integer.
*/
int getIntValue() { result = getValue().toInt() }
int getIntValue() { result = this.getValue().toInt() }
}
/**
@@ -178,12 +180,12 @@ class YAMLInteger extends YAMLScalar {
* ```
*/
class YAMLFloat extends YAMLScalar {
YAMLFloat() { hasStandardTypeTag("float") }
YAMLFloat() { this.hasStandardTypeTag("float") }
/**
* Gets the value of this scalar, as a floating point number.
*/
float getFloatValue() { result = getValue().toFloat() }
float getFloatValue() { result = this.getValue().toFloat() }
}
/**
@@ -196,12 +198,12 @@ class YAMLFloat extends YAMLScalar {
* ```
*/
class YAMLTimestamp extends YAMLScalar {
YAMLTimestamp() { hasStandardTypeTag("timestamp") }
YAMLTimestamp() { this.hasStandardTypeTag("timestamp") }
/**
* Gets the value of this scalar, as a date.
*/
date getDateValue() { result = getValue().toDate() }
date getDateValue() { result = this.getValue().toDate() }
}
/**
@@ -214,12 +216,12 @@ class YAMLTimestamp extends YAMLScalar {
* ```
*/
class YAMLBool extends YAMLScalar {
YAMLBool() { hasStandardTypeTag("bool") }
YAMLBool() { this.hasStandardTypeTag("bool") }
/**
* Gets the value of this scalar, as a Boolean.
*/
boolean getBoolValue() { if getValue() = "true" then result = true else result = false }
boolean getBoolValue() { if this.getValue() = "true" then result = true else result = false }
}
/**
@@ -232,7 +234,7 @@ class YAMLBool extends YAMLScalar {
* ```
*/
class YAMLNull extends YAMLScalar {
YAMLNull() { hasStandardTypeTag("null") }
YAMLNull() { this.hasStandardTypeTag("null") }
}
/**
@@ -245,7 +247,7 @@ class YAMLNull extends YAMLScalar {
* ```
*/
class YAMLString extends YAMLScalar {
YAMLString() { hasStandardTypeTag("str") }
YAMLString() { this.hasStandardTypeTag("str") }
}
/**
@@ -259,7 +261,7 @@ class YAMLString extends YAMLScalar {
* ```
*/
class YAMLMergeKey extends YAMLScalar {
YAMLMergeKey() { hasStandardTypeTag("merge") }
YAMLMergeKey() { this.hasStandardTypeTag("merge") }
}
/**
@@ -270,11 +272,11 @@ class YAMLMergeKey extends YAMLScalar {
* ```
*/
class YAMLInclude extends YAMLScalar {
YAMLInclude() { getTag() = "!include" }
YAMLInclude() { this.getTag() = "!include" }
override YAMLValue eval() {
exists(YAMLDocument targetDoc |
targetDoc.getFile().getAbsolutePath() = getTargetPath() and
targetDoc.getFile().getAbsolutePath() = this.getTargetPath() and
result = targetDoc.eval()
)
}
@@ -283,10 +285,10 @@ class YAMLInclude extends YAMLScalar {
* Gets the absolute path of the file included by this directive.
*/
private string getTargetPath() {
exists(string path | path = getValue() |
exists(string path | path = this.getValue() |
if path.matches("/%")
then result = path
else result = getDocument().getFile().getParentContainer().getAbsolutePath() + "/" + path
else result = this.getDocument().getFile().getParentContainer().getAbsolutePath() + "/" + path
)
}
}
@@ -328,7 +330,7 @@ class YAMLMapping extends YAMLCollection, @yaml_mapping_node {
*/
YAMLNode getKeyNode(int i) {
i >= 0 and
exists(int j | i = j - 1 and result = getChildNode(j))
exists(int j | i = j - 1 and result = this.getChildNode(j))
}
/**
@@ -336,32 +338,32 @@ class YAMLMapping extends YAMLCollection, @yaml_mapping_node {
*/
YAMLNode getValueNode(int i) {
i >= 0 and
exists(int j | i = -j - 1 and result = getChildNode(j))
exists(int j | i = -j - 1 and result = this.getChildNode(j))
}
/**
* Gets the `i`th key of this mapping, as a YAML value.
*/
YAMLValue getKey(int i) { result = getKeyNode(i).eval() }
YAMLValue getKey(int i) { result = this.getKeyNode(i).eval() }
/**
* Gets the `i`th value of this mapping, as a YAML value.
*/
YAMLValue getValue(int i) { result = getValueNode(i).eval() }
YAMLValue getValue(int i) { result = this.getValueNode(i).eval() }
/**
* Holds if this mapping maps `key` to `value`.
*/
predicate maps(YAMLValue key, YAMLValue value) {
exists(int i | key = getKey(i) and value = getValue(i))
exists(int i | key = this.getKey(i) and value = this.getValue(i))
or
exists(YAMLMergeKey merge, YAMLMapping that | maps(merge, that) | that.maps(key, value))
exists(YAMLMergeKey merge, YAMLMapping that | this.maps(merge, that) | that.maps(key, value))
}
/**
* Gets the value that this mapping maps `key` to.
*/
YAMLValue lookup(string key) { exists(YAMLScalar s | s.getValue() = key | maps(s, result)) }
YAMLValue lookup(string key) { exists(YAMLScalar s | s.getValue() = key | this.maps(s, result)) }
override string getAPrimaryQlClass() { result = "YAMLMapping" }
}
@@ -381,12 +383,12 @@ class YAMLSequence extends YAMLCollection, @yaml_sequence_node {
/**
* Gets the `i`th element in this sequence.
*/
YAMLNode getElementNode(int i) { result = getChildNode(i) }
YAMLNode getElementNode(int i) { result = this.getChildNode(i) }
/**
* Gets the `i`th element in this sequence, as a YAML value.
*/
YAMLValue getElement(int i) { result = getElementNode(i).eval() }
YAMLValue getElement(int i) { result = this.getElementNode(i).eval() }
override string getAPrimaryQlClass() { result = "YAMLSequence" }
}
@@ -402,7 +404,7 @@ class YAMLSequence extends YAMLCollection, @yaml_sequence_node {
*/
class YAMLAliasNode extends YAMLNode, @yaml_alias_node {
override YAMLValue eval() {
result.getAnchor() = getTarget() and
result.getAnchor() = this.getTarget() and
result.getDocument() = this.getDocument()
}
@@ -426,7 +428,7 @@ class YAMLAliasNode extends YAMLNode, @yaml_alias_node {
* ```
*/
class YAMLDocument extends YAMLNode {
YAMLDocument() { not exists(getParentNode()) }
YAMLDocument() { not exists(this.getParentNode()) }
}
/**
@@ -437,5 +439,5 @@ class YAMLParseError extends @yaml_error, Error {
override string getMessage() { yaml_errors(this, result) }
override string toString() { result = getMessage() }
override string toString() { result = this.getMessage() }
}

View File

@@ -100,7 +100,7 @@ abstract class CustomAbstractValueDefinition extends Locatable {
*/
AbstractValue getAPrototype() {
exists(AbstractProtoProperty proto |
proto.getBase() = getAbstractValue() and
proto.getBase() = this.getAbstractValue() and
result = proto.getAValue()
)
}

View File

@@ -73,7 +73,7 @@ module DataFlow {
* additionally includes the `InvokeExpr` corresponding to reflective calls.
*/
Expr getEnclosingExpr() {
result = asExpr() or
result = this.asExpr() or
this = DataFlow::reflectiveCallNode(result)
}
@@ -84,10 +84,10 @@ module DataFlow {
BasicBlock getBasicBlock() { none() }
/** Gets the container in which this node occurs. */
StmtContainer getContainer() { result = getBasicBlock().getContainer() }
StmtContainer getContainer() { result = this.getBasicBlock().getContainer() }
/** Gets the toplevel in which this node occurs. */
TopLevel getTopLevel() { result = getContainer().getTopLevel() }
TopLevel getTopLevel() { result = this.getContainer().getTopLevel() }
/**
* Holds if this data flow node accesses the global variable `g`, either directly
@@ -98,25 +98,25 @@ module DataFlow {
/** Holds if this node may evaluate to the string `s`, possibly through local data flow. */
pragma[nomagic]
predicate mayHaveStringValue(string s) {
getAPredecessor().mayHaveStringValue(s)
this.getAPredecessor().mayHaveStringValue(s)
or
s = getStringValue()
s = this.getStringValue()
}
/** Gets the string value of this node, if it is a string literal or constant string concatenation. */
string getStringValue() { result = asExpr().getStringValue() }
string getStringValue() { result = this.asExpr().getStringValue() }
/** Holds if this node may evaluate to the Boolean value `b`. */
predicate mayHaveBooleanValue(boolean b) {
getAPredecessor().mayHaveBooleanValue(b)
this.getAPredecessor().mayHaveBooleanValue(b)
or
b = true and asExpr().(BooleanLiteral).getValue() = "true"
b = true and this.asExpr().(BooleanLiteral).getValue() = "true"
or
b = false and asExpr().(BooleanLiteral).getValue() = "false"
b = false and this.asExpr().(BooleanLiteral).getValue() = "false"
}
/** Gets the integer value of this node, if it is an integer constant. */
int getIntValue() { result = asExpr().getIntValue() }
int getIntValue() { result = this.asExpr().getIntValue() }
/** Gets a function value that may reach this node. */
final FunctionNode getAFunctionValue() {
@@ -133,7 +133,7 @@ module DataFlow {
* possibly derived from a partial function invocation.
*/
final FunctionNode getABoundFunctionValue(int boundArgs) {
result = getAFunctionValue() and boundArgs = 0
result = this.getAFunctionValue() and boundArgs = 0
or
CallGraph::getABoundFunctionReference(result, boundArgs, _).flowsTo(this)
}
@@ -161,16 +161,16 @@ module DataFlow {
File getFile() { none() } // overridden in subclasses
/** Gets the start line of this data flow node. */
int getStartLine() { hasLocationInfo(_, result, _, _, _) }
int getStartLine() { this.hasLocationInfo(_, result, _, _, _) }
/** Gets the start column of this data flow node. */
int getStartColumn() { hasLocationInfo(_, _, result, _, _) }
int getStartColumn() { this.hasLocationInfo(_, _, result, _, _) }
/** Gets the end line of this data flow node. */
int getEndLine() { hasLocationInfo(_, _, _, result, _) }
int getEndLine() { this.hasLocationInfo(_, _, _, result, _) }
/** Gets the end column of this data flow node. */
int getEndColumn() { hasLocationInfo(_, _, _, _, result) }
int getEndColumn() { this.hasLocationInfo(_, _, _, _, result) }
/** Gets a textual representation of this element. */
cached
@@ -242,7 +242,7 @@ module DataFlow {
result = pattern.getTypeAnnotation()
)
or
result = getAPredecessor().getFallbackTypeAnnotation()
result = this.getAPredecessor().getFallbackTypeAnnotation()
or
exists(DataFlow::ClassNode cls, string fieldName |
this = cls.getAReceiverNode().getAPropertyRead(fieldName) and
@@ -257,9 +257,9 @@ module DataFlow {
cached
predicate hasUnderlyingType(string globalName) {
Stages::TypeTracking::ref() and
getType().hasUnderlyingType(globalName)
this.getType().hasUnderlyingType(globalName)
or
getFallbackTypeAnnotation().getAnUnderlyingType().hasQualifiedName(globalName)
this.getFallbackTypeAnnotation().getAnUnderlyingType().hasQualifiedName(globalName)
}
/**
@@ -269,9 +269,9 @@ module DataFlow {
cached
predicate hasUnderlyingType(string moduleName, string typeName) {
Stages::TypeTracking::ref() and
getType().hasUnderlyingType(moduleName, typeName)
this.getType().hasUnderlyingType(moduleName, typeName)
or
getFallbackTypeAnnotation().getAnUnderlyingType().hasQualifiedName(moduleName, typeName)
this.getFallbackTypeAnnotation().getAnUnderlyingType().hasQualifiedName(moduleName, typeName)
}
}
@@ -528,13 +528,13 @@ module DataFlow {
* Holds if this data flow node accesses property `p` on base node `base`.
*/
pragma[noinline]
predicate accesses(Node base, string p) { getBase() = base and getPropertyName() = p }
predicate accesses(Node base, string p) { this.getBase() = base and this.getPropertyName() = p }
/**
* Holds if this data flow node reads or writes a private field in a class.
*/
predicate isPrivateField() {
getPropertyName().charAt(0) = "#" and getPropertyNameExpr() instanceof Label
this.getPropertyName().charAt(0) = "#" and this.getPropertyNameExpr() instanceof Label
}
/**
@@ -581,9 +581,9 @@ module DataFlow {
*/
pragma[noinline]
predicate writes(DataFlow::Node base, string prop, DataFlow::Node rhs) {
base = getBase() and
prop = getPropertyName() and
rhs = getRhs()
base = this.getBase() and
prop = this.getPropertyName() and
rhs = this.getRhs()
}
/**
@@ -1110,11 +1110,11 @@ module DataFlow {
astNode.isSpreadArgument(i)
or
exists(astNode.getArgument(i)) and
isIndexAfterSpread(i - 1)
this.isIndexAfterSpread(i - 1)
}
override DataFlow::Node getArgument(int i) {
not isIndexAfterSpread(i) and
not this.isIndexAfterSpread(i) and
result = DataFlow::valueNode(astNode.getArgument(i))
}
@@ -1185,7 +1185,7 @@ module DataFlow {
}
override DataFlow::Node getAnArgument() {
kind = "call" and result = originalCall.getAnArgument() and result != getReceiver()
kind = "call" and result = originalCall.getAnArgument() and result != this.getReceiver()
}
override DataFlow::Node getASpreadArgument() {
@@ -1278,10 +1278,12 @@ module DataFlow {
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
getTag().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
this.getTag()
.getLocation()
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
override string toString() { result = getTag().toString() }
override string toString() { result = this.getTag().toString() }
}
/**

View File

@@ -49,7 +49,9 @@ class ParameterNode extends DataFlow::SourceNode {
predicate isRestParameter() { p.isRestParameter() }
/** Gets the data flow node for an expression that is applied to this decorator. */
DataFlow::Node getADecorator() { result = getParameter().getADecorator().getExpression().flow() }
DataFlow::Node getADecorator() {
result = this.getParameter().getADecorator().getExpression().flow()
}
}
/**
@@ -98,7 +100,7 @@ class InvokeNode extends DataFlow::SourceNode {
DataFlow::Node getAnArgument() { result = this.(DataFlow::Impl::InvokeNodeDef).getAnArgument() }
/** Gets the data flow node corresponding to the last argument of this invocation. */
DataFlow::Node getLastArgument() { result = getArgument(getNumArgument() - 1) }
DataFlow::Node getLastArgument() { result = this.getArgument(this.getNumArgument() - 1) }
/**
* Gets a data flow node corresponding to an array of values being passed as
@@ -119,7 +121,7 @@ class InvokeNode extends DataFlow::SourceNode {
/** Gets the number of arguments of this invocation, if it can be determined. */
int getNumArgument() { result = this.(DataFlow::Impl::InvokeNodeDef).getNumArgument() }
Function getEnclosingFunction() { result = getBasicBlock().getContainer() }
Function getEnclosingFunction() { result = this.getBasicBlock().getContainer() }
/**
* Gets a function passed as the `i`th argument of this invocation.
@@ -127,7 +129,7 @@ class InvokeNode extends DataFlow::SourceNode {
* This predicate only performs local data flow tracking.
* Consider using `getABoundCallbackParameter` to handle interprocedural flow of callback functions.
*/
FunctionNode getCallback(int i) { result.flowsTo(getArgument(i)) }
FunctionNode getCallback(int i) { result.flowsTo(this.getArgument(i)) }
/**
* Gets a parameter of a callback passed into this call.
@@ -155,7 +157,7 @@ class InvokeNode extends DataFlow::SourceNode {
ParameterNode getABoundCallbackParameter(int callback, int param) {
exists(int boundArgs |
result =
getArgument(callback).getABoundFunctionValue(boundArgs).getParameter(param + boundArgs)
this.getArgument(callback).getABoundFunctionValue(boundArgs).getParameter(param + boundArgs)
)
}
@@ -165,16 +167,16 @@ class InvokeNode extends DataFlow::SourceNode {
*/
pragma[nomagic]
DataFlow::ValueNode getOptionArgument(int i, string name) {
getOptionsArgument(i).hasPropertyWrite(name, result)
this.getOptionsArgument(i).hasPropertyWrite(name, result)
}
pragma[noinline]
private ObjectLiteralNode getOptionsArgument(int i) { result.flowsTo(getArgument(i)) }
private ObjectLiteralNode getOptionsArgument(int i) { result.flowsTo(this.getArgument(i)) }
/** Gets an abstract value representing possible callees of this call site. */
final AbstractValue getACalleeValue() {
exists(DataFlow::Node callee, DataFlow::AnalyzedNode analyzed |
pragma[only_bind_into](callee) = getCalleeNode() and
pragma[only_bind_into](callee) = this.getCalleeNode() and
pragma[only_bind_into](analyzed) = callee.analyze() and
pragma[only_bind_into](result) = analyzed.getAValue()
)
@@ -186,7 +188,7 @@ class InvokeNode extends DataFlow::SourceNode {
* To alter the call graph as seen by the interprocedural data flow libraries, override
* the `getACallee(int imprecision)` predicate instead.
*/
final Function getACallee() { result = getACallee(0) }
final Function getACallee() { result = this.getACallee(0) }
/**
* Gets a callee of this call site where `imprecision` is a heuristic measure of how
@@ -208,7 +210,9 @@ class InvokeNode extends DataFlow::SourceNode {
* Holds if the approximation of possible callees for this call site is
* affected by the given analysis incompleteness `cause`.
*/
predicate isIndefinite(DataFlow::Incompleteness cause) { getACalleeValue().isIndefinite(cause) }
predicate isIndefinite(DataFlow::Incompleteness cause) {
this.getACalleeValue().isIndefinite(cause)
}
/**
* Holds if our approximation of possible callees for this call site is
@@ -222,8 +226,8 @@ class InvokeNode extends DataFlow::SourceNode {
* imprecision.
*/
predicate isImprecise() {
isIndefinite("global") and
exists(DefiniteAbstractValue v | v = getACalleeValue() | not v instanceof AbstractCallable)
this.isIndefinite("global") and
exists(DefiniteAbstractValue v | v = this.getACalleeValue() | not v instanceof AbstractCallable)
}
/**
@@ -233,20 +237,20 @@ class InvokeNode extends DataFlow::SourceNode {
predicate isIncomplete() {
// the flow analysis identifies a source of incompleteness other than
// global flow (which usually leads to imprecision rather than incompleteness)
any(DataFlow::Incompleteness cause | isIndefinite(cause)) != "global"
any(DataFlow::Incompleteness cause | this.isIndefinite(cause)) != "global"
}
/**
* Holds if our approximation of possible callees for this call site is
* likely to be imprecise or incomplete.
*/
predicate isUncertain() { isImprecise() or isIncomplete() }
predicate isUncertain() { this.isImprecise() or this.isIncomplete() }
/**
* Gets the data flow node representing an exception thrown from this invocation.
*/
DataFlow::ExceptionalInvocationReturnNode getExceptionalReturn() {
DataFlow::exceptionalInvocationReturnNode(result, asExpr())
DataFlow::exceptionalInvocationReturnNode(result, this.asExpr())
}
}
@@ -289,8 +293,8 @@ class MethodCallNode extends CallNode {
* Holds if this data flow node calls method `methodName` on receiver node `receiver`.
*/
predicate calls(DataFlow::Node receiver, string methodName) {
receiver = getReceiver() and
methodName = getMethodName()
receiver = this.getReceiver() and
methodName = this.getMethodName()
}
}
@@ -474,13 +478,13 @@ class FunctionNode extends DataFlow::ValueNode, DataFlow::SourceNode {
ParameterNode getParameter(int i) { result = DataFlow::parameterNode(astNode.getParameter(i)) }
/** Gets a parameter of this function. */
ParameterNode getAParameter() { result = getParameter(_) }
ParameterNode getAParameter() { result = this.getParameter(_) }
/** Gets the number of parameters declared on this function. */
int getNumParameter() { result = count(astNode.getAParameter()) }
/** Gets the last parameter of this function. */
ParameterNode getLastParameter() { result = getParameter(getNumParameter() - 1) }
ParameterNode getLastParameter() { result = this.getParameter(this.getNumParameter() - 1) }
/** Holds if the last parameter of this function is a rest parameter. */
predicate hasRestParameter() { astNode.hasRestParameter() }
@@ -500,7 +504,7 @@ class FunctionNode extends DataFlow::ValueNode, DataFlow::SourceNode {
* Gets the function whose `this` binding a `this` expression in this function refers to,
* which is the nearest enclosing non-arrow function.
*/
FunctionNode getThisBinder() { result.getFunction() = getFunction().getThisBinder() }
FunctionNode getThisBinder() { result.getFunction() = this.getFunction().getThisBinder() }
/**
* Gets the dataflow node holding the value of the receiver passed to the given function.
@@ -616,25 +620,25 @@ class RegExpLiteralNode extends DataFlow::ValueNode, DataFlow::SourceNode {
* ```
*/
class ArrayConstructorInvokeNode extends DataFlow::InvokeNode {
ArrayConstructorInvokeNode() { getCalleeNode() = DataFlow::globalVarRef("Array") }
ArrayConstructorInvokeNode() { this.getCalleeNode() = DataFlow::globalVarRef("Array") }
/** Gets the `i`th initial element of this array, if one is provided. */
DataFlow::ValueNode getElement(int i) {
getNumArgument() > 1 and // A single-argument invocation specifies the array length, not an element.
result = getArgument(i)
this.getNumArgument() > 1 and // A single-argument invocation specifies the array length, not an element.
result = this.getArgument(i)
}
/** Gets an initial element of this array, if one is provided. */
DataFlow::ValueNode getAnElement() {
getNumArgument() > 1 and
result = getAnArgument()
this.getNumArgument() > 1 and
result = this.getAnArgument()
}
/** Gets the initial size of the created array, if it can be determined. */
int getSize() {
if getNumArgument() = 1
then result = getArgument(0).getIntValue()
else result = count(getAnElement())
if this.getNumArgument() = 1
then result = this.getArgument(0).getIntValue()
else result = count(this.getAnElement())
}
}
@@ -665,7 +669,7 @@ class ArrayCreationNode extends DataFlow::ValueNode, DataFlow::SourceNode {
}
/** Gets an initial element of this array, if one if provided. */
DataFlow::ValueNode getAnElement() { result = getElement(_) }
DataFlow::ValueNode getAnElement() { result = this.getElement(_) }
/** Gets the initial size of the created array, if it can be determined. */
int getSize() {
@@ -678,7 +682,7 @@ class ArrayCreationNode extends DataFlow::ValueNode, DataFlow::SourceNode {
* individual arguments to this array creation.
*/
DataFlow::Node getASpreadArgument() {
exists(SpreadElement arg | arg = getAnElement().getEnclosingExpr() |
exists(SpreadElement arg | arg = this.getAnElement().getEnclosingExpr() |
result = DataFlow::valueNode(arg.getOperand())
)
}
@@ -919,7 +923,9 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
*
* This predicate can be overridden to customize the class hierarchy.
*/
ClassNode getADirectSuperClass() { result.getAClassReference().flowsTo(getASuperClassNode()) }
ClassNode getADirectSuperClass() {
result.getAClassReference().flowsTo(this.getASuperClassNode())
}
/**
* Gets a direct subclass of this class.
@@ -930,9 +936,9 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
* Gets the receiver of an instance member or constructor of this class.
*/
DataFlow::SourceNode getAReceiverNode() {
result = getConstructor().getReceiver()
result = this.getConstructor().getReceiver()
or
result = getAnInstanceMember().getReceiver()
result = this.getAnInstanceMember().getReceiver()
}
/**
@@ -943,7 +949,7 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
/**
* Gets the abstract value representing an instance of this class.
*/
AbstractValue getAbstractInstanceValue() { result = AbstractInstance::of(getAstNode()) }
AbstractValue getAbstractInstanceValue() { result = AbstractInstance::of(this.getAstNode()) }
/**
* Gets a dataflow node that refers to this class object.
@@ -952,14 +958,14 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
*/
DataFlow::SourceNode getAClassReference(DataFlow::TypeTracker t) {
t.start() and
result.(AnalyzedNode).getAValue() = getAbstractClassValue() and
result.(AnalyzedNode).getAValue() = this.getAbstractClassValue() and
(
not CallGraph::isIndefiniteGlobal(result)
or
result.getAstNode().getFile() = this.getAstNode().getFile()
)
or
exists(DataFlow::TypeTracker t2 | result = getAClassReference(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.getAClassReference(t2).track(t2, t))
}
/**
@@ -967,7 +973,7 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
*/
cached
final DataFlow::SourceNode getAClassReference() {
result = getAClassReference(DataFlow::TypeTracker::end())
result = this.getAClassReference(DataFlow::TypeTracker::end())
}
/**
@@ -976,14 +982,14 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
* This predicate can be overridden to customize the tracking of class instances.
*/
DataFlow::SourceNode getAnInstanceReference(DataFlow::TypeTracker t) {
result = getAClassReference(t.continue()).getAnInstantiation()
result = this.getAClassReference(t.continue()).getAnInstantiation()
or
t.start() and
result.(AnalyzedNode).getAValue() = getAbstractInstanceValue() and
result.(AnalyzedNode).getAValue() = this.getAbstractInstanceValue() and
not result = any(DataFlow::ClassNode cls).getAReceiverNode()
or
t.start() and
result = getAReceiverNode()
result = this.getAReceiverNode()
or
// Use a parameter type as starting point of type tracking.
// Use `t.call()` to emulate the value being passed in through an unseen
@@ -994,7 +1000,7 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
result = DataFlow::parameterNode(param)
)
or
result = getAnInstanceReferenceAux(t) and
result = this.getAnInstanceReferenceAux(t) and
// Avoid tracking into the receiver of other classes.
// Note that this also blocks flows into a property of the receiver,
// but the `localFieldStep` rule will often compensate for this.
@@ -1003,7 +1009,7 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
pragma[noinline]
private DataFlow::SourceNode getAnInstanceReferenceAux(DataFlow::TypeTracker t) {
exists(DataFlow::TypeTracker t2 | result = getAnInstanceReference(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.getAnInstanceReference(t2).track(t2, t))
}
/**
@@ -1011,7 +1017,7 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
*/
cached
final DataFlow::SourceNode getAnInstanceReference() {
result = getAnInstanceReference(DataFlow::TypeTracker::end())
result = this.getAnInstanceReference(DataFlow::TypeTracker::end())
}
/**
@@ -1043,7 +1049,7 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
* Gets an access to a static member of this class.
*/
DataFlow::PropRead getAStaticMemberAccess(string name) {
result = getAClassReference().getAPropertyRead(name)
result = this.getAClassReference().getAPropertyRead(name)
}
/**
@@ -1051,7 +1057,7 @@ class ClassNode extends DataFlow::SourceNode instanceof ClassNode::Range {
*/
pragma[noinline]
predicate hasQualifiedName(string name) {
getAClassReference().flowsTo(AccessPath::getAnAssignmentTo(name))
this.getAClassReference().flowsTo(AccessPath::getAnAssignmentTo(name))
}
/**
@@ -1159,7 +1165,7 @@ module ClassNode {
)
or
kind = MemberKind::method() and
result = getConstructor().getReceiver().getAPropertySource(name)
result = this.getConstructor().getReceiver().getAPropertySource(name)
}
override FunctionNode getAnInstanceMember(MemberKind kind) {
@@ -1171,7 +1177,7 @@ module ClassNode {
)
or
kind = MemberKind::method() and
result = getConstructor().getReceiver().getAPropertySource()
result = this.getConstructor().getReceiver().getAPropertySource()
}
override FunctionNode getStaticMethod(string name) {
@@ -1181,7 +1187,7 @@ module ClassNode {
result = method.getBody().flow()
)
or
result = getAPropertySource(name)
result = this.getAPropertySource(name)
}
override FunctionNode getAStaticMethod() {
@@ -1191,7 +1197,7 @@ module ClassNode {
result = method.getBody().flow()
)
or
result = getAPropertySource()
result = this.getAPropertySource()
}
override DataFlow::Node getASuperClassNode() { result = astNode.getSuperClass().flow() }
@@ -1239,7 +1245,7 @@ module ClassNode {
or
exists(string name |
this = AccessPath::getAnAssignmentTo(name) and
exists(getAPrototypeReferenceInFile(name, getFile()))
exists(getAPrototypeReferenceInFile(name, this.getFile()))
)
)
}
@@ -1251,7 +1257,7 @@ module ClassNode {
override FunctionNode getConstructor() { result = this }
private PropertyAccessor getAnAccessor(MemberKind kind) {
result.getObjectExpr() = getAPrototypeReference().asExpr() and
result.getObjectExpr() = this.getAPrototypeReference().asExpr() and
(
kind = MemberKind::getter() and
result instanceof PropertyGetter
@@ -1263,13 +1269,13 @@ module ClassNode {
override FunctionNode getInstanceMember(string name, MemberKind kind) {
kind = MemberKind::method() and
result = getAPrototypeReference().getAPropertySource(name)
result = this.getAPrototypeReference().getAPropertySource(name)
or
kind = MemberKind::method() and
result = getConstructor().getReceiver().getAPropertySource(name)
result = this.getConstructor().getReceiver().getAPropertySource(name)
or
exists(PropertyAccessor accessor |
accessor = getAnAccessor(kind) and
accessor = this.getAnAccessor(kind) and
accessor.getName() = name and
result = accessor.getInit().flow()
)
@@ -1277,20 +1283,20 @@ module ClassNode {
override FunctionNode getAnInstanceMember(MemberKind kind) {
kind = MemberKind::method() and
result = getAPrototypeReference().getAPropertySource()
result = this.getAPrototypeReference().getAPropertySource()
or
kind = MemberKind::method() and
result = getConstructor().getReceiver().getAPropertySource()
result = this.getConstructor().getReceiver().getAPropertySource()
or
exists(PropertyAccessor accessor |
accessor = getAnAccessor(kind) and
accessor = this.getAnAccessor(kind) and
result = accessor.getInit().flow()
)
}
override FunctionNode getStaticMethod(string name) { result = getAPropertySource(name) }
override FunctionNode getStaticMethod(string name) { result = this.getAPropertySource(name) }
override FunctionNode getAStaticMethod() { result = getAPropertySource() }
override FunctionNode getAStaticMethod() { result = this.getAPropertySource() }
/**
* Gets a reference to the prototype of this class.
@@ -1304,11 +1310,11 @@ module ClassNode {
or
exists(string name |
this = AccessPath::getAnAssignmentTo(name) and
result = getAPrototypeReferenceInFile(name, getFile())
result = getAPrototypeReferenceInFile(name, this.getFile())
)
or
exists(ExtendCall call |
call.getDestinationOperand() = getAPrototypeReference() and
call.getDestinationOperand() = this.getAPrototypeReference() and
result = call.getASourceOperand()
)
}
@@ -1316,7 +1322,7 @@ module ClassNode {
override DataFlow::Node getASuperClassNode() {
// C.prototype = Object.create(D.prototype)
exists(DataFlow::InvokeNode objectCreate, DataFlow::PropRead superProto |
getAPropertySource("prototype") = objectCreate and
this.getAPropertySource("prototype") = objectCreate and
objectCreate = DataFlow::globalVarRef("Object").getAMemberCall("create") and
superProto.flowsTo(objectCreate.getArgument(0)) and
superProto.getPropertyName() = "prototype" and
@@ -1325,7 +1331,7 @@ module ClassNode {
or
// C.prototype = new D()
exists(DataFlow::NewNode newCall |
getAPropertySource("prototype") = newCall and
this.getAPropertySource("prototype") = newCall and
result = newCall.getCalleeNode()
)
or
@@ -1353,9 +1359,9 @@ module ClassNode {
class PartialInvokeNode extends DataFlow::Node instanceof PartialInvokeNode::Range {
/** Gets a node holding a callback invoked by this partial invocation node. */
DataFlow::Node getACallbackNode() {
isPartialArgument(result, _, _)
this.isPartialArgument(result, _, _)
or
exists(getBoundReceiver(result))
exists(this.getBoundReceiver(result))
}
/**
@@ -1420,27 +1426,27 @@ module PartialInvokeNode {
*/
private class BindPartialCall extends PartialInvokeNode::Range, DataFlow::MethodCallNode {
BindPartialCall() {
getMethodName() = "bind" and
this.getMethodName() = "bind" and
// Avoid overlap with angular.bind and goog.bind
not this = AngularJS::angular().getAMethodCall() and
not getReceiver().accessesGlobal("goog")
not this.getReceiver().accessesGlobal("goog")
}
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
index >= 0 and
callback = getReceiver() and
argument = getArgument(index + 1)
callback = this.getReceiver() and
argument = this.getArgument(index + 1)
}
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
callback = getReceiver() and
boundArgs = getNumArgument() - 1 and
callback = this.getReceiver() and
boundArgs = this.getNumArgument() - 1 and
result = this
}
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
callback = getReceiver() and
result = getArgument(0)
callback = this.getReceiver() and
result = this.getArgument(0)
}
}
@@ -1452,13 +1458,13 @@ module PartialInvokeNode {
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
index >= 0 and
callback = getArgument(0) and
argument = getArgument(index + 1)
callback = this.getArgument(0) and
argument = this.getArgument(index + 1)
}
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
callback = getArgument(0) and
boundArgs = getNumArgument() - 1 and
callback = this.getArgument(0) and
boundArgs = this.getNumArgument() - 1 and
result = this
}
}
@@ -1493,10 +1499,10 @@ module PartialInvokeNode {
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
(
callbackIndex >= 0 and
callback = getArgument(callbackIndex)
callback = this.getArgument(callbackIndex)
or
callbackIndex = -1 and
callback = getLastArgument()
callback = this.getLastArgument()
) and
boundArgs = 0 and
result = this
@@ -1509,16 +1515,16 @@ module PartialInvokeNode {
private class RamdaPartialCall extends PartialInvokeNode::Range, DataFlow::CallNode {
RamdaPartialCall() { this = DataFlow::moduleMember("ramda", "partial").getACall() }
private DataFlow::ArrayCreationNode getArgumentsArray() { result.flowsTo(getArgument(1)) }
private DataFlow::ArrayCreationNode getArgumentsArray() { result.flowsTo(this.getArgument(1)) }
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
callback = getArgument(0) and
argument = getArgumentsArray().getElement(index)
callback = this.getArgument(0) and
argument = this.getArgumentsArray().getElement(index)
}
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
callback = getArgument(0) and
boundArgs = getArgumentsArray().getSize() and
callback = this.getArgument(0) and
boundArgs = this.getArgumentsArray().getSize() and
result = this
}
}
@@ -1534,8 +1540,8 @@ module PartialInvokeNode {
}
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
callback = getArgument(1) and
result = getArgument(2)
callback = this.getArgument(1) and
result = this.getArgument(2)
}
}
}
@@ -1566,7 +1572,7 @@ class RegExpConstructorInvokeNode extends DataFlow::InvokeNode {
* Gets the AST of the regular expression created here, provided that the
* first argument is a string literal.
*/
RegExpTerm getRoot() { result = getArgument(0).asExpr().(StringLiteral).asRegExp() }
RegExpTerm getRoot() { result = this.getArgument(0).asExpr().(StringLiteral).asRegExp() }
/**
* Gets the flags provided in the second argument, or an empty string if no
@@ -1575,9 +1581,9 @@ class RegExpConstructorInvokeNode extends DataFlow::InvokeNode {
* Has no result if the flags are provided but are not constant.
*/
string getFlags() {
result = getArgument(1).getStringValue()
result = this.getArgument(1).getStringValue()
or
not exists(getArgument(1)) and
not exists(this.getArgument(1)) and
result = ""
}
@@ -1586,9 +1592,9 @@ class RegExpConstructorInvokeNode extends DataFlow::InvokeNode {
* flags are provided, or the string `"?"` if the provided flags are not known.
*/
string tryGetFlags() {
result = getFlags()
result = this.getFlags()
or
not exists(getFlags()) and
not exists(this.getFlags()) and
result = RegExp::unknownFlag()
}
}
@@ -1638,16 +1644,16 @@ class RegExpCreationNode extends DataFlow::SourceNode {
}
/** Holds if the constructed predicate has the `g` flag. */
predicate isGlobal() { RegExp::isGlobal(getFlags()) }
predicate isGlobal() { RegExp::isGlobal(this.getFlags()) }
/** Gets a data flow node referring to this regular expression. */
private DataFlow::SourceNode getAReference(DataFlow::TypeTracker t) {
t.start() and
result = this
or
exists(DataFlow::TypeTracker t2 | result = getAReference(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.getAReference(t2).track(t2, t))
}
/** Gets a data flow node referring to this regular expression. */
DataFlow::SourceNode getAReference() { result = getAReference(DataFlow::TypeTracker::end()) }
DataFlow::SourceNode getAReference() { result = this.getAReference(DataFlow::TypeTracker::end()) }
}

View File

@@ -96,7 +96,7 @@ class TypeTracker extends TTypeTracker {
* Holds if this is the starting point of type tracking, and the initial value is a promise.
* The type tracking only ends after the value has been extracted from the promise.
*/
predicate startInPromise() { startInProp(Promises::valueProp()) }
predicate startInPromise() { this.startInProp(Promises::valueProp()) }
/**
* Holds if this is the starting point of type tracking

View File

@@ -46,12 +46,12 @@ abstract class NPMDependency extends Dependency {
abstract Import getAnImport();
override predicate info(string id, string v) {
id = getNPMPackageName() and
v = getVersion()
id = this.getNPMPackageName() and
v = this.getVersion()
}
override Locatable getAUse(string kind) {
exists(Import i | i = getAnImport() |
exists(Import i | i = this.getAnImport() |
kind = "import" and result = i
or
kind = "use" and result = getATargetVariable(i).getAnAccess()
@@ -95,16 +95,16 @@ class BundledNPMDependency extends NPMDependency {
private NPMPackage getPackage() { this = result.getAModule() }
/** Gets the `package.json` of the package to which this module belongs. */
private PackageJSON getPackageJSON() { result = getPackage().getPackageJSON() }
private PackageJSON getPackageJSON() { result = this.getPackage().getPackageJSON() }
override string getNPMPackageName() { result = getPackageJSON().getPackageName() }
override string getNPMPackageName() { result = this.getPackageJSON().getPackageName() }
override string getVersion() { result = getPackageJSON().getVersion() }
override string getVersion() { result = this.getPackageJSON().getVersion() }
override Import getAnImport() {
this = result.getImportedModule() and
// ignore intra-package imports; they do not induce dependencies
not result.getEnclosingModule() = getPackage().getAModule()
not result.getEnclosingModule() = this.getPackage().getAModule()
}
}
@@ -136,15 +136,15 @@ class ExternalNPMDependency extends NPMDependency {
}
override string getVersion() {
result = getVersionNumber()
result = this.getVersionNumber()
or
// if no version is specified or could not be parsed, report version `unknown`
not exists(getVersionNumber()) and
not exists(this.getVersionNumber()) and
result = "unknown"
}
override Import getAnImport() {
exists(int depth | depth = importsDependency(result, getDeclaringPackage(), this) |
exists(int depth | depth = importsDependency(result, this.getDeclaringPackage(), this) |
// restrict to those results for which this is the closest matching dependency
depth = min(importsDependency(result, _, _))
)
@@ -201,7 +201,7 @@ abstract class ScriptDependency extends Dependency {
kind = "import" and
result = this.getFile().(HTML::HtmlFile).getATopLevel()
or
kind = "use" and result = getAnApiUse()
kind = "use" and result = this.getAnApiUse()
}
}

View File

@@ -106,14 +106,14 @@ class AngularModule extends TAngularModule {
* Get the array of dependencies from this module's definition.
*/
ArrayExpr getDependencyArray() {
getADefinition().getArgument(1).getALocalSource().asExpr() = result
this.getADefinition().getArgument(1).getALocalSource().asExpr() = result
}
/**
* Gets another module that this module lists as a dependency.
*/
AngularModule getADependency() {
getDependencyArray().getAnElement().mayHaveStringValue(result.getName())
this.getDependencyArray().getAnElement().mayHaveStringValue(result.getName())
}
/**
@@ -185,7 +185,7 @@ class ModuleApiCallDependencyInjection extends DependencyInjection {
}
override DataFlow::Node getAnInjectableFunction() {
result = call.getArgument(injectableArgPos())
result = call.getArgument(this.injectableArgPos())
}
}
@@ -231,15 +231,15 @@ class DirectiveInstance extends TDirectiveInstance {
/**
* Gets a DOM element matching this directive.
*/
DOM::ElementDefinition getAMatchingElement() { result = getATarget().getElement() }
DOM::ElementDefinition getAMatchingElement() { result = this.getATarget().getElement() }
/** Gets a textual representation of this directive. */
string toString() { result = getName() }
string toString() { result = this.getName() }
/**
* Gets a scope object for this directive.
*/
AngularScope getAScope() { result.mayApplyTo(getAMatchingElement()) }
AngularScope getAScope() { result.mayApplyTo(this.getAMatchingElement()) }
}
/**
@@ -265,10 +265,10 @@ abstract class CustomDirective extends DirectiveInstance {
abstract DataFlow::ValueNode getMemberInit(string name);
/** Gets the member `name` of this directive. */
DataFlow::SourceNode getMember(string name) { result.flowsTo(getMemberInit(name)) }
DataFlow::SourceNode getMember(string name) { result.flowsTo(this.getMemberInit(name)) }
/** Gets the method `name` of this directive. */
Function getMethod(string name) { DataFlow::valueNode(result) = getMember(name) }
Function getMethod(string name) { DataFlow::valueNode(result) = this.getMember(name) }
/** Gets a link function of this directive. */
abstract Function getALinkFunction();
@@ -283,39 +283,39 @@ abstract class CustomDirective extends DirectiveInstance {
abstract DataFlow::SourceNode getAnInstantiation();
/** Gets the controller function of this directive, if any. */
InjectableFunction getController() { result = getMember("controller") }
InjectableFunction getController() { result = this.getMember("controller") }
/** Gets the template URL of this directive, if any. */
string getTemplateUrl() { getMember("templateUrl").asExpr().mayHaveStringValue(result) }
string getTemplateUrl() { this.getMember("templateUrl").asExpr().mayHaveStringValue(result) }
/**
* Gets a template file for this directive, if any.
*/
HTML::HtmlFile getATemplateFile() {
result.getAbsolutePath().regexpMatch(".*/\\Q" + getTemplateUrl() + "\\E")
result.getAbsolutePath().regexpMatch(".*/\\Q" + this.getTemplateUrl() + "\\E")
}
/**
* Gets a scope object for this directive.
*/
override AngularScope getAScope() {
if hasIsolateScope()
if this.hasIsolateScope()
then result = MkIsolateScope(this)
else result = DirectiveInstance.super.getAScope()
}
private string getRestrictionString() {
getMember("restrict").asExpr().mayHaveStringValue(result)
this.getMember("restrict").asExpr().mayHaveStringValue(result)
}
private predicate hasTargetType(DirectiveTargetType type) {
not exists(getRestrictionString()) or
getRestrictionString().indexOf(type.toString()) != -1
not exists(this.getRestrictionString()) or
this.getRestrictionString().indexOf(type.toString()) != -1
}
override DirectiveTarget getATarget() {
result = DirectiveInstance.super.getATarget() and
hasTargetType(result.getType())
this.hasTargetType(result.getType())
}
}
@@ -342,11 +342,11 @@ class GeneralDirective extends CustomDirective, MkCustomDirective {
}
override DataFlow::ValueNode getMemberInit(string name) {
getAnInstantiation().hasPropertyWrite(name, result)
this.getAnInstantiation().hasPropertyWrite(name, result)
}
/** Gets the compile function of this directive, if any. */
Function getCompileFunction() { result = getMethod("compile") }
Function getCompileFunction() { result = this.getMethod("compile") }
/**
* Gets a pre/post link function of this directive defined on its definition object.
@@ -360,15 +360,15 @@ class GeneralDirective extends CustomDirective, MkCustomDirective {
private DataFlow::FunctionNode getLinkFunction(string kind) {
// { link: function postLink() { ... } }
kind = "post" and
result = getMember("link")
result = this.getMember("link")
or
// { link: { pre: function preLink() { ... }, post: function postLink() { ... } } }
(kind = "pre" or kind = "post") and
result = getMember("link").getAPropertySource(kind)
result = this.getMember("link").getAPropertySource(kind)
or
// { compile: function() { ... return link; } }
exists(Expr compileReturn, DataFlow::SourceNode compileReturnSrc |
compileReturn = getCompileFunction().getAReturnedExpr() and
compileReturn = this.getCompileFunction().getAReturnedExpr() and
compileReturnSrc.flowsToExpr(compileReturn)
|
// link = function postLink() { ... }
@@ -382,18 +382,18 @@ class GeneralDirective extends CustomDirective, MkCustomDirective {
}
/** Gets the pre-link function of this directive. */
Function getPreLinkFunction() { result = getLinkFunction("pre").getAstNode() }
Function getPreLinkFunction() { result = this.getLinkFunction("pre").getAstNode() }
/** Gets the post-link function of this directive. */
Function getPostLinkFunction() { result = getLinkFunction("post").getAstNode() }
Function getPostLinkFunction() { result = this.getLinkFunction("post").getAstNode() }
override Function getALinkFunction() { result = getLinkFunction(_).getAstNode() }
override Function getALinkFunction() { result = this.getLinkFunction(_).getAstNode() }
override predicate bindsToController() {
getMemberInit("bindToController").asExpr().mayHaveBooleanValue(true)
this.getMemberInit("bindToController").asExpr().mayHaveBooleanValue(true)
}
override predicate hasIsolateScope() { getMember("scope").asExpr() instanceof ObjectExpr }
override predicate hasIsolateScope() { this.getMember("scope").asExpr() instanceof ObjectExpr }
}
/**
@@ -527,7 +527,9 @@ class DirectiveTargetName extends string {
* Holds if the first component of this name is `x` or `data`,
* and hence should be stripped when normalizing.
*/
predicate stripFirstComponent() { getRawComponent(0) = "x" or getRawComponent(0) = "data" }
predicate stripFirstComponent() {
this.getRawComponent(0) = "x" or this.getRawComponent(0) = "data"
}
/**
* Gets the `i`th component of this name after processing:
@@ -537,9 +539,9 @@ class DirectiveTargetName extends string {
string getProcessedComponent(int i) {
exists(int j, string raw |
i >= 0 and
if stripFirstComponent() then j = i + 1 else j = i
if this.stripFirstComponent() then j = i + 1 else j = i
|
raw = getRawComponent(j) and
raw = this.getRawComponent(j) and
if i = 0 then result = raw else result = capitalize(raw)
)
}
@@ -548,7 +550,7 @@ class DirectiveTargetName extends string {
* Gets the camelCase version of this name.
*/
string normalize() {
result = concat(string c, int i | c = getProcessedComponent(i) | c, "" order by i)
result = concat(string c, int i | c = this.getProcessedComponent(i) | c, "" order by i)
}
}
@@ -760,27 +762,27 @@ class LinkFunction extends Function {
/**
* Gets the scope parameter of this function.
*/
Parameter getScopeParameter() { result = getParameter(0) }
Parameter getScopeParameter() { result = this.getParameter(0) }
/**
* Gets the element parameter of this function (contains a jqLite-wrapped DOM element).
*/
Parameter getElementParameter() { result = getParameter(1) }
Parameter getElementParameter() { result = this.getParameter(1) }
/**
* Gets the attributes parameter of this function.
*/
Parameter getAttributesParameter() { result = getParameter(2) }
Parameter getAttributesParameter() { result = this.getParameter(2) }
/**
* Gets the controller parameter of this function.
*/
Parameter getControllerParameter() { result = getParameter(3) }
Parameter getControllerParameter() { result = this.getParameter(3) }
/**
* Gets the transclude-function parameter of this function.
*/
Parameter getTranscludeFnParameter() { result = getParameter(4) }
Parameter getTranscludeFnParameter() { result = this.getParameter(4) }
}
/**
@@ -912,7 +914,7 @@ class RouteSetup extends DataFlow::CallNode, DependencyInjection {
* Gets the value of property `name` of the params-object provided to this call.
*/
DataFlow::SourceNode getRouteParam(string name) {
result.flowsTo(getOptionArgument(optionsArgumentIndex, name))
result.flowsTo(this.getOptionArgument(optionsArgumentIndex, name))
}
/**
@@ -921,7 +923,7 @@ class RouteSetup extends DataFlow::CallNode, DependencyInjection {
InjectableFunction getController() {
exists(DataFlow::SourceNode controllerProperty |
// Note that `.getController` cannot be used here, since that involves a cast to InjectableFunction, and that cast only succeeds because of this method
controllerProperty = getRouteParam("controller")
controllerProperty = this.getRouteParam("controller")
|
result = controllerProperty
or
@@ -933,7 +935,7 @@ class RouteSetup extends DataFlow::CallNode, DependencyInjection {
)
}
override DataFlow::Node getAnInjectableFunction() { result = getRouteParam("controller") }
override DataFlow::Node getAnInjectableFunction() { result = this.getRouteParam("controller") }
}
/**
@@ -974,7 +976,7 @@ private class DirectiveController extends Controller {
}
override predicate boundTo(DOM::ElementDefinition elem) {
boundAnonymously(elem) or boundToAs(elem, _)
this.boundAnonymously(elem) or this.boundToAs(elem, _)
}
override predicate boundToAs(DOM::ElementDefinition elem, string alias) {
@@ -1014,7 +1016,7 @@ private class RouteInstantiatedController extends Controller {
}
override predicate boundToAs(DOM::ElementDefinition elem, string name) {
boundTo(elem) and
this.boundTo(elem) and
setup.getRouteParam("controllerAs").asExpr().mayHaveStringValue(name)
}
}
@@ -1049,18 +1051,18 @@ private class BindCall extends DataFlow::PartialInvokeNode::Range, DataFlow::Cal
override predicate isPartialArgument(DataFlow::Node callback, DataFlow::Node argument, int index) {
index >= 0 and
callback = getArgument(1) and
argument = getArgument(index + 2)
callback = this.getArgument(1) and
argument = this.getArgument(index + 2)
}
override DataFlow::SourceNode getBoundFunction(DataFlow::Node callback, int boundArgs) {
callback = getArgument(1) and
boundArgs = getNumArgument() - 2 and
callback = this.getArgument(1) and
boundArgs = this.getNumArgument() - 2 and
result = this
}
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
callback = getArgument(1) and
result = getArgument(0)
callback = this.getArgument(1) and
result = this.getArgument(0)
}
}

View File

@@ -52,7 +52,7 @@ class NgSource extends MkNgSource {
NgSourceProvider getProvider() { result = provider }
/** Gets a textual representation of this element. */
string toString() { result = getText() }
string toString() { result = this.getText() }
}
/**
@@ -68,17 +68,17 @@ private class HtmlTextNodeAsNgSourceProvider extends NgSourceProvider, HTML::Tex
int offset;
HtmlTextNodeAsNgSourceProvider() {
source = getText().regexpFind(getInterpolatedExpressionPattern(), _, offset)
source = this.getText().regexpFind(getInterpolatedExpressionPattern(), _, offset)
}
override predicate providesSourceAt(
string src, string path, int startLine, int startColumn, int endLine, int endColumn
) {
src = source and
getLocation().hasLocationInfo(path, startLine, startColumn, endLine, endColumn) // this is the entire surrounding text element, we could be more precise by counting lines
this.getLocation().hasLocationInfo(path, startLine, startColumn, endLine, endColumn) // this is the entire surrounding text element, we could be more precise by counting lines
}
override DOM::ElementDefinition getEnclosingElement() { result = getParent() }
override DOM::ElementDefinition getEnclosingElement() { result = this.getParent() }
}
/**
@@ -88,8 +88,8 @@ abstract private class HtmlAttributeAsNgSourceProvider extends NgSourceProvider,
override predicate providesSourceAt(
string src, string path, int startLine, int startColumn, int endLine, int endColumn
) {
src = getSource() and
getLocation().hasLocationInfo(path, startLine, startColumn - getOffset(), endLine, _) and
src = this.getSource() and
this.getLocation().hasLocationInfo(path, startLine, startColumn - this.getOffset(), endLine, _) and
endColumn = startColumn + src.length() - 1
}
@@ -99,7 +99,7 @@ abstract private class HtmlAttributeAsNgSourceProvider extends NgSourceProvider,
/** The offset into the attribute where the expression starts. */
abstract int getOffset();
override DOM::ElementDefinition getEnclosingElement() { result = getElement() }
override DOM::ElementDefinition getEnclosingElement() { result = this.getElement() }
}
/**
@@ -110,7 +110,7 @@ private class HtmlAttributeAsInterpolatedNgSourceProvider extends HtmlAttributeA
int offset;
HtmlAttributeAsInterpolatedNgSourceProvider() {
source = getValue().regexpFind(getInterpolatedExpressionPattern(), _, offset) and
source = this.getValue().regexpFind(getInterpolatedExpressionPattern(), _, offset) and
not this instanceof HtmlAttributeAsPlainNgSourceProvider
}
@@ -137,7 +137,7 @@ private class HtmlAttributeAsPlainNgSourceProvider extends HtmlAttributeAsNgSour
)
}
override string getSource() { result = getValue() }
override string getSource() { result = this.getValue() }
override int getOffset() { result = 0 }
}
@@ -162,7 +162,7 @@ private class TemplateFieldNgSourceProvider extends NgSourceProvider {
string src, string path, int startLine, int startColumn, int endLine, int endColumn
) {
src = source and
getLocation().hasLocationInfo(path, startLine, startColumn - offset, endLine, _) and
this.getLocation().hasLocationInfo(path, startLine, startColumn - offset, endLine, _) and
endColumn = startColumn + src.length() - 1
}
@@ -180,7 +180,7 @@ abstract class NgToken extends TNgToken {
/** Gets a textual representation of this element. */
string toString() {
exists(string content |
is(content) and
this.is(content) and
result = "(" + this.ppKind() + ": " + content + ")"
)
}
@@ -370,7 +370,7 @@ abstract class NgAstNode extends TNode {
string ppChildren() {
result =
concat(NgAstNode child, int idx |
child = getChild(idx) and
child = this.getChild(idx) and
not child instanceof Empty
|
child.pp(), " " order by idx
@@ -378,7 +378,7 @@ abstract class NgAstNode extends TNode {
}
/** Gets a textual representation of this element. */
string toString() { result = pp() }
string toString() { result = this.pp() }
/**
* Pretty-prints this node.
@@ -394,8 +394,8 @@ class NgAst extends TNgAst, NgAstNode {
override string pp() {
exists(string oneTime |
(if isOneTime() then oneTime = " <oneTime>" else oneTime = "") and
result = "(NgAst:" + oneTime + " " + ppChildren() + ")"
(if this.isOneTime() then oneTime = " <oneTime>" else oneTime = "") and
result = "(NgAst:" + oneTime + " " + this.ppChildren() + ")"
)
}
@@ -413,7 +413,7 @@ class NgAst extends TNgAst, NgAstNode {
class NgExprStmt extends TNgExprStmt, NgAstNode {
override predicate at(NgToken start, NgToken end) { this = TNgExprStmt(start, end, _) }
override string pp() { result = "(NgExprStmt: " + ppChildren() + ")" }
override string pp() { result = "(NgExprStmt: " + this.ppChildren() + ")" }
override NgAstNode getChild(int n) { n = 0 and this = TNgExprStmt(_, _, result) }
}
@@ -426,12 +426,12 @@ class NgExprStmt extends TNgExprStmt, NgAstNode {
class NgFilterChain extends TNgFilterChain, NgAstNode {
override predicate at(NgToken start, NgToken end) { this = TNgFilterChain(start, end, _, _) }
override string pp() { result = "(NgFilterChain: " + ppChildren() + ")" }
override string pp() { result = "(NgFilterChain: " + this.ppChildren() + ")" }
override NgAstNode getChild(int n) {
n = 0 and result = getExpr()
n = 0 and result = this.getExpr()
or
n = 1 and result = getFilter()
n = 1 and result = this.getFilter()
}
/**
@@ -458,12 +458,12 @@ abstract class NgMaybeFilter extends NgAstNode { }
class NgFilter extends TNgFilter, NgMaybeFilter {
override predicate at(NgToken start, NgToken end) { this = TNgFilter(start, end, _, _) }
override string pp() { result = "(NgFilter: " + ppChildren() + ")" }
override string pp() { result = "(NgFilter: " + this.ppChildren() + ")" }
override NgAstNode getChild(int n) {
n = 0 and result = getHeadFilter()
n = 0 and result = this.getHeadFilter()
or
n = 1 and result = getTailFilter()
n = 1 and result = this.getTailFilter()
}
/**
@@ -488,11 +488,11 @@ class NgSingleFilter extends TNgSingleFilter, NgAstNode {
override string pp() {
exists(string sep |
(
if forall(NgAstNode child | child = getChild(_) | child instanceof Empty)
if forall(NgAstNode child | child = this.getChild(_) | child instanceof Empty)
then sep = ""
else sep = " "
) and
result = "(NgSingleFilter: " + getName() + sep + ppChildren() + ")"
result = "(NgSingleFilter: " + this.getName() + sep + this.ppChildren() + ")"
)
}
@@ -506,7 +506,7 @@ class NgSingleFilter extends TNgSingleFilter, NgAstNode {
/**
* Gets the `i`th argument expression of this filter call.
*/
NgExpr getArgument(int i) { result = getChild(0).(NgFilterArgument).getElement(i) }
NgExpr getArgument(int i) { result = this.getChild(0).(NgFilterArgument).getElement(i) }
}
/**
@@ -524,7 +524,7 @@ class NgVarExpr extends TNgVarExpr, NgExpr {
override predicate at(NgToken start, NgToken end) { start = end and start = identifier }
override string pp() { result = "(NgVarExpr: " + getName() + ")" }
override string pp() { result = "(NgVarExpr: " + this.getName() + ")" }
override NgAstNode getChild(int n) { none() }
@@ -540,9 +540,11 @@ class NgVarExpr extends TNgVarExpr, NgExpr {
class NgDotExpr extends TNgDotExpr, NgExpr {
override predicate at(NgToken start, NgToken end) { this = TNgDotExpr(start, end, _, _) }
override string pp() { result = "(NgDotExpr: " + getBase().pp() + "." + getName() + ")" }
override string pp() {
result = "(NgDotExpr: " + this.getBase().pp() + "." + this.getName() + ")"
}
override NgAstNode getChild(int n) { n = 0 and result = getBase() }
override NgAstNode getChild(int n) { n = 0 and result = this.getBase() }
/**
* Gets the node for the base expression of this expression.
@@ -561,7 +563,7 @@ class NgDotExpr extends TNgDotExpr, NgExpr {
class NgCallExpr extends TNgCallExpr, NgExpr {
override predicate at(NgToken start, NgToken end) { this = TNgCallExpr(start, end, _, _) }
override string pp() { result = "(NgCallExpr: " + ppChildren() + ")" }
override string pp() { result = "(NgCallExpr: " + this.ppChildren() + ")" }
override NgAstNode getChild(int n) {
n = 0 and this = TNgCallExpr(_, _, result, _)
@@ -572,12 +574,12 @@ class NgCallExpr extends TNgCallExpr, NgExpr {
/**
* Gets the callee expression of this call.
*/
NgExpr getCallee() { result = getChild(0) }
NgExpr getCallee() { result = this.getChild(0) }
/**
* Gets the `i`th argument expression of this call.
*/
NgExpr getArgument(int i) { result = getChild(1).(NgConsCallArgument).getElement(i) }
NgExpr getArgument(int i) { result = this.getChild(1).(NgConsCallArgument).getElement(i) }
}
/**
@@ -590,7 +592,7 @@ class NgString extends TNgString, NgExpr {
override predicate at(NgToken start, NgToken end) { start = end and start = stringToken }
override string pp() { result = getRawValue() }
override string pp() { result = this.getRawValue() }
override NgAstNode getChild(int n) { none() }
@@ -602,7 +604,9 @@ class NgString extends TNgString, NgExpr {
/**
* Gets the string value of this expression, excluding surrounding quotes.
*/
string getStringValue() { result = getRawValue().substring(1, getRawValue().length() - 1) }
string getStringValue() {
result = this.getRawValue().substring(1, this.getRawValue().length() - 1)
}
}
/**
@@ -615,7 +619,7 @@ class NgNumber extends TNgNumber, NgExpr {
override predicate at(NgToken start, NgToken end) { start = end and start = numberToken }
override string pp() { result = getValue() }
override string pp() { result = this.getValue() }
override NgAstNode getChild(int n) { none() }
@@ -636,7 +640,7 @@ abstract class NgMaybeFilterArgument extends NgAstNode { }
class NgFilterArgument extends TNgFilterArgument, NgMaybeFilterArgument {
override predicate at(NgToken start, NgToken end) { this = TNgFilterArgument(start, end, _, _) }
override string pp() { result = "(NgFilterArgument: " + ppChildren() + ")" }
override string pp() { result = "(NgFilterArgument: " + this.ppChildren() + ")" }
override NgAstNode getChild(int n) {
n = 0 and this = TNgFilterArgument(_, _, result, _)
@@ -649,8 +653,8 @@ class NgFilterArgument extends TNgFilterArgument, NgMaybeFilterArgument {
*/
NgExpr getElement(int i) {
if i = 0
then result = getChild(0)
else result = getChild(1).(NgFilterArgument).getElement(i - 1)
then result = this.getChild(0)
else result = this.getChild(1).(NgFilterArgument).getElement(i - 1)
}
}
@@ -665,7 +669,7 @@ abstract class NgCallArguments extends NgAstNode { }
class NgConsCallArgument extends TNgConsCallArgument, NgCallArguments {
override predicate at(NgToken start, NgToken end) { this = TNgConsCallArgument(start, end, _, _) }
override string pp() { result = "(NgConsCallArgument: " + ppChildren() + ")" }
override string pp() { result = "(NgConsCallArgument: " + this.ppChildren() + ")" }
override NgAstNode getChild(int n) {
n = 0 and this = TNgConsCallArgument(_, _, result, _)
@@ -678,8 +682,8 @@ class NgConsCallArgument extends TNgConsCallArgument, NgCallArguments {
*/
NgExpr getElement(int i) {
if i = 0
then result = getChild(0)
else result = getChild(1).(NgConsCallArgument).getElement(i - 1)
then result = this.getChild(0)
else result = this.getChild(1).(NgConsCallArgument).getElement(i - 1)
}
}

View File

@@ -63,7 +63,7 @@ class ClientRequest extends DataFlow::InvokeNode instanceof ClientRequest::Range
* Gets a node that refers to data from the response, possibly
* wrapped in a promise object.
*/
DataFlow::Node getAResponseDataNode() { result = getAResponseDataNode(_, _) }
DataFlow::Node getAResponseDataNode() { result = this.getAResponseDataNode(_, _) }
/**
* Gets a data-flow node that determines where in the file-system the result of the request should be saved.
@@ -151,41 +151,41 @@ module ClientRequest {
}
override DataFlow::Node getUrl() {
result = getArgument(0) or
result = getOptionArgument(0, urlPropertyName())
result = this.getArgument(0) or
result = this.getOptionArgument(0, urlPropertyName())
}
override DataFlow::Node getHost() { none() }
/** Gets the response type from the options passed in. */
string getResponseType() {
if getOptionArgument(1, "json").mayHaveBooleanValue(true)
if this.getOptionArgument(1, "json").mayHaveBooleanValue(true)
then result = "json"
else result = "text"
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean pr) {
responseType = getResponseType() and
responseType = this.getResponseType() and
promise = true and
pr = true and
result = this
or
responseType = getResponseType() and
responseType = this.getResponseType() and
promise = false and
pr = false and
(
result = getCallback([1 .. 2]).getParameter(2)
result = this.getCallback([1 .. 2]).getParameter(2)
or
result = getCallback([1 .. 2]).getParameter(1).getAPropertyRead("body")
result = this.getCallback([1 .. 2]).getParameter(1).getAPropertyRead("body")
)
or
responseType = "error" and
promise = false and
pr = false and
result = getCallback([1 .. 2]).getParameter(0)
result = this.getCallback([1 .. 2]).getParameter(0)
}
override DataFlow::Node getADataNode() { result = getArgument(1) }
override DataFlow::Node getADataNode() { result = this.getArgument(1) }
override DataFlow::Node getASavePath() {
exists(DataFlow::CallNode write |
@@ -224,50 +224,50 @@ module ClientRequest {
}
private DataFlow::Node getOptionArgument(string name) {
result = getOptionArgument(getOptionsArgIndex(), name)
result = this.getOptionArgument(this.getOptionsArgIndex(), name)
}
override DataFlow::Node getUrl() {
result = getArgument(0) or
result = getOptionArgument(urlPropertyName())
result = this.getArgument(0) or
result = this.getOptionArgument(urlPropertyName())
}
override DataFlow::Node getHost() { result = getOptionArgument("host") }
override DataFlow::Node getHost() { result = this.getOptionArgument("host") }
override DataFlow::Node getADataNode() {
method = "request" and
result = getOptionArgument(0, "data")
result = this.getOptionArgument(0, "data")
or
method = ["post", "put"] and
result = [getArgument(1), getOptionArgument(2, "data")]
result = [this.getArgument(1), this.getOptionArgument(2, "data")]
or
result = getOptionArgument([0 .. 2], ["headers", "params"])
result = this.getOptionArgument([0 .. 2], ["headers", "params"])
}
/** Gets the response type from the options passed in. */
string getResponseType() {
exists(DataFlow::Node option | option = getOptionArgument("responseType") |
exists(DataFlow::Node option | option = this.getOptionArgument("responseType") |
option.mayHaveStringValue(result)
or
option.analyze().getAValue().isIndefinite(_) and
result = ""
)
or
not exists(getOptionArgument("responseType")) and
not exists(this.getOptionArgument("responseType")) and
result = "json"
or
getArgument(getOptionsArgIndex()).analyze().getAValue().isIndefinite(_) and
this.getArgument(this.getOptionsArgIndex()).analyze().getAValue().isIndefinite(_) and
result = ""
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
responseType = getResponseType() and
responseType = this.getResponseType() and
promise = true and
result = this
or
responseType = getResponseType() and
responseType = this.getResponseType() and
promise = false and
result = getReturn().getPromisedError().getMember("response").getAnImmediateUse()
result = this.getReturn().getPromisedError().getMember("response").getAnImmediateUse()
}
}
@@ -303,7 +303,7 @@ module ClientRequest {
fetch = DataFlow::globalVarRef("fetch") // https://fetch.spec.whatwg.org/#fetch-api
|
this = fetch.getACall() and
url = getArgument(0)
url = this.getArgument(0)
)
}
@@ -312,7 +312,9 @@ module ClientRequest {
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() {
exists(string name | name = "headers" or name = "body" | result = getOptionArgument(1, name))
exists(string name | name = "headers" or name = "body" |
result = this.getOptionArgument(1, name)
)
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
@@ -334,14 +336,14 @@ module ClientRequest {
PromisedNeedleRequest() { this = DataFlow::moduleImport("needle").getACall() }
override DataFlow::Node getUrl() { result = getArgument(1) }
override DataFlow::Node getUrl() { result = this.getArgument(1) }
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() {
result = getOptionArgument([2, 3], "headers")
result = this.getOptionArgument([2, 3], "headers")
or
result = getArgument(2)
result = this.getArgument(2)
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
@@ -373,20 +375,20 @@ module ClientRequest {
)
}
override DataFlow::Node getUrl() { result = getArgument(0) }
override DataFlow::Node getUrl() { result = this.getArgument(0) }
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() {
hasData = true and
(
result = getArgument(1)
result = this.getArgument(1)
or
result = getOptionArgument(2, "headers")
result = this.getOptionArgument(2, "headers")
)
or
hasData = false and
result = getOptionArgument(1, "headers")
result = this.getOptionArgument(1, "headers")
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
@@ -416,8 +418,8 @@ module ClientRequest {
}
override DataFlow::Node getUrl() {
result = getArgument(0) and
not exists(getOptionArgument(1, "baseUrl"))
result = this.getArgument(0) and
not exists(this.getOptionArgument(1, "baseUrl"))
}
override DataFlow::Node getHost() {
@@ -425,34 +427,34 @@ module ClientRequest {
name = "host" or
name = "hostname"
|
result = getOptionArgument(1, name)
result = this.getOptionArgument(1, name)
)
}
override DataFlow::Node getADataNode() {
exists(string name | name = "headers" or name = "body" or name = "query" |
result = getOptionArgument(1, name)
result = this.getOptionArgument(1, name)
)
}
/** Holds if the result is a stream. */
predicate isStream() {
getOptionArgument(1, "stream").mayHaveBooleanValue(true)
this.getOptionArgument(1, "stream").mayHaveBooleanValue(true)
or
this = DataFlow::moduleMember("got", "stream").getACall()
}
/** Holds if the result is a JSON object. */
predicate isJson() { getOptionArgument(1, "json").mayHaveBooleanValue(true) }
predicate isJson() { this.getOptionArgument(1, "json").mayHaveBooleanValue(true) }
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
result = this and
if isStream()
if this.isStream()
then
responseType = "stream" and
promise = false
else
if isJson()
if this.isJson()
then (
responseType = "json" and
promise = true
@@ -487,10 +489,10 @@ module ClientRequest {
}
override DataFlow::Node getUrl() {
result = getArgument([0, 1]) // there are multiple overrides of `connect`, and the URL can be in the first or second argument.
result = this.getArgument([0, 1]) // there are multiple overrides of `connect`, and the URL can be in the first or second argument.
}
override DataFlow::Node getHost() { result = getOptionArgument(0, "host") }
override DataFlow::Node getHost() { result = this.getOptionArgument(0, "host") }
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
responseType = "text" and
@@ -520,7 +522,7 @@ module ClientRequest {
exists(string moduleName, DataFlow::SourceNode callee | this = callee.getACall() |
moduleName = "superagent" and
callee = DataFlow::moduleMember(moduleName, httpMethodName()) and
url = getArgument(0)
url = this.getArgument(0)
)
}
@@ -540,7 +542,7 @@ module ClientRequest {
result = this
or
exists(DataFlow::FunctionNode callback |
callback = getAChainedMethodCall("end").getCallback(0) and
callback = this.getAChainedMethodCall("end").getCallback(0) and
promise = false and
(
responseType = "error" and result = callback.getParameter(0)
@@ -564,14 +566,14 @@ module ClientRequest {
this = Closure::moduleImport("goog.net.XmlHttp").getAnInvocation()
}
override DataFlow::Node getUrl() { result = getAMethodCall("open").getArgument(1) }
override DataFlow::Node getUrl() { result = this.getAMethodCall("open").getArgument(1) }
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() { result = getAMethodCall("send").getArgument(0) }
override DataFlow::Node getADataNode() { result = this.getAMethodCall("send").getArgument(0) }
private string getExplicitResponseType() {
getAPropertyWrite("responseType").getRhs().mayHaveStringValue(result)
this.getAPropertyWrite("responseType").getRhs().mayHaveStringValue(result)
}
/**
@@ -579,17 +581,17 @@ module ClientRequest {
* but not the explicitly typed properties, `reponseText` and `responseXML`.
*/
string getAssignedResponseType() {
result = getExplicitResponseType()
result = this.getExplicitResponseType()
or
not exists(getExplicitResponseType()) and
not exists(this.getExplicitResponseType()) and
result = "text"
}
/** Gets an event listener registered on this XHR object. */
DataFlow::FunctionNode getAnEventListener() {
result = getAPropertyWrite("on" + any(string s)).getRhs().getAFunctionValue()
result = this.getAPropertyWrite("on" + any(string s)).getRhs().getAFunctionValue()
or
result = getAMethodCall("addEventListener").getArgument(1).getAFunctionValue()
result = this.getAMethodCall("addEventListener").getArgument(1).getAFunctionValue()
}
/**
@@ -601,14 +603,14 @@ module ClientRequest {
result = this
or
// The value of `this` in an event listener refers to the XHR object
result = getAnEventListener().getReceiver()
result = this.getAnEventListener().getReceiver()
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
promise = false and
(
exists(string prop | result = getAnAlias().getAPropertyRead(prop) |
prop = "response" and responseType = getAssignedResponseType()
exists(string prop | result = this.getAnAlias().getAPropertyRead(prop) |
prop = "response" and responseType = this.getAssignedResponseType()
or
prop = "responseText" and responseType = "text"
or
@@ -619,7 +621,7 @@ module ClientRequest {
prop = "responseXML" and responseType = "document"
)
or
exists(string method | result = getAnAlias().getAMethodCall(method) |
exists(string method | result = this.getAnAlias().getAMethodCall(method) |
method = "getAllResponseHeaders" and responseType = "headers"
or
method = "getResponseHeader" and responseType = "header"
@@ -647,16 +649,16 @@ module ClientRequest {
)
}
override DataFlow::Node getUrl() { result = getArgument(0) }
override DataFlow::Node getUrl() { result = this.getArgument(0) }
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() { result = getArgument([2 .. 3]) }
override DataFlow::Node getADataNode() { result = this.getArgument([2 .. 3]) }
/** Gets an event listener with `this` bound to this object. */
DataFlow::FunctionNode getAnEventListener() {
static = true and
result = getAnArgument().getAFunctionValue()
result = this.getAnArgument().getAFunctionValue()
or
static = false and
exists(DataFlow::MethodCallNode listen, string name |
@@ -676,7 +678,7 @@ module ClientRequest {
static = false and
result = base
or
result = getAnEventListener().getReceiver()
result = this.getAnEventListener().getReceiver()
}
/**
@@ -684,16 +686,16 @@ module ClientRequest {
* for explicitly typed calls like `getResponseJson()`.
*/
string getAssignedResponseType() {
getAMethodCall("setResponseType").getArgument(0).mayHaveStringValue(result)
this.getAMethodCall("setResponseType").getArgument(0).mayHaveStringValue(result)
or
not exists(getAMethodCall("setResponseType")) and
not exists(this.getAMethodCall("setResponseType")) and
result = "text"
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
promise = false and
exists(string method | result = getAnAlias().getAMethodCall(method) |
method = "getResponse" and responseType = getAssignedResponseType()
exists(string method | result = this.getAnAlias().getAMethodCall(method) |
method = "getResponse" and responseType = this.getAssignedResponseType()
or
method = "getResponseHeader" and responseType = "header"
or
@@ -752,7 +754,7 @@ module ClientRequest {
}
override DataFlow::Node getUrl() {
result = getArgument(optionsArg).getALocalSource().getAPropertyWrite("url").getRhs()
result = this.getArgument(optionsArg).getALocalSource().getAPropertyWrite("url").getRhs()
}
override DataFlow::Node getHost() { none() }
@@ -766,7 +768,7 @@ module ClientRequest {
class Nugget extends ClientRequest::Range, DataFlow::CallNode {
Nugget() { this = DataFlow::moduleImport("nugget").getACall() }
override DataFlow::Node getUrl() { result = getArgument(0) }
override DataFlow::Node getUrl() { result = this.getArgument(0) }
override DataFlow::Node getHost() { none() }
@@ -812,7 +814,7 @@ module ClientRequest {
this = API::moduleImport("jsdom").getMember("JSDOM").getMember("fromURL").getACall()
}
override DataFlow::Node getUrl() { result = getArgument(0) }
override DataFlow::Node getUrl() { result = this.getArgument(0) }
override DataFlow::Node getHost() { none() }
@@ -842,7 +844,7 @@ module ClientRequest {
class ApolloClientRequest extends ClientRequest::Range, API::InvokeNode {
ApolloClientRequest() { this = apolloUriCallee().getAnInvocation() }
override DataFlow::Node getUrl() { result = getParameter(0).getMember("uri").getARhs() }
override DataFlow::Node getUrl() { result = this.getParameter(0).getMember("uri").getARhs() }
override DataFlow::Node getHost() { none() }
@@ -861,9 +863,9 @@ module ClientRequest {
this = form.getMember("submit").getACall()
}
override DataFlow::Node getUrl() { result = getArgument(0) }
override DataFlow::Node getUrl() { result = this.getArgument(0) }
override DataFlow::Node getHost() { result = getParameter(0).getMember("host").getARhs() }
override DataFlow::Node getHost() { result = this.getParameter(0).getMember("host").getARhs() }
override DataFlow::Node getADataNode() {
result = form.getMember("append").getACall().getParameter(1).getARhs()

View File

@@ -29,10 +29,10 @@ module ConnectExpressShared {
/** Gets the number of parameters taken by this signature. */
pragma[noinline]
int getArity() { result = count(getParameterIndex(_)) }
int getArity() { result = count(this.getParameterIndex(_)) }
/** Holds if this signature takes a parameter of the given kind. */
predicate has(string kind) { exists(getParameterIndex(kind)) }
predicate has(string kind) { exists(this.getParameterIndex(kind)) }
}
private module RouteHandlerSignature {

View File

@@ -112,7 +112,7 @@ private module JsCookie {
ReadAccess() { this = libMemberCall("get") }
override PersistentWriteAccess getAWrite() {
getArgument(0).mayHaveStringValue(result.(WriteAccess).getKey())
this.getArgument(0).mayHaveStringValue(result.(WriteAccess).getKey())
}
}
@@ -120,9 +120,9 @@ private module JsCookie {
CookieWrites::ClientSideCookieWrite {
WriteAccess() { this = libMemberCall("set") }
string getKey() { getArgument(0).mayHaveStringValue(result) }
string getKey() { this.getArgument(0).mayHaveStringValue(result) }
override DataFlow::Node getValue() { result = getArgument(1) }
override DataFlow::Node getValue() { result = this.getArgument(1) }
override predicate isSecure() {
// A cookie is secure if there are cookie options with the `secure` flag set to `true`.
@@ -150,7 +150,7 @@ private module BrowserCookies {
ReadAccess() { this = libMemberCall("get") }
override PersistentWriteAccess getAWrite() {
getArgument(0).mayHaveStringValue(result.(WriteAccess).getKey())
this.getArgument(0).mayHaveStringValue(result.(WriteAccess).getKey())
}
}
@@ -158,9 +158,9 @@ private module BrowserCookies {
CookieWrites::ClientSideCookieWrite {
WriteAccess() { this = libMemberCall("set") }
string getKey() { getArgument(0).mayHaveStringValue(result) }
string getKey() { this.getArgument(0).mayHaveStringValue(result) }
override DataFlow::Node getValue() { result = getArgument(1) }
override DataFlow::Node getValue() { result = this.getArgument(1) }
override predicate isSecure() {
// A cookie is secure if there are cookie options with the `secure` flag set to `true`.
@@ -199,9 +199,9 @@ private module LibCookie {
CookieWrites::ClientSideCookieWrite {
WriteAccess() { this = libMemberCall("serialize") }
string getKey() { getArgument(0).mayHaveStringValue(result) }
string getKey() { this.getArgument(0).mayHaveStringValue(result) }
override DataFlow::Node getValue() { result = getArgument(1) }
override DataFlow::Node getValue() { result = this.getArgument(1) }
override predicate isSecure() {
// A cookie is secure if there are cookie options with the `secure` flag set to `true`.
@@ -256,7 +256,7 @@ private module ExpressCookies {
override predicate isSecure() {
// The flag `secure` is set to `false` by default for HTTP, `true` by default for HTTPS (https://github.com/expressjs/cookie-session#cookie-options).
// A cookie is secure if the `secure` flag is not explicitly set to `false`.
not getCookieFlagValue(CookieWrites::secure()).mayHaveBooleanValue(false)
not this.getCookieFlagValue(CookieWrites::secure()).mayHaveBooleanValue(false)
}
override predicate isSensitive() {
@@ -266,7 +266,7 @@ private module ExpressCookies {
override predicate isHttpOnly() {
// The flag `httpOnly` is set to `true` by default (https://github.com/expressjs/cookie-session#cookie-options).
// A cookie is httpOnly if the `httpOnly` flag is not explicitly set to `false`.
not getCookieFlagValue(CookieWrites::httpOnly()).mayHaveBooleanValue(false)
not this.getCookieFlagValue(CookieWrites::httpOnly()).mayHaveBooleanValue(false)
}
}
@@ -282,7 +282,7 @@ private module ExpressCookies {
override predicate isSecure() {
// The flag `secure` is not set by default (https://github.com/expressjs/session#Cookiesecure).
// The default value for cookie options is { path: '/', httpOnly: true, secure: false, maxAge: null }.
exists(DataFlow::Node value | value = getCookieFlagValue(CookieWrites::secure()) |
exists(DataFlow::Node value | value = this.getCookieFlagValue(CookieWrites::secure()) |
not value.mayHaveBooleanValue(false) // anything but `false` is accepted as being maybe true
)
}
@@ -295,7 +295,7 @@ private module ExpressCookies {
// The flag `httpOnly` is set by default (https://github.com/expressjs/session#Cookiesecure).
// The default value for cookie options is { path: '/', httpOnly: true, secure: false, maxAge: null }.
// A cookie is httpOnly if the `httpOnly` flag is not explicitly set to `false`.
not getCookieFlagValue(CookieWrites::httpOnly()).mayHaveBooleanValue(false)
not this.getCookieFlagValue(CookieWrites::httpOnly()).mayHaveBooleanValue(false)
}
}
}

View File

@@ -51,7 +51,7 @@ module Electron {
private class BrowserObjectByType extends BrowserObject {
BrowserObjectByType() {
exists(string tp | tp = "BrowserWindow" or tp = "BrowserView" |
asExpr().getType().hasUnderlyingType("electron", tp)
this.asExpr().getType().hasUnderlyingType("electron", tp)
)
}
}
@@ -162,7 +162,7 @@ module Electron {
*/
override DataFlow::Node getSentItem(int i) {
i >= 1 and
result = getArgument(i)
result = this.getArgument(i)
}
/**
@@ -206,8 +206,8 @@ module Electron {
}
override DataFlow::Node getUrl() {
result = getArgument(0) or
result = getOptionArgument(0, "url")
result = this.getArgument(0) or
result = this.getOptionArgument(0, "url")
}
override DataFlow::Node getHost() {
@@ -215,7 +215,7 @@ module Electron {
name = "host" or
name = "hostname"
|
result = getOptionArgument(0, name)
result = this.getOptionArgument(0, name)
)
}

View File

@@ -80,18 +80,18 @@ module Express {
*/
class RouteSetup extends HTTP::Servers::StandardRouteSetup, MethodCallExpr {
RouteSetup() {
isRouter(getReceiver()) and
getMethodName() = routeSetupMethodName()
isRouter(this.getReceiver()) and
this.getMethodName() = routeSetupMethodName()
}
/** Gets the path associated with the route. */
string getPath() { getArgument(0).mayHaveStringValue(result) }
string getPath() { this.getArgument(0).mayHaveStringValue(result) }
/** Gets the router on which handlers are being registered. */
RouterDefinition getRouter() { isRouter(getReceiver(), result) }
RouterDefinition getRouter() { isRouter(this.getReceiver(), result) }
/** Holds if this is a call `use`, such as `app.use(handler)`. */
predicate isUseCall() { getMethodName() = "use" }
predicate isUseCall() { this.getMethodName() = "use" }
/**
* Gets the `n`th handler registered by this setup, with 0 being the first.
@@ -102,30 +102,34 @@ module Express {
Expr getRouteHandlerExpr(int index) {
// The first argument is a URI pattern if it is a string. If it could possibly be
// a function, we consider it to be a route handler, otherwise a URI pattern.
exists(AnalyzedNode firstArg | firstArg = getArgument(0).analyze() |
exists(AnalyzedNode firstArg | firstArg = this.getArgument(0).analyze() |
if firstArg.getAType() = TTFunction()
then result = getArgument(index)
then result = this.getArgument(index)
else (
index >= 0 and result = getArgument(index + 1)
index >= 0 and result = this.getArgument(index + 1)
)
)
}
/** Gets an argument that represents a route handler being registered. */
Expr getARouteHandlerExpr() { result = getRouteHandlerExpr(_) }
Expr getARouteHandlerExpr() { result = this.getRouteHandlerExpr(_) }
/** Gets the last argument representing a route handler being registered. */
Expr getLastRouteHandlerExpr() { result = max(int i | | getRouteHandlerExpr(i) order by i) }
Expr getLastRouteHandlerExpr() {
result = max(int i | | this.getRouteHandlerExpr(i) order by i)
}
override DataFlow::SourceNode getARouteHandler() {
result = getARouteHandler(DataFlow::TypeBackTracker::end())
result = this.getARouteHandler(DataFlow::TypeBackTracker::end())
}
private DataFlow::SourceNode getARouteHandler(DataFlow::TypeBackTracker t) {
t.start() and
result = getARouteHandlerExpr().flow().getALocalSource()
result = this.getARouteHandlerExpr().flow().getALocalSource()
or
exists(DataFlow::TypeBackTracker t2, DataFlow::SourceNode succ | succ = getARouteHandler(t2) |
exists(DataFlow::TypeBackTracker t2, DataFlow::SourceNode succ |
succ = this.getARouteHandler(t2)
|
result = succ.backtrack(t2, t)
or
HTTP::routeHandlerStep(result, succ) and
@@ -133,19 +137,19 @@ module Express {
)
}
override Expr getServer() { result.(Application).getARouteHandler() = getARouteHandler() }
override Expr getServer() { result.(Application).getARouteHandler() = this.getARouteHandler() }
/**
* Gets the HTTP request type this is registered for, if any.
*
* Has no result for `use`, `all`, or `param` calls.
*/
HTTP::RequestMethodName getRequestMethod() { result.toLowerCase() = getMethodName() }
HTTP::RequestMethodName getRequestMethod() { result.toLowerCase() = this.getMethodName() }
/**
* Holds if this registers a route for all request methods.
*/
predicate handlesAllRequestMethods() { getMethodName() = ["use", "all", "param"] }
predicate handlesAllRequestMethods() { this.getMethodName() = ["use", "all", "param"] }
/**
* Holds if this route setup sets up a route for the same
@@ -161,7 +165,7 @@ module Express {
/**
* Holds if this route setup is a parameter handler, such as `app.param("foo", ...)`.
*/
predicate isParameterHandler() { getMethodName() = "param" }
predicate isParameterHandler() { this.getMethodName() = "param" }
}
/**
@@ -228,7 +232,7 @@ module Express {
* Gets the function body of this handler, if it is defined locally.
*/
RouteHandler getBody() {
exists(DataFlow::SourceNode source | source = flow().getALocalSource() |
exists(DataFlow::SourceNode source | source = this.flow().getALocalSource() |
result = source
or
DataFlow::functionOneWayForwardingStep(result.(DataFlow::SourceNode).getALocalUse(), source)
@@ -296,7 +300,7 @@ module Express {
* `r2` installed on a subrouter, `r1` will not be recognized as an ancestor of `r2`.
*/
Express::RouteHandlerExpr getAMatchingAncestor() {
result = getPreviousMiddleware+() and
result = this.getPreviousMiddleware+() and
exists(RouteSetup resSetup | resSetup = result.getSetup() |
// check whether request methods are compatible
resSetup.handlesSameRequestMethodAs(setup) and
@@ -343,17 +347,17 @@ module Express {
/**
* Gets the parameter of the route handler that contains the request object.
*/
Parameter getRequestParameter() { result = getRouteHandlerParameter("request") }
Parameter getRequestParameter() { result = this.getRouteHandlerParameter("request") }
/**
* Gets the parameter of the route handler that contains the response object.
*/
Parameter getResponseParameter() { result = getRouteHandlerParameter("response") }
Parameter getResponseParameter() { result = this.getRouteHandlerParameter("response") }
/**
* Gets a request body access of this handler.
*/
Expr getARequestBodyAccess() { result.(PropAccess).accesses(getARequestExpr(), "body") }
Expr getARequestBodyAccess() { result.(PropAccess).accesses(this.getARequestExpr(), "body") }
}
/**
@@ -412,7 +416,7 @@ module Express {
* An Express response source, based on static type information.
*/
private class TypedResponseSource extends ResponseSource {
TypedResponseSource() { hasUnderlyingType("express", "Response") }
TypedResponseSource() { this.hasUnderlyingType("express", "Response") }
override RouteHandler getRouteHandler() { none() } // Not known.
}
@@ -439,7 +443,7 @@ module Express {
* An Express request source, based on static type information.
*/
private class TypedRequestSource extends RequestSource {
TypedRequestSource() { hasUnderlyingType("express", "Request") }
TypedRequestSource() { this.hasUnderlyingType("express", "Request") }
override RouteHandler getRouteHandler() { none() } // Not known.
}
@@ -637,7 +641,7 @@ module Express {
RedirectInvocation() { this = response.ref().getAMethodCall("redirect").asExpr() }
override Expr getUrlArgument() { result = getLastArgument() }
override Expr getUrlArgument() { result = this.getLastArgument() }
override RouteHandler getRouteHandler() { result = response.getRouteHandler() }
}
@@ -662,17 +666,17 @@ module Express {
SetMultipleHeaders() {
this = response.ref().getAMethodCall(["set", "header"]) and
getNumArgument() = 1
this.getNumArgument() = 1
}
/**
* Gets a reference to the multiple headers object that is to be set.
*/
private DataFlow::SourceNode getAHeaderSource() { result.flowsTo(getArgument(0)) }
private DataFlow::SourceNode getAHeaderSource() { result.flowsTo(this.getArgument(0)) }
override predicate definesExplicitly(string headerName, Expr headerValue) {
exists(string header |
getAHeaderSource().hasPropertyWrite(header, DataFlow::valueNode(headerValue)) and
this.getAHeaderSource().hasPropertyWrite(header, DataFlow::valueNode(headerValue)) and
headerName = header.toLowerCase()
)
}
@@ -680,7 +684,7 @@ module Express {
override RouteHandler getRouteHandler() { result = response.getRouteHandler() }
override Expr getNameExpr() {
exists(DataFlow::PropWrite write | getAHeaderSource().getAPropertyWrite() = write |
exists(DataFlow::PropWrite write | this.getAHeaderSource().getAPropertyWrite() = write |
result = write.getPropertyNameExpr()
)
}
@@ -712,9 +716,9 @@ module Express {
SetCookie() { this = response.ref().getAMethodCall("cookie").asExpr() }
override Expr getNameArgument() { result = getArgument(0) }
override Expr getNameArgument() { result = this.getArgument(0) }
override Expr getValueArgument() { result = getArgument(1) }
override Expr getValueArgument() { result = this.getArgument(1) }
override RouteHandler getRouteHandler() { result = response.getRouteHandler() }
}
@@ -776,18 +780,18 @@ module Express {
t.start() and
result = DataFlow::exprNode(this)
or
exists(string name | result = ref(t.continue()).getAMethodCall(name) |
exists(string name | result = this.ref(t.continue()).getAMethodCall(name) |
name = "route" or
name = routeSetupMethodName()
)
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
}
/**
* Holds if `sink` may refer to this router.
*/
predicate flowsTo(Expr sink) { ref(DataFlow::TypeTracker::end()).flowsToExpr(sink) }
predicate flowsTo(Expr sink) { this.ref(DataFlow::TypeTracker::end()).flowsToExpr(sink) }
/**
* Gets a `RouteSetup` that was used for setting up a route on this router.
@@ -799,7 +803,7 @@ module Express {
*
* Example: `router2` for `router1.use(router2)` or `router1.use("/route2", router2)`
*/
RouterDefinition getASubRouter() { result.flowsTo(getARouteSetup().getAnArgument()) }
RouterDefinition getASubRouter() { result.flowsTo(this.getARouteSetup().getAnArgument()) }
/**
* Gets a route handler registered on this router.
@@ -807,7 +811,7 @@ module Express {
* Example: `fun` for `router1.use(fun)` or `router.use("/route", fun)`
*/
HTTP::RouteHandler getARouteHandler() {
result.(DataFlow::SourceNode).flowsToExpr(getARouteSetup().getAnArgument())
result.(DataFlow::SourceNode).flowsToExpr(this.getARouteSetup().getAnArgument())
}
/**
@@ -831,14 +835,14 @@ module Express {
setup.isUseCall()
)
then result = node.(Express::RouteSetup).getLastRouteHandlerExpr()
else result = getMiddlewareStackAt(node.getAPredecessor())
else result = this.getMiddlewareStackAt(node.getAPredecessor())
}
/**
* Gets the final middleware registered on this router.
*/
Express::RouteHandlerExpr getMiddlewareStack() {
result = getMiddlewareStackAt(getContainer().getExit())
result = this.getMiddlewareStackAt(this.getContainer().getExit())
}
}
@@ -869,20 +873,20 @@ module Express {
DataFlow::MethodCallNode {
ResponseSendFileAsFileSystemAccess() {
exists(string name | name = "sendFile" or name = "sendfile" |
calls(any(ResponseExpr res).flow(), name)
this.calls(any(ResponseExpr res).flow(), name)
)
}
override DataFlow::Node getADataNode() { none() }
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getRootPathArgument() {
result = this.(DataFlow::CallNode).getOptionArgument(1, "root")
}
override predicate isUpwardNavigationRejected(DataFlow::Node argument) {
argument = getAPathArgument()
argument = this.getAPathArgument()
}
}
@@ -918,8 +922,8 @@ module Express {
methodName = "use" or
methodName = any(HTTP::RequestMethodName m).toLowerCase()
|
getMethodName() = methodName and
exists(DataFlow::ValueNode arg | arg = getAnArgument() |
this.getMethodName() = methodName and
exists(DataFlow::ValueNode arg | arg = this.getAnArgument() |
exists(DataFlow::ArrayCreationNode array |
array.flowsTo(arg) and
routeHandlerArg = array.getAnElement()
@@ -970,10 +974,10 @@ module Express {
this = any(ResponseSource res).ref().getAMethodCall("render")
}
override DataFlow::Node getTemplateFileNode() { result = getArgument(0) }
override DataFlow::Node getTemplateFileNode() { result = this.getArgument(0) }
override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) }
override DataFlow::Node getTemplateParamsNode() { result = this.getArgument(1) }
override DataFlow::SourceNode getOutput() { result = getCallback(2).getParameter(1) }
override DataFlow::SourceNode getOutput() { result = this.getCallback(2).getParameter(1) }
}
}

View File

@@ -97,7 +97,7 @@ module Fastify {
}
override DataFlow::SourceNode getARouteHandler() {
result = getARouteHandler(DataFlow::TypeBackTracker::end())
result = this.getARouteHandler(DataFlow::TypeBackTracker::end())
}
private DataFlow::SourceNode getARouteHandler(DataFlow::TypeBackTracker t) {
@@ -121,7 +121,7 @@ module Fastify {
"onRequest", "preParsing", "preValidation", "preHandler", "preSerialization",
"onSend", "onResponse", "handler"
])
else result = getLastArgument().flow()
else result = this.getLastArgument().flow()
}
}
@@ -275,7 +275,7 @@ module Fastify {
override predicate definesExplicitly(string headerName, Expr headerValue) {
exists(string header |
getAHeaderSource().hasPropertyWrite(header, headerValue.flow()) and
this.getAHeaderSource().hasPropertyWrite(header, headerValue.flow()) and
headerName = header.toLowerCase()
)
}
@@ -283,7 +283,7 @@ module Fastify {
override RouteHandler getRouteHandler() { result = rh }
override Expr getNameExpr() {
exists(DataFlow::PropWrite write | getAHeaderSource().getAPropertyWrite() = write |
exists(DataFlow::PropWrite write | this.getAHeaderSource().getAPropertyWrite() = write |
result = write.getPropertyNameExpr()
)
}
@@ -297,10 +297,10 @@ module Fastify {
private class ViewCall extends Templating::TemplateInstantiation::Range, DataFlow::CallNode {
ViewCall() { this = any(ReplySource rep).ref().getAMethodCall("view") }
override DataFlow::SourceNode getOutput() { result = getCallback(2).getParameter(1) }
override DataFlow::SourceNode getOutput() { result = this.getCallback(2).getParameter(1) }
override DataFlow::Node getTemplateFileNode() { result = getArgument(0) }
override DataFlow::Node getTemplateFileNode() { result = this.getArgument(0) }
override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) }
override DataFlow::Node getTemplateParamsNode() { result = this.getArgument(1) }
}
}

View File

@@ -176,10 +176,10 @@ private module FStream {
FStream() { this = getAnFStreamProperty(writer).getAnInvocation() }
override DataFlow::Node getAPathArgument() {
result = getOptionArgument(0, "path")
result = this.getOptionArgument(0, "path")
or
not exists(getOptionArgument(0, "path")) and
result = getArgument(0)
not exists(this.getOptionArgument(0, "path")) and
result = this.getArgument(0)
}
}
@@ -212,9 +212,9 @@ private class WriteFileAtomic extends FileSystemWriteAccess, DataFlow::CallNode
this = DataFlow::moduleMember("write-file-atomic", "sync").getACall()
}
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getADataNode() { result = getArgument(1) }
override DataFlow::Node getADataNode() { result = this.getArgument(1) }
}
/**
@@ -223,18 +223,20 @@ private class WriteFileAtomic extends FileSystemWriteAccess, DataFlow::CallNode
private class RecursiveReadDir extends FileSystemAccess, FileNameProducer, DataFlow::CallNode {
RecursiveReadDir() { this = DataFlow::moduleImport("recursive-readdir").getACall() }
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getAFileName() { result = trackFileSource(DataFlow::TypeTracker::end()) }
override DataFlow::Node getAFileName() {
result = this.trackFileSource(DataFlow::TypeTracker::end())
}
private DataFlow::SourceNode trackFileSource(DataFlow::TypeTracker t) {
t.start() and result = getCallback([1 .. 2]).getParameter(1)
t.start() and result = this.getCallback([1 .. 2]).getParameter(1)
or
t.startInPromise() and not exists(getCallback([1 .. 2])) and result = this
t.startInPromise() and not exists(this.getCallback([1 .. 2])) and result = this
or
// Tracking out of a promise
exists(DataFlow::TypeTracker t2 |
result = PromiseTypeTracking::promiseStep(trackFileSource(t2), t, t2)
result = PromiseTypeTracking::promiseStep(this.trackFileSource(t2), t, t2)
)
}
}
@@ -253,16 +255,16 @@ private module JSONFile {
.getACall()
}
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getADataNode() { result = trackRead(DataFlow::TypeTracker::end()) }
override DataFlow::Node getADataNode() { result = this.trackRead(DataFlow::TypeTracker::end()) }
private DataFlow::SourceNode trackRead(DataFlow::TypeTracker t) {
this.getCalleeName() = "readFile" and
(
t.start() and result = getCallback([1 .. 2]).getParameter(1)
t.start() and result = this.getCallback([1 .. 2]).getParameter(1)
or
t.startInPromise() and not exists(getCallback([1 .. 2])) and result = this
t.startInPromise() and not exists(this.getCallback([1 .. 2])) and result = this
)
or
t.start() and
@@ -271,7 +273,7 @@ private module JSONFile {
or
// Tracking out of a promise
exists(DataFlow::TypeTracker t2 |
result = PromiseTypeTracking::promiseStep(trackRead(t2), t, t2)
result = PromiseTypeTracking::promiseStep(this.trackRead(t2), t, t2)
)
}
}
@@ -286,9 +288,9 @@ private module JSONFile {
.getACall()
}
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getADataNode() { result = getArgument(1) }
override DataFlow::Node getADataNode() { result = this.getArgument(1) }
}
}
@@ -302,9 +304,9 @@ private class LoadJsonFile extends FileSystemReadAccess, DataFlow::CallNode {
this = DataFlow::moduleMember("load-json-file", "sync").getACall()
}
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getADataNode() { result = trackRead(DataFlow::TypeTracker::end()) }
override DataFlow::Node getADataNode() { result = this.trackRead(DataFlow::TypeTracker::end()) }
private DataFlow::SourceNode trackRead(DataFlow::TypeTracker t) {
this.getCalleeName() = "sync" and t.start() and result = this
@@ -313,7 +315,7 @@ private class LoadJsonFile extends FileSystemReadAccess, DataFlow::CallNode {
or
// Tracking out of a promise
exists(DataFlow::TypeTracker t2 |
result = PromiseTypeTracking::promiseStep(trackRead(t2), t, t2)
result = PromiseTypeTracking::promiseStep(this.trackRead(t2), t, t2)
)
}
}
@@ -328,9 +330,9 @@ private class WriteJsonFile extends FileSystemWriteAccess, DataFlow::CallNode {
this = DataFlow::moduleMember("write-json-file", "sync").getACall()
}
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getADataNode() { result = getArgument(1) }
override DataFlow::Node getADataNode() { result = this.getArgument(1) }
}
/**
@@ -345,17 +347,19 @@ private class WalkDir extends FileNameProducer, FileSystemAccess, DataFlow::Call
this = DataFlow::moduleMember("walkdir", "async").getACall()
}
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getAFileName() { result = trackFileSource(DataFlow::TypeTracker::end()) }
override DataFlow::Node getAFileName() {
result = this.trackFileSource(DataFlow::TypeTracker::end())
}
private DataFlow::SourceNode trackFileSource(DataFlow::TypeTracker t) {
not this.getCalleeName() = any(string s | s = "sync" or s = "async") and
t.start() and
(
result = getCallback(getNumArgument() - 1).getParameter(0)
result = this.getCallback(this.getNumArgument() - 1).getParameter(0)
or
result = getAMethodCall(EventEmitter::on()).getCallback(1).getParameter(0)
result = this.getAMethodCall(EventEmitter::on()).getCallback(1).getParameter(0)
)
or
t.start() and this.getCalleeName() = "sync" and result = this
@@ -364,7 +368,7 @@ private class WalkDir extends FileNameProducer, FileSystemAccess, DataFlow::Call
or
// Tracking out of a promise
exists(DataFlow::TypeTracker t2 |
result = PromiseTypeTracking::promiseStep(trackFileSource(t2), t, t2)
result = PromiseTypeTracking::promiseStep(this.trackFileSource(t2), t, t2)
)
}
}
@@ -387,13 +391,14 @@ private class Globule extends FileNameProducer, FileSystemAccess, DataFlow::Call
override DataFlow::Node getAPathArgument() {
(this.getCalleeName() = "match" or this.getCalleeName() = "isMatch") and
result = getArgument(1)
result = this.getArgument(1)
or
this.getCalleeName() = "mapping" and
(
result = getAnArgument() and not exists(result.getALocalSource().getAPropertyWrite("src"))
result = this.getAnArgument() and
not exists(result.getALocalSource().getAPropertyWrite("src"))
or
result = getAnArgument().getALocalSource().getAPropertyWrite("src").getRhs()
result = this.getAnArgument().getALocalSource().getAPropertyWrite("src").getRhs()
)
}
@@ -445,7 +450,7 @@ private class LibraryAccess extends FileSystemAccess, DataFlow::InvokeNode {
)
}
override DataFlow::Node getAPathArgument() { result = getArgument(pathArgument) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathArgument) }
}
/**
@@ -454,11 +459,11 @@ private class LibraryAccess extends FileSystemAccess, DataFlow::InvokeNode {
class Chokidar extends FileNameProducer, FileSystemAccess, API::CallNode {
Chokidar() { this = API::moduleImport("chokidar").getMember("watch").getACall() }
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
override DataFlow::Node getAFileName() {
exists(DataFlow::CallNode onCall, int pathIndex |
onCall = getAChainedMethodCall("on") and
onCall = this.getAChainedMethodCall("on") and
if onCall.getArgument(0).mayHaveStringValue("all") then pathIndex = 1 else pathIndex = 0
|
result = onCall.getCallback(1).getParameter(pathIndex)
@@ -476,5 +481,5 @@ private class Mkdirp extends FileSystemAccess, API::CallNode {
this = API::moduleImport("mkdirp").getMember("sync").getACall()
}
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
}

View File

@@ -49,18 +49,18 @@ module HTTP {
* An expression that sets HTTP response headers implicitly.
*/
abstract class ImplicitHeaderDefinition extends HeaderDefinition {
override string getAHeaderName() { defines(result, _) }
override string getAHeaderName() { this.defines(result, _) }
}
/**
* An expression that sets HTTP response headers explicitly.
*/
abstract class ExplicitHeaderDefinition extends HeaderDefinition {
override string getAHeaderName() { definesExplicitly(result, _) }
override string getAHeaderName() { this.definesExplicitly(result, _) }
override predicate defines(string headerName, string headerValue) {
exists(Expr e |
definesExplicitly(headerName, e) and
this.definesExplicitly(headerName, e) and
headerValue = e.getStringValue()
)
}
@@ -270,13 +270,13 @@ module HTTP {
t.start() and
result = DataFlow::exprNode(this)
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
}
/**
* Holds if `sink` may refer to this server definition.
*/
predicate flowsTo(Expr sink) { ref(DataFlow::TypeTracker::end()).flowsToExpr(sink) }
predicate flowsTo(Expr sink) { this.ref(DataFlow::TypeTracker::end()).flowsToExpr(sink) }
}
/**
@@ -310,17 +310,17 @@ module HTTP {
abstract RouteHandler getRouteHandler();
/** DEPRECATED. Use `ref().flowsTo()` instead. */
deprecated predicate flowsTo(DataFlow::Node nd) { ref().flowsTo(nd) }
deprecated predicate flowsTo(DataFlow::Node nd) { this.ref().flowsTo(nd) }
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and
result = this
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
}
/** Gets a `SourceNode` that refers to this request object. */
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) }
}
/**
@@ -335,17 +335,17 @@ module HTTP {
abstract RouteHandler getRouteHandler();
/** DEPRECATED. Use `ref().flowsTo()` instead. */
deprecated predicate flowsTo(DataFlow::Node nd) { ref().flowsTo(nd) }
deprecated predicate flowsTo(DataFlow::Node nd) { this.ref().flowsTo(nd) }
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and
result = this
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
}
/** Gets a `SourceNode` that refers to this response object. */
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) }
}
/**
@@ -377,7 +377,7 @@ module HTTP {
override MethodCallExpr astNode;
override predicate definesExplicitly(string headerName, Expr headerValue) {
headerName = getNameExpr().getStringValue().toLowerCase() and
headerName = this.getNameExpr().getStringValue().toLowerCase() and
headerValue = astNode.getArgument(1)
}
@@ -422,7 +422,7 @@ module HTTP {
* An access to a user-controlled HTTP request input.
*/
abstract class RequestInputAccess extends RemoteFlowSource {
override string getSourceType() { result = "Server request " + getKind() }
override string getSourceType() { result = "Server request " + this.getKind() }
/**
* Gets the route handler whose request input is accessed.
@@ -453,7 +453,7 @@ module HTTP {
* Headers are never considered third-party controllable by this predicate, although the
* third party does have some control over the the Referer and Origin headers.
*/
predicate isThirdPartyControllable() { getKind() = ["parameter", "url", "body"] }
predicate isThirdPartyControllable() { this.getKind() = ["parameter", "url", "body"] }
}
/**
@@ -560,7 +560,7 @@ module HTTP {
)
) and
exists(RouteHandlerCandidate candidate |
getAPossiblyDecoratedHandler(candidate).flowsTo(getAPropertyWrite().getRhs())
getAPossiblyDecoratedHandler(candidate).flowsTo(this.getAPropertyWrite().getRhs())
)
}

View File

@@ -40,7 +40,9 @@ module Koa {
/**
* Gets the parameter of the route handler that contains the context object.
*/
Parameter getContextParameter() { result = getAFunctionValue().getFunction().getParameter(0) }
Parameter getContextParameter() {
result = this.getAFunctionValue().getFunction().getParameter(0)
}
/**
* Gets an expression that contains the "context" object of
@@ -56,13 +58,17 @@ module Koa {
* Gets an expression that contains the context or response
* object of a route handler invocation.
*/
Expr getAResponseOrContextExpr() { result = getAResponseExpr() or result = getAContextExpr() }
Expr getAResponseOrContextExpr() {
result = this.getAResponseExpr() or result = this.getAContextExpr()
}
/**
* Gets an expression that contains the context or request
* object of a route handler invocation.
*/
Expr getARequestOrContextExpr() { result = getARequestExpr() or result = getAContextExpr() }
Expr getARequestOrContextExpr() {
result = this.getARequestExpr() or result = this.getAContextExpr()
}
/**
* Gets a reference to a request parameter defined by this route handler.
@@ -112,17 +118,17 @@ module Koa {
*/
RouteHandler getRouteHandler() { result = rh }
predicate flowsTo(DataFlow::Node nd) { ref().flowsTo(nd) }
predicate flowsTo(DataFlow::Node nd) { this.ref().flowsTo(nd) }
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and
result = this
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
}
/** Gets a source node that refers to this context object. */
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) }
}
/**
@@ -203,7 +209,7 @@ module Koa {
private class RequestSource extends HTTP::Servers::RequestSource {
ContextExpr ctx;
RequestSource() { asExpr().(PropAccess).accesses(ctx, "request") }
RequestSource() { this.asExpr().(PropAccess).accesses(ctx, "request") }
/**
* Gets the route handler that provides this response.
@@ -238,7 +244,7 @@ module Koa {
private class ResponseSource extends HTTP::Servers::ResponseSource {
ContextExpr ctx;
ResponseSource() { asExpr().(PropAccess).accesses(ctx, "response") }
ResponseSource() { this.asExpr().(PropAccess).accesses(ctx, "response") }
/**
* Gets the route handler that provides this response.
@@ -384,16 +390,16 @@ module Koa {
RouteSetup() {
// app.use(fun)
server.flowsTo(getReceiver()) and
getMethodName() = "use"
server.flowsTo(this.getReceiver()) and
this.getMethodName() = "use"
}
override DataFlow::SourceNode getARouteHandler() {
// `StandardRouteHandler` uses this predicate in it's charpred, so making this predicate return a `RouteHandler` would give an empty recursion.
result.flowsToExpr(getArgument(0))
result.flowsToExpr(this.getArgument(0))
or
// For the route-handlers that does not depend on this predicate in their charpred.
result.(RouteHandler).getARouteHandlerRegistrationObject().flowsToExpr(getArgument(0))
result.(RouteHandler).getARouteHandlerRegistrationObject().flowsToExpr(this.getArgument(0))
}
override Expr getServer() { result = server }
@@ -423,7 +429,7 @@ module Koa {
RedirectInvocation() { this.(MethodCallExpr).calls(rh.getAResponseOrContextExpr(), "redirect") }
override Expr getUrlArgument() { result = getArgument(0) }
override Expr getUrlArgument() { result = this.getArgument(0) }
override RouteHandler getRouteHandler() { result = rh }
}
@@ -438,10 +444,10 @@ module Koa {
override DataFlow::SourceNode getOutput() { none() }
override DataFlow::Node getTemplateFileNode() { result = getArgument(0) }
override DataFlow::Node getTemplateFileNode() { result = this.getArgument(0) }
override DataFlow::Node getTemplateParamsNode() {
result = getArgument(1)
result = this.getArgument(1)
or
result = ctx.ref().getAPropertyReference("state")
}

View File

@@ -29,7 +29,7 @@ module LazyCache {
// To avoid recursion, this should not depend on `SourceNode`.
exists(Require req |
req.getArgument(0).getStringValue() = "lazy-cache" and
getAnAssignedExpr().(CallExpr).getCallee() = req
this.getAnAssignedExpr().(CallExpr).getCallee() = req
)
}
}
@@ -40,19 +40,19 @@ module LazyCache {
class LazyCacheImport extends CallExpr, Import {
LazyCacheVariable cache;
LazyCacheImport() { getCallee() = cache.getAnAccess() }
LazyCacheImport() { this.getCallee() = cache.getAnAccess() }
/** Gets the name of the package as it's exposed on the lazy-cache object. */
string getLocalAlias() {
result = getArgument(1).getStringValue()
result = this.getArgument(1).getStringValue()
or
not exists(getArgument(1)) and
result = getArgument(0).getStringValue()
not exists(this.getArgument(1)) and
result = this.getArgument(0).getStringValue()
}
override Module getEnclosingModule() { result = getTopLevel() }
override Module getEnclosingModule() { result = this.getTopLevel() }
override PathExpr getImportedPath() { result = getArgument(0) }
override PathExpr getImportedPath() { result = this.getArgument(0) }
private LazyCacheVariable getVariable() { result = cache }
@@ -63,10 +63,10 @@ module LazyCache {
or
exists(LazyCacheVariable variable, Expr base, PropAccess access, string localName |
// To avoid recursion, this should not depend on `SourceNode`.
variable = getVariable() and
variable = this.getVariable() and
base = variable.getAnAccess() and
access.getBase() = base and
localName = getLocalAlias() and
localName = this.getLocalAlias() and
access.getPropertyName() = localName and
result = access.flow()
)
@@ -77,6 +77,6 @@ module LazyCache {
private class LazyCachePathExpr extends PathExpr, ConstantString {
LazyCachePathExpr() { this = any(LazyCacheImport rp).getArgument(0) }
override string getValue() { result = getStringValue() }
override string getValue() { result = this.getStringValue() }
}
}

View File

@@ -106,13 +106,13 @@ module Markdown {
/**
* Gets the input that is processed.
*/
DataFlow::Node getInput() { result = getArgument(0) }
DataFlow::Node getInput() { result = this.getArgument(0) }
/**
* Gets the processed output.
*/
DataFlow::Node getOutput() {
this.getCalleeName() = "process" and result = getABoundCallbackParameter(1, 1)
this.getCalleeName() = "process" and result = this.getABoundCallbackParameter(1, 1)
or
this.getCalleeName() = "processSync" and result = this
}

View File

@@ -72,10 +72,10 @@ private module MongoDB {
)
}
override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) }
override DataFlow::Node getAQueryArgument() { result = this.getArgument(queryArgIdx) }
DataFlow::Node getACodeOperator() {
result = getADollarWhereProperty(getParameter(queryArgIdx))
result = getADollarWhereProperty(this.getParameter(queryArgIdx))
}
}
@@ -595,10 +595,10 @@ private module Minimongo {
)
}
override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) }
override DataFlow::Node getAQueryArgument() { result = this.getArgument(queryArgIdx) }
DataFlow::Node getACodeOperator() {
result = getADollarWhereProperty(getParameter(queryArgIdx))
result = getADollarWhereProperty(this.getParameter(queryArgIdx))
}
}
@@ -631,10 +631,10 @@ private module MarsDB {
)
}
override DataFlow::Node getAQueryArgument() { result = getArgument(queryArgIdx) }
override DataFlow::Node getAQueryArgument() { result = this.getArgument(queryArgIdx) }
DataFlow::Node getACodeOperator() {
result = getADollarWhereProperty(getParameter(queryArgIdx))
result = getADollarWhereProperty(this.getParameter(queryArgIdx))
}
}

View File

@@ -91,12 +91,12 @@ module NodeJSLib {
/**
* Gets the parameter of the route handler that contains the request object.
*/
Parameter getRequestParameter() { result = getFunction().getParameter(0) }
Parameter getRequestParameter() { result = this.getFunction().getParameter(0) }
/**
* Gets the parameter of the route handler that contains the response object.
*/
Parameter getResponseParameter() { result = getFunction().getParameter(1) }
Parameter getResponseParameter() { result = this.getFunction().getParameter(1) }
}
/**
@@ -222,23 +222,25 @@ module NodeJSLib {
RouteSetup() {
server.flowsTo(this) and
handler = getLastArgument()
handler = this.getLastArgument()
or
server.flowsTo(getReceiver()) and
server.flowsTo(this.getReceiver()) and
this.(MethodCallExpr).getMethodName().regexpMatch("on(ce)?") and
getArgument(0).getStringValue() = "request" and
handler = getArgument(1)
this.getArgument(0).getStringValue() = "request" and
handler = this.getArgument(1)
}
override DataFlow::SourceNode getARouteHandler() {
result = getARouteHandler(DataFlow::TypeBackTracker::end())
result = this.getARouteHandler(DataFlow::TypeBackTracker::end())
}
private DataFlow::SourceNode getARouteHandler(DataFlow::TypeBackTracker t) {
t.start() and
result = handler.flow().getALocalSource()
or
exists(DataFlow::TypeBackTracker t2, DataFlow::SourceNode succ | succ = getARouteHandler(t2) |
exists(DataFlow::TypeBackTracker t2, DataFlow::SourceNode succ |
succ = this.getARouteHandler(t2)
|
result = succ.backtrack(t2, t)
or
t = t2 and
@@ -516,7 +518,7 @@ module NodeJSLib {
string getMethodName() { result = methodName }
override DataFlow::Node getAPathArgument() {
exists(int i | fsFileParam(methodName, i) | result = getArgument(i))
exists(int i | fsFileParam(methodName, i) | result = this.getArgument(i))
}
}
@@ -535,11 +537,11 @@ module NodeJSLib {
if paramName = "callback"
then
exists(DataFlow::ParameterNode p |
p = getCallback(i).getAParameter() and
p = this.getCallback(i).getAParameter() and
p.getName().regexpMatch("(?i)data|buffer|string") and
result = p
)
else result = getArgument(i)
else result = this.getArgument(i)
)
}
}
@@ -561,11 +563,11 @@ module NodeJSLib {
if paramName = "callback"
then
exists(DataFlow::ParameterNode p |
p = getCallback(i).getAParameter() and
p = this.getCallback(i).getAParameter() and
p.getName().regexpMatch("(?i)data|buffer|string") and
result = p
)
else result = getArgument(i)
else result = this.getArgument(i)
)
}
}
@@ -586,7 +588,7 @@ module NodeJSLib {
)
}
override DataFlow::Node getADataNode() { result = getArgument(0) }
override DataFlow::Node getADataNode() { result = this.getArgument(0) }
override DataFlow::Node getAPathArgument() { result = stream.getAPathArgument() }
}
@@ -609,11 +611,11 @@ module NodeJSLib {
result = this
or
method = "pipe" and
result = getArgument(0)
result = this.getArgument(0)
or
method = EventEmitter::on() and
getArgument(0).mayHaveStringValue("data") and
result = getCallback(1).getParameter(0)
this.getArgument(0).mayHaveStringValue("data") and
result = this.getCallback(1).getParameter(0)
}
override DataFlow::Node getAPathArgument() { result = stream.getAPathArgument() }
@@ -699,17 +701,19 @@ module NodeJSLib {
methodName = ["execFile", "execFileSync", "spawn", "spawnSync", "fork"]
) and
// all of the above methods take the command as their first argument
result = getParameter(0).getARhs()
result = this.getParameter(0).getARhs()
}
override DataFlow::Node getACommandArgument() { result = getACommandArgument(_) }
override DataFlow::Node getACommandArgument() { result = this.getACommandArgument(_) }
override predicate isShellInterpreted(DataFlow::Node arg) { arg = getACommandArgument(true) }
override predicate isShellInterpreted(DataFlow::Node arg) {
arg = this.getACommandArgument(true)
}
override DataFlow::Node getArgumentList() {
methodName = ["execFile", "execFileSync", "fork", "spawn", "spawnSync"] and
// all of the above methods take the argument list as their second argument
result = getParameter(1).getARhs()
result = this.getParameter(1).getARhs()
}
override predicate isSync() { methodName.matches("%Sync") }
@@ -717,16 +721,16 @@ module NodeJSLib {
override DataFlow::Node getOptionsArg() {
not result.getALocalSource() instanceof DataFlow::FunctionNode and // looks like callback
not result.getALocalSource() instanceof DataFlow::ArrayCreationNode and // looks like argumentlist
not result = getParameter(0).getARhs() and
not result = this.getParameter(0).getARhs() and
// fork/spawn and all sync methos always has options as the last argument
if
methodName.regexpMatch("fork.*") or
methodName.regexpMatch("spawn.*") or
methodName.regexpMatch(".*Sync")
then result = getLastArgument()
then result = this.getLastArgument()
else
// the rest (exec/execFile) has the options argument as their second last.
result = getParameter(this.getNumArgument() - 2).getARhs()
result = this.getParameter(this.getNumArgument() - 2).getARhs()
}
}
@@ -781,7 +785,7 @@ module NodeJSLib {
"runInThisContext"
] and
// all of the above methods/constructors take the command as their first argument
result = getArgument(0)
result = this.getArgument(0)
}
}
@@ -795,12 +799,12 @@ module NodeJSLib {
DataFlow::ValueNode arg;
RouteSetupCandidate() {
getMethodName() = "createServer" and
arg = getLastArgument()
this.getMethodName() = "createServer" and
arg = this.getLastArgument()
or
getMethodName().regexpMatch("on(ce)?") and
getArgument(0).mayHaveStringValue("request") and
arg = getArgument(1)
this.getMethodName().regexpMatch("on(ce)?") and
this.getArgument(0).mayHaveStringValue("request") and
arg = this.getArgument(1)
}
override DataFlow::ValueNode getARouteHandlerArg() { result = arg }
@@ -838,7 +842,7 @@ module NodeJSLib {
or
callee = DataFlow::moduleMember(moduleName, "request")
) and
url = getArgument(0)
url = this.getArgument(0)
)
}
@@ -849,7 +853,7 @@ module NodeJSLib {
name = "host" or
name = "hostname"
|
result = getOptionArgument(1, name)
result = this.getOptionArgument(1, name)
)
}
@@ -862,7 +866,7 @@ module NodeJSLib {
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
promise = false and
exists(DataFlow::ParameterNode res, DataFlow::CallNode onData |
res = getCallback(1).getParameter(0) and
res = this.getCallback(1).getParameter(0) and
onData = res.getAMethodCall(EventEmitter::on()) and
onData.getArgument(0).mayHaveStringValue("data") and
result = onData.getCallback(1).getParameter(0) and
@@ -933,7 +937,7 @@ module NodeJSLib {
* A data flow node that is a login callback for an HTTP or HTTPS request made by a Node.js process.
*/
private class ClientRequestLoginHandler extends ClientRequestHandler {
ClientRequestLoginHandler() { getAHandledEvent() = "login" }
ClientRequestLoginHandler() { this.getAHandledEvent() = "login" }
}
/**
@@ -1116,13 +1120,13 @@ module NodeJSLib {
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and result = this
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
}
/**
* Gets a reference to this server.
*/
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) }
}
/**

View File

@@ -81,7 +81,7 @@ private class RxJSPipe extends DataFlow::MethodCallNode {
*/
DataFlow::Node getOutput(int i) {
isIdentityPipe(this.getArgument(i).getALocalSource()) and
result = getOutput(i - 1)
result = this.getOutput(i - 1)
or
not isIdentityPipe(this.getArgument(i).getALocalSource()) and
result = pipeOutput(this.getArgument(i).getALocalSource())

View File

@@ -77,7 +77,7 @@ private module MySql {
)
}
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
override DataFlow::Node getAQueryArgument() { result = this.getArgument(0) }
}
/** An expression that is passed to the `query` method and hence interpreted as SQL. */
@@ -174,7 +174,7 @@ private module Postgres {
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
QueryCall() { this = [client(), pool()].getMember("query").getACall() }
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
override DataFlow::Node getAQueryArgument() { result = this.getArgument(0) }
}
/** An expression that is passed to the `query` method and hence interpreted as SQL. */
@@ -263,9 +263,9 @@ private module Postgres {
/** Gets an argument interpreted as a SQL string, not including raw interpolation variables. */
private DataFlow::Node getADirectQueryArgument() {
result = getArgument(0)
result = this.getArgument(0)
or
result = getOptionArgument(0, "text")
result = this.getOptionArgument(0, "text")
}
/**
@@ -276,7 +276,7 @@ private module Postgres {
private string getARawParameterName() {
exists(string sqlString, string placeholderRegexp, string regexp |
placeholderRegexp = "\\$(\\d+|[{(\\[/]\\w+[})\\]/])" and // For example: $1 or ${prop}
sqlString = getADirectQueryArgument().getStringValue()
sqlString = this.getADirectQueryArgument().getStringValue()
|
// Match $1:raw or ${prop}:raw
regexp = placeholderRegexp + "(:raw|\\^)" and
@@ -299,28 +299,29 @@ private module Postgres {
/** Gets the argument holding the values to plug into placeholders. */
private DataFlow::Node getValues() {
result = getArgument(1)
result = this.getArgument(1)
or
result = getOptionArgument(0, "values")
result = this.getOptionArgument(0, "values")
}
/** Gets a value that is plugged into a raw placeholder variable, making it a sink for SQL injection. */
private DataFlow::Node getARawValue() {
result = getValues() and getARawParameterName() = "1" // Special case: if the argument is not an array or object, it's just plugged into $1
result = this.getValues() and this.getARawParameterName() = "1" // Special case: if the argument is not an array or object, it's just plugged into $1
or
exists(DataFlow::SourceNode values | values = getValues().getALocalSource() |
result = values.getAPropertyWrite(getARawParameterName()).getRhs()
exists(DataFlow::SourceNode values | values = this.getValues().getALocalSource() |
result = values.getAPropertyWrite(this.getARawParameterName()).getRhs()
or
// Array literals do not have PropWrites with property names so handle them separately,
// and also translate to 0-based indexing.
result = values.(DataFlow::ArrayCreationNode).getElement(getARawParameterName().toInt() - 1)
result =
values.(DataFlow::ArrayCreationNode).getElement(this.getARawParameterName().toInt() - 1)
)
}
override DataFlow::Node getAQueryArgument() {
result = getADirectQueryArgument()
result = this.getADirectQueryArgument()
or
result = getARawValue()
result = this.getARawValue()
}
}
@@ -365,7 +366,7 @@ private module Sqlite {
this = database().getMember("prepare").getACall()
}
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
override DataFlow::Node getAQueryArgument() { result = this.getArgument(0) }
}
/** An expression that is passed to the `query` method and hence interpreted as SQL. */
@@ -424,7 +425,7 @@ private module MsSql {
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
QueryCall() { this = [mssql(), request()].getMember(["query", "batch"]).getACall() }
override DataFlow::Node getAQueryArgument() { result = getArgument(0) }
override DataFlow::Node getAQueryArgument() { result = this.getArgument(0) }
}
/** An expression that is passed to a method that interprets it as SQL. */
@@ -488,9 +489,9 @@ private module Sequelize {
QueryCall() { this = instance().getMember("query").getACall() }
override DataFlow::Node getAQueryArgument() {
result = getArgument(0)
result = this.getArgument(0)
or
result = getOptionArgument(0, "query")
result = this.getOptionArgument(0, "query")
}
}
@@ -606,9 +607,9 @@ private module Spanner {
}
override DataFlow::Node getAQueryArgument() {
result = getArgument(0)
result = this.getArgument(0)
or
result = getOptionArgument(0, "sql")
result = this.getOptionArgument(0, "sql")
}
}
@@ -621,9 +622,9 @@ private module Spanner {
override DataFlow::Node getAQueryArgument() {
// just use the whole array as the query argument, as arrays becomes tainted if one of the elements
// are tainted
result = getArgument(0)
result = this.getArgument(0)
or
result = getParameter(0).getUnknownMember().getMember("sql").getARhs()
result = this.getParameter(0).getUnknownMember().getMember("sql").getARhs()
}
}
@@ -636,7 +637,7 @@ private module Spanner {
this = v1SpannerClient().getMember(["executeSql", "executeStreamingSql"]).getACall()
}
override DataFlow::Node getAQueryArgument() { result = getOptionArgument(0, "sql") }
override DataFlow::Node getAQueryArgument() { result = this.getOptionArgument(0, "sql") }
}
/**

View File

@@ -45,7 +45,7 @@ module SocketIO {
NamespaceObject getDefaultNamespace() { result = MkNamespace(this, "/") }
/** Gets the default namespace of this server. */
override NamespaceObject getNamespace() { result = getDefaultNamespace() }
override NamespaceObject getNamespace() { result = this.getDefaultNamespace() }
/** Gets the namespace with the given path of this server. */
NamespaceObject getNamespace(string path) { result = MkNamespace(this, path) }
@@ -56,7 +56,7 @@ module SocketIO {
private DataFlow::SourceNode server(DataFlow::TypeTracker t) {
result = this and t.start()
or
exists(DataFlow::TypeTracker t2, DataFlow::SourceNode pred | pred = server(t2) |
exists(DataFlow::TypeTracker t2, DataFlow::SourceNode pred | pred = this.server(t2) |
result = pred.track(t2, t)
or
// invocation of a chainable method
@@ -81,7 +81,7 @@ module SocketIO {
)
}
override DataFlow::SourceNode ref() { result = server(DataFlow::TypeTracker::end()) }
override DataFlow::SourceNode ref() { result = this.server(DataFlow::TypeTracker::end()) }
/**
* DEPRECATED. Always returns `this` as a `ServerObject` now represents the origin of a server.
@@ -149,7 +149,7 @@ module SocketIO {
private DataFlow::SourceNode namespace(DataFlow::TypeTracker t) {
t.start() and result = this
or
exists(DataFlow::SourceNode pred, DataFlow::TypeTracker t2 | pred = namespace(t2) |
exists(DataFlow::SourceNode pred, DataFlow::TypeTracker t2 | pred = this.namespace(t2) |
result = pred.track(t2, t)
or
// invocation of a chainable method
@@ -168,7 +168,7 @@ module SocketIO {
)
}
override DataFlow::SourceNode ref() { result = namespace(DataFlow::TypeTracker::end()) }
override DataFlow::SourceNode ref() { result = this.namespace(DataFlow::TypeTracker::end()) }
}
/** A data flow node that may produce a namespace object. */
@@ -204,7 +204,7 @@ module SocketIO {
private DataFlow::SourceNode socket(DataFlow::TypeTracker t) {
result = this and t.start()
or
exists(DataFlow::SourceNode pred, DataFlow::TypeTracker t2 | pred = socket(t2) |
exists(DataFlow::SourceNode pred, DataFlow::TypeTracker t2 | pred = this.socket(t2) |
result = pred.track(t2, t)
or
// invocation of a chainable method
@@ -239,7 +239,7 @@ module SocketIO {
)
}
override DataFlow::SourceNode ref() { result = socket(DataFlow::TypeTracker::end()) }
override DataFlow::SourceNode ref() { result = this.socket(DataFlow::TypeTracker::end()) }
}
/** A data flow node that may produce a socket object. */
@@ -264,12 +264,12 @@ module SocketIO {
SocketObject getSocket() { result = emitter }
/** Gets the callback that handles data received from a client. */
DataFlow::FunctionNode getListener() { result = getCallback(1) }
DataFlow::FunctionNode getListener() { result = this.getCallback(1) }
/** Gets the `i`th parameter through which data is received from a client. */
override DataFlow::SourceNode getReceivedItem(int i) {
exists(DataFlow::FunctionNode cb |
cb = getListener() and
cb = this.getListener() and
result = cb.getParameter(i) and
// exclude last parameter if it looks like a callback
not (result = cb.getLastParameter() and exists(result.getAnInvocation()))
@@ -279,7 +279,7 @@ module SocketIO {
override string getChannel() { this.getArgument(0).mayHaveStringValue(result) }
/** Gets a parameter through which data is received from a client. */
DataFlow::SourceNode getAReceivedItem() { result = getReceivedItem(_) }
DataFlow::SourceNode getAReceivedItem() { result = this.getReceivedItem(_) }
/** Gets a client-side node that may be sending the data received here. */
SendNode getASender() { result.getAReceiver() = this }
@@ -288,7 +288,7 @@ module SocketIO {
ReceiveCallback getAck() { result.getReceiveNode() = this }
/** DEPRECATED. Use `getChannel()` instead. */
deprecated string getEventName() { result = getChannel() }
deprecated string getEventName() { result = this.getChannel() }
}
/** An acknowledgment callback when receiving a message. */
@@ -355,29 +355,31 @@ module SocketIO {
/** Gets the event name associated with the data, if it can be determined. */
override string getChannel() {
if firstDataIndex = 1 then getArgument(0).mayHaveStringValue(result) else result = "message"
if firstDataIndex = 1
then this.getArgument(0).mayHaveStringValue(result)
else result = "message"
}
/** Gets the `i`th argument through which data is sent to the client. */
override DataFlow::Node getSentItem(int i) {
result = getArgument(i + firstDataIndex) and
result = this.getArgument(i + firstDataIndex) and
i >= 0 and
(
// exclude last argument if it looks like a callback
result != getLastArgument() or not exists(SendCallback c | c.getSendNode() = this)
result != this.getLastArgument() or not exists(SendCallback c | c.getSendNode() = this)
)
}
/** Gets a client-side node that may be receiving the data sent here. */
override SocketIOClient::ReceiveNode getAReceiver() {
result.getSocket().getATargetNamespace() = getNamespace()
result.getSocket().getATargetNamespace() = this.getNamespace()
}
/** Gets the acknowledgment callback, if any. */
SendCallback getAck() { result.getSendNode() = this }
/** DEPRECATED. Use `getChannel()` instead. */
deprecated string getEventName() { result = getChannel() }
deprecated string getEventName() { result = this.getChannel() }
}
/** A socket.io namespace, identified by its server and its path. */
@@ -453,10 +455,10 @@ module SocketIOClient {
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and result = this
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
}
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) }
/** Gets the path of the namespace this socket belongs to, if it can be determined. */
string getNamespacePath() {
@@ -488,22 +490,22 @@ module SocketIOClient {
SocketIO::ServerObject getATargetServer() {
getPackage(result) = getPackage(this) and
(
not exists(getNamespacePath()) or
exists(result.getNamespace(getNamespacePath()))
not exists(this.getNamespacePath()) or
exists(result.getNamespace(this.getNamespacePath()))
)
}
/** Gets a namespace this socket may be communicating with. */
SocketIO::NamespaceObject getATargetNamespace() {
result = getATargetServer().getNamespace(getNamespacePath())
result = this.getATargetServer().getNamespace(this.getNamespacePath())
or
// if the namespace of this socket cannot be determined, overapproximate
not exists(getNamespacePath()) and
result = getATargetServer().getNamespace(_)
not exists(this.getNamespacePath()) and
result = this.getATargetServer().getNamespace(_)
}
/** Gets a server-side socket this client-side socket may be communicating with. */
SocketIO::SocketObject getATargetSocket() { result.getNamespace() = getATargetNamespace() }
SocketIO::SocketObject getATargetSocket() { result.getNamespace() = this.getATargetNamespace() }
}
/** A data flow node that may produce a socket object. */
@@ -547,36 +549,38 @@ module SocketIOClient {
SocketObject getSocket() { result = emitter }
/** Gets the event name associated with the data, if it can be determined. */
override string getChannel() { getArgument(0).mayHaveStringValue(result) }
override string getChannel() { this.getArgument(0).mayHaveStringValue(result) }
private DataFlow::SourceNode getListener(DataFlow::TypeBackTracker t) {
t.start() and
result = getArgument(1).getALocalSource()
result = this.getArgument(1).getALocalSource()
or
exists(DataFlow::TypeBackTracker t2 | result = getListener(t2).backtrack(t2, t))
exists(DataFlow::TypeBackTracker t2 | result = this.getListener(t2).backtrack(t2, t))
}
/** Gets the callback that handles data received from the server. */
DataFlow::FunctionNode getListener() { result = getListener(DataFlow::TypeBackTracker::end()) }
DataFlow::FunctionNode getListener() {
result = this.getListener(DataFlow::TypeBackTracker::end())
}
/** Gets the `i`th parameter through which data is received from the server. */
override DataFlow::SourceNode getReceivedItem(int i) {
exists(DataFlow::FunctionNode cb | cb = getListener() and result = cb.getParameter(i) |
exists(DataFlow::FunctionNode cb | cb = this.getListener() and result = cb.getParameter(i) |
// exclude the last parameter if it looks like a callback
result != cb.getLastParameter() or not exists(result.getAnInvocation())
)
}
/** Gets a data flow node representing data received from the server. */
DataFlow::SourceNode getAReceivedItem() { result = getReceivedItem(_) }
DataFlow::SourceNode getAReceivedItem() { result = this.getReceivedItem(_) }
/** Gets the acknowledgment callback, if any. */
DataFlow::SourceNode getAck() { result.(ReceiveCallback).getReceiveNode() = this }
/** Gets a server-side node that may be sending the data received here. */
SocketIO::SendNode getASender() {
result.getNamespace() = getSocket().getATargetNamespace() and
not result.getChannel() != getChannel()
result.getNamespace() = this.getSocket().getATargetNamespace() and
not result.getChannel() != this.getChannel()
}
}
@@ -634,32 +638,34 @@ module SocketIOClient {
/** Gets the event name associated with the data, if it can be determined. */
override string getChannel() {
if firstDataIndex = 1 then getArgument(0).mayHaveStringValue(result) else result = "message"
if firstDataIndex = 1
then this.getArgument(0).mayHaveStringValue(result)
else result = "message"
}
/** Gets the `i`th argument through which data is sent to the server. */
override DataFlow::Node getSentItem(int i) {
result = getArgument(i + firstDataIndex) and
result = this.getArgument(i + firstDataIndex) and
i >= 0 and
(
// exclude last argument if it looks like a callback
result != getLastArgument() or not exists(SendCallback c | c.getSendNode() = this)
result != this.getLastArgument() or not exists(SendCallback c | c.getSendNode() = this)
)
}
/** Gets a data flow node representing data sent to the client. */
DataFlow::Node getASentItem() { result = getSentItem(_) }
DataFlow::Node getASentItem() { result = this.getSentItem(_) }
/** Gets a server-side node that may be receiving the data sent here. */
override SocketIO::ReceiveNode getAReceiver() {
result.getSocket().getNamespace() = getSocket().getATargetNamespace()
result.getSocket().getNamespace() = this.getSocket().getATargetNamespace()
}
/** Gets the acknowledgment callback, if any. */
DataFlow::FunctionNode getAck() { result.(SendCallback).getSendNode() = this }
/** DEPRECATED. Use `getChannel()` instead. */
deprecated string getEventName() { result = getChannel() }
deprecated string getEventName() { result = this.getChannel() }
}
/**

View File

@@ -57,20 +57,22 @@ module Templating {
* in the output without escaping it.
*/
predicate isRawInterpolation() {
getRawText().regexpMatch(getLikelyTemplateSyntax(getFile()).getRawInterpolationRegexp())
this.getRawText()
.regexpMatch(getLikelyTemplateSyntax(this.getFile()).getRawInterpolationRegexp())
}
/**
* Holds if this performs HTML escaping on the result before inserting it in the template.
*/
predicate isEscapingInterpolation() {
getRawText().regexpMatch(getLikelyTemplateSyntax(getFile()).getEscapingInterpolationRegexp())
this.getRawText()
.regexpMatch(getLikelyTemplateSyntax(this.getFile()).getEscapingInterpolationRegexp())
}
/** Holds if this occurs in a `script` tag. */
predicate isInScriptTag() {
// We want to exclude non-code scripts like JSON.
toplevel_parent_xml_node(any(InlineScript scr), getParent())
toplevel_parent_xml_node(any(InlineScript scr), this.getParent())
}
/**
@@ -80,14 +82,14 @@ module Templating {
* which cancels out the benefit of HTML escaping.
*/
predicate isInCodeAttribute() {
exists(TopLevel code | code = getParent().(HTML::Attribute).getCodeInAttribute() |
exists(TopLevel code | code = this.getParent().(HTML::Attribute).getCodeInAttribute() |
code instanceof EventHandlerCode or
code instanceof JavaScriptURL
)
}
/** Holds if this placeholder occurs in JS code. */
predicate isInCodeContext() { isInScriptTag() or isInCodeAttribute() }
predicate isInCodeContext() { this.isInScriptTag() or this.isInCodeAttribute() }
/**
* Holds if this placeholder occurs in the definition of another template, which means the output
@@ -95,17 +97,17 @@ module Templating {
*/
predicate isInNestedTemplateContext(string templateType) {
templateType = "AngularJS" and
AngularJS::isInterpretedByAngularJS(getParent()) and
AngularJS::isInterpretedByAngularJS(this.getParent()) and
// Exclude delimiters that coincide with those of AngularJS's own template engine.
// It's too unlikely to happen, more likely is that one of our heuristics got it wrong.
not getRawText().regexpMatch("(?s)\\{\\{.*\\}\\}")
not this.getRawText().regexpMatch("(?s)\\{\\{.*\\}\\}")
}
/**
* Gets the innermost JavaScript expression containing this template tag, if any.
*/
pragma[nomagic]
Expr getEnclosingExpr() { expr_contains_template_tag_location(result, getLocation()) }
Expr getEnclosingExpr() { expr_contains_template_tag_location(result, this.getLocation()) }
}
/**
@@ -117,10 +119,10 @@ module Templating {
*/
class PipeRefExpr extends Expr, @template_pipe_ref {
/** Gets the identifier node naming the pipe. */
Identifier getIdentifier() { result = getChildExpr(0) }
Identifier getIdentifier() { result = this.getChildExpr(0) }
/** Gets the name of the pipe being referenced. */
string getName() { result = getIdentifier().getName() }
string getName() { result = this.getIdentifier().getName() }
override string getAPrimaryQlClass() { result = "Templating::PipeRefExpr" }
}
@@ -145,16 +147,16 @@ module Templating {
/** The top-level containing the expression in a template placeholder. */
class TemplateTopLevel extends TopLevel, @template_toplevel {
/** Gets the expression in this top-level. */
Expr getExpression() { result = getChildStmt(0).(ExprStmt).getExpr() }
Expr getExpression() { result = this.getChildStmt(0).(ExprStmt).getExpr() }
/** Gets the data flow node representing the initialization of the given variable in this scope. */
DataFlow::Node getVariableInit(string name) {
result = DataFlow::ssaDefinitionNode(SSA::implicitInit(getScope().getVariable(name)))
result = DataFlow::ssaDefinitionNode(SSA::implicitInit(this.getScope().getVariable(name)))
}
/** Gets a data flow node corresponding to a use of the given template variable within this top-level. */
DataFlow::SourceNode getAVariableUse(string name) {
result = getScope().getVariable(name).getAnAccess().flow()
result = this.getScope().getVariable(name).getAnAccess().flow()
}
}
@@ -177,7 +179,7 @@ module Templating {
/** Gets the template file instantiated here, if any. */
TemplateFile getTemplateFile() {
result = getTemplateFileNode().(TemplateFileReference).getTemplateFile()
result = this.getTemplateFileNode().(TemplateFileReference).getTemplateFile()
}
/**
@@ -267,13 +269,13 @@ module Templating {
/** Gets a template file referenced by this one via a template inclusion tag, such as `{% include foo %}` */
TemplateFile getAnImportedFile() {
result = getAPlaceholder().(TemplateInclusionTag).getImportedFile()
result = this.getAPlaceholder().(TemplateInclusionTag).getImportedFile()
}
}
/** Any HTML file, seen as a possible target for template instantiation. */
private class TemplateFileByExtension extends TemplateFile {
TemplateFileByExtension() { getFileType().isHtml() }
TemplateFileByExtension() { this.getFileType().isHtml() }
}
/**
@@ -287,7 +289,7 @@ module Templating {
abstract class TemplateFileReference extends DataFlow::Node {
/** Gets the value that identifies the template. */
string getValue() {
result = getStringValue()
result = this.getStringValue()
or
exists(API::Node node |
this = node.getARhs() and
@@ -296,11 +298,11 @@ module Templating {
}
pragma[nomagic]
private Folder getFolder() { result = getFile().getParentContainer() }
private Folder getFolder() { result = this.getFile().getParentContainer() }
/** Gets the template file referenced by this node. */
final TemplateFile getTemplateFile() {
result = this.getValue().(TemplateFileReferenceString).getTemplateFile(getFolder())
result = this.getValue().(TemplateFileReferenceString).getTemplateFile(this.getFolder())
}
}
@@ -337,7 +339,7 @@ module Templating {
/**
* Gets the stem, similar to `Container.getStem`.
*/
string getStem() { result = getBaseName().regexpCapture("(.*?)(?:\\.([^.]*))?", 1) }
string getStem() { result = this.getBaseName().regexpCapture("(.*?)(?:\\.([^.]*))?", 1) }
/** Gets the template file referenced by this string when resolved from `baseFolder`. */
final TemplateFile getTemplateFile(Folder baseFolder) {
@@ -346,7 +348,7 @@ module Templating {
exists(UpwardTraversalSuffix up |
this = up.getOriginal() and
result = up.(TemplateFileReferenceString).getTemplateFile(baseFolder.getParentContainer()) and
baseFolder = getContextFolder()
baseFolder = this.getContextFolder()
)
}
}
@@ -363,7 +365,7 @@ module Templating {
result = pragma[only_bind_out](r).getFile().getParentContainer()
}
override Folder getContextFolder() { result = getFileReferenceFolder() }
override Folder getContextFolder() { result = this.getFileReferenceFolder() }
}
/** The `X` in a path of form `../X`, treated as a separate path string with a different context folder. */
@@ -609,10 +611,10 @@ module Templating {
override DataFlow::SourceNode getOutput() { result = this }
/** Gets a data flow node that refers a template file to be instantiated, if any. */
override DataFlow::Node getTemplateFileNode() { result = getArgument(0) }
override DataFlow::Node getTemplateFileNode() { result = this.getArgument(0) }
/** Gets a data flow node that refers to an object whose properties become variables in the template. */
override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) }
override DataFlow::Node getTemplateParamsNode() { result = this.getArgument(1) }
}
/**
@@ -646,11 +648,11 @@ module Templating {
TemplateInclusionTag() {
rawPath =
getRawText()
this.getRawText()
.regexpCapture("[{<]% *(?:import|include|extend|require)s? *(?:[(] *)?['\"]?(.*?)['\"]? *(?:[)] *)?%[}>]",
1)
or
rawPath = getRawText().regexpCapture("\\{\\{!?[<>](.*?)\\}\\}", 1)
rawPath = this.getRawText().regexpCapture("\\{\\{!?[<>](.*?)\\}\\}", 1)
}
/** Gets the imported path (normalized). */
@@ -659,7 +661,9 @@ module Templating {
/** Gets the file referenced by this inclusion tag. */
TemplateFile getImportedFile() {
result =
getPath().(TemplateFileReferenceString).getTemplateFile(getFile().getParentContainer())
this.getPath()
.(TemplateFileReferenceString)
.getTemplateFile(this.getFile().getParentContainer())
}
}
@@ -683,14 +687,14 @@ module Templating {
override TemplateSyntax getTemplateSyntax() { result.getAPackageName() = engine }
override DataFlow::SourceNode getOutput() {
result = getParameter([1, 2]).getParameter(1).getAnImmediateUse()
result = this.getParameter([1, 2]).getParameter(1).getAnImmediateUse()
or
not exists(getParameter([1, 2]).getParameter(1)) and
not exists(this.getParameter([1, 2]).getParameter(1)) and
result = this
}
override DataFlow::Node getTemplateFileNode() { result = getArgument(0) }
override DataFlow::Node getTemplateFileNode() { result = this.getArgument(0) }
override DataFlow::Node getTemplateParamsNode() { result = getArgument(1) }
override DataFlow::Node getTemplateParamsNode() { result = this.getArgument(1) }
}
}

View File

@@ -56,17 +56,17 @@ module Typeahead {
private DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
t.start() and result = this
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
}
/** Gets a Bloodhound instance that fetches remote server data. */
private DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
private DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) }
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
responseType = "json" and
promise = false and
exists(TypeaheadSource source |
ref() = source.getALocalSource() or ref().getAMethodCall("ttAdapter") = source
this.ref() = source.getALocalSource() or this.ref().getAMethodCall("ttAdapter") = source
|
result = source.getASuggestion()
)

View File

@@ -91,7 +91,7 @@ module ClientWebSocket {
*/
LibraryName getLibrary() { result = socketClass.getLibrary() }
override DataFlow::Node getUrl() { result = getArgument(0) }
override DataFlow::Node getUrl() { result = this.getArgument(0) }
override DataFlow::Node getHost() { none() }
@@ -285,7 +285,7 @@ module ServerWebSocket {
override DataFlow::Node getSentItem(int i) {
i = 0 and
result = getArgument(0)
result = this.getArgument(0)
}
override ClientWebSocket::ReceiveNode getAReceiver() {

View File

@@ -122,9 +122,9 @@ deprecated class JQueryMethodCall extends CallExpr {
* A call to `jQuery.parseXML`.
*/
private class JQueryParseXmlCall extends XML::ParserInvocation {
JQueryParseXmlCall() { flow().(JQuery::MethodCall).getMethodName() = "parseXML" }
JQueryParseXmlCall() { this.flow().(JQuery::MethodCall).getMethodName() = "parseXML" }
override Expr getSourceArgument() { result = getArgument(0) }
override Expr getSourceArgument() { result = this.getArgument(0) }
override predicate resolvesEntities(XML::EntityKind kind) { kind = XML::InternalEntity() }
}
@@ -305,35 +305,35 @@ private module JQueryClientRequest {
JQueryAjaxCall() { this = jquery().getAMemberCall("ajax") }
override DataFlow::Node getUrl() {
result = getArgument(0) and not exists(getOptionArgument(0, _))
result = this.getArgument(0) and not exists(this.getOptionArgument(0, _))
or
result = getOptionArgument([0 .. 1], "url")
result = this.getOptionArgument([0 .. 1], "url")
}
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() { result = getOptionArgument([0 .. 1], "data") }
override DataFlow::Node getADataNode() { result = this.getOptionArgument([0 .. 1], "data") }
private string getResponseType() {
getOptionArgument([0 .. 1], "dataType").mayHaveStringValue(result)
this.getOptionArgument([0 .. 1], "dataType").mayHaveStringValue(result)
}
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
(
responseType = getResponseType()
responseType = this.getResponseType()
or
not exists(getResponseType()) and responseType = ""
not exists(this.getResponseType()) and responseType = ""
) and
promise = false and
(
result =
getOptionArgument([0 .. 1], "success")
this.getOptionArgument([0 .. 1], "success")
.getALocalSource()
.(DataFlow::FunctionNode)
.getParameter(0)
or
result =
getAResponseNodeFromAnXHRObject(getOptionArgument([0 .. 1],
getAResponseNodeFromAnXHRObject(this.getOptionArgument([0 .. 1],
any(string method | method = "error" or method = "complete"))
.getALocalSource()
.(DataFlow::FunctionNode)
@@ -397,20 +397,20 @@ private module JQueryClientRequest {
this = JQuery::objectRef().getAMethodCall(name)
}
override DataFlow::Node getUrl() { result = getArgument(0) }
override DataFlow::Node getUrl() { result = this.getArgument(0) }
override DataFlow::Node getHost() { none() }
override DataFlow::Node getADataNode() {
result = getArgument(1) and
result = this.getArgument(1) and
not name = "getScript" and // doesn't have a data-node.
not result.getALocalSource() instanceof DataFlow::FunctionNode // looks like the success callback.
}
private string getResponseType() {
(name = "get" or name = "post") and
getLastArgument().mayHaveStringValue(result) and
getNumArgument() > 1
this.getLastArgument().mayHaveStringValue(result) and
this.getNumArgument() > 1
or
name = "getJSON" and result = "json"
or
@@ -420,14 +420,15 @@ private module JQueryClientRequest {
override DataFlow::Node getAResponseDataNode(string responseType, boolean promise) {
(
responseType = getResponseType()
responseType = this.getResponseType()
or
not exists(getResponseType()) and responseType = ""
not exists(this.getResponseType()) and responseType = ""
) and
promise = false and
(
// one of the two last arguments
result = getCallback([getNumArgument() - 2 .. getNumArgument() - 1]).getParameter(0)
result =
this.getCallback([this.getNumArgument() - 2 .. this.getNumArgument() - 1]).getParameter(0)
or
result = getAnAjaxCallbackDataNode(this)
)
@@ -513,9 +514,9 @@ module JQuery {
DefaultRange() {
this.asExpr() instanceof JQueryObjectInternal
or
hasUnderlyingType("JQuery")
this.hasUnderlyingType("JQuery")
or
hasUnderlyingType("jQuery")
this.hasUnderlyingType("jQuery")
}
}
@@ -593,11 +594,11 @@ module JQuery {
predicate interpretsArgumentAsHtml(DataFlow::Node node) {
// some methods interpret all their arguments as (potential) HTML
JQuery::isMethodArgumentInterpretedAsHtml(name) and
node = getAnArgument()
node = this.getAnArgument()
or
// for `$, it's only the first one
name = "$" and
node = getArgument(0)
node = this.getArgument(0)
}
/**
@@ -610,11 +611,11 @@ module JQuery {
predicate interpretsArgumentAsSelector(DataFlow::Node node) {
// some methods interpret all their arguments as (potential) selectors
JQuery::isMethodArgumentInterpretedAsSelector(name) and
node = getAnArgument()
node = this.getAnArgument()
or
// for `$, it's only the first one
name = "$" and
node = getArgument(0)
node = this.getArgument(0)
}
}

View File

@@ -24,7 +24,9 @@ abstract class JSLintDirective extends SlashStarComment {
*/
string getContent() {
result =
getText().regexpReplaceAll("[\\n\\r\\u2028\\u2029]", " ").regexpCapture("\\s*\\w+ (.*)", 1)
this.getText()
.regexpReplaceAll("[\\n\\r\\u2028\\u2029]", " ")
.regexpCapture("\\s*\\w+ (.*)", 1)
}
/**
@@ -63,10 +65,10 @@ abstract class JSLintDirective extends SlashStarComment {
* function, or the toplevel.
*/
StmtContainer getScope() {
result = getASurroundingFunction() and
not getASurroundingFunction().getEnclosingContainer+() = result
result = this.getASurroundingFunction() and
not this.getASurroundingFunction().getEnclosingContainer+() = result
or
not exists(getASurroundingFunction()) and result = getTopLevel()
not exists(this.getASurroundingFunction()) and result = this.getTopLevel()
}
/**
@@ -76,7 +78,7 @@ abstract class JSLintDirective extends SlashStarComment {
* is the empty string.
*/
predicate definesFlag(string name, string value) {
exists(string defn | defn = getContent().splitAt(",").trim() |
exists(string defn | defn = this.getContent().splitAt(",").trim() |
if defn.matches("%:%")
then (
name = defn.splitAt(":", 0).trim() and
@@ -94,7 +96,7 @@ abstract class JSLintDirective extends SlashStarComment {
*/
predicate appliesTo(ExprOrStmt s) {
exists(StmtContainer sc | sc = s.(Stmt).getContainer() or sc = s.(Expr).getContainer() |
getScope() = sc.getEnclosingContainer*()
this.getScope() = sc.getEnclosingContainer*()
)
}
}
@@ -109,8 +111,8 @@ abstract class JSLintGlobal extends Linting::GlobalDeclaration, JSLintDirective
override predicate appliesTo(ExprOrStmt s) { JSLintDirective.super.appliesTo(s) }
override predicate declaresGlobalForAccess(GlobalVarAccess gva) {
declaresGlobal(gva.getName(), _) and
getScope() = gva.getContainer().getEnclosingContainer*()
this.declaresGlobal(gva.getName(), _) and
this.getScope() = gva.getContainer().getEnclosingContainer*()
}
}
@@ -119,7 +121,7 @@ class JSLintExplicitGlobal extends JSLintGlobal {
JSLintExplicitGlobal() { getDirectiveName(this) = "global" }
override predicate declaresGlobal(string name, boolean writable) {
exists(string value | definesFlag(name, value) |
exists(string value | this.definesFlag(name, value) |
writable = true and value = "true"
or
writable = false and
@@ -139,7 +141,7 @@ class JSLintProperties extends JSLintDirective {
/**
* Gets a property declared by this directive.
*/
string getAProperty() { result = getContent().splitAt(",").trim() }
string getAProperty() { result = this.getContent().splitAt(",").trim() }
}
/** A JSLint options directive. */
@@ -191,7 +193,7 @@ private string jsLintImplicitGlobal(string category) {
private class JSLintImplicitGlobal extends JSLintOptions, JSLintGlobal {
JSLintImplicitGlobal() {
exists(string category |
definesFlag(category, "true") and
this.definesFlag(category, "true") and
exists(jsLintImplicitGlobal(category))
)
}
@@ -199,7 +201,7 @@ private class JSLintImplicitGlobal extends JSLintOptions, JSLintGlobal {
override predicate declaresGlobal(string name, boolean writable) {
writable = false and
exists(string category |
definesFlag(category, "true") and
this.definesFlag(category, "true") and
name = jsLintImplicitGlobal(category)
)
}

View File

@@ -57,7 +57,7 @@ class SensitiveCall extends SensitiveExpr, InvokeExpr {
)
}
override string describe() { result = "a call to " + getCalleeName() }
override string describe() { result = "a call to " + this.getCalleeName() }
override SensitiveDataClassification getClassification() { result = classification }
}
@@ -145,7 +145,7 @@ abstract class SensitiveAction extends DataFlow::Node { }
/** A call that may perform authorization. */
class AuthorizationCall extends SensitiveAction, DataFlow::CallNode {
AuthorizationCall() {
exists(string s | s = getCalleeName() |
exists(string s | s = this.getCalleeName() |
// name contains `login` or `auth`, but not as part of `loginfo` or `unauth`;
// also exclude `author`
s.regexpMatch("(?i).*(login(?!fo)|(?<!un)auth(?!or\\b)|verify).*") and
@@ -158,7 +158,7 @@ class AuthorizationCall extends SensitiveAction, DataFlow::CallNode {
/** A call to a function whose name suggests that it encodes or encrypts its arguments. */
class ProtectCall extends DataFlow::CallNode {
ProtectCall() {
exists(string s | getCalleeName().regexpMatch("(?i).*" + s + ".*") |
exists(string s | this.getCalleeName().regexpMatch("(?i).*" + s + ".*") |
s = "protect" or s = "encode" or s = "encrypt"
)
}

View File

@@ -31,13 +31,13 @@ private class CommandCall extends DataFlow::InvokeNode {
* Gets the callback (if it exists) for an async `exec`-like call.
*/
DataFlow::FunctionNode getCallback() {
not this.isSync() and result = getLastArgument().getALocalSource()
not this.isSync() and result = this.getLastArgument().getALocalSource()
}
/**
* Holds if the executed command execution has an argument list as a separate argument.
*/
predicate hasArgumentList() { exists(getArgumentList()) }
predicate hasArgumentList() { exists(this.getArgumentList()) }
/**
* Gets the data-flow node (if it exists) for an options argument for an `exec`-like call.
@@ -52,12 +52,12 @@ private class CommandCall extends DataFlow::InvokeNode {
if this.hasArgumentList()
then
result =
getConstantStringParts(getArgumentList()
getConstantStringParts(this.getArgumentList()
.getALocalSource()
.(DataFlow::ArrayCreationNode)
.getElement(_))
else
exists(string commandString | commandString = getConstantStringParts(getArgument(0)) |
exists(string commandString | commandString = getConstantStringParts(this.getArgument(0)) |
result = commandString.suffix(1 + commandString.indexOf(" ", 0, 0))
)
}
@@ -68,9 +68,9 @@ private class CommandCall extends DataFlow::InvokeNode {
bindingset[name]
predicate isACallTo(string name) {
if this.hasArgumentList()
then getArgument(0).mayHaveStringValue(name)
then this.getArgument(0).mayHaveStringValue(name)
else
exists(string arg | arg = getConstantStringParts(getArgument(0)) |
exists(string arg | arg = getConstantStringParts(this.getArgument(0)) |
arg.prefix(name.length()) = name
)
}
@@ -100,27 +100,27 @@ private string getConstantStringParts(DataFlow::Node node) {
class UselessCat extends CommandCall {
UselessCat() {
this = command and
isACallTo(getACatExecuteable()) and
this.isACallTo(getACatExecuteable()) and
// There is a file to read, it's not just spawning `cat`.
not (
not exists(getArgumentList()) and
getArgument(0).mayHaveStringValue(getACatExecuteable())
not exists(this.getArgumentList()) and
this.getArgument(0).mayHaveStringValue(getACatExecuteable())
) and
// wildcards, pipes, redirections, other bash features, and multiple files (spaces) are OK.
not containsNonTrivialShellChar(getNonCommandConstantString()) and
not containsNonTrivialShellChar(this.getNonCommandConstantString()) and
// Only acceptable option is "encoding", everything else is non-trivial to emulate with fs.readFile.
(
not exists(getOptionsArg())
not exists(this.getOptionsArg())
or
forex(string prop | exists(getOptionsArg().getALocalSource().getAPropertyWrite(prop)) |
forex(string prop | exists(this.getOptionsArg().getALocalSource().getAPropertyWrite(prop)) |
prop = "encoding"
)
) and
// If there is a callback, then it must either have one or two parameters, or if there is a third parameter it must be unused.
(
not exists(getCallback())
not exists(this.getCallback())
or
exists(DataFlow::FunctionNode func | func = getCallback() |
exists(DataFlow::FunctionNode func | func = this.getCallback() |
func.getNumParameter() = 1
or
func.getNumParameter() = 2
@@ -132,7 +132,7 @@ class UselessCat extends CommandCall {
) and
// The process returned by an async call is unused.
(
isSync()
this.isSync()
or
inVoidContext(this.getEnclosingExpr())
or

View File

@@ -38,7 +38,7 @@ module CleartextLogging {
MaskingReplacer() {
this.isGlobal() and
exists(this.getRawReplacement().getStringValue()) and
any(RegExpDot term).getLiteral() = getRegExp().asExpr()
any(RegExpDot term).getLiteral() = this.getRegExp().asExpr()
}
}
@@ -77,7 +77,7 @@ module CleartextLogging {
*/
private class NonObject extends NonCleartextPassword {
NonObject() {
forall(AbstractValue v | v = analyze().getAValue() | not v.getType() = TTObject())
forall(AbstractValue v | v = this.analyze().getAValue() | not v.getType() = TTObject())
}
}
@@ -94,7 +94,7 @@ module CleartextLogging {
* A call that might obfuscate a password, for example through hashing.
*/
private class ObfuscatorCall extends Barrier, DataFlow::InvokeNode {
ObfuscatorCall() { getCalleeName().regexpMatch(notSensitiveRegexp()) }
ObfuscatorCall() { this.getCalleeName().regexpMatch(notSensitiveRegexp()) }
}
/**
@@ -156,7 +156,7 @@ module CleartextLogging {
string name;
CallPasswordSource() {
name = getCalleeName() and
name = this.getCalleeName() and
name.regexpMatch("(?is)getPassword")
}

View File

@@ -57,15 +57,15 @@ deprecated predicate isSafeLocationProperty(PropAccess pacc) {
* A call to a DOM method.
*/
class DomMethodCallExpr extends MethodCallExpr {
DomMethodCallExpr() { isDomValue(getReceiver()) }
DomMethodCallExpr() { isDomValue(this.getReceiver()) }
/**
* Holds if `arg` is an argument that is interpreted as HTML.
*/
predicate interpretsArgumentsAsHTML(Expr arg) {
exists(int argPos, string name |
arg = getArgument(argPos) and
name = getMethodName()
arg = this.getArgument(argPos) and
name = this.getMethodName()
|
// individual signatures:
name = "write"
@@ -89,7 +89,7 @@ class DomMethodCallExpr extends MethodCallExpr {
) and
// restrict to potentially dangerous attributes
exists(string attr | attr = ["action", "formaction", "href", "src", "xlink:href", "data"] |
getArgument(argPos - 1).getStringValue().toLowerCase() = attr
this.getArgument(argPos - 1).getStringValue().toLowerCase() = attr
)
)
}
@@ -102,7 +102,7 @@ class DomPropWriteNode extends Assignment {
PropAccess lhs;
DomPropWriteNode() {
lhs = getLhs() and
lhs = this.getLhs() and
isDomValue(lhs.getBase())
}
@@ -165,7 +165,7 @@ private module PersistentWebStorage {
override PersistentWriteAccess getAWrite() {
exists(string name |
getArgument(0).mayHaveStringValue(name) and
this.getArgument(0).mayHaveStringValue(name) and
result = getAWriteByName(name, kind)
)
}
@@ -179,11 +179,11 @@ private module PersistentWebStorage {
WriteAccess() { this = webStorage(kind).getAMethodCall("setItem") }
string getKey() { getArgument(0).mayHaveStringValue(result) }
string getKey() { this.getArgument(0).mayHaveStringValue(result) }
string getKind() { result = kind }
override DataFlow::Node getValue() { result = getArgument(1) }
override DataFlow::Node getValue() { result = this.getArgument(1) }
}
}
@@ -209,7 +209,7 @@ class PostMessageEventHandler extends Function {
/**
* Gets the parameter that contains the event.
*/
Parameter getEventParameter() { result = getParameter(paramIndex) }
Parameter getEventParameter() { result = this.getParameter(paramIndex) }
}
/**

View File

@@ -81,9 +81,9 @@ module IncompleteHtmlAttributeSanitization {
class HtmlAttributeConcatenationAsSink extends Sink, DataFlow::ValueNode,
HtmlAttributeConcatenation {
override string getADangerousCharacter() {
isInterpretedAsJavaScript() and result = "&"
this.isInterpretedAsJavaScript() and result = "&"
or
result = getQuote()
result = this.getQuote()
}
}

View File

@@ -110,7 +110,7 @@ class DatabaseAccessAsExpensiveAction extends ExpensiveAction {
*/
class RouteHandlerExpressionWithRateLimiter extends RateLimitedRouteHandlerExpr {
RouteHandlerExpressionWithRateLimiter() {
any(RateLimitingMiddleware m).ref().flowsToExpr(getAMatchingAncestor())
any(RateLimitingMiddleware m).ref().flowsToExpr(this.getAMatchingAncestor())
}
}
@@ -132,13 +132,13 @@ abstract class RateLimitingMiddleware extends DataFlow::SourceNode {
t.start() and
result = this
or
DataFlow::functionOneWayForwardingStep(ref(t.continue()).getALocalUse(), result)
DataFlow::functionOneWayForwardingStep(this.ref(t.continue()).getALocalUse(), result)
or
exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t))
exists(DataFlow::TypeTracker t2 | result = this.ref(t2).track(t2, t))
}
/** Gets a data flow node referring to this middleware. */
DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) }
DataFlow::SourceNode ref() { result = this.ref(DataFlow::TypeTracker::end()) }
}
/**
@@ -194,7 +194,7 @@ class RateLimiterFlexibleRateLimiter extends DataFlow::FunctionNode {
rateLimiterClassName.matches("RateLimiter%") and
rateLimiterClass = API::moduleImport("rate-limiter-flexible").getMember(rateLimiterClassName) and
rateLimiterConsume = rateLimiterClass.getInstance().getMember("consume") and
request.getParameter() = getRouteHandlerParameter(getFunction(), "request") and
request.getParameter() = getRouteHandlerParameter(this.getFunction(), "request") and
request.getAPropertyRead().flowsTo(rateLimiterConsume.getAParameter().getARhs())
)
}

View File

@@ -128,7 +128,7 @@ private class RemoteFlowSourceAccessPath extends JSONString {
}
/** Gets the index of the last component of this access path. */
int getMaxComponentIndex() { result = max(int i | exists(getComponent(i))) }
int getMaxComponentIndex() { result = max(int i | exists(this.getComponent(i))) }
/**
* Gets the API node to which the prefix of the access path up to and including `i` resolves.
@@ -139,11 +139,11 @@ private class RemoteFlowSourceAccessPath extends JSONString {
i = -1 and
result = API::root()
or
result = resolveUpTo(i - 1).getASuccessor(getComponent(i))
result = this.resolveUpTo(i - 1).getASuccessor(this.getComponent(i))
}
/** Gets the API node to which this access path resolves. */
API::Use resolve() { result = resolveUpTo(getMaxComponentIndex()) }
API::Use resolve() { result = this.resolveUpTo(this.getMaxComponentIndex()) }
}
/**

View File

@@ -56,7 +56,7 @@ module ServerSideUrlRedirect {
override predicate sanitizes(boolean outcome, Expr e) {
// `isLocalUrl(e)` sanitizes `e` if it evaluates to `true`
getAnArgument().asExpr() = e and
this.getAnArgument().asExpr() = e and
outcome = true
}
}

View File

@@ -106,7 +106,7 @@ module TaintedPath {
/** Holds if this path may contain `../` components. */
predicate canContainDotDotSlash() {
// Absolute normalized path is the only combination that cannot contain `../`.
not (isNormalized() and isAbsolute())
not (this.isNormalized() and this.isAbsolute())
}
}
@@ -133,7 +133,7 @@ module TaintedPath {
NormalizingPathCall() {
this = NodeJSLib::Path::moduleMember("normalize").getACall() and
input = getArgument(0) and
input = this.getArgument(0) and
output = this
}
@@ -157,16 +157,16 @@ module TaintedPath {
ResolvingPathCall() {
this = NodeJSLib::Path::moduleMember("resolve").getACall() and
input = getAnArgument() and
input = this.getAnArgument() and
output = this
or
this = NodeJSLib::FS::moduleMember("realpathSync").getACall() and
input = getArgument(0) and
input = this.getArgument(0) and
output = this
or
this = NodeJSLib::FS::moduleMember("realpath").getACall() and
input = getArgument(0) and
output = getCallback(1).getParameter(1)
input = this.getArgument(0) and
output = this.getCallback(1).getParameter(1)
}
/**
@@ -189,7 +189,7 @@ module TaintedPath {
NormalizingRelativePathCall() {
this = NodeJSLib::Path::moduleMember("relative").getACall() and
input = getAnArgument() and
input = this.getAnArgument() and
output = this
}
@@ -214,12 +214,12 @@ module TaintedPath {
PreservingPathCall() {
this =
NodeJSLib::Path::moduleMember(["dirname", "toNamespacedPath", "parse", "format"]).getACall() and
input = getAnArgument() and
input = this.getAnArgument() and
output = this
or
// non-global replace or replace of something other than /\.\./g, /[/]/g, or /[\.]/g.
this instanceof StringReplaceCall and
input = getReceiver() and
input = this.getReceiver() and
output = this and
not exists(RegExpLiteral literal, RegExpTerm term |
this.(StringReplaceCall).getRegExp().asExpr() = literal and
@@ -252,10 +252,10 @@ module TaintedPath {
DataFlow::Node output;
DotDotSlashPrefixRemovingReplace() {
input = getReceiver() and
input = this.getReceiver() and
output = this and
exists(RegExpLiteral literal, RegExpTerm term |
getRegExp().asExpr() = literal and
this.getRegExp().asExpr() = literal and
(term instanceof RegExpStar or term instanceof RegExpPlus) and
term.getChild(0) = getADotDotSlashMatcher()
|
@@ -302,11 +302,11 @@ module TaintedPath {
DataFlow::Node output;
DotRemovingReplaceCall() {
input = getReceiver() and
input = this.getReceiver() and
output = this and
isGlobal() and
this.isGlobal() and
exists(RegExpLiteral literal, RegExpTerm term |
getRegExp().asExpr() = literal and
this.getRegExp().asExpr() = literal and
literal.getRoot() = term and
not term.getAMatchedString() = "/"
|

View File

@@ -264,8 +264,8 @@ module UnsafeShellCommandConstruction {
override predicate sanitizes(boolean outcome, Expr e) {
outcome = true and
(
e = getArgument(0).asExpr() or
e = getArgument(0).(StringOps::ConcatenationRoot).getALeaf().asExpr()
e = this.getArgument(0).asExpr() or
e = this.getArgument(0).(StringOps::ConcatenationRoot).getALeaf().asExpr()
)
}
}

View File

@@ -33,12 +33,12 @@ module Shared {
*/
class MetacharEscapeSanitizer extends Sanitizer, StringReplaceCall {
MetacharEscapeSanitizer() {
isGlobal() and
this.isGlobal() and
(
RegExp::alwaysMatchesMetaCharacter(getRegExp().getRoot(), ["<", "'", "\""])
RegExp::alwaysMatchesMetaCharacter(this.getRegExp().getRoot(), ["<", "'", "\""])
or
// or it's like a wild-card.
RegExp::isWildcardLike(getRegExp().getRoot())
RegExp::isWildcardLike(this.getRegExp().getRoot())
)
}
}
@@ -91,13 +91,13 @@ module Shared {
class ContainsHTMLGuard extends SanitizerGuard, StringOps::RegExpTest {
ContainsHTMLGuard() {
exists(RegExpCharacterClass regExp |
regExp = getRegExp() and
regExp = this.getRegExp() and
forall(string s | s = ["\"", "&", "<", ">"] | regExp.getAMatchedString() = s)
)
}
override predicate sanitizes(boolean outcome, Expr e) {
outcome = getPolarity().booleanNot() and e = this.getStringOperand().asExpr()
outcome = this.getPolarity().booleanNot() and e = this.getStringOperand().asExpr()
}
}
@@ -229,7 +229,7 @@ module DomBasedXss {
exists(JQuery::MethodCall call |
call.interpretsArgumentAsHtml(this) and
call.interpretsArgumentAsSelector(this) and
pragma[only_bind_out](analyze()).getAType() = TTString()
pragma[only_bind_out](this.analyze()).getAType() = TTString()
)
}
@@ -246,7 +246,7 @@ module DomBasedXss {
class JQueryHtmlOrSelectorSink extends Sink, JQueryHtmlOrSelectorArgument {
JQueryHtmlOrSelectorSink() {
// If a prefix of the string is known, it must start with '<' or be an empty string
forall(string strval | strval = getAPrefix() | strval.regexpMatch("(?s)\\s*<.*|"))
forall(string strval | strval = this.getAPrefix() | strval.regexpMatch("(?s)\\s*<.*|"))
}
}