Skip to content

Commit 0933235

Browse files
committed
whitelist calls to functions that always throw an exception
1 parent a2993f1 commit 0933235

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

javascript/ql/src/Statements/UseOfReturnlessFunction.ql

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ predicate returnsVoid(Function f) {
2121
}
2222

2323
predicate isStub(Function f) {
24-
f.getBodyStmt(0) instanceof ThrowStmt
25-
or
2624
f.getBody().(BlockStmt).getNumChild() = 0
2725
or
2826
f instanceof ExternalDecl
@@ -76,10 +74,20 @@ predicate oneshotClosure(InvokeExpr call) {
7674
call.getCallee().getUnderlyingValue() instanceof ImmediatelyInvokedFunctionExpr
7775
}
7876

77+
predicate alwaysThrows(Function f) {
78+
exists(ReachableBasicBlock entry, DataFlow::Node throwNode |
79+
entry = f.getEntryBB() and
80+
throwNode.asExpr() = any(ThrowStmt t).getExpr() and
81+
entry.dominates(throwNode.getBasicBlock())
82+
)
83+
}
84+
7985
from DataFlow::CallNode call
8086
where
8187
not call.isIndefinite(_) and
82-
forex(Function f | f = call.getACallee() | returnsVoid(f) and not isStub(f)) and
88+
forex(Function f | f = call.getACallee() |
89+
returnsVoid(f) and not isStub(f) and not alwaysThrows(f)
90+
) and
8391

8492
not benignContext(call.asExpr()) and
8593

javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,16 @@
5656
var oneOfEach = Math.random() > 0.5 ? onlySideEffects : returnsValue;
5757
var g = oneOfEach(); // OK
5858
console.log(g);
59+
60+
function alwaysThrows() {
61+
if (Math.random() > 0.5) {
62+
console.log("Whatever!")
63+
} else {
64+
console.log("Boo!")
65+
}
66+
throw new Error("Important error!")
67+
}
68+
69+
var h = returnsValue() || alwaysThrows(); // OK!
70+
console.log(h);
5971
})();

0 commit comments

Comments
 (0)