Skip to content

Commit ae36f94

Browse files
authored
Merge pull request #19844 from tamasvajk/tamasvajk/threadpoolexecutor
Java: Add `java/javautilconcurrentscheduledthreadpoolexecutor` query for zero thread pool size
2 parents afc78ce + 1bd543a commit ae36f94

File tree

7 files changed

+78
-0
lines changed

7 files changed

+78
-0
lines changed

java/ql/integration-tests/java/query-suite/java-code-quality-extended.qls.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ ql/java/ql/src/Likely Bugs/Concurrency/CallsToRunnableRun.ql
3232
ql/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLocking.ql
3333
ql/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLockingWithInitRace.ql
3434
ql/java/ql/src/Likely Bugs/Concurrency/NonSynchronizedOverride.ql
35+
ql/java/ql/src/Likely Bugs/Concurrency/ScheduledThreadPoolExecutorZeroThread.ql
3536
ql/java/ql/src/Likely Bugs/Concurrency/SynchOnBoxedType.ql
3637
ql/java/ql/src/Likely Bugs/Concurrency/SynchSetUnsynchGet.ql
3738
ql/java/ql/src/Likely Bugs/Frameworks/JUnit/JUnit5MissingNestedAnnotation.ql

java/ql/integration-tests/java/query-suite/java-code-quality.qls.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ ql/java/ql/src/Likely Bugs/Concurrency/CallsToRunnableRun.ql
3030
ql/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLocking.ql
3131
ql/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLockingWithInitRace.ql
3232
ql/java/ql/src/Likely Bugs/Concurrency/NonSynchronizedOverride.ql
33+
ql/java/ql/src/Likely Bugs/Concurrency/ScheduledThreadPoolExecutorZeroThread.ql
3334
ql/java/ql/src/Likely Bugs/Concurrency/SynchOnBoxedType.ql
3435
ql/java/ql/src/Likely Bugs/Concurrency/SynchSetUnsynchGet.ql
3536
ql/java/ql/src/Likely Bugs/Frameworks/JUnit/JUnit5MissingNestedAnnotation.ql
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## Overview
2+
3+
According to the Java documentation on `ScheduledThreadPoolExecutor`, it is not a good idea to set `corePoolSize` to zero, since doing so indicates the executor to keep 0 threads in its pool and the executor will serve no purpose.
4+
5+
## Recommendation
6+
7+
Set the `ScheduledThreadPoolExecutor` to have 1 or more threads in its thread pool and use the class's other methods to create a thread execution schedule.
8+
9+
## Example
10+
11+
```java
12+
public class Test {
13+
void f() {
14+
int i = 0;
15+
ScheduledThreadPoolExecutor s = new ScheduledThreadPoolExecutor(1); // COMPLIANT
16+
ScheduledThreadPoolExecutor s1 = new ScheduledThreadPoolExecutor(0); // NON_COMPLIANT
17+
s.setCorePoolSize(0); // NON_COMPLIANT
18+
s.setCorePoolSize(i); // NON_COMPLIANT
19+
}
20+
}
21+
```
22+
23+
## References
24+
- [ScheduledThreadPoolExecutor](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/concurrent/ScheduledThreadPoolExecutor.html)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @id java/java-util-concurrent-scheduledthreadpoolexecutor
3+
* @name Zero threads set for `java.util.concurrent.ScheduledThreadPoolExecutor`
4+
* @description Setting `java.util.concurrent.ScheduledThreadPoolExecutor` to have 0 threads serves
5+
* no purpose and may indicate programmer error.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity recommendation
9+
* @previous-id java/javautilconcurrentscheduledthreadpoolexecutor
10+
* @tags quality
11+
* reliability
12+
* correctness
13+
* concurrency
14+
*/
15+
16+
import java
17+
import semmle.code.java.dataflow.DataFlow
18+
19+
/**
20+
* A `Call` that has the ability to set or modify the `corePoolSize` of the `java.util.concurrent.ScheduledThreadPoolExecutor` type.
21+
*/
22+
class Sink extends Call {
23+
Sink() {
24+
this.getCallee()
25+
.hasQualifiedName("java.util.concurrent", "ThreadPoolExecutor", "setCorePoolSize") or
26+
this.getCallee()
27+
.hasQualifiedName("java.util.concurrent", "ScheduledThreadPoolExecutor",
28+
"ScheduledThreadPoolExecutor")
29+
}
30+
}
31+
32+
from IntegerLiteral zero, Sink set
33+
where
34+
DataFlow::localFlow(DataFlow::exprNode(zero), DataFlow::exprNode(set.getArgument(0))) and
35+
zero.getIntValue() = 0
36+
select set, "ScheduledThreadPoolExecutor.corePoolSize is set to have 0 threads."
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| Test.java:7:42:7:75 | new ScheduledThreadPoolExecutor(...) | ScheduledThreadPoolExecutor.corePoolSize is set to have 0 threads. |
2+
| Test.java:8:9:8:28 | setCorePoolSize(...) | ScheduledThreadPoolExecutor.corePoolSize is set to have 0 threads. |
3+
| Test.java:9:9:9:28 | setCorePoolSize(...) | ScheduledThreadPoolExecutor.corePoolSize is set to have 0 threads. |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
query: Likely Bugs/Concurrency/ScheduledThreadPoolExecutorZeroThread.ql
2+
postprocess: utils/test/InlineExpectationsTestQuery.ql
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import java.util.concurrent.ScheduledThreadPoolExecutor;
2+
3+
public class Test {
4+
void f() {
5+
int i = 0;
6+
ScheduledThreadPoolExecutor s = new ScheduledThreadPoolExecutor(1); // Compliant
7+
ScheduledThreadPoolExecutor s1 = new ScheduledThreadPoolExecutor(0); // $ Alert
8+
s.setCorePoolSize(0); // $ Alert
9+
s.setCorePoolSize(i); // $ Alert
10+
}
11+
}

0 commit comments

Comments
 (0)