ReadLoopProcessesEofFailure
warning native on by default PHP ≥ 7.0Group: Probable bugs
An EOF-tested loop can pass a failed read to a strict string consumer. Loop on the successful read result before processing a line.
Example
php
<?php
declare(strict_types=1);$h=tmpfile();while(!feof($h)){strlen(fgets($h));}
$g=tmpfile();while(!feof($g)){$line=fgets($g);echo trim($line);}Reported:
- line 2: Loop on successful reads before consuming line data.
- line 3: Loop on successful reads before consuming line data.
Detection
- A while condition is !feof(simpleLocalHandle); under declare(strict_types=1) (the directive name is case-insensitive), its body unconditionally assigns fgets(sameHandle) to a local then passes it to resolved strlen, trim or strtoupper without a false guard, or directly nests fgets in that consumer. These consumers require strings and reject the false read result in strict mode. Highlight loop condition. Echo and coercive consumers are excluded because false can be harmless there.
- Resolve builtin functions, classes, constants and methods; user-defined lookalikes are excluded. Follow only bounded local proof in one lexical scope.
- Emit one finding per violating operation, not per supporting evidence statement. When the proof is inconclusive, nothing is reported.
Exceptions (no report)
- Do not report unresolved or shadowed builtin names, unknown values, or incomplete receiver/type provenance. Unknown calls, aliases escaping, and intervening writes invalidate local proof. Similar code outside the stated detection contract is not a finding.
- Both standard suppression forms suppress this native ID.
Fix
None. Choosing a repair requires intent or additional runtime information.
PHP versions
Requires PHP 7.0 or later and strict scalar typing for the reported consumer.
Configure
In custos.json:
json
{
"rules": {
"ReadLoopProcessesEofFailure": {
"enabled": false
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
php
// @custos-ignore ReadLoopProcessesEofFailure