Skip to content

Commit b31e6a7

Browse files
committed
Java: Improved java/jvm-exit query to remove FP's.
1 parent b348487 commit b31e6a7

File tree

4 files changed

+72
-24
lines changed

4 files changed

+72
-24
lines changed

java/ql/src/Violations of Best Practice/Undesirable Calls/CallsToSystemExit.ql

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,67 @@
1313

1414
import java
1515

16-
from Method m, MethodCall sysexitCall, Method sysexit, Class system
17-
where
18-
sysexitCall = m.getACallSite(sysexit) and
19-
(sysexit.hasName("exit") or sysexit.hasName("halt")) and
20-
sysexit.getDeclaringType() = system and
21-
(
22-
system.hasQualifiedName("java.lang", "System") or
23-
system.hasQualifiedName("java.lang", "Runtime")
24-
) and
25-
m.fromSource() and
26-
not m instanceof MainMethod
27-
select sysexitCall,
28-
"Avoid calls to " + sysexit.getDeclaringType().getName() + "." + sysexit.getName() +
29-
"() as this makes code harder to reuse."
16+
/**
17+
* A `Method` which, when called, causes the JVM to exit or halt.
18+
* Explicitly includes these methods from the java standard library:
19+
* - `java.lang.System.exit`
20+
* - `java.lang.Runtime.halt`
21+
* - `java.lang.Runtime.exit`
22+
*/
23+
class ExitOrHaltMethod extends Method {
24+
ExitOrHaltMethod() {
25+
exists(Class system |
26+
this.getDeclaringType() = system and
27+
(
28+
this.hasName("exit") and
29+
(
30+
system.hasQualifiedName("java.lang", "System") or
31+
system.hasQualifiedName("java.lang", "Runtime")
32+
)
33+
or
34+
this.hasName("halt") and
35+
system.hasQualifiedName("java.lang", "Runtime")
36+
)
37+
)
38+
}
39+
}
40+
41+
/** A `MethodCall` to an `ExitOrHaltMethod`, which causes the JVM to exit abruptly. */
42+
class ExitOrHaltMethodCall extends MethodCall {
43+
ExitOrHaltMethodCall() {
44+
exists(ExitOrHaltMethod exitMethod | this.getMethod() = exitMethod |
45+
exists(SourceMethodNotMainOrTest srcMethod | this = srcMethod.getACallSite(exitMethod))
46+
)
47+
}
48+
}
49+
50+
/**
51+
* Represents an intentional `MethodCall` to a system or runtime "exit" method, such as for
52+
* functions which exist for the purpose of exiting the program. Assumes that a an exit method
53+
* call within a method is intentional if the exit code is passed from a parameter of the
54+
* enclosing method.
55+
*/
56+
class IntentionalExitMethodCall extends ExitOrHaltMethodCall {
57+
IntentionalExitMethodCall() {
58+
this.getMethod().hasName("exit") and
59+
this.getAnArgument() = this.getEnclosingCallable().getAParameter().getAnAccess()
60+
}
61+
}
62+
63+
/**
64+
* A `Method` that is defined in source code and is not a `MainMethod` or a `LikelyTestMethod`.
65+
*/
66+
class SourceMethodNotMainOrTest extends Method {
67+
SourceMethodNotMainOrTest() {
68+
this.fromSource() and
69+
not this instanceof MainMethod and
70+
not this instanceof LikelyTestMethod and
71+
not this.getEnclosingCallable() instanceof LikelyTestMethod
72+
}
73+
}
74+
75+
from ExitOrHaltMethodCall mc
76+
where not mc instanceof IntentionalExitMethodCall
77+
select mc,
78+
"Avoid calls to " + mc.getMethod().getDeclaringType().getName() + "." + mc.getMethod().getName() +
79+
"() as this prevents runtime cleanup and makes code harder to reuse."
Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
| ExampleRuntimeExit.java:22:17:22:44 | exit(...) | Avoid calls to Runtime.exit() as this makes code harder to reuse. |
2-
| ExampleRuntimeExit.java:25:17:25:44 | exit(...) | Avoid calls to Runtime.exit() as this makes code harder to reuse. |
3-
| ExampleRuntimeExit.java:35:9:35:43 | exit(...) | Avoid calls to Runtime.exit() as this makes code harder to reuse. |
4-
| ExampleRuntimeHalt.java:18:17:18:44 | halt(...) | Avoid calls to Runtime.halt() as this makes code harder to reuse. |
5-
| ExampleRuntimeHalt.java:21:17:21:44 | halt(...) | Avoid calls to Runtime.halt() as this makes code harder to reuse. |
6-
| ExampleSystemExit.java:22:17:22:30 | exit(...) | Avoid calls to System.exit() as this makes code harder to reuse. |
7-
| ExampleSystemExit.java:25:17:25:30 | exit(...) | Avoid calls to System.exit() as this makes code harder to reuse. |
8-
| ExampleSystemExit.java:35:9:35:29 | exit(...) | Avoid calls to System.exit() as this makes code harder to reuse. |
1+
| ExampleRuntimeExit.java:22:17:22:44 | exit(...) | Avoid calls to Runtime.exit() as this prevents runtime cleanup and makes code harder to reuse. |
2+
| ExampleRuntimeExit.java:25:17:25:44 | exit(...) | Avoid calls to Runtime.exit() as this prevents runtime cleanup and makes code harder to reuse. |
3+
| ExampleRuntimeHalt.java:18:17:18:44 | halt(...) | Avoid calls to Runtime.halt() as this prevents runtime cleanup and makes code harder to reuse. |
4+
| ExampleRuntimeHalt.java:21:17:21:44 | halt(...) | Avoid calls to Runtime.halt() as this prevents runtime cleanup and makes code harder to reuse. |
5+
| ExampleSystemExit.java:22:17:22:30 | exit(...) | Avoid calls to System.exit() as this prevents runtime cleanup and makes code harder to reuse. |
6+
| ExampleSystemExit.java:25:17:25:30 | exit(...) | Avoid calls to System.exit() as this prevents runtime cleanup and makes code harder to reuse. |

java/ql/test/query-tests/CallsToSystemExit/ExampleRuntimeExit.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ public void run() {
3232

3333
protected static void printUsageAndExit(final String message, final int exitCode) {
3434
System.err.println("Usage: <example_cmd> <example_args> : " + message);
35-
Runtime.getRuntime().exit(exitCode); // $ SPURIOUS: Alert
35+
Runtime.getRuntime().exit(exitCode); // COMPLIANT
3636
}
3737
}

java/ql/test/query-tests/CallsToSystemExit/ExampleSystemExit.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ public void run() {
3232

3333
protected static void printUsageAndExit(final String message, final int exitCode) {
3434
System.err.println("Usage: <example_cmd> <example_args> : " + message);
35-
System.exit(exitCode); // $ SPURIOUS: Alert
35+
System.exit(exitCode); // COMPLIANT
3636
}
3737
}

0 commit comments

Comments
 (0)