Loop Control Variable Modified In Body
ID |
javascript.loop_control_var_reassigned_in_body |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
reliability |
Description
Reports an assignment, increment or decrement, inside a for loop body, of the very variable the loop’s update clause advances.
The counter is identified from both ends of the header: it must be advanced by the update clause and declared in the initializer. It is then matched by resolved symbol rather than by name, so a body-local or callback-parameter variable that shadows the counter is not mistaken for it.
Rationale
// Bad
for (let i = 0; i < parts.length; i++) {
if (parts[i] === "--") {
i++; // consumes the next part
}
emit(parts[i]); // may now read past the end
}
-
The loop has two places that move the counter, so the reader has to simulate both to know how many iterations run.
-
The usual outcome is an off-by-one, a skipped element, or a loop that never ends once the two updates disagree.
-
Reading an element past the end yields
undefinedrather than an error, so the defect propagates instead of failing where it happened.
Remediation
Advance the counter only in the update clause. When an iteration needs to consume extra input, read it through a separate index or restructure the walk with an explicit cursor.
// Good
let i = 0;
while (i < parts.length) {
const step = parts[i] === "--" ? 2 : 1;
emit(parts[i + step - 1]);
i += step;
}