LinkedListDeleteIterationUnexpected
warning native off by default PHP ≥ 5.3Group: Probable bugs
Preserve linked-list elements during iteration. This opt-in inspection applies the policy stated in Detection.
Example
Finding with the rule explicitly enabled:
php
<?php
$l = new SplDoublyLinkedList(); $l->setIteratorMode(SplDoublyLinkedList::IT_MODE_DELETE); foreach ($l as $item) {}Reported:
- line 2: Preserve linked-list elements during iteration.
Detection
- Enabled policy requires non-destructive linked-list traversal. Track setIteratorMode flags for resolved builtin SplDoublyLinkedList (and inherited SplQueue/SplStack behavior); report foreach iterable when the current mode includes IT_MODE_DELETE.
- Emit one finding per violating operation. Flow facts require a reachable path with no intervening mutation, escaped alias, unknown call involving the tracked value or analysis-budget exhaustion. Uncertain facts cannot prove a violation.
- The mode is the one set by the last
setIteratorModecall that runs unconditionally before the loop on the same list. It only counts as proven when no other mode change can run between that call and the first execution of the loop. Mode changes placed after the loop are ignored unless an enclosing loop can replay them before a later execution of this loop. A possible replay prevents a fixed-mode proof.
Exceptions (no report)
- Exclude IT_MODE_KEEP, unknown modes, clones and custom iteration behavior. Direction bits alone do not imply deletion.
- No report when, after the last unconditional mode call and before the loop, a
setIteratorModecall (or a method call with a dynamic name) sits where it is not guaranteed to run or cannot be tied to the list: inside anif/else/switchbranch, atryblock, a loop header or body, a ternary or short-circuit operand, or on a nullsafe or unproven receiver. The mode is then unknown rather thanIT_MODE_DELETE. - No report when, anywhere before the loop, a closure or arrow function contains a
setIteratorModecall or refers to the list variable (includingusecaptures), or the list variable is placed in an array literal such as a[$list, 'setIteratorMode']callable. The list has escaped and its mode can be changed out of sight. - Exclude shadowed builtin symbols, unresolved required types, incomplete syntax and unsupported PHP versions.
Fix
No automatic fix. Choosing a repair requires runtime information, error-handling policy or a semantic decision.
All edits use exact byte ranges, preserve comments and evaluation order, and require syntax supported by the target PHP version. A fix must never add an evaluation or silently change unrelated arguments.
PHP versions
Minimum PHP 5.3.
Options
None. Enabling the rule declares the policy stated in Detection; the rule is disabled by default.
Configure
In custos.json:
json
{
"rules": {
"LinkedListDeleteIterationUnexpected": {
"enabled": true
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
php
// @custos-ignore LinkedListDeleteIterationUnexpected