Skip to content

ZipSourceRemovedBeforeArchiveClose ​

warning native on by default PHP ≥ 5.3

Group: Probable bugs

Keep ZIP source files until the archive closes.

Example ​

php
<?php
$z=new ZipArchive(); $z->open("bundle.zip",ZipArchive::CREATE); if ($z->addFile("source.txt","note.txt")) { unlink("source.txt"); $z->close(); }

Reported:

  • line 2: Keep ZIP source files until the archive closes.

Detection ​

  • Report unlink of a proven literal source path within the successful true branch of resolved ZipArchive::addFile using default flags, when no preceding close on that receiver exists. The matching literal path establishes source identity. Unknown paths, explicit flags, unguarded additions and conditional failed additions are excluded.
  • A close on the same archive object counts as preceding when it is written before the unlink in the same function scope and is evaluated on every ordinary path that reaches the unlink. Besides a plain statement this covers a close used as an if or elseif condition (the code in either branch of that condition, or after an if guard that leaves), the left operand of a short-circuit operator, a ternary condition, a close in a try block whose finally block or following code holds the unlink, and a close in a finally block. When the unlink sits in the finally block, or after a try that has catch blocks, the close must belong to the first statement of the try block: an earlier protected statement could throw and skip it. A close that may be skipped does not count: one inside a branch body, loop body, ternary or match arm, the right operand of a short-circuit operator or of ??=, a catch block or a callback; nor does a try-block close when the unlink sits in a catch block of that try.
  • The same archive object means the same proven flow identity. An archive without one, such as a property or the result of a factory call, is matched by its receiver spelling (a variable, or a property chain rooted in a variable or a static property), provided neither the receiver nor an object it is read from is assigned between the addFile guard and the close.
  • 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) ​

Only the successful branch establishes the deferred source-file dependency; a failed addition’s else branch is excluded.

  • An unlink written inside a closure or arrow function nested in the successful branch is not reported: it runs when the callback is invoked, which the rule does not track.
  • 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.

Configure ​

In custos.json:

json
{
  "rules": {
    "ZipSourceRemovedBeforeArchiveClose": {
      "enabled": false
    }
  }
}

Suppress ​

Before the statement or declaration (or the first statement of the file):

php
// @custos-ignore ZipSourceRemovedBeforeArchiveClose

Released under the MIT License. Native rules and rules modeled on Php Inspections (EA Extended); independent clean-room implementation.