Unset Loop References
ID |
php.unset_loop_references |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Php |
Tags |
dangling-reference, reliability |
Description
Reports a foreach loop that binds its value by reference (foreach ($arr as &$value))
without releasing that reference with unset($value) after the loop. The reference variable
outlives the loop and keeps pointing at the last element of the array.
Rationale
When a foreach binds the value by reference, the variable stays a live reference to the
final array element after the loop ends. Any later write to a variable of the same name —
very commonly a second foreach over the same array — silently overwrites that last element
instead of creating a fresh variable. This is one of PHP’s most surprising behaviours and the
source of hard-to-spot data-corruption bugs. Releasing the reference with unset() right after
the loop removes the hazard.
<?php
foreach ($items as &$item) { // FLAW — reference left dangling
$item = trim($item);
}
// ... later, $item still references $items[last]
foreach ($rows as &$row) { // OK — reference released after use
$row = normalize($row);
}
unset($row);