Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8c2a77b

Browse files
bug #20474 [Routing] Fail properly when a route parameter name cannot be used as a PCRE subpattern name (fancyweb)
This PR was squashed before being merged into the 2.7 branch (closes #20474). Discussion ---------- [Routing] Fail properly when a route parameter name cannot be used as a PCRE subpattern name | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | symfony/symfony-docs#7139 This is a follow up PR to #20327. I also decided to improve the current `is_numeric()` check that is done by a truer one. The current limitation is that a PCRE subpattern name must not start with a digit which is different. Commits ------- 73fbd08 [Routing] Fail properly when a route parameter name cannot be used as a PCRE subpattern name
2 parents b550d7e + 73fbd08 commit 8c2a77b

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

src/Symfony/Component/Routing/RouteCompiler.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,20 @@ class RouteCompiler implements RouteCompilerInterface
2828
*/
2929
const SEPARATORS = '/,;.:-_~+*=@|';
3030

31+
/**
32+
* The maximum supported length of a PCRE subpattern name
33+
* http://pcre.org/current/doc/html/pcre2pattern.html#SEC16.
34+
*
35+
* @internal
36+
*/
37+
const VARIABLE_MAXIMUM_LENGTH = 32;
38+
3139
/**
3240
* {@inheritdoc}
3341
*
3442
* @throws \LogicException If a variable is referenced more than once
35-
* @throws \DomainException If a variable name is numeric because PHP raises an error for such
36-
* subpatterns in PCRE and thus would break matching, e.g. "(?P<123>.+)".
43+
* @throws \DomainException If a variable name starts with a digit or if it is too long to be successfully used as
44+
* a PCRE subpattern.
3745
*/
3846
public static function compile(Route $route)
3947
{
@@ -95,13 +103,19 @@ private static function compilePattern(Route $route, $pattern, $isHost)
95103
$precedingChar = strlen($precedingText) > 0 ? substr($precedingText, -1) : '';
96104
$isSeparator = '' !== $precedingChar && false !== strpos(static::SEPARATORS, $precedingChar);
97105

98-
if (is_numeric($varName)) {
99-
throw new \DomainException(sprintf('Variable name "%s" cannot be numeric in route pattern "%s". Please use a different name.', $varName, $pattern));
106+
// A PCRE subpattern name must start with a non-digit. Also a PHP variable cannot start with a digit so the
107+
// variable would not be usable as a Controller action argument.
108+
if (preg_match('/^\d/', $varName)) {
109+
throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern));
100110
}
101111
if (in_array($varName, $variables)) {
102112
throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName));
103113
}
104114

115+
if (strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) {
116+
throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %s characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern));
117+
}
118+
105119
if ($isSeparator && strlen($precedingText) > 1) {
106120
$tokens[] = array('text', substr($precedingText, 0, -1));
107121
} elseif (!$isSeparator && strlen($precedingText) > 0) {

src/Symfony/Component/Routing/Tests/RouteCompilerTest.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Routing\Tests;
1313

1414
use Symfony\Component\Routing\Route;
15+
use Symfony\Component\Routing\RouteCompiler;
1516

1617
class RouteCompilerTest extends \PHPUnit_Framework_TestCase
1718
{
@@ -176,16 +177,16 @@ public function testRouteWithSameVariableTwice()
176177
}
177178

178179
/**
179-
* @dataProvider getNumericVariableNames
180+
* @dataProvider getVariableNamesStartingWithADigit
180181
* @expectedException \DomainException
181182
*/
182-
public function testRouteWithNumericVariableName($name)
183+
public function testRouteWithVariableNameStartingWithADigit($name)
183184
{
184185
$route = new Route('/{'.$name.'}');
185186
$route->compile();
186187
}
187188

188-
public function getNumericVariableNames()
189+
public function getVariableNamesStartingWithADigit()
189190
{
190191
return array(
191192
array('09'),
@@ -264,4 +265,13 @@ public function provideCompileWithHostData()
264265
),
265266
);
266267
}
268+
269+
/**
270+
* @expectedException \DomainException
271+
*/
272+
public function testRouteWithTooLongVariableName()
273+
{
274+
$route = new Route(sprintf('/{%s}', str_repeat('a', RouteCompiler::VARIABLE_MAXIMUM_LENGTH + 1)));
275+
$route->compile();
276+
}
267277
}

0 commit comments

Comments
 (0)