Skip to content

Commit 31c09ba

Browse files
committed
implement flow for .apply() by adding a ReflectiveParametersNode data-flow node
1 parent d86b7f6 commit 31c09ba

File tree

5 files changed

+99
-1
lines changed

5 files changed

+99
-1
lines changed

javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,32 @@ module DataFlow {
10291029
override File getFile() { result = function.getFile() }
10301030
}
10311031

1032+
/**
1033+
* A data flow node representing the arguments object given to a function.
1034+
*/
1035+
class ReflectiveParametersNode extends DataFlow::Node, TReflectiveParametersNode {
1036+
Function function;
1037+
1038+
ReflectiveParametersNode() { this = TReflectiveParametersNode(function) }
1039+
1040+
override string toString() { result = "the arguments object of " + function.describe() }
1041+
1042+
override predicate hasLocationInfo(
1043+
string filepath, int startline, int startcolumn, int endline, int endcolumn
1044+
) {
1045+
function.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
1046+
}
1047+
1048+
override BasicBlock getBasicBlock() { result = function.getEntry().getBasicBlock() }
1049+
1050+
/**
1051+
* Gets the function corresponding to this reflektive parameters node.
1052+
*/
1053+
Function getFunction() { result = function }
1054+
1055+
override File getFile() { result = function.getFile() }
1056+
}
1057+
10321058
/**
10331059
* A data flow node representing the exceptions thrown by the callee of an invocation.
10341060
*/
@@ -1627,6 +1653,26 @@ module DataFlow {
16271653
exists(Function f | not f.isAsyncOrGenerator() |
16281654
DataFlow::functionReturnNode(succ, f) and pred = valueNode(f.getAReturnedExpr())
16291655
)
1656+
or
1657+
// from a reflective params node to a reference to the arguments object.
1658+
exists(DataFlow::ReflectiveParametersNode params, Function f | f = params.getFunction() |
1659+
succ = f.getArgumentsVariable().getAnAccess().flow() and
1660+
pred = params
1661+
)
1662+
}
1663+
1664+
/**
1665+
* A step from a reflective parameter node to each parameter.
1666+
*/
1667+
private class ReflectiveParamsStep extends PreCallGraphStep {
1668+
override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) {
1669+
exists(DataFlow::ReflectiveParametersNode params, DataFlow::FunctionNode f, int i |
1670+
f.getFunction() = params.getFunction() and
1671+
obj = params and
1672+
prop = i + "" and
1673+
element = f.getParameter(i)
1674+
)
1675+
}
16301676
}
16311677

16321678
/**

javascript/ql/lib/semmle/javascript/dataflow/Sources.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ module SourceNode {
332332
or
333333
// Include return nodes because they model the implicit Promise creation in async functions.
334334
DataFlow::functionReturnNode(this, _)
335+
or
336+
this instanceof DataFlow::ReflectiveParametersNode
335337
}
336338
}
337339
}

javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ newtype TNode =
3131
TExceptionalFunctionReturnNode(Function f) or
3232
TExceptionalInvocationReturnNode(InvokeExpr e) or
3333
TGlobalAccessPathRoot() or
34-
TTemplatePlaceholderTag(Templating::TemplatePlaceholderTag tag)
34+
TTemplatePlaceholderTag(Templating::TemplatePlaceholderTag tag) or
35+
TReflectiveParametersNode(Function f)

javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,14 @@ private module CachedSteps {
224224
or
225225
arg = invk.(DataFlow::PropWrite).getRhs() and
226226
parm = DataFlow::parameterNode(f.getParameter(0))
227+
or
228+
calls(invk, f) and
229+
exists(MethodCallExpr apply |
230+
invk = DataFlow::reflectiveCallNode(apply) and
231+
apply.getMethodName() = "apply" and
232+
arg = apply.getArgument(1).flow()
233+
) and
234+
parm.(DataFlow::ReflectiveParametersNode).getFunction() = f
227235
)
228236
or
229237
exists(DataFlow::Node callback, int i, Parameter p, Function target |

0 commit comments

Comments
 (0)