@@ -16,7 +16,6 @@ import Statements.UselessConditional
1616
1717predicate returnsVoid ( Function f ) {
1818 f .getBody ( ) instanceof Stmt and
19- not f instanceof ExternalDecl and
2019 not f .isGenerator ( ) and
2120 not f .isAsync ( ) and
2221 not exists ( f .getAReturnedExpr ( ) )
@@ -25,7 +24,9 @@ predicate returnsVoid(Function f) {
2524predicate isStub ( Function f ) {
2625 f .getBodyStmt ( 0 ) instanceof ThrowStmt
2726 or
28- f .getBody ( ) .( BlockStmt ) .getNumChild ( ) = 0
27+ f .getBody ( ) .( BlockStmt ) .getNumChild ( ) = 0
28+ or
29+ f instanceof ExternalDecl
2930}
3031
3132predicate benignContext ( Expr e ) {
@@ -37,10 +38,6 @@ predicate benignContext(Expr e) {
3738 exists ( ConditionalExpr cond | cond .getABranch ( ) = e and benignContext ( cond ) )
3839 or
3940 exists ( LogicalBinaryExpr bin | bin .getAnOperand ( ) = e and benignContext ( bin ) )
40- or
41- exists ( SeqExpr seq , int i , int n | e = seq .getOperand ( i ) and n = seq .getNumOperands ( ) |
42- i < n - 1 or benignContext ( seq )
43- exists ( SeqExpr seq | seq .getLastOperand ( ) = e and benignContext ( seq ) )
4441 or
4542 exists ( Expr parent | parent .getUnderlyingValue ( ) = e and benignContext ( parent ) )
4643 or
@@ -52,7 +49,6 @@ exists(SeqExpr seq | seq.getLastOperand() = e and benignContext(seq))
5249 // and JSX-attributes.
5350 e = any ( JSXAttribute attr ) .getValue ( ) or
5451
55- // It is ok (or to be flagged by another query?) to await a non-async function.
5652 exists ( AwaitExpr await | await .getOperand ( ) = e and benignContext ( await ) )
5753 or
5854 // Avoid double reporting with js/trivial-conditional
@@ -69,35 +65,21 @@ exists(SeqExpr seq | seq.getLastOperand() = e and benignContext(seq))
6965 or
7066 // Avoid double reporting with js/call-to-non-callable
7167 any ( InvokeExpr invoke ) .getCallee ( ) = e
72- }
73-
74- predicate functionBlacklist ( Function f ) {
75- not returnsVoid ( f )
76- or
77- isStub ( f )
78- }
79-
80- predicate callBlacklist ( DataFlow:: CallNode call ) {
81- call .asExpr ( ) .getTopLevel ( ) .isMinified ( ) or
82-
83- benignContext ( call .asExpr ( ) ) or
84-
85- // anonymous one-shot closure. Those are used in weird ways and we ignore them.
86- call .asExpr ( ) = any ( ImmediatelyInvokedFunctionExpr f ) .getInvocation ( ) or
87-
68+ or
8869 // arguments to Promise.resolve (and promise library variants) are benign.
89- call = any ( ResolvedPromiseDefinition promise ) .getValue ( )
70+ e = any ( ResolvedPromiseDefinition promise ) .getValue ( ) . asExpr ( )
9071}
9172
73+
9274from DataFlow:: CallNode call
9375where
94- // Intentionally only considering very precise callee information. It makes almost no difference.
9576 not call .isIndefinite ( _) and
96- forex ( Function f | f = call .getACallee ( ) | not functionBlacklist ( f ) ) and
77+ forex ( Function f | f = call .getACallee ( ) | returnsVoid ( f ) and not isStub ( f ) ) and
9778
98- exists ( call .asExpr ( ) ) and // TODO: Need to figure out what to do about reflective calls.
79+ not benignContext ( call .asExpr ( ) ) and
9980
100- not callBlacklist ( call )
81+ // anonymous one-shot closure. Those are used in weird ways and we ignore them.
82+ call .asExpr ( ) != any ( ImmediatelyInvokedFunctionExpr f ) .getInvocation ( )
10183select
10284 call , "the function $@ does not return anything, yet the return value is used." , call .getACallee ( ) , call .getCalleeName ( )
10385
0 commit comments