Skip to content

Commit e2e2954

Browse files
[DependencyInjection] Fix combinatory explosion when autowiring union and intersection types
1 parent 99dae35 commit e2e2954

File tree

1 file changed

+23
-40
lines changed

1 file changed

+23
-40
lines changed

Compiler/AutowirePass.php

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ class AutowirePass extends AbstractRecursivePass
4545
private $decoratedMethodIndex;
4646
private $decoratedMethodArgumentIndex;
4747
private $typesClone;
48-
private $combinedAliases;
4948

5049
public function __construct(bool $throwOnAutowireException = true)
5150
{
@@ -61,8 +60,6 @@ public function __construct(bool $throwOnAutowireException = true)
6160
*/
6261
public function process(ContainerBuilder $container)
6362
{
64-
$this->populateCombinedAliases($container);
65-
6663
try {
6764
$this->typesClone = clone $this;
6865
parent::process($container);
@@ -75,7 +72,6 @@ public function process(ContainerBuilder $container)
7572
$this->decoratedMethodIndex = null;
7673
$this->decoratedMethodArgumentIndex = null;
7774
$this->typesClone = null;
78-
$this->combinedAliases = [];
7975
}
8076
}
8177

@@ -371,12 +367,12 @@ private function getAutowiredReference(TypedReference $reference, bool $filterTy
371367
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
372368
}
373369

374-
if (null !== ($alias = $this->combinedAliases[$alias] ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
370+
if (null !== ($alias = $this->getCombinedAlias($type, $name) ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
375371
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
376372
}
377373

378374
if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) {
379-
foreach ($this->container->getAliases() + $this->combinedAliases as $id => $alias) {
375+
foreach ($this->container->getAliases() as $id => $alias) {
380376
if ($name === (string) $alias && str_starts_with($id, $type.' $')) {
381377
return new TypedReference($name, $type, $reference->getInvalidBehavior());
382378
}
@@ -388,7 +384,7 @@ private function getAutowiredReference(TypedReference $reference, bool $filterTy
388384
return new TypedReference($type, $type, $reference->getInvalidBehavior());
389385
}
390386

391-
if (null !== ($alias = $this->combinedAliases[$type] ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
387+
if (null !== ($alias = $this->getCombinedAlias($type) ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
392388
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
393389
}
394390

@@ -582,44 +578,31 @@ private function populateAutowiringAlias(string $id): void
582578
}
583579
}
584580

585-
private function populateCombinedAliases(ContainerBuilder $container): void
581+
private function getCombinedAlias(string $type, string $name = null): ?string
586582
{
587-
$this->combinedAliases = [];
588-
$reverseAliases = [];
589-
590-
foreach ($container->getAliases() as $id => $alias) {
591-
if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^((?&V)(?:\\\\(?&V))*+)(?: \$((?&V)))?$/', $id, $m)) {
592-
continue;
593-
}
594-
595-
$type = $m[2];
596-
$name = $m[3] ?? '';
597-
$reverseAliases[(string) $alias][$name][] = $type;
583+
if (str_contains($type, '&')) {
584+
$types = explode('&', $type);
585+
} elseif (str_contains($type, '|')) {
586+
$types = explode('|', $type);
587+
} else {
588+
return null;
598589
}
599590

600-
foreach ($reverseAliases as $alias => $names) {
601-
foreach ($names as $name => $types) {
602-
if (2 > $count = \count($types)) {
603-
continue;
604-
}
605-
sort($types);
606-
$i = 1 << $count;
607-
608-
// compute the powerset of the list of types
609-
while ($i--) {
610-
$set = [];
611-
for ($j = 0; $j < $count; ++$j) {
612-
if ($i & (1 << $j)) {
613-
$set[] = $types[$j];
614-
}
615-
}
591+
$alias = null;
592+
$suffix = $name ? ' $'.$name : '';
616593

617-
if (2 <= \count($set)) {
618-
$this->combinedAliases[implode('&', $set).('' === $name ? '' : ' $'.$name)] = $alias;
619-
$this->combinedAliases[implode('|', $set).('' === $name ? '' : ' $'.$name)] = $alias;
620-
}
621-
}
594+
foreach ($types as $type) {
595+
if (!$this->container->hasAlias($type.$suffix)) {
596+
return null;
597+
}
598+
599+
if (null === $alias) {
600+
$alias = (string) $this->container->getAlias($type.$suffix);
601+
} elseif ((string) $this->container->getAlias($type.$suffix) !== $alias) {
602+
return null;
622603
}
623604
}
605+
606+
return $alias;
624607
}
625608
}

0 commit comments

Comments
 (0)