2023-05-03 11:06:20 +02:00
== Why is this an issue?
2023-08-17 14:53:18 +02:00
A `for` loop with a counter moving away from the end of the specified range is likely a programming mistake.
If the intention is to iterate over the specified range, this differs from what the loop does because the counter moves in the wrong direction.
If the intention is to have an infinite loop or a loop terminated only by a break statement, there are two problems:
1. The loop condition is not infinite because the counter variable will eventually overflow and fulfill the condition. This can take a long time, depending on the data type of the counter.
2. An infinite loop terminated by a `break` statement should be implemented using a `while` or `do` `while` loop to make the developer's intention clear to the reader.
2021-09-21 15:40:35 +02:00
2023-06-27 15:03:47 +02:00
== How to fix it
2021-09-21 15:40:35 +02:00
2023-06-27 15:03:47 +02:00
=== Code examples
2021-09-21 15:40:35 +02:00
2023-06-27 15:03:47 +02:00
==== Noncompliant code example
2021-09-21 15:40:35 +02:00
2023-08-17 14:53:18 +02:00
Change the direction of the counter.
2023-06-27 15:03:47 +02:00
[source,java,diff-id=1,diff-type=noncompliant]
----
2023-08-17 14:53:18 +02:00
for (int i = 10; i > 0; i++) { // Noncompliant, wrong direction
System.out.println("Hello, world!") // executed ca. 2 billion times
}
----
[source,java,diff-id=2,diff-type=noncompliant]
----
2023-06-27 15:03:47 +02:00
public void doSomething(String [] strings) {
2023-08-17 14:53:18 +02:00
for (int i = 0; i < strings.length; i--) { // Noncompliant, wrong direction
2023-06-27 15:03:47 +02:00
String string = strings[i]; // ArrayIndexOutOfBoundsException when i reaches -1
2023-08-17 14:53:18 +02:00
// ...
2023-06-27 15:03:47 +02:00
}
2023-08-17 14:53:18 +02:00
}
2023-06-27 15:03:47 +02:00
----
2021-06-02 20:44:38 +02:00
2023-06-27 15:03:47 +02:00
==== Compliant solution
2021-09-20 15:38:42 +02:00
2023-06-27 15:03:47 +02:00
[source,java,diff-id=1,diff-type=compliant]
----
2023-08-17 14:53:18 +02:00
for (int i = 10; i > 0; i--) { // Compliant
System.out.println("Hello, world!") // executed 10 times
}
----
[source,java,diff-id=2,diff-type=compliant]
----
2023-06-27 15:03:47 +02:00
public void doSomething(String [] strings) {
2023-08-17 14:53:18 +02:00
for (int i = 0; i < strings.length; i++) { // Compliant
2023-06-27 15:03:47 +02:00
String string = strings[i];
2023-08-17 14:53:18 +02:00
// ...
2023-06-27 15:03:47 +02:00
}
2023-08-17 14:53:18 +02:00
}
2023-06-27 15:03:47 +02:00
----
2021-09-20 15:38:42 +02:00
2023-08-17 14:53:18 +02:00
==== Noncompliant code example
If the intention is to have an infinite loop or a loop terminated only by a break statement, use a `while` or a `do` `while` statement instead.
2023-09-13 16:39:32 +02:00
[source,java,diff-id=3,diff-type=noncompliant]
2023-08-17 14:53:18 +02:00
----
for (int i = 0; i < 0; i++) { // Noncompliant, loop is not infinite
String event = waitForNextEvent();
if (event == "terminate") break;
processEvent(event);
}
----
==== Compliant solution
2023-09-13 16:39:32 +02:00
[source,java,diff-id=3,diff-type=compliant]
2023-08-17 14:53:18 +02:00
----
while (true) { // Compliant
String event = waitForNextEvent();
if (event == "terminate") break;
processEvent(event);
}
----
2023-06-27 15:03:47 +02:00
== Resources
2021-09-20 15:38:42 +02:00
2023-06-27 15:03:47 +02:00
=== Documentation
2021-06-02 20:44:38 +02:00
2023-06-27 15:03:47 +02:00
* https://wiki.sei.cmu.edu/confluence/x/aTdGBQ[CERT, MSC54-J.] - Avoid inadvertent wrapping of loop counters
2023-06-22 10:38:01 +02:00
2023-08-17 14:53:18 +02:00
=== Articles & blog posts
* https://en.wikipedia.org/wiki/Integer_overflow[Wikipedia - Integer overflow]
2023-06-27 15:03:47 +02:00
include::../rspecator.adoc[]