Unmatchable Boundary
ID |
php.regex_unmatchable_boundary |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Php |
Tags |
regex, reliability |
Description
Reports a boundary (^, $, \A, \Z, \z) placed next to input that still has to be consumed on the wrong side of it, so the pattern can never match anything.
Rationale
^ and \A match only at the start of the subject; $, \Z and \z only at the end. Swap them, or leave one where a character still has to be matched on the far side, and the pattern becomes impossible to satisfy:
// Bad
preg_match('/$[a-z]+/', 'abc'); // 0 -- and 0 for every other subject
The end boundary is already past the input by the time the character class needs a character to consume.
-
Usually a typo —
^and$swapped, or a boundary left behind after editing a pattern. -
preg_matchreturns0rather thanfalse, so nothing distinguishes this from "no match here": the guard just never fires, for any input.
Remediation
Put the boundary on the side of what it anchors.
// Good
preg_match('/^[a-z]+$/', 'abc'); // 1
What is not reported
Under the m modifier — set on the literal as /…/m or turned on inside the pattern with (?m) — ^ and $ legitimately match mid-pattern at a line break, so the rule stays silent for both there. \A, \Z and \z are unaffected by the modifier and are still checked.
\b and \B are word boundaries, not input boundaries, and are out of scope. Only the atom immediately adjacent to the boundary is examined: a boundary next to an atom that is itself optional (?, *, {0,n}) is a related but different unmatchable shape, accepted here as a false negative rather than guessed at.