diff --git a/java/ql/src/Likely Bugs/Termination/ConstantLoopCondition.ql b/java/ql/src/Likely Bugs/Termination/ConstantLoopCondition.ql index f5f1eb5e1485..41be2be2c52c 100644 --- a/java/ql/src/Likely Bugs/Termination/ConstantLoopCondition.ql +++ b/java/ql/src/Likely Bugs/Termination/ConstantLoopCondition.ql @@ -79,7 +79,11 @@ where ) and // And `cond` does not use method calls, field reads, or array reads. not exists(MethodAccess ma | ma.getParent*() = cond) and - not exists(FieldRead fa | fa.getParent*() = cond) and + not exists(FieldRead fa | + // Ignore if field is final + not fa.getField().isFinal() and + fa.getParent*() = cond + ) and not exists(ArrayAccess aa | aa.getParent*() = cond) select cond, "$@ might not terminate, as this loop condition is constant within the loop.", loop, "Loop" diff --git a/java/ql/test/query-tests/ConstantLoopCondition/A.java b/java/ql/test/query-tests/ConstantLoopCondition/A.java index c5ce23118af4..444954476dab 100644 --- a/java/ql/test/query-tests/ConstantLoopCondition/A.java +++ b/java/ql/test/query-tests/ConstantLoopCondition/A.java @@ -1,4 +1,6 @@ class A { + final boolean cond = otherCond(); + boolean otherCond() { return 3 > 5; } void f(int initx) { @@ -30,5 +32,9 @@ void f(int initx) { while(initx > 0) { // OK: loop used as an if-statement break; } + + while (cond) { // BAD: read of final field + i++; + } } } diff --git a/java/ql/test/query-tests/ConstantLoopCondition/ConstantLoopCondition.expected b/java/ql/test/query-tests/ConstantLoopCondition/ConstantLoopCondition.expected index 561b13618bef..688cdd7f258a 100644 --- a/java/ql/test/query-tests/ConstantLoopCondition/ConstantLoopCondition.expected +++ b/java/ql/test/query-tests/ConstantLoopCondition/ConstantLoopCondition.expected @@ -1,3 +1,4 @@ -| A.java:6:11:6:15 | !... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:6:5:6:16 | stmt | Loop | -| A.java:13:11:13:15 | ... > ... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:12:5:12:19 | stmt | Loop | -| A.java:27:20:27:32 | ... < ... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:27:5:27:38 | stmt | Loop | +| A.java:8:11:8:15 | !... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:8:5:8:16 | stmt | Loop | +| A.java:15:11:15:15 | ... > ... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:14:5:14:19 | stmt | Loop | +| A.java:29:20:29:32 | ... < ... | $@ might not terminate, as this loop condition is constant within the loop. | A.java:29:5:29:38 | stmt | Loop | +| A.java:36:12:36:15 | cond | $@ might not terminate, as this loop condition is constant within the loop. | A.java:36:5:36:16 | stmt | Loop |