ZipExtractionExceedsConfiguredBudget
warning native off by default PHP ≥ 5.3Group: Probable bugs
Validate ZIP extraction against configured limits. This opt-in rule applies the policy described in Detection.
Example
<?php
$z=new ZipArchive(); $z->open("bundle.zip"); $z->extractTo("output");Reported:
- line 2: Validate ZIP extraction against configured limits.
Detection
- Enabled policy requires maxEntries and maxExpandedBytes. Report extractTo in a known local archive lifecycle unless a terminating numFiles > configured-count guard and a complete ascending index loop bound extraction. The supported loop starts an accumulator at zero immediately before traversal, reads statIndex for every index, separately rejects false metadata and negative size, rejects size > configured-byte-limit minus accumulated bytes before adding the size, and increments every index once. A guard rejects only when its body always abandons the extraction: it throws, returns, exits, or jumps with a literal
break/continuelevel that leaves a loop enclosing both the validation and the extraction. For the three guards inside the traversal that means level 2 or more, becausecontinueorbreakaimed at the traversal itself only skips or truncates the accounting while extractTo still writes every entry. Agoto, a computed jump level, or such a jump anywhere in the guard body removes the proof; jumps confined to loops, switches or callables nested in the body are ignored. This proves both total size and overflow safety. Earlier direct statIndex reads alone are insufficient. Unknown external validation receiving the archive is excluded rather than certified safe; metadata budgets do not guarantee runtime decompressor resource limits. - 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.
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.
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.
Options
maxExpandedBytes: positive integer; default20971520.maxEntries: positive integer; default1000.
Configure
In custos.json:
{
"rules": {
"ZipExtractionExceedsConfiguredBudget": {
"enabled": true,
"options": {
"maxExpandedBytes": 20971520,
"maxEntries": 1000
}
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
// @custos-ignore ZipExtractionExceedsConfiguredBudget