bug #4909 Report regular expression errors from the matches operator (fabpot)

This PR was merged into the 3.x branch.

Discussion
----------

Report regular expression errors from the matches operator

The `matches` operator now throws a `RuntimeError` when PCRE cannot evaluate a regular expression instead of silently treating the error as a non-match.

This makes failures such as exhausted backtrack limits visible to template authors.

Commits
-------

e5347301d7 Throw on PCRE errors in the matches operator
This commit is contained in:
Fabien Potencier
2026-08-28 15:10:19 +02:00
3 changed files with 15 additions and 2 deletions
+1
View File
@@ -1,5 +1,6 @@
# 3.29.0 (2026-XX-XX)
* Fix the `matches` operator silently treating PCRE execution errors as non-matches
* Add the `HtmlExtension::htmlAttrValue()` method to resolve a single HTML attribute value the way the `html_attr` function renders it
* Fix `html_attr` JSON encoding a `Stringable` value in a `data-*` attribute instead of using its string representation
* Add documentation comments to attach metadata to nodes (experimental)
+6 -2
View File
@@ -1188,7 +1188,7 @@ final class CoreExtension extends AbstractExtension
}
/**
* @throws RuntimeError When an invalid pattern is used
* @throws RuntimeError When the regular expression cannot be evaluated
*
* @internal
*/
@@ -1198,7 +1198,11 @@ final class CoreExtension extends AbstractExtension
throw new RuntimeError(\sprintf('Regexp "%s" passed to "matches" is not valid', $regexp).substr($m, 12));
});
try {
return preg_match($regexp, $str ?? '');
if (false === $result = preg_match($regexp, $str ?? '')) {
throw new RuntimeError(\sprintf('Regexp "%s" passed to "matches" failed: %s.', $regexp, preg_last_error_msg()));
}
return $result;
} finally {
restore_error_handler();
}
@@ -0,0 +1,8 @@
--TEST--
Twig reports PCRE execution failures for the "matches" operator
--TEMPLATE--
{{ subject matches regexp }}
--DATA--
return ['subject' => 'aX', 'regexp' => '~(*LIMIT_MATCH=1)^(a+)+$~'];
--EXCEPTION--
Twig\Error\RuntimeError: Regexp "~(*LIMIT_MATCH=1)^(a+)+$~" passed to "matches" failed: Backtrack limit exhausted in "index.twig" at line 2.