forked from github/codeql
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCallsToSystemExit.ql
More file actions
81 lines (75 loc) · 2.57 KB
/
CallsToSystemExit.ql
File metadata and controls
81 lines (75 loc) · 2.57 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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* @name Forcible JVM termination
* @description Calling 'System.exit', 'Runtime.halt', or 'Runtime.exit' may make code harder to
* reuse and prevent important cleanup steps from running.
* @kind problem
* @problem.severity warning
* @precision medium
* @id java/jvm-exit
* @tags quality
* reliability
* correctness
* external/cwe/cwe-382
*/
import java
/**
* A `Method` which, when called, causes the JVM to exit or halt.
* Explicitly includes these methods from the java standard library:
* - `java.lang.System.exit`
* - `java.lang.Runtime.halt`
* - `java.lang.Runtime.exit`
*/
class ExitOrHaltMethod extends Method {
ExitOrHaltMethod() {
exists(Class system | this.getDeclaringType() = system |
this.hasName("exit") and
system.hasQualifiedName("java.lang", ["System", "Runtime"])
or
this.hasName("halt") and
system.hasQualifiedName("java.lang", "Runtime")
)
}
}
/** A `MethodCall` to an `ExitOrHaltMethod`, which causes the JVM to exit abruptly. */
class ExitOrHaltMethodCall extends MethodCall {
ExitOrHaltMethodCall() {
exists(ExitOrHaltMethod exitMethod | this.getMethod() = exitMethod |
exists(SourceMethodNotMainOrTest srcMethod | this = srcMethod.getACallSite(exitMethod))
)
}
}
/**
* An intentional `MethodCall` to a system or runtime "exit" method, such as for
* functions which exist for the purpose of exiting the program. Assumes that an exit method
* call within a method is intentional if the exit code is passed from a parameter of the
* enclosing method.
*/
class IntentionalExitMethodCall extends ExitOrHaltMethodCall {
IntentionalExitMethodCall() {
this.getMethod().hasName("exit") and
this.getAnArgument() = this.getEnclosingCallable().getAParameter().getAnAccess()
}
}
/**
* A `Method` that is defined in source code and is not a `MainMethod` or a `LikelyTestMethod`.
*/
class SourceMethodNotMainOrTest extends Method {
SourceMethodNotMainOrTest() {
this.fromSource() and
not this instanceof MainMethod and
not (
this.getEnclosingCallable*() instanceof LikelyTestMethod
or
this.getDeclaringType()
.getEnclosingType*()
.(LocalClassOrInterface)
.getLocalTypeDeclStmt()
.getEnclosingCallable() instanceof LikelyTestMethod
)
}
}
from ExitOrHaltMethodCall mc
where not mc instanceof IntentionalExitMethodCall
select mc,
"Avoid calls to " + mc.getMethod().getDeclaringType().getName() + "." + mc.getMethod().getName() +
"() as this prevents runtime cleanup and makes code harder to reuse."