Skip to content

Commit 9bcac10

Browse files
committed
summarize exceptions thrown by immidiatly awaited function calls
1 parent 30dc77e commit 9bcac10

File tree

4 files changed

+32
-8
lines changed

4 files changed

+32
-8
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,17 @@ private predicate flowThroughCall(
10001000
not isLabeledBarrierEdge(cfg, ret, output, summary.getEndLabel()) and
10011001
not cfg.isLabeledBarrier(output, summary.getEndLabel())
10021002
)
1003+
or
1004+
// exception thrown inside an immidiatly awaited function call.
1005+
exists(DataFlow::FunctionNode f, DataFlow::Node invk, DataFlow::Node ret |
1006+
f.getFunction().isAsync()
1007+
|
1008+
(calls(invk, f.getFunction()) or callsBound(invk, f.getFunction(), _)) and
1009+
reachableFromInput(f.getFunction(), invk, input, ret, cfg, summary) and
1010+
output = invk.asExpr().getExceptionTarget() and
1011+
f.getExceptionalReturn() = getThrowTarget(ret) and
1012+
invk = getAwaitOperand(_)
1013+
)
10031014
}
10041015

10051016
/**

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

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,23 +70,34 @@ predicate localExceptionStep(DataFlow::Node pred, DataFlow::Node succ) {
7070
* The `async` flag is true if the successor
7171
*/
7272
predicate localExceptionStepWithAsyncFlag(DataFlow::Node pred, DataFlow::Node succ, boolean async) {
73-
exists(Expr expr |
74-
expr = any(ThrowStmt throw).getExpr() and
75-
pred = expr.flow()
76-
or
77-
DataFlow::exceptionalInvocationReturnNode(pred, expr)
78-
|
73+
exists(DataFlow::Node target | target = getThrowTarget(pred) |
7974
async = false and
80-
succ = expr.getExceptionTarget() and
75+
succ = target and
8176
not succ = any(DataFlow::FunctionNode f | f.getFunction().isAsync()).getExceptionalReturn()
8277
or
8378
async = true and
84-
exists(DataFlow::FunctionNode f | f.getExceptionalReturn() = expr.getExceptionTarget() |
79+
exists(DataFlow::FunctionNode f | f.getExceptionalReturn() = target |
8580
succ = f.getReturnNode() // returns a rejected promise - therefore using the ordinary return node.
8681
)
8782
)
8883
}
8984

85+
/**
86+
* Gets the dataflow-node that an exception thrown at `thrower` will flow to.
87+
*
88+
* The predicate that all functions are not async.
89+
*/
90+
DataFlow::Node getThrowTarget(DataFlow::Node thrower) {
91+
exists(Expr expr |
92+
expr = any(ThrowStmt throw).getExpr() and
93+
thrower = expr.flow()
94+
or
95+
DataFlow::exceptionalInvocationReturnNode(thrower, expr)
96+
|
97+
result = expr.getExceptionTarget()
98+
)
99+
}
100+
90101
/**
91102
* Implements a set of data flow predicates that are used by multiple predicates and
92103
* hence should only be computed once.

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ typeInferenceMismatch
5252
| exceptions.js:21:17:21:24 | source() | exceptions.js:24:10:24:21 | e.toString() |
5353
| exceptions.js:21:17:21:24 | source() | exceptions.js:25:10:25:18 | e.message |
5454
| exceptions.js:21:17:21:24 | source() | exceptions.js:26:10:26:19 | e.fileName |
55+
| exceptions.js:59:24:59:31 | source() | exceptions.js:61:12:61:12 | e |
5556
| exceptions.js:88:6:88:13 | source() | exceptions.js:11:10:11:10 | e |
5657
| exceptions.js:88:6:88:13 | source() | exceptions.js:32:10:32:10 | e |
5758
| exceptions.js:88:6:88:13 | source() | exceptions.js:33:10:33:21 | e.toString() |

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
| constructor-calls.js:14:15:14:22 | source() | constructor-calls.js:17:8:17:14 | c.param |
3232
| constructor-calls.js:14:15:14:22 | source() | constructor-calls.js:25:8:25:14 | d.param |
3333
| exceptions.js:3:15:3:22 | source() | exceptions.js:5:10:5:10 | e |
34+
| exceptions.js:59:24:59:31 | source() | exceptions.js:61:12:61:12 | e |
3435
| exceptions.js:88:6:88:13 | source() | exceptions.js:11:10:11:10 | e |
3536
| exceptions.js:93:11:93:18 | source() | exceptions.js:95:10:95:10 | e |
3637
| exceptions.js:100:13:100:20 | source() | exceptions.js:102:12:102:12 | e |

0 commit comments

Comments
 (0)