Skip to content

Commit f1298b5

Browse files
dgondrejmirtes
authored andcommitted
fixed escaped hash in regex extended mode
\# was incorrectly treated as comment start in /x mode
1 parent b056b7f commit f1298b5

File tree

2 files changed

+17
-1
lines changed

2 files changed

+17
-1
lines changed

src/Type/Regex/RegexGroupParser.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ public function parseGroups(string $regex): ?RegexAstWalkResult
8585

8686
if (str_contains($modifiers, 'x')) {
8787
// in freespacing mode the # character starts a comment and runs until the end of the line
88-
$regex = preg_replace('/(?<!\?)#.*/', '', $regex) ?? '';
88+
// but \# is an escaped literal hash, and (?#...) is an inline comment - neither starts a line comment
89+
$regex = preg_replace('/(?<!\\\\)(?<!\(\?)#.*/', '', $regex) ?? '';
8990
}
9091

9192
$rawRegex = $this->regexExpressionHelper->removeDelimitersAndModifiers($regex);

tests/PHPStan/Analyser/nsrt/preg_match_shapes.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,3 +1073,18 @@ function bug12792(string $string): void {
10731073
assertType('array{string, non-empty-string}', $match); // could be array{'acd'|'ayd'|'bd', 'c'|'xb'|'y'}
10741074
}
10751075
}
1076+
1077+
function testExtendedSyntaxEscapedHash(string $string): void {
1078+
// \# in extended mode should be treated as literal hash, not comment
1079+
if (preg_match('/^ ([\#.]) $/x', $string, $matches)) {
1080+
assertType("array{non-falsy-string, '#'|'.'}", $matches);
1081+
}
1082+
1083+
// Real comment vs escaped hash
1084+
if (preg_match('/
1085+
(\d+) # this is a comment
1086+
([\#ab]+) # hash in character class (escaped)
1087+
/x', $string, $matches)) {
1088+
assertType('array{non-falsy-string, numeric-string, non-empty-string}', $matches);
1089+
}
1090+
}

0 commit comments

Comments
 (0)