github / github/codeql

False Negative: ConstantLoopCondition.ql misses loops whose exit condition stays constant after being wrapped in helpers.

オープン
#21,537 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
CodeQL
スター
10.1k
フォーク
2.1k
平均マージ
2日 15時間
マージ済み PR(30日)
141

説明

Version
codeql 2.24.3

## Checker
- Checker id: `Likely Bugs/Termination/ConstantLoopCondition.ql`
- Checker description: This checker detects loop conditions that are constant within the loop body, potentially leading to non-terminating loops.

## Description of the false negative
These loops are still non-terminating for the same reason as the direct patterns: the value that controls exit never changes inside the loop. The code only wraps that check in a helper or rewrites the exit test into an equivalent form.

That should not move the sample outside the scope of `Likely Bugs/Termination/ConstantLoopCondition.ql`.

## Affected test cases
### `PosCase1_Var5.java`
`x` is never updated, so `check(x)` never changes. The helper only obscures an otherwise obvious infinite loop.

```java
// while loop with condition variable defined outside and no updates in body should be flagged as infinite loop
package scensct.var.pos;

public class PosCase1_Var5 {
private static boolean check(int val) {
return val > 0;
}

public static void main(String[] args) {
int x = 5;
// condition via helper method, x not updated
while (check(x)) {
System.out.println("stuck via method");
}
}
}
```

### `PosCase2_Var4.java`
`conditionHolds(y)` is stable because `y` is never modified in the loop body. This is still a constant loop condition.

```java
// while loop with condition using final field and variable defined outside should be flagged as infinite loop
package scensct.var.pos;

public class PosCase2_Var4 {
private static final int LIMIT = 10;
public static void main(String[] args) {
int y = 3;
// Extract condition evaluation to a helper method
while (conditionHolds(y)) {
System.out.println("stuck");
}
}
private static boolean conditionHolds(int val) {
return val < LIMIT;
}
}
```

### `PosCase5_Var5.java`
The loop exit is written as a guarded `return`, but `counter` never changes, so `shouldExit(counter)` remains false forever and the loop still does not terminate.

```java
// while true loop with if condition using variable defined outside controlling all exits should be flagged as infinite loop
package scensct.var.pos;

public class PosCase5_Var5 {
// Helper method to compute constant condition
private static boolean shouldExit(int c) {
return c == 1;
}

public static void main(String[] args) {
int counter = 0;
while (true) {
// Exit condition hidden in method call
if (shouldExit(counter)) {
return;
}
System.out.println("stuck");
}
}
}
```

## Cause analysis
The misses point to a query that is matching specific loop syntax rather than the underlying stability of the condition. Once the condition is computed in a helper or turned into an equivalent exit guard, the analysis seems to stop following it.

That leaves a real blind spot. Developers often factor loop predicates into helpers, and those helpers do not make a non-terminating loop any safer.

## References
None known.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

Likely Bugs/Termination/ConstantLoopCondition.ql から始め、既存のテストで定数ループ条件がどのようにカバーされているかを確認します。PosCase1_Var5.java、PosCase2_Var4.java、PosCase5_Var5.java で検出されていないケースを再現し、その後、関連するクエリテストを実行します。3つすべてのヘルパーでラップされた、またはガードで保護された非終了ループが、既存のカバレッジを失うことなく検出されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
java
領域
devtools, security
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
静か
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。