diff --git a/src/Dispatcher/CharCountBased.php b/src/Dispatcher/CharCountBased.php index 79a803a..131cca1 100644 --- a/src/Dispatcher/CharCountBased.php +++ b/src/Dispatcher/CharCountBased.php @@ -7,6 +7,7 @@ use FastRoute\Dispatcher\Result\Matched; use function assert; use function end; +use function preg_match; /** @final */ class CharCountBased extends RegexBasedAbstract @@ -17,7 +18,7 @@ class CharCountBased extends RegexBasedAbstract foreach ($routeData as $data) { assert(isset($data['suffix'])); - if ($this->matchRoute($data['regex'], $uri . $data['suffix'], $matches) !== 1) { + if (preg_match($data['regex'], $uri . $data['suffix'], $matches) !== 1) { continue; } diff --git a/src/Dispatcher/GroupCountBased.php b/src/Dispatcher/GroupCountBased.php index 9dc3546..2448904 100644 --- a/src/Dispatcher/GroupCountBased.php +++ b/src/Dispatcher/GroupCountBased.php @@ -6,6 +6,7 @@ namespace FastRoute\Dispatcher; use FastRoute\Dispatcher\Result\Matched; use function count; +use function preg_match; /** @final */ class GroupCountBased extends RegexBasedAbstract @@ -14,7 +15,7 @@ class GroupCountBased extends RegexBasedAbstract protected function dispatchVariableRoute(array $routeData, string $uri): ?Matched { foreach ($routeData as $data) { - if ($this->matchRoute($data['regex'], $uri, $matches) !== 1) { + if (preg_match($data['regex'], $uri, $matches) !== 1) { continue; } diff --git a/src/Dispatcher/GroupPosBased.php b/src/Dispatcher/GroupPosBased.php index b78be01..d2eebf5 100644 --- a/src/Dispatcher/GroupPosBased.php +++ b/src/Dispatcher/GroupPosBased.php @@ -6,6 +6,7 @@ namespace FastRoute\Dispatcher; use FastRoute\Dispatcher\Result\Matched; use function assert; +use function preg_match; /** @final */ class GroupPosBased extends RegexBasedAbstract @@ -14,7 +15,7 @@ class GroupPosBased extends RegexBasedAbstract protected function dispatchVariableRoute(array $routeData, string $uri): ?Matched { foreach ($routeData as $data) { - if ($this->matchRoute($data['regex'], $uri, $matches) !== 1) { + if (preg_match($data['regex'], $uri, $matches) !== 1) { continue; } diff --git a/src/Dispatcher/MarkBased.php b/src/Dispatcher/MarkBased.php index be30558..bef8297 100644 --- a/src/Dispatcher/MarkBased.php +++ b/src/Dispatcher/MarkBased.php @@ -5,6 +5,8 @@ namespace FastRoute\Dispatcher; use FastRoute\Dispatcher\Result\Matched; +use function preg_match; + /** @final */ class MarkBased extends RegexBasedAbstract { @@ -12,7 +14,7 @@ class MarkBased extends RegexBasedAbstract protected function dispatchVariableRoute(array $routeData, string $uri): ?Matched { foreach ($routeData as $data) { - if ($this->matchRoute($data['regex'], $uri, $matches) !== 1) { + if (preg_match($data['regex'], $uri, $matches) !== 1) { continue; } diff --git a/src/Dispatcher/RegexBasedAbstract.php b/src/Dispatcher/RegexBasedAbstract.php index 74de790..9dce400 100644 --- a/src/Dispatcher/RegexBasedAbstract.php +++ b/src/Dispatcher/RegexBasedAbstract.php @@ -8,11 +8,6 @@ use FastRoute\Dispatcher; use FastRoute\Dispatcher\Result\Matched; use FastRoute\Dispatcher\Result\MethodNotAllowed; use FastRoute\Dispatcher\Result\NotMatched; -use RuntimeException; - -use function preg_last_error_msg; -use function preg_match; -use function sprintf; /** * @internal @@ -40,26 +35,6 @@ abstract class RegexBasedAbstract implements Dispatcher /** @param DynamicRouteChunks $routeData */ abstract protected function dispatchVariableRoute(array $routeData, string $uri): ?Matched; - /** - * Matches a route regex, distinguishing a genuine "no match" (preg_match() - * returns 0) from a PCRE engine failure such as PREG_BACKTRACK_LIMIT_ERROR - * (returns false), which would otherwise fail unrelated routes sharing the - * same combined regex chunk. - * - * @param array|null $matches - */ - protected function matchRoute(string $regex, string $subject, ?array &$matches = null): int - { - $result = preg_match($regex, $subject, $matches); - if ($result === false) { - throw new RuntimeException( - sprintf('Regex matching failed for "%s": %s', $regex, preg_last_error_msg()), - ); - } - - return $result; - } - public function dispatch(string $httpMethod, string $uri): Matched|NotMatched|MethodNotAllowed { if (isset($this->staticRouteMap[$httpMethod][$uri])) { diff --git a/test/Dispatcher/DispatcherTestCase.php b/test/Dispatcher/DispatcherTestCase.php index 2d8cfcf..ba45688 100644 --- a/test/Dispatcher/DispatcherTestCase.php +++ b/test/Dispatcher/DispatcherTestCase.php @@ -13,11 +13,8 @@ use FastRoute\Dispatcher\Result\MethodNotAllowed; use FastRoute\Dispatcher\Result\NotMatched; use PHPUnit\Framework\Attributes as PHPUnit; use PHPUnit\Framework\TestCase; -use RuntimeException; use function FastRoute\simpleDispatcher; -use function ini_set; -use function str_repeat; /** @phpstan-import-type ExtraParameters from DataGenerator */ abstract class DispatcherTestCase extends TestCase @@ -180,36 +177,6 @@ abstract class DispatcherTestCase extends TestCase }, $this->generateDispatcherOptions()); } - /** - * A PCRE engine failure must surface instead of being reported as - * NOT_FOUND for an unrelated route in the same combined regex chunk. - * - * @see https://github.com/nikic/FastRoute/issues/167 - */ - #[PHPUnit\Test] - public function regexEngineFailureIsNotSilentlyTreatedAsNotFound(): void - { - $previousLimit = ini_set('pcre.backtrack_limit', '1000'); - self::assertNotFalse($previousLimit, 'Unable to lower pcre.backtrack_limit for this test'); - - try { - $this->expectException(RuntimeException::class); - $this->expectExceptionMessageMatches('/Backtrack limit exhausted/'); - - $dispatcher = simpleDispatcher(static function (ConfigureRoutes $r): void { - // Catastrophically backtracking pattern. - $r->addRoute('GET', '/{p:(?:a?a?)*}/complicated', 'complicated_pattern'); - // Cheap route in the same chunk: it would match on its own, but the - // chunk's preg_match() call fails. - $r->addRoute('GET', '/{p:a+}', 'cheap_route'); - }, $this->generateDispatcherOptions()); - - $dispatcher->dispatch('GET', '/' . str_repeat('a', 30)); - } finally { - ini_set('pcre.backtrack_limit', $previousLimit); - } - } - /** @return iterable}> */ public static function provideFoundDispatchCases(): iterable {