From 86bf26c466fa695a64b8836decc8a1c8b6296682 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Jun 2017 19:23:28 +0200 Subject: [PATCH] [Config] Always protect ClassExistenceResource against bad parents --- .../Resource/ClassExistenceResource.php | 40 +++++++++---------- .../Resource/ClassExistenceResourceTest.php | 4 +- .../Compiler/AutowirePass.php | 6 +-- .../DependencyInjection/ContainerBuilder.php | 12 ++---- .../DependencyInjection/composer.json | 2 +- 5 files changed, 28 insertions(+), 36 deletions(-) diff --git a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php index 040cfc510eb9b..8a86a4209961b 100644 --- a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php +++ b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php @@ -21,25 +21,21 @@ */ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializable { - const EXISTS_OK = 1; - const EXISTS_KO = 0; - const EXISTS_KO_WITH_THROWING_AUTOLOADER = -1; - private $resource; - private $existsStatus; + private $exists; private static $autoloadLevel = 0; private static $existsCache = array(); /** - * @param string $resource The fully-qualified class name - * @param int|null $existsStatus One of the self::EXISTS_* const if the existency check has already been done + * @param string $resource The fully-qualified class name + * @param bool|null $exists Boolean when the existency check has already been done */ - public function __construct($resource, $existsStatus = null) + public function __construct($resource, $exists = null) { $this->resource = $resource; - if (null !== $existsStatus) { - $this->existsStatus = (int) $existsStatus; + if (null !== $exists) { + $this->exists = (bool) $exists; } } @@ -64,11 +60,13 @@ public function getResource() */ public function isFresh($timestamp) { + $loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false); + if (null !== $exists = &self::$existsCache[$this->resource]) { - $exists = $exists || class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false); - } elseif (self::EXISTS_KO_WITH_THROWING_AUTOLOADER === $this->existsStatus) { + $exists = $exists || $loaded; + } elseif (!$exists = $loaded) { if (!self::$autoloadLevel++) { - spl_autoload_register('Symfony\Component\Config\Resource\ClassExistenceResource::throwOnRequiredClass'); + spl_autoload_register(__CLASS__.'::throwOnRequiredClass'); } try { @@ -77,18 +75,16 @@ public function isFresh($timestamp) $exists = false; } finally { if (!--self::$autoloadLevel) { - spl_autoload_unregister('Symfony\Component\Config\Resource\ClassExistenceResource::throwOnRequiredClass'); + spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass'); } } - } else { - $exists = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false); } - if (null === $this->existsStatus) { - $this->existsStatus = $exists ? self::EXISTS_OK : self::EXISTS_KO; + if (null === $this->exists) { + $this->exists = $exists; } - return self::EXISTS_OK === $this->existsStatus xor !$exists; + return $this->exists xor !$exists; } /** @@ -96,11 +92,11 @@ public function isFresh($timestamp) */ public function serialize() { - if (null === $this->existsStatus) { + if (null === $this->exists) { $this->isFresh(0); } - return serialize(array($this->resource, $this->existsStatus)); + return serialize(array($this->resource, $this->exists)); } /** @@ -108,7 +104,7 @@ public function serialize() */ public function unserialize($serialized) { - list($this->resource, $this->existsStatus) = unserialize($serialized); + list($this->resource, $this->exists) = unserialize($serialized); } /** diff --git a/src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php index f429a33626564..3daef17ee1300 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php @@ -66,7 +66,7 @@ public function testExistsKo() $loadedClass = 123; - $res = new ClassExistenceResource('MissingFooClass', ClassExistenceResource::EXISTS_KO); + $res = new ClassExistenceResource('MissingFooClass', false); $this->assertSame(123, $loadedClass); } finally { @@ -76,7 +76,7 @@ public function testExistsKo() public function testConditionalClass() { - $res = new ClassExistenceResource(ConditionalClass::class, ClassExistenceResource::EXISTS_KO_WITH_THROWING_AUTOLOADER); + $res = new ClassExistenceResource(ConditionalClass::class, false); $this->assertFalse($res->isFresh(0)); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 49138f91bea34..8382d303859e1 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -388,7 +388,7 @@ private function populateAvailableType($id, Definition $definition) unset($this->ambiguousServiceTypes[$type]); } - if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), true)) { + if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass())) { return; } @@ -444,7 +444,7 @@ private function set($type, $id) */ private function createAutowiredDefinition($type) { - if (!($typeHint = $this->container->getReflectionClass($type, true)) || !$typeHint->isInstantiable()) { + if (!($typeHint = $this->container->getReflectionClass($type)) || !$typeHint->isInstantiable()) { return; } @@ -478,7 +478,7 @@ private function createAutowiredDefinition($type) private function createTypeNotFoundMessage(TypedReference $reference, $label) { - if (!$r = $this->container->getReflectionClass($type = $reference->getType(), true)) { + if (!$r = $this->container->getReflectionClass($type = $reference->getType())) { $message = sprintf('has type "%s" but this class does not exist.', $type); } else { $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists'; diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 3887e56fc244a..14dd957e9ea13 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -337,13 +337,12 @@ public function addClassResource(\ReflectionClass $class) * Retrieves the requested reflection class and registers it for resource tracking. * * @param string $class - * @param bool $koWithThrowingAutoloader Whether autoload should be protected against bad parents or not * * @return \ReflectionClass|null * * @final */ - public function getReflectionClass($class, $koWithThrowingAutoloader = false) + public function getReflectionClass($class) { if (!$class = $this->getParameterBag()->resolveValue($class)) { return; @@ -353,12 +352,9 @@ public function getReflectionClass($class, $koWithThrowingAutoloader = false) try { if (isset($this->classReflectors[$class])) { $classReflector = $this->classReflectors[$class]; - } elseif ($koWithThrowingAutoloader) { - $resource = new ClassExistenceResource($class, ClassExistenceResource::EXISTS_KO_WITH_THROWING_AUTOLOADER); - - $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); } else { - $classReflector = new \ReflectionClass($class); + $resource = new ClassExistenceResource($class, false); + $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); } } catch (\ReflectionException $e) { $classReflector = false; @@ -366,7 +362,7 @@ public function getReflectionClass($class, $koWithThrowingAutoloader = false) if ($this->trackResources) { if (!$classReflector) { - $this->addResource($resource ?: new ClassExistenceResource($class, ClassExistenceResource::EXISTS_KO)); + $this->addResource($resource ?: new ClassExistenceResource($class, false)); } elseif (!$classReflector->isInternal()) { $path = $classReflector->getFileName(); diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 3a2916635ffb8..8c88d4f02a790 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -32,7 +32,7 @@ "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them" }, "conflict": { - "symfony/config": "<3.3", + "symfony/config": "<3.3.1", "symfony/finder": "<3.3", "symfony/yaml": "<3.3" }, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy