forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIllegalInvocation.ql
More file actions
64 lines (59 loc) · 1.94 KB
/
IllegalInvocation.ql
File metadata and controls
64 lines (59 loc) · 1.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
* @name Illegal invocation
* @description Attempting to invoke a method or an arrow function using 'new',
* or invoking a constructor as a function, will cause a runtime
* error.
* @kind problem
* @problem.severity error
* @id js/illegal-invocation
* @tags correctness
* language-features
* @precision high
*/
import javascript
/**
* Holds if call site `cs` may invoke function `callee` as specified by `how`.
*/
predicate calls(DataFlow::InvokeNode cs, Function callee, string how) {
callee = cs.getACallee() and
(
cs instanceof DataFlow::CallNode and not cs.asExpr() instanceof SuperCall and
how = "as a function"
or
cs instanceof DataFlow::NewNode and
how = "using 'new'"
)
}
/**
* Holds if call site `cs` may illegally invoke function `callee` as specified by `how`;
* `calleeDesc` describes what kind of function `callee` is.
*/
predicate illegalInvocation(DataFlow::InvokeNode cs, Function callee, string calleeDesc, string how) {
calls(cs, callee, how) and
(
how = "as a function" and
callee instanceof Constructor and
calleeDesc = "a constructor"
or
how = "using 'new'" and
callee.isNonConstructible(calleeDesc)
)
}
/**
* Holds if `ce` is a call with at least one call target that isn't a constructor.
*/
predicate isCallToFunction(DataFlow::InvokeNode ce) {
ce instanceof DataFlow::CallNode and
exists (Function f | f = ce.getACallee() |
not f instanceof Constructor
)
}
from DataFlow::InvokeNode cs, Function callee, string calleeDesc, string how
where illegalInvocation(cs, callee, calleeDesc, how) and
// filter out some easy cases
not isCallToFunction(cs) and
// conservatively only flag call sites where _all_ callees are illegal
forex (Function otherCallee | otherCallee = cs.getACallee() |
illegalInvocation(cs, otherCallee, _, _)
)
select cs, "Illegal invocation of $@ " + how + ".", callee, calleeDesc