mirror of
https://github.com/github/codeql.git
synced 2026-05-04 05:05:12 +02:00
add explicit this to all member calls
This commit is contained in:
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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() }
|
||||
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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") }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() = "/"
|
||||
|
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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*<.*|"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user