Java: Add java/javautilconcurrentscheduledthreadpoolexecutor query for zero thread pool size

This commit is contained in:
Tamas Vajk
2025-06-23 11:59:55 +02:00
parent 12cda86141
commit 60e726bdf2
7 changed files with 77 additions and 0 deletions

View File

@@ -33,6 +33,7 @@ ql/java/ql/src/Likely Bugs/Concurrency/CallsToRunnableRun.ql
ql/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLocking.ql
ql/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLockingWithInitRace.ql
ql/java/ql/src/Likely Bugs/Concurrency/NonSynchronizedOverride.ql
ql/java/ql/src/Likely Bugs/Concurrency/ScheduledThreadPoolExecutorZeroThread.ql
ql/java/ql/src/Likely Bugs/Concurrency/SynchOnBoxedType.ql
ql/java/ql/src/Likely Bugs/Concurrency/SynchSetUnsynchGet.ql
ql/java/ql/src/Likely Bugs/Frameworks/JUnit/JUnit5MissingNestedAnnotation.ql

View File

@@ -31,6 +31,7 @@ ql/java/ql/src/Likely Bugs/Concurrency/CallsToRunnableRun.ql
ql/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLocking.ql
ql/java/ql/src/Likely Bugs/Concurrency/DoubleCheckedLockingWithInitRace.ql
ql/java/ql/src/Likely Bugs/Concurrency/NonSynchronizedOverride.ql
ql/java/ql/src/Likely Bugs/Concurrency/ScheduledThreadPoolExecutorZeroThread.ql
ql/java/ql/src/Likely Bugs/Concurrency/SynchOnBoxedType.ql
ql/java/ql/src/Likely Bugs/Concurrency/SynchSetUnsynchGet.ql
ql/java/ql/src/Likely Bugs/Frameworks/JUnit/JUnit5MissingNestedAnnotation.ql

View File

@@ -0,0 +1,24 @@
## Overview
According 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.
## Recommendation
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.
## Example
```java
public class Test {
void f() {
int i = 0;
ScheduledThreadPoolExecutor s = new ScheduledThreadPoolExecutor(1); // COMPLIANT
ScheduledThreadPoolExecutor s1 = new ScheduledThreadPoolExecutor(0); // NON_COMPLIANT
s.setCorePoolSize(0); // NON_COMPLIANT
s.setCorePoolSize(i); // NON_COMPLIANT
}
}
```
## References
- [ScheduledThreadPoolExecutor](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/concurrent/ScheduledThreadPoolExecutor.html)

View File

@@ -0,0 +1,35 @@
/**
* @id java/javautilconcurrentscheduledthreadpoolexecutor
* @name Zero threads set for `java.util.concurrent.ScheduledThreadPoolExecutor`
* @description Setting `java.util.concurrent.ScheduledThreadPoolExecutor` to have 0 threads serves
* no purpose and may indicate programmer error.
* @kind problem
* @precision very-high
* @problem.severity recommendation
* @tags quality
* reliability
* correctness
* concurrency
*/
import java
import semmle.code.java.dataflow.DataFlow
/**
* A `Call` that has the ability to set or modify the `corePoolSize` of the `java.util.concurrent.ScheduledThreadPoolExecutor` type.
*/
class Sink extends Call {
Sink() {
this.getCallee()
.hasQualifiedName("java.util.concurrent", "ThreadPoolExecutor", "setCorePoolSize") or
this.getCallee()
.hasQualifiedName("java.util.concurrent", "ScheduledThreadPoolExecutor",
"ScheduledThreadPoolExecutor")
}
}
from IntegerLiteral zero, Sink set
where
DataFlow::localFlow(DataFlow::exprNode(zero), DataFlow::exprNode(set.getArgument(0))) and
zero.getIntValue() = 0
select set, "ScheduledThreadPoolExecutor.corePoolSize is set to have 0 threads."

View File

@@ -0,0 +1,3 @@
| Test.java:7:42:7:75 | new ScheduledThreadPoolExecutor(...) | ScheduledThreadPoolExecutor.corePoolSize is set to have 0 threads. |
| Test.java:8:9:8:28 | setCorePoolSize(...) | ScheduledThreadPoolExecutor.corePoolSize is set to have 0 threads. |
| Test.java:9:9:9:28 | setCorePoolSize(...) | ScheduledThreadPoolExecutor.corePoolSize is set to have 0 threads. |

View File

@@ -0,0 +1,2 @@
query: Likely Bugs/Concurrency/ScheduledThreadPoolExecutorZeroThread.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,11 @@
import java.util.concurrent.ScheduledThreadPoolExecutor;
public class Test {
void f() {
int i = 0;
ScheduledThreadPoolExecutor s = new ScheduledThreadPoolExecutor(1); // Compliant
ScheduledThreadPoolExecutor s1 = new ScheduledThreadPoolExecutor(0); // $ Alert
s.setCorePoolSize(0); // $ Alert
s.setCorePoolSize(i); // $ Alert
}
}