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);

Remediation

Add unset($value); immediately after the loop, using the same name as the by-reference loop variable. If a reference is not actually required, drop the & and iterate by value instead.