CurlMultiSuccessAssumedPerTransfer
warning native on by defaultGroup: Probable bugs
Successful multi-transfer execution does not establish that each request succeeded. Inspect the completion result for every added transfer.
Example
php
<?php
function bad(){$h=curl_multi_init();curl_multi_add_handle($h,curl_init());if(curl_multi_exec($h,$running)===CURLM_OK && !$running){return true;}}Reported:
- line 2: Inspect each completed transfer result.
Detection
- A curl_multi_exec result compared to CURLM_OK and completed running count guards unconditional true return, with no curl_multi_info_read inspection on that handle. Match complete function-local transfer lifecycle, not arbitrary success-named consumers.
- Require at least one resolved curl_multi_add_handle on the same locally initialized multi handle before execution. Empty multi handles are valid and excluded. The handle must be held in a plain local variable.
- D1b. Before the guarding
if, every use of that variable must be either the target of a plain assignment or a direct argument of a resolved lifecycle builtin: curl_multi_add_handle, curl_multi_exec, curl_multi_select, curl_multi_setopt or curl_multi_errno. These drive the handle without exposing per-transfer results and without detaching transfers. - 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.
- Any other use of the handle variable before the guarding
ifdrops the report, because the code receiving the handle may inspect or change the transfers: passing it to a user function, method, static method, constructor, dynamic callee or any builtin outside the D1b list (including curl_multi_info_read, curl_multi_remove_handle and curl_multi_close), spreading it, copying it to another variable, binding it by reference, storing it in a property or array, capturing it in a closure or arrow function, or reaching it by name through a variable variable,compact()orget_defined_vars(). - Both standard suppression forms suppress this native ID.
Fix
None. Choosing a repair requires intent or additional runtime information.
PHP versions
Available throughout supported PHP 5.3–8.5 where the referenced builtin/extension is available. Respect syntax/version-specific receiver contracts; unavailable APIs are not this rule’s concern.
Configure
In custos.json:
json
{
"rules": {
"CurlMultiSuccessAssumedPerTransfer": {
"enabled": false
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
php
// @custos-ignore CurlMultiSuccessAssumedPerTransfer