Skip to content

Commit 26d9a6f

Browse files
committed
minor symfony#16810 [DependencyInjection] Validate class names and factory methods (nicolas-grekas)
This PR was merged into the 2.7 branch. Discussion ---------- [DependencyInjection] Validate class names and factory methods | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Because, you know, people do mistakes... I saw this happening during a workshop: when e.g. the factory tag has no `method` attribute, we generate an container that embeds a parse error. Commits ------- b2e3850 [DependencyInjection] Validate class names and factory methods
2 parents 944bddf + b2e3850 commit 26d9a6f

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -759,6 +759,10 @@ private function addNewInstance($id, Definition $definition, $return, $instantia
759759
if (null !== $definition->getFactory()) {
760760
$callable = $definition->getFactory();
761761
if (is_array($callable)) {
762+
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $callable[1])) {
763+
throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $callable[1] ?: 'n/a'));
764+
}
765+
762766
if ($callable[0] instanceof Reference
763767
|| ($callable[0] instanceof Definition && $this->definitionVariables->contains($callable[0]))) {
764768
return sprintf(" $return{$instantiation}%s->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '');
@@ -1310,8 +1314,12 @@ private function dumpValue($value, $interpolate = true)
13101314
}
13111315

13121316
if (is_array($factory)) {
1317+
if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $factory[1])) {
1318+
throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $factory[1] ?: 'n/a'));
1319+
}
1320+
13131321
if (is_string($factory[0])) {
1314-
return sprintf('\\%s::%s(%s)', $factory[0], $factory[1], implode(', ', $arguments));
1322+
return sprintf('%s::%s(%s)', $this->dumpLiteralClass($this->dumpValue($factory[0])), $factory[1], implode(', ', $arguments));
13151323
}
13161324

13171325
if ($factory[0] instanceof Definition) {
@@ -1342,12 +1350,8 @@ private function dumpValue($value, $interpolate = true)
13421350
if (null === $class) {
13431351
throw new RuntimeException('Cannot dump definitions which have no class nor factory.');
13441352
}
1345-
$class = $this->dumpValue($class);
1346-
if (false !== strpos($class, '$')) {
1347-
throw new RuntimeException('Cannot dump definitions which have a variable class name.');
1348-
}
13491353

1350-
return sprintf('new \\%s(%s)', substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
1354+
return sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments));
13511355
} elseif ($value instanceof Variable) {
13521356
return '$'.$value;
13531357
} elseif ($value instanceof Reference) {
@@ -1388,9 +1392,18 @@ private function dumpValue($value, $interpolate = true)
13881392
* @param string $class
13891393
*
13901394
* @return string
1395+
*
1396+
* @throws RuntimeException
13911397
*/
13921398
private function dumpLiteralClass($class)
13931399
{
1400+
if (false !== strpos($class, '$')) {
1401+
throw new RuntimeException('Cannot dump definitions which have a variable class name.');
1402+
}
1403+
if (0 !== strpos($class, "'") || !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
1404+
throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a'));
1405+
}
1406+
13941407
return '\\'.substr(str_replace('\\\\', '\\', $class), 1, -1);
13951408
}
13961409

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,31 @@ public function testAddServiceInvalidServiceId()
154154
$dumper->dump();
155155
}
156156

157+
/**
158+
* @dataProvider provideInvalidFactories
159+
* @expectedException Symfony\Component\DependencyInjection\Exception\RuntimeException
160+
* @expectedExceptionMessage Cannot dump definition
161+
*/
162+
public function testInvalidFactories($factory)
163+
{
164+
$container = new ContainerBuilder();
165+
$def = new Definition('stdClass');
166+
$def->setFactory($factory);
167+
$container->setDefinition('bar', $def);
168+
$dumper = new PhpDumper($container);
169+
$dumper->dump();
170+
}
171+
172+
public function provideInvalidFactories()
173+
{
174+
return array(
175+
array(array('', 'method')),
176+
array(array('class', '')),
177+
array(array('...', 'method')),
178+
array(array('class', '...')),
179+
);
180+
}
181+
157182
public function testAliases()
158183
{
159184
$container = include self::$fixturesPath.'/containers/container9.php';

0 commit comments

Comments
 (0)