SplFixedArrayIndexOutOfBounds
error native on by default PHP ≥ 5.3Group: Probable bugs
Use an index within the fixed array size.
Example
Finding:
php
<?php
$a = new SplFixedArray(3); $a[3] = "outside";Reported:
- line 2: Use an index within the fixed array size.
Detection
- Track literal nonnegative size from new SplFixedArray, fromArray and setSize. Report read/write/unset of a proven integer index below zero or greater than/equal to size. For fromArray, preserved indices determine size; with preserveKeys=false use element count.
- 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 size stays proven only while every earlier mention of the receiver is inert: an offset access, a named builtin method call, its own plain assignment, by-value
foreach,isset/empty,clone, or a direct argument of a read-only builtin such ascountorvar_dump. AsetSizecall counts only when it runs on every path to the access; a conditional one, or one later in a loop that also contains the access, removes proof. When the access is inside a loop, every mention anywhere in the outermost enclosing loop is treated as earlier. - A receiver that is not a plain local variable (a property, for instance) additionally loses proof when any method call on another receiver, user function call, static call or instantiation of a non-builtin class, or
include/requireappears before the access. - An element
unsetdoes not discard afromArrayallocation: the unset itself and later accesses are still checked, provided nosetSizefollows the allocation.
Exceptions (no report)
- Unknown sizes/indices and guarded in-range paths are excluded. Do not use ordinary PHP array bounds for SplFixedArray.
- Exclude shadowed builtin symbols, unresolved required types, incomplete syntax and unsupported PHP versions.
- Existence probes never throw and are not reported: an out-of-range offset that is an operand of
isset()orempty(), or the left operand of??, including when it is the base of a longer offset or property chain in that position (isset($a[9][0]),$a[9]->name ?? null). The probe does not extend to an index expression, a method call on the element or the right operand of??, and??=is still reported because it writes the offset. - No report once the receiver may have been resized or replaced out of sight: captured by a closure
useor mentioned in an arrow function, copied or referenced into another variable, passed to a user function, method, constructor or callback-invoking builtin, iterated by reference, unset as a whole, or called through a dynamic method name. - A size passed through an unpacked argument (
new SplFixedArray(...$args)) is unknown: no report.
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.
Configure
In custos.json:
json
{
"rules": {
"SplFixedArrayIndexOutOfBounds": {
"enabled": false
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
php
// @custos-ignore SplFixedArrayIndexOutOfBounds