Skip to content

Commit 59bac82

Browse files
author
Max Schaefer
committed
JavaScript: Refactor flowsIntoHigherOrderCall predicate.
1 parent edc5117 commit 59bac82

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

javascript/ql/src/semmle/javascript/dataflow/Configuration.qll

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -619,20 +619,35 @@ private predicate flowThroughProperty(
619619
)
620620
}
621621

622+
/**
623+
* Holds if `arg` and `cb` are passed as arguments to a function which in turn
624+
* invokes `cb`, passing `arg` as its `i`th argument. All of this is done under
625+
* configuration `cfg`, and `arg` flows along a path summarized by `summary`,
626+
* while `cb` is only tracked locally.
627+
*/
628+
private predicate higherOrderCall(
629+
DataFlow::Node arg, DataFlow::Node cb, int i, DataFlow::Configuration cfg, PathSummary summary
630+
) {
631+
exists (Function f, DataFlow::InvokeNode outer, DataFlow::InvokeNode inner |
632+
reachableFromInput(f, outer, arg, inner.getArgument(i), cfg, summary) and
633+
argumentPassing(outer, cb, f, inner.getCalleeNode().getALocalSource())
634+
)
635+
}
636+
622637
/**
623638
* Holds if `pred` is passed as an argument to a function `f` which also takes a
624639
* callback parameter `cb` and then invokes `cb`, passing `pred` into parameter `succ`
625-
* of `cb`.
640+
* of `cb`. All of this is done under configuration `cfg`, and `arg` flows along a path
641+
* summarized by `summary`, while `cb` is only tracked locally.
626642
*/
627643
private predicate flowIntoHigherOrderCall(
628644
DataFlow::Node pred, DataFlow::Node succ, DataFlow::Configuration cfg, PathSummary summary
629645
) {
630646
exists(
631-
Function f, DataFlow::InvokeNode fCall, DataFlow::Node fArg, DataFlow::FunctionNode cb,
632-
DataFlow::InvokeNode cbCall, int i, PathSummary oldSummary
647+
DataFlow::Node fArg, DataFlow::FunctionNode cb,
648+
int i, PathSummary oldSummary
633649
|
634-
reachableFromInput(f, fCall, pred, cbCall.getArgument(i), cfg, oldSummary) and
635-
argumentPassing(fCall, fArg, f, cbCall.getCalleeNode().getALocalSource()) and
650+
higherOrderCall(pred, fArg, i, cfg, oldSummary) and
636651
cb = fArg.getALocalSource() and
637652
succ = cb.getParameter(i) and
638653
summary = oldSummary.append(PathSummary::call())

javascript/ql/src/semmle/javascript/dataflow/TrackedNodes.qll

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,20 +205,34 @@ private module NodeTracking {
205205
)
206206
}
207207

208+
/**
209+
* Holds if `arg` and `cb` are passed as arguments to a function which in turn
210+
* invokes `cb`, passing `arg` as its `i`th argument. `arg` flows along a path summarized
211+
* by `summary`, while `cb` is only tracked locally.
212+
*/
213+
private predicate higherOrderCall(
214+
DataFlow::Node arg, DataFlow::Node cb, int i, PathSummary summary
215+
) {
216+
exists (Function f, DataFlow::InvokeNode outer, DataFlow::InvokeNode inner |
217+
reachableFromInput(f, outer, arg, inner.getArgument(i), summary) and
218+
argumentPassing(outer, cb, f, inner.getCalleeNode().getALocalSource())
219+
)
220+
}
221+
208222
/**
209223
* Holds if `pred` is passed as an argument to a function `f` which also takes a
210224
* callback parameter `cb` and then invokes `cb`, passing `pred` into parameter `succ`
211-
* of `cb`.
225+
* of `cb`. `arg` flows along a path summarized by `summary`, while `cb` is only tracked
226+
* locally.
212227
*/
213228
private predicate flowIntoHigherOrderCall(
214229
DataFlow::Node pred, DataFlow::Node succ, PathSummary summary
215230
) {
216231
exists(
217-
Function f, DataFlow::InvokeNode fCall, DataFlow::Node fArg, DataFlow::FunctionNode cb,
218-
DataFlow::InvokeNode cbCall, int i, PathSummary oldSummary
232+
DataFlow::Node fArg, DataFlow::FunctionNode cb,
233+
int i, PathSummary oldSummary
219234
|
220-
reachableFromInput(f, fCall, pred, cbCall.getArgument(i), oldSummary) and
221-
argumentPassing(fCall, fArg, f, cbCall.getCalleeNode().getALocalSource()) and
235+
higherOrderCall(pred, fArg, i, oldSummary) and
222236
cb = fArg.getALocalSource() and
223237
succ = cb.getParameter(i) and
224238
summary = oldSummary.append(PathSummary::call())

0 commit comments

Comments
 (0)