Skip to content

SqliteFetchBothLeaksDuplicateColumns ​

warning native off by default quick-fix

Group: Probable bugs

Fetch named SQLite columns before JSON serialization. This inspection is disabled by default; enabling it selects the stated policy.

Example ​

php
<?php
function f(SQLite3Result $r) { $row=$r->fetchArray(SQLITE3_BOTH); echo json_encode($row); }

Reported:

  • line 2: Fetch named SQLite columns before JSON serialization.

Detection ​

  • SQLite3Result fetchArray explicitly uses SQLITE3_BOTH or omits its mode, and its unchanged result flows to json_encode. Enabling establishes named-column JSON policy. Numeric indexing or mixed-key consumers before serialization invalidate proof.
  • D1a. When the fetched row is stored in a plain local variable, json_encode must be its only consumer. Every other mention of that variable in the scope invalidates the proof, including element writes, unset, destructuring, interpolation and reads after such a write, because a modified row is still the fetched row. A mention is unrelated only when it is a complete plain overwrite, when it sits textually before the fetch in code that cannot repeat, or when local flow proves it holds another complete value. Inside a loop, every other mention counts, wherever it appears.
  • Resolve builtin functions, extension classes, constants and method receivers, including aliases and supported named arguments. Inspect reachable operations in one lexical scope with bounded local flow.
  • Emit one finding per violating operation. Never infer policy from names or comments. When the proof is inconclusive, nothing is reported.

Exceptions (no report) ​

Resolve inserted SQLITE3_ASSOC to the global builtin constant. Parentheses around the fetch do not bypass consumer checks. Captures into nested scopes and exhausted consumer budgets withhold the finding.

  • Exclude shadowed or unresolved symbols, incomplete code, unknown required constants, ambiguous receiver identity and unsupported versions. Reassignment, escaping aliases, and unknown calls invalidate dependent flow facts.
  • E1a. Exclude scopes that can reach the row without naming it: variable-variables, compact, extract, get_defined_vars, include or require, eval and goto in the same scope, and $GLOBALS when the row is a file-level variable. Exclude a row variable that is a by-reference parameter, a by-reference closure capture, or declared global or static, and a fetch stored through a compound or reference assignment.
  • E1b. Exclude a fetchArray written as a first-class callable, which yields a Closure rather than a row, and a fetchArray whose arguments contain a spread, whose mode is unknown.
  • Both @custos-ignore SqliteFetchBothLeaksDuplicateColumns and @noinspection SqliteFetchBothLeaksDuplicateColumns suppress this native rule.

Fix ​

Replace the explicit resolved SQLITE3_BOTH constant with SQLITE3_ASSOC, or append SQLITE3_ASSOC to an argument-free fetchArray. Require the named-column policy and no other consumers as defined by D1a, E1a and E1b; a report is never emitted without that proof, so no fix can remove a numeric key that later code reads.

Use exact byte edits and preserve comments, evaluation count, argument order and supported PHP syntax. Withhold the fix whenever its prerequisites cannot be proven.

PHP versions ​

Apply throughout PHP 5.3–8.5 only where the extension API and syntax exist. Do not flag API unavailability through this rule.

Options ​

None. Use normal rule configuration to enable or disable the inspection.

Configure ​

In custos.json:

json
{
  "rules": {
    "SqliteFetchBothLeaksDuplicateColumns": {
      "enabled": true
    }
  }
}

Suppress ​

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

php
// @custos-ignore SqliteFetchBothLeaksDuplicateColumns

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