Skip to content

Commit 10db0d5

Browse files
committed
JS: copy changes to TrackedNode
1 parent 3a6e6f9 commit 10db0d5

File tree

1 file changed

+51
-13
lines changed

1 file changed

+51
-13
lines changed

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

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -216,43 +216,81 @@ private module NodeTracking {
216216
* invokes `cb`, passing `arg` as its `i`th argument. `arg` flows along a path summarized
217217
* by `summary`, while `cb` is only tracked locally.
218218
*/
219-
private predicate higherOrderCall(
219+
private predicate summarizedHigherOrderCall(
220220
DataFlow::Node arg, DataFlow::Node cb, int i, PathSummary summary
221221
) {
222-
exists (Function f, DataFlow::InvokeNode outer, DataFlow::InvokeNode inner, int j,
223-
DataFlow::Node innerArg, DataFlow::ParameterNode cbParm, PathSummary oldSummary |
222+
exists(
223+
Function f, DataFlow::InvokeNode outer, DataFlow::InvokeNode inner, int j,
224+
DataFlow::Node innerArg, DataFlow::ParameterNode cbParm, PathSummary oldSummary
225+
|
224226
reachableFromInput(f, outer, arg, innerArg, oldSummary) and
225227
argumentPassing(outer, cb, f, cbParm) and
226-
innerArg = inner.getArgument(j) |
228+
innerArg = inner.getArgument(j)
229+
|
227230
// direct higher-order call
228231
cbParm.flowsTo(inner.getCalleeNode()) and
229232
i = j and
230233
summary = oldSummary
231234
or
232235
// indirect higher-order call
233-
exists (DataFlow::Node cbArg, PathSummary newSummary |
236+
exists(DataFlow::Node cbArg, PathSummary newSummary |
234237
cbParm.flowsTo(cbArg) and
235-
higherOrderCall(innerArg, cbArg, i, newSummary) and
238+
summarizedHigherOrderCall(innerArg, cbArg, i, newSummary) and
236239
summary = oldSummary.append(PathSummary::call()).append(newSummary)
237240
)
238241
)
239242
}
240243

244+
/**
245+
* Holds if `arg` is passed as the `i`th argument to `callback` through a callback invocation.
246+
*
247+
* This can be a summarized call, that is, `arg` and `callback` flow into a call,
248+
* `f(arg, callback)`, which performs the invocation.
249+
*
250+
* Alternatively, the callback can flow into a call `f(callback)` which itself provides the `arg`.
251+
* That is, `arg` refers to a value defined in `f` or one of its callees.
252+
*/
253+
predicate higherOrderCall(
254+
DataFlow::Node arg, DataFlow::SourceNode callback, int i,
255+
PathSummary summary
256+
) {
257+
// Summarized call
258+
exists(DataFlow::Node cb |
259+
summarizedHigherOrderCall(arg, cb, i, summary) and
260+
callback.flowsTo(cb)
261+
)
262+
or
263+
// Local invocation of a parameter
264+
isRelevant(arg) and
265+
exists(DataFlow::InvokeNode invoke |
266+
arg = invoke.getArgument(i) and
267+
invoke = callback.(DataFlow::ParameterNode).getACall() and
268+
summary = PathSummary::call()
269+
)
270+
or
271+
// Forwarding of the callback parameter (but not the argument).
272+
// We use a return summary since flow moves back towards the call site.
273+
// This ensures that an argument that is only tainted in some contexts cannot flow
274+
// out to every callback.
275+
exists(DataFlow::Node cbArg, DataFlow::SourceNode innerCb, PathSummary oldSummary |
276+
higherOrderCall(arg, innerCb, i, oldSummary) and
277+
callStep(cbArg, innerCb) and
278+
callback.flowsTo(cbArg) and
279+
summary = PathSummary::return().append(oldSummary)
280+
)
281+
}
282+
241283
/**
242284
* Holds if `pred` is passed as an argument to a function `f` which also takes a
243285
* callback parameter `cb` and then invokes `cb`, passing `pred` into parameter `succ`
244286
* of `cb`. `arg` flows along a path summarized by `summary`, while `cb` is only tracked
245287
* locally.
246288
*/
247289
private predicate flowIntoHigherOrderCall(
248-
DataFlow::Node pred, DataFlow::Node succ, PathSummary summary
290+
DataFlow::Node pred, DataFlow::Node succ, PathSummary summary
249291
) {
250-
exists(
251-
DataFlow::Node fArg, DataFlow::FunctionNode cb,
252-
int i, PathSummary oldSummary
253-
|
254-
higherOrderCall(pred, fArg, i, oldSummary) and
255-
cb = fArg.getALocalSource() and
292+
exists(DataFlow::FunctionNode cb, int i, PathSummary oldSummary |
293+
higherOrderCall(pred, cb, i, oldSummary) and
256294
succ = cb.getParameter(i) and
257295
summary = oldSummary.append(PathSummary::call())
258296
)

0 commit comments

Comments
 (0)