JS: Add FunctionSelfReferenceNode

This commit is contained in:
Asger F
2023-10-10 10:25:36 +02:00
parent 760873c01c
commit f316da78d2
4 changed files with 34 additions and 0 deletions

View File

@@ -1888,6 +1888,8 @@ module PathNode {
or
// Skip captured variable nodes as the successor will be a use of that variable anyway.
nd = DataFlow::capturedVariableNode(_)
or
nd instanceof DataFlow::FunctionSelfReferenceNode
}
}

View File

@@ -1432,6 +1432,30 @@ module DataFlow {
override StmtContainer getContainer() { result = this.getTag().getInnerTopLevel() }
}
/**
* A node representing the hidden parameter of a function by which a function can refer to itself.
*/
class FunctionSelfReferenceNode extends DataFlow::Node, TFunctionSelfReferenceNode {
private Function function;
FunctionSelfReferenceNode() { this = TFunctionSelfReferenceNode(function) }
/** Gets the function. */
Function getFunction() { result = function }
override StmtContainer getContainer() { result = function }
override BasicBlock getBasicBlock() { result = function.getEntryBB() }
override string toString() { result = "[function self-reference] " + function.toString() }
override predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
function.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
}
/**
* A post-update node whose pre-node corresponds to an expression. See `DataFlow::PostUpdateNode` for more details.
*/

View File

@@ -24,6 +24,7 @@ private module Cached {
(kind = "call" or kind = "apply")
} or
TThisNode(StmtContainer f) { f.(Function).getThisBinder() = f or f instanceof TopLevel } or
TFunctionSelfReferenceNode(Function f) or
TDestructuredModuleImportNode(ImportDeclaration decl) {
exists(decl.getASpecifier().getImportedName())
} or

View File

@@ -152,6 +152,8 @@ private predicate isArgumentNodeImpl(Node n, DataFlowCall call, ArgumentPosition
n = call.asBoundCall(boundArgs).getArgument(pos.asPositional() - boundArgs)
)
or
pos.isFunctionSelfReference() and n = call.asOrdinaryCall().getCalleeNode()
or
pos.isThis() and n = TConstructorThisArgumentNode(call.asOrdinaryCall().asExpr())
or
// For now, treat all spread argument as flowing into the 'arguments' array, regardless of preceding arguments
@@ -348,6 +350,7 @@ newtype TParameterPosition =
MkPositionalParameter(int n) { n = [0 .. getMaxArity()] } or
MkPositionalLowerBound(int n) { n = [0 .. getMaxArity()] } or
MkThisParameter() or
MkFunctionSelfReferenceParameter() or
MkArgumentsArrayParameter()
class ParameterPosition extends TParameterPosition {
@@ -363,6 +366,8 @@ class ParameterPosition extends TParameterPosition {
predicate isThis() { this = MkThisParameter() }
predicate isFunctionSelfReference() { this = MkFunctionSelfReferenceParameter() }
predicate isArgumentsArray() { this = MkArgumentsArrayParameter() }
string toString() {
@@ -372,6 +377,8 @@ class ParameterPosition extends TParameterPosition {
or
this.isThis() and result = "this"
or
this.isFunctionSelfReference() and result = "function"
or
this.isArgumentsArray() and result = "arguments-array"
}
}