AssertionContainsRequiredSideEffect
warning native on by defaultGroup: Probable bugs
Identify an assert call containing an assignment to a previously undefined local when a reachable subsequent read requires that local before any unconditional assignment. Restrict to straight-line scope; exclude parameters, global/static locals, references, any earlier local definition or prior read. Do not guess about other side effects.
Detection
- Report an assert call containing an assignment to a previously undefined local when a reachable subsequent read requires that local before any unconditional assignment. Restrict to straight-line scope; exclude parameters, global/static locals, references, any earlier local definition or prior read. Do not guess about other side effects.
- A later use counts as a required read only when it executes regardless of the assertion setting. A read placed inside another resolved builtin
assert()call disappears together with the reported one and is not a required read. A variable passed to an in-out by-reference parameter (sort,array_push,array_splice,settype, the output list ofexec, ...) is still a required read, because the callee consumes the previous value. - The proof is abandoned, with no finding, when the local is rebound before any required read by a construct that does not consume its value: a
foreachkey or value target (unless the iterated expression itself reads the local), acatchvariable, or a positional argument bound to a write-only by-reference parameter of a resolved builtin (the match array ofpreg_match/preg_match_all, the count ofstr_replace/str_ireplace/preg_replace/preg_replace_callback, the result ofparse_str/mb_parse_str, the percentage ofsimilar_text, the result code ofexec/system/passthru, the image information ofgetimagesize/getimagesizefromstring, both outputs ofheaders_sent,getmxrrandfsockopen, and the callable name ofis_callable). Named or unpacked arguments, and calls where another argument reads the local, do not qualify. Loops and handlers are not straight-line code, so these rebinding sites end the analysis instead of acting as an assignment after which later reads could be ignored. - Resolve builtin functions, classes, constants and methods, including imports and supported named arguments. Follow only bounded local facts within one lexical scope. Receiver and argument provenance must establish the specific API contract; variable names and comments never prove intent.
- Report one finding per violating operation. A reachable path, unchanged value identity and applicable API behavior are required. Intervening mutation, unknown calls involving tracked values or escaped aliases invalidate proof. When the proof is inconclusive, nothing is reported.
Exceptions (no report)
- Exclude unresolved required symbols, user-defined lookalikes, incomplete syntax, unknown required values and unsupported versions.
- Both
@custos-ignore AssertionContainsRequiredSideEffectand@noinspection AssertionContainsRequiredSideEffectsuppress this native rule.
Fix
None. A repair requires a semantic decision or application error-handling policy.
PHP versions
Available in PHP 5.3–8.5 where the referenced API exists. Do not apply extension contracts when the resolved API is unavailable. Gate syntax and version-specific behavior to the configured target.
Configure
In custos.json:
json
{
"rules": {
"AssertionContainsRequiredSideEffect": {
"enabled": false
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
php
// @custos-ignore AssertionContainsRequiredSideEffect