Skip to content

PregMatchAllLayoutMismatch ​

warning native on by default

Group: Probable bugs

Regex result indices depend on whether output is grouped by capture or by match. Read indices consistent with the selected layout.

Example ​

php
<?php
preg_match_all("/(\d+)/","12 34",$m,PREG_PATTERN_ORDER);echo $m[2][0];

Reported:

  • line 2: Use indices matching the selected regex result layout.

Detection ​

  • Resolved preg_match_all uses explicit PREG_PATTERN_ORDER with one capturing group and known literal subject containing at least two matches. Subsequent access reads result[1][0] while result[0][1] is explicitly compared to that value for equality, establishing mismatched group-versus-match indexing. More generally report only provably out-of-range literal capture/match indices with proven pattern shape and match count.
  • Regex proof supports ordinary ASCII patterns compatible with RE2, no modifiers, lookarounds, backreferences, or unsupported PCRE extensions. Unknown matching behavior is excluded.
  • Regex proof requires an ASCII subject and an ordinary compatible PCRE subset without modifiers or whitespace escapes \s or \S. Reject patterns matching an empty string, subjects larger than 32768 bytes, and results with 1024 or more matches.
  • D1c. A brace group is accepted only in the portable quantifier forms {n}, {n,} and {n,m}, or as plain literal text that no engine could read as a quantifier. An unescaped brace group made only of digits, commas and blanks in any other arrangement, such as {,2}, { 2 } or {1, 2}, is a quantifier on recent PCRE2 releases and literal text on older ones, so the match count is not provable and nothing is reported.
  • Require an actual value read of the proven absent result dimension. Exclude writes, unset, by-reference uses and unknown argument uses, and exclude statements that also mutate the result array. The regex offset must be omitted or statically known zero; nonzero or unknown offsets are unsupported.
  • All argument uses are excluded because they can involve reference passing. Also exclude increment/decrement, unset and write contexts. Any same-statement mutation or call receiving the result array discards the actual-read proof.
  • 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) ​

  • Unknown pattern shape/count, complex regex constructs, version-dependent brace quantifiers (D1c), intentionally grouped output, or mere m[1][0] access without incompatible use is excluded.
  • 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.

See the PHP regex result and offset contract for the relevant builtin behavior.

Configure ​

In custos.json:

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

Suppress ​

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

php
// @custos-ignore PregMatchAllLayoutMismatch

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