Back-Reference To A Missing Group
ID |
php.back_references_regular_expr_refer |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Php |
Tags |
regex, reliability |
Description
Reports a back-reference that points at a capturing group the pattern does not have, or at one that is not yet fully defined where the reference appears — a self-reference inside the group’s own body, or a forward reference before the group opens.
All the PCRE spellings are read: \1, \g1, \g{1}, \k<name>, \k{name} and \k’name'.
Rationale
The two shapes fail differently, and neither fails loudly.
// Bad
preg_match('/(\d+)-(\d+)\3/', '12-34'); // false + warning: there is no group 3
preg_match('/(a\1b)/', 'aab'); // 0: group 1 has captured nothing yet
preg_match('/(?<year>\d{4})\k<yer>/', '2026'); // false + warning: the group is named year
-
A reference to a group that does not exist is a compile error. PCRE refuses the pattern,
preg_matchwarns and returnsfalse, and the guard silently never fires. -
A reference to a group that is not yet defined compiles cleanly and simply never matches, because at that point the group holds nothing.
-
Both normally arrive from editing: a group was removed or reordered and the numbers after it shifted, or a group name was changed in one place only.
Remediation
Point the reference at a group that exists and is already closed, and prefer names over numbers so that reordering groups cannot break it.
// Good
preg_match('/(\d+)-(\d+)\2/', $s);
preg_match('/(?<year>\d{4})\k<year>/', $s);
What is not reported
A bare two-digit reference above 9 is left alone unless that many groups exist. PCRE reads \10 as an octal escape when the pattern has fewer than ten groups, so /(a)\10/ is the valid pattern "group 1’s text, then a backspace". The braced spellings carry no such ambiguity and are always references, so \g{5} against two groups is reported.
Which alternation branch a reference sits in is not modelled: /(a|(b))\2/ is judged purely on textual order, never on whether the two branches could both execute. Relative references such as \g{-1} are also left alone.