LocalizedNumberTrailingInputAccepted
warning native off by default PHP ≥ 5.3Group: Probable bugs
Reject unparsed number suffixes. This opt-in rule applies the policy described in Detection.
Example
php
<?php
$f = new NumberFormatter("en_US", NumberFormatter::DECIMAL); $n = $f->parse("37tail", NumberFormatter::TYPE_DOUBLE, $end); echo $n;Reported:
- line 2: Reject unparsed number suffixes.
Detection
- When enabled, require whole-input number parsing. Report an echoed NumberFormatter::parse result for a proven ASCII numeric prefix followed by an alphabetic suffix (excluding exponent syntax), unless a guard from D4 covers the echo. Other locale-dependent inputs and UTF-16 offset checks remain outside this bounded detection subset.
- Resolve builtin functions, extension classes, method receivers, constants and named arguments. Follow unchanged locals and aliases only within the same bounded lexical scope. Require a reachable path; merge branch facts only when all incoming paths establish them.
- Emit one finding at the violating operation, not one per evidence statement. Rebinding, writes, by-reference escape, unresolved calls that can mutate relevant state, and exhausted analysis budgets remove proof.
- D4. A guard proves that the offset the parse call returned through a local equals the input length: a strict or ordered comparison of that local, after the parse, with
strlenof the input (ormb_strlenwith'8bit'), with the literal length, or with a local holding either, operands in either order. The offset never exceeds the input length, so a guard that leaves when the offset is smaller also proves it. It covers the echo wherever the conditions guarding it hold only for that length: in the branch of anif/elseif/elsechain such a comparison selects, after anifwhose branch for a shorter offset always leaves (return, throw, exit, break, continue), with or without other arms, or behind a boolean local holding the comparison. Conditions combine through parentheses,!,&&/andand||/or. A jump label between the guard and the echo, or a later write of the offset, voids it. - The receiver must be proven to be a formatter that stops at the suffix: a direct
new NumberFormatterwith exactly a locale and a style resolving to NumberFormatter::DECIMAL, with no pattern argument. When it is held in a variable, every earlier use of that variable in the scope (anywhere in an enclosing loop of the parse call) must be its assignment or a call to parse, parseCurrency, format, formatCurrency, getErrorCode, getErrorMessage, getLocale, getPattern, getAttribute, getTextAttribute or getSymbol.
Exceptions (no report)
- Exclude shadowed builtins, unresolved receivers, incomplete syntax and unknown prerequisite facts. An extension function name alone does not prove an application function is that builtin.
- A dominating valid guard or repair described in Detection prevents the finding. Both legacy noinspection and custos-ignore forms suppress this ID.
- No report when the formatter may consume the suffix or cannot be proven plain: another style such as PATTERN_DECIMAL, an explicit pattern, an unknown style, a subclass, or a formatter that was reconfigured (setPattern, setTextAttribute, setSymbol, setAttribute), aliased, captured by a closure or passed to another call before the parse.
Fix
No automatic fix. The required repair depends on error handling, data selection, lifecycle ordering or application policy.
All edits use exact byte ranges and preserve comments and evaluation order. Offer no fix when its stated prerequisites cannot be proven or the replacement is unsupported by the configured PHP version.
PHP versions
Requires PHP 5.3 or later and the referenced extension API. Respect method-specific introduction versions within PHP 5.3–8.5; unsupported optional APIs cannot establish facts. Named arguments require PHP 8.0 or later.
Configure
In custos.json:
json
{
"rules": {
"LocalizedNumberTrailingInputAccepted": {
"enabled": true
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
php
// @custos-ignore LocalizedNumberTrailingInputAccepted