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

Skip to content

Commit 7025ba3

Browse files
committed
refactor of js/use-of-returnless-function
1 parent 00bf82d commit 7025ba3

2 files changed

Lines changed: 35 additions & 21 deletions

File tree

javascript/ql/src/Statements/UseOfReturnlessFunction.ql

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -70,38 +70,45 @@ predicate benignContext(Expr e) {
7070
exists(InvokeExpr invoke | invoke.getCallee() = e)
7171
}
7272

73-
from Function f, DataFlow::CallNode call
74-
where
75-
// Intentionally only considering very precise callee information. It makes almost no difference.
76-
f = call.getACallee(0) and
77-
count(call.getACallee(0)) = 1 and
78-
79-
returnsVoid(f) and
80-
81-
// reflective calls don't have an ast-node, thus we can't decide whether or not they are in void-context.
82-
exists(call.asExpr()) and
83-
84-
not isStub(f) and
85-
86-
not call.getTopLevel().isMinified() and
73+
predicate functionBlacklist(Function f) {
74+
not returnsVoid(f)
75+
or
76+
isStub(f)
77+
}
78+
79+
predicate callBlacklist(DataFlow::CallNode call) {
80+
call.asExpr().getTopLevel().isMinified() or
8781

88-
not benignContext(call.asExpr()) and
82+
benignContext(call.asExpr()) or
8983

9084
// anonymous one-shot closure. Those are used in weird ways and we ignore them.
91-
not call.getCalleeNode().asExpr() instanceof FunctionExpr and
85+
call.asExpr() = any(ImmediatelyInvokedFunctionExpr f).getInvocation() or
9286

9387
// weeds out calls inside html-attributes.
94-
not(call.asExpr().getParent*() instanceof CodeInAttribute) and
88+
call.asExpr().getParent*() instanceof CodeInAttribute or
9589
// and JSX-attributes.
96-
not(call.asExpr().getParent*() instanceof JSXAttribute) and
90+
call.asExpr().getParent*() instanceof JSXAttribute or
9791

9892
// Calls on "this" tend to overloaded. So future overloads might start returning something.
99-
not call.asExpr().(MethodCallExpr).getReceiver() instanceof ThisExpr and
93+
call.asExpr().(MethodCallExpr).getReceiver() instanceof ThisExpr or
10094
// similarly, methods received through parameters might later receive new dataflow. We have just only seen one callee.
101-
not call.getCalleeNode().getALocalSource() instanceof DataFlow::ParameterNode and
95+
call.getCalleeNode().getALocalSource() instanceof DataFlow::ParameterNode or
10296

10397
// arguments to Promise.resolve (and promise library variants) are benign.
104-
not exists(MethodCallExpr e | e.getCalleeName() = "resolve" and call.asExpr() = e.getArgument(0))
98+
exists(MethodCallExpr e | e.getCalleeName() = "resolve" and call.asExpr() = e.getArgument(0))
99+
}
100+
101+
from Function f, DataFlow::CallNode call
102+
where
103+
// Intentionally only considering very precise callee information. It makes almost no difference.
104+
f = call.getACallee(0) and
105+
count(call.getACallee(0)) = 1 and
106+
107+
not functionBlacklist(f) and
108+
109+
exists(call.asExpr()) and // TODO: Need to figure out what to do about reflective calls.
110+
111+
not callBlacklist(call)
105112
select
106113
call, "the function $@ does not return anything, yet the return value is used.", f, call.getCalleeName()
107114

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,11 @@
3737
for (i = 0; onlySideEffects(); i++) {
3838
// nothing.
3939
}
40+
41+
var myObj = {
42+
onlySideEffects: onlySideEffects
43+
}
44+
45+
var e = myObj.onlySideEffects.apply(this, arguments); // NOT OK!
46+
console.log(e);
4047
})();

0 commit comments

Comments
 (0)