Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b780bc4

Browse files
committed
JS: Also track into callbacks
1 parent e8e6491 commit b780bc4

5 files changed

Lines changed: 28 additions & 3 deletions

File tree

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
private import javascript
7272
private import internal.FlowSteps
7373
private import internal.AccessPaths
74+
private import internal.CallGraphs
7475

7576
/**
7677
* A data flow tracking configuration for finding inter-procedural paths from
@@ -620,10 +621,11 @@ private predicate exploratoryFlowStep(
620621
isAdditionalStoreStep(pred, succ, _, cfg) or
621622
isAdditionalLoadStep(pred, succ, _, cfg) or
622623
isAdditionalLoadStoreStep(pred, succ, _, cfg) or
623-
// the following two disjuncts taken together over-approximate flow through
624+
// the following three disjuncts taken together over-approximate flow through
624625
// higher-order calls
625626
callback(pred, succ) or
626-
succ = pred.(DataFlow::FunctionNode).getAParameter()
627+
succ = pred.(DataFlow::FunctionNode).getAParameter() or
628+
exploratoryBoundInvokeStep(pred, succ)
627629
}
628630

629631
/**
@@ -1032,6 +1034,13 @@ private predicate flowIntoHigherOrderCall(
10321034
succ = cb.getParameter(i) and
10331035
summary = oldSummary.append(PathSummary::call())
10341036
)
1037+
or
1038+
exists(DataFlow::SourceNode cb, DataFlow::FunctionNode f, int i, int boundArgs, PathSummary oldSummary |
1039+
higherOrderCall(pred, cb, i, cfg, oldSummary) and
1040+
cb = CallGraph::getABoundFunctionReference(f, boundArgs, false) and
1041+
succ = f.getParameter(boundArgs + i) and
1042+
summary = oldSummary.append(PathSummary::call())
1043+
)
10351044
}
10361045

10371046
/**

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@ private module CachedSteps {
104104
CallGraph::getABoundFunctionReference(f.flow(), boundArgs, false).flowsTo(invk.getCalleeNode())
105105
}
106106

107+
/**
108+
* Holds if `pred` may flow to `succ` through an invocation of a bound function.
109+
*
110+
* Should only be used for graph pruning, as the edge may lead to spurious flow.
111+
*/
112+
cached
113+
predicate exploratoryBoundInvokeStep(DataFlow::Node pred, DataFlow::Node succ) {
114+
exists(DataFlow::InvokeNode invk, DataFlow::FunctionNode f, int i, int boundArgs |
115+
CallGraph::getABoundFunctionReference(f, boundArgs, _).flowsTo(invk.getCalleeNode()) and
116+
pred = invk.getArgument(i) and
117+
succ = f.getParameter(i + boundArgs)
118+
)
119+
}
120+
107121
/**
108122
* Holds if `invk` may invoke `f` indirectly through the given `callback` argument.
109123
*

javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ typeInferenceMismatch
1717
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:22:10:22:10 | x |
1818
| bound-function.js:12:12:12:19 | source() | bound-function.js:4:10:4:10 | y |
1919
| bound-function.js:14:6:14:13 | source() | bound-function.js:4:10:4:10 | y |
20+
| bound-function.js:22:8:22:15 | source() | bound-function.js:25:10:25:10 | y |
2021
| bound-function.js:45:10:45:17 | source() | bound-function.js:45:6:45:18 | id3(source()) |
2122
| bound-function.js:49:12:49:19 | source() | bound-function.js:54:6:54:14 | source0() |
2223
| bound-function.js:49:12:49:19 | source() | bound-function.js:55:6:55:14 | source1() |

javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:22:10:22:10 | x |
99
| bound-function.js:12:12:12:19 | source() | bound-function.js:4:10:4:10 | y |
1010
| bound-function.js:14:6:14:13 | source() | bound-function.js:4:10:4:10 | y |
11+
| bound-function.js:22:8:22:15 | source() | bound-function.js:25:10:25:10 | y |
1112
| bound-function.js:45:10:45:17 | source() | bound-function.js:45:6:45:18 | id3(source()) |
1213
| bound-function.js:49:12:49:19 | source() | bound-function.js:54:6:54:14 | source0() |
1314
| bound-function.js:49:12:49:19 | source() | bound-function.js:55:6:55:14 | source1() |

javascript/ql/test/library-tests/TaintTracking/bound-function.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ foo2(null, source()); // OK
1919

2020

2121
function takesCallback(cb) {
22-
cb(source()); // NOT OK - but not found
22+
cb(source()); // NOT OK
2323
}
2424
function callback(x, y) {
2525
sink(y);

0 commit comments

Comments
 (0)