Skip to content

UnserializeFalseAmbiguity ​

warning native on by default

Group: Probable bugs

A false unserialize result can represent the valid serialized boolean false. Do not classify decoding failure solely from that value.

Example ​

php
<?php
if(unserialize($bytes,["allowed_classes"=>false])===false){throw new RuntimeException();}

Reported:

  • line 2: Distinguish valid serialized false from decoding failure.

Detection ​

  • Resolved unserialize result is compared strictly to false in an if condition whose branch unconditionally throws/returns failure. Include direct calls or unmodified local result. Allowed_classes does not eliminate serialized false.
  • 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.
  • Do not report when the code already tells the two outcomes apart: the plain variable passed as the unserialize payload is compared (===, !==, ==, !=, either operand order) with the serialized form of false, written as the string literal 'b:0;' or as a call to the builtin serialize(false). The comparison must sit in the same variable scope (nested functions and closures do not count) and start no later than the end of the rejecting branch, so both an early guard before decoding and a check inside the branch qualify. This is evidence of intent rather than a proof: writes to the variable between the comparison and the decode are not tracked. A payload that is not a plain variable never qualifies.
  • 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": {
    "UnserializeFalseAmbiguity": {
      "enabled": false
    }
  }
}

Suppress ​

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

php
// @custos-ignore UnserializeFalseAmbiguity

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