Files
nikic-FastRoute/src/Dispatcher/GroupCountBased.php
T
dualfroz 7ac8857878 fix(dispatcher): surface preg_match() engine failures instead of treating them as no-match
All dispatcher strategies checked preg_match() results with `!== 1`,
which conflates a genuine no-match (0) with a PCRE engine failure
(false), e.g. PREG_BACKTRACK_LIMIT_ERROR from a catastrophically
backtracking route pattern. Because dynamic routes for the same
method are combined into shared regex chunks, one such route could
make the preg_match() call for the whole chunk fail, silently
turning an unrelated, cheap route in that chunk into a spurious
NOT_FOUND.

Add a shared matchRoute() helper on RegexBasedAbstract that calls
preg_match() and throws a RuntimeException (including
preg_last_error_msg()) when it returns false, while preserving the
existing 0/1 no-match/match behavior. Update GroupCountBased,
GroupPosBased, CharCountBased and MarkBased to use it.

Fixes #167
2026-09-06 01:25:06 +02:00

40 lines
954 B
PHP

<?php
declare(strict_types=1);
namespace FastRoute\Dispatcher;
use FastRoute\Dispatcher\Result\Matched;
use function count;
/** @final */
class GroupCountBased extends RegexBasedAbstract
{
/** @inheritDoc */
protected function dispatchVariableRoute(array $routeData, string $uri): ?Matched
{
foreach ($routeData as $data) {
if ($this->matchRoute($data['regex'], $uri, $matches) !== 1) {
continue;
}
[$handler, $varNames, $extraParameters] = $data['routeMap'][count($matches)];
$vars = [];
$i = 0;
foreach ($varNames as $varName) {
$vars[$varName] = $matches[++$i];
}
$result = new Matched();
$result->handler = $handler;
$result->variables = $vars;
$result->extraParameters = $extraParameters;
return $result;
}
return null;
}
}