mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
JS: Canonicalize ThisNode
This commit is contained in:
@@ -303,6 +303,16 @@ class ThisExpr extends @thisexpr, Expr {
|
||||
Function getBinder() {
|
||||
result = 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()
|
||||
or
|
||||
result = getContainer().(TopLevel)
|
||||
}
|
||||
}
|
||||
|
||||
/** An array literal. */
|
||||
|
||||
@@ -206,6 +206,17 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine
|
||||
result = this
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the function or top-level whose `this` binding a `this` expression in this function refers to,
|
||||
* which is the nearest enclosing non-arrow function or top-level.
|
||||
*/
|
||||
StmtContainer getThisBindingContainer() {
|
||||
result = getThisBinder()
|
||||
or
|
||||
not exists(getThisBinder()) and
|
||||
result = getTopLevel()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this function has a mapped `arguments` variable whose indices are aliased
|
||||
* with the function's parameters.
|
||||
|
||||
@@ -32,6 +32,7 @@ module DataFlow {
|
||||
or TReflectiveCallNode(MethodCallExpr ce, string kind) {
|
||||
ce.getMethodName() = kind and (kind = "call" or kind = "apply")
|
||||
}
|
||||
or TThisNode(StmtContainer f) { f.(Function).getThisBinder() = f or f instanceof TopLevel }
|
||||
|
||||
/**
|
||||
* A node in the data flow graph.
|
||||
@@ -867,6 +868,13 @@ module DataFlow {
|
||||
nd = TDestructuringPatternNode(p)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Use `thisNode(StmtContainer container)` instead.
|
||||
*/
|
||||
predicate thisNode(DataFlow::Node node, StmtContainer container) {
|
||||
node = TThisNode(container)
|
||||
}
|
||||
|
||||
/**
|
||||
* A classification of flows that are not modeled, or only modeled incompletely, by
|
||||
* `DataFlowNode`:
|
||||
@@ -970,6 +978,11 @@ module DataFlow {
|
||||
pred = valueNode(defSourceNode(def)) and
|
||||
succ = TDestructuringPatternNode(def.getTarget())
|
||||
)
|
||||
or
|
||||
// flow from 'this' parameter into 'this' expressions
|
||||
exists (ThisExpr thiz |
|
||||
pred = TThisNode(thiz.getBindingContainer()) and
|
||||
succ = valueNode(thiz))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -198,16 +198,36 @@ class NewNode extends InvokeNode {
|
||||
override DataFlow::Impl::NewNodeDef impl;
|
||||
}
|
||||
|
||||
/** A data flow node corresponding to a `this` expression. */
|
||||
class ThisNode extends DataFlow::ValueNode, DataFlow::DefaultSourceNode {
|
||||
override ThisExpr astNode;
|
||||
/** A data flow node corresponding to the `this` parameter in a function or `this` at the top-level. */
|
||||
class ThisNode extends DataFlow::Node, DataFlow::DefaultSourceNode {
|
||||
ThisNode() {
|
||||
DataFlow::thisNode(this, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the function whose `this` binding this expression refers to,
|
||||
* which is the nearest enclosing non-arrow function.
|
||||
*/
|
||||
FunctionNode getBinder() {
|
||||
result = DataFlow::valueNode(astNode.getBinder())
|
||||
exists (Function binder |
|
||||
DataFlow::thisNode(this, binder) and
|
||||
result = DataFlow::valueNode(binder))
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
DataFlow::thisNode(this, result)
|
||||
}
|
||||
|
||||
override string toString() { result = "this" }
|
||||
|
||||
override predicate hasLocationInfo(string filepath, int startline, int startcolumn,
|
||||
int endline, int endcolumn) {
|
||||
// Use the function entry as the location
|
||||
getBindingContainer().getEntry().getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -185,7 +185,6 @@ class DefaultSourceNode extends SourceNode {
|
||||
astNode instanceof ObjectExpr or
|
||||
astNode instanceof ArrayExpr or
|
||||
astNode instanceof JSXNode or
|
||||
astNode instanceof ThisExpr or
|
||||
astNode instanceof GlobalVarAccess or
|
||||
astNode instanceof ExternalModuleReference
|
||||
)
|
||||
@@ -198,5 +197,7 @@ class DefaultSourceNode extends SourceNode {
|
||||
DataFlow::parameterNode(this, _)
|
||||
or
|
||||
this instanceof DataFlow::Impl::InvokeNodeDef
|
||||
or
|
||||
DataFlow::thisNode(this, _)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,10 +52,10 @@ abstract class ReactComponent extends ASTNode {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a `this` access in an instance method of this component.
|
||||
* Gets the `this` node in an instance method of this component.
|
||||
*/
|
||||
DataFlow::SourceNode getAThisAccess() {
|
||||
result.asExpr().(ThisExpr).getBinder() = getInstanceMethod(_)
|
||||
result.(DataFlow::ThisNode).getBinder().getFunction() = getInstanceMethod(_)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user