Skip to content

Commit

Permalink
:octocat: ugly fix for nikic#167
Browse files Browse the repository at this point in the history
  • Loading branch information
codemasher committed Mar 12, 2019
1 parent 9580f20 commit 479564f
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 10 deletions.
6 changes: 5 additions & 1 deletion src/DataGenerator/DataGeneratorAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ private function regexHasCapturingGroups(string $regex):bool
}

// Semi-accurate detection for capturing groups
return (bool) preg_match(
$preg_match = preg_match(
'~
(?:
\(\?\(
Expand All @@ -178,5 +178,9 @@ private function regexHasCapturingGroups(string $regex):bool
~x',
$regex
);

\FastRoute\catch_preg_error(__METHOD__, '-', $regex);

return (bool)$preg_match;
}
}
5 changes: 4 additions & 1 deletion src/Dispatcher/DispatcherCharCountBased.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ class DispatcherCharCountBased extends DispatcherAbstract
protected function dispatchVariableRoute(array $routeData, string $uri):array
{
foreach ($routeData as $data) {
if (!preg_match($data['regex'], $uri . $data['suffix'], $matches)) {
$preg_match = preg_match($data['regex'], $uri . $data['suffix'], $matches);
\FastRoute\catch_preg_error(__METHOD__, $data['regex'], $uri.$data['suffix']);

if (!$preg_match) {
continue;
}

Expand Down
5 changes: 4 additions & 1 deletion src/Dispatcher/DispatcherGroupCountBased.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ class DispatcherGroupCountBased extends DispatcherAbstract
protected function dispatchVariableRoute(array $routeData, string $uri):array
{
foreach ($routeData as $data) {
if (!preg_match($data['regex'], $uri, $matches)) {
$preg_match = preg_match($data['regex'], $uri, $matches);
\FastRoute\catch_preg_error(__METHOD__, $data['regex'], $uri);

if (!$preg_match) {
continue;
}

Expand Down
5 changes: 4 additions & 1 deletion src/Dispatcher/DispatcherGroupPosBased.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ class DispatcherGroupPosBased extends DispatcherAbstract
protected function dispatchVariableRoute(array $routeData, string $uri):array
{
foreach ($routeData as $data) {
if (!preg_match($data['regex'], $uri, $matches)) {
$preg_match = preg_match($data['regex'], $uri, $matches);
\FastRoute\catch_preg_error(__METHOD__, $data['regex'], $uri);

if (!$preg_match) {
continue;
}

Expand Down
5 changes: 4 additions & 1 deletion src/Dispatcher/DispatcherMarkBased.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ class DispatcherMarkBased extends DispatcherAbstract
protected function dispatchVariableRoute(array $routeData, string $uri):array
{
foreach ($routeData as $data) {
if (!preg_match($data['regex'], $uri, $matches)) {
$preg_match = preg_match($data['regex'], $uri, $matches);
\FastRoute\catch_preg_error(__METHOD__, $data['regex'], $uri);

if (!$preg_match) {
continue;
}

Expand Down
4 changes: 3 additions & 1 deletion src/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public function __construct(string $httpMethod, $handler, string $regex, array $
public function matches(string $str):bool
{
$regex = '~^' . $this->regex . '$~';
return (bool) preg_match($regex, $str);
$preg_match = preg_match($regex, $str);
\FastRoute\catch_preg_error(__METHOD__, $regex, $str);
return (bool) $preg_match;
}
}
8 changes: 4 additions & 4 deletions src/RouteParser/Std.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ public function parse(string $route):array
*/
private function parsePlaceholders(string $route):array
{
if (!preg_match_all(
'~' . self::VARIABLE_REGEX . '~x', $route, $matches,
PREG_OFFSET_CAPTURE | PREG_SET_ORDER
)) {
$preg_match_all = preg_match_all('~' . self::VARIABLE_REGEX . '~x', $route, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
\FastRoute\catch_preg_error(__METHOD__, '-', $route);

if (!$preg_match_all) {
return [$route];
}

Expand Down
21 changes: 21 additions & 0 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,25 @@ function cachedDispatcher(callable $routeDefinitionCallback, array $options = []

return new $options['dispatcher']($dispatchData);
}

function catch_preg_error(string $fn, string $pattern, string $data):void{
$preg_error = preg_last_error();

if($preg_error !== PREG_NO_ERROR){
$errors = [
PREG_INTERNAL_ERROR => 'PREG_INTERNAL_ERROR',
PREG_BACKTRACK_LIMIT_ERROR => 'PREG_BACKTRACK_LIMIT_ERROR',
PREG_RECURSION_LIMIT_ERROR => 'PREG_RECURSION_LIMIT_ERROR',
PREG_BAD_UTF8_ERROR => 'PREG_BAD_UTF8_ERROR',
PREG_BAD_UTF8_OFFSET_ERROR => 'PREG_BAD_UTF8_OFFSET_ERROR',
PREG_JIT_STACKLIMIT_ERROR => 'PREG_JIT_STACKLIMIT_ERROR',
];

throw new \RuntimeException(
$fn.': '.($errors[$preg_error] ?? 'unknown preg_error').PHP_EOL
.'pattern: '.$pattern.PHP_EOL
.'data: '.$data
);
}
}
}
33 changes: 33 additions & 0 deletions test/PregErrorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace FastRouteTest;

use FastRoute\RouteCollector;
use PHPUnit\Framework\TestCase;

class PregErrorTest extends TestCase{

protected function setUp():void{
// http://php.net/manual/pcre.configuration.php
ini_set('pcre.backtrack_limit', '1000000');
ini_set('pcre.recursion_limit', '100000');
ini_set('pcre.jit', '1');
}

// https://github.com/nikic/FastRoute/issues/167
public function testPregBacktrackLimitError(){
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage(
'FastRoute\\Dispatcher\\DispatcherGroupCountBased::dispatchVariableRoute: PREG_BACKTRACK_LIMIT_ERROR'.PHP_EOL.
'pattern: ~^(?|/((?:a?a?)*)/complicated|/(a+)())$~'.PHP_EOL.
'data: /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' // @infinite_scream
);

(\FastRoute\simpleDispatcher(function (RouteCollector $r) {
$r->addRoute(['GET'], '/{p:(?:a?a?)*}/complicated', 'complicated_pattern');
$r->addRoute(['GET'], '/{p:a+}', 'a');
}))->dispatch('GET', '/'.str_repeat('a', 42));

}

}

0 comments on commit 479564f

Please sign in to comment.