From 7146b95303187d5859110741be07f88cda83919c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 19 May 2019 07:50:55 -0300 Subject: [PATCH 1/8] [DI] fix using bindings with locators of service subscribers --- .../Compiler/ServiceLocatorTagPass.php | 12 +- .../Compiler/ServiceLocatorTagPassTest.php | 147 ++++++++++++++++++ .../Tests/Fixtures/TestDefinition2.php | 9 ++ 3 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/ServiceLocatorTagPassTest.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/TestDefinition2.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php index 93e489c8f6..51de4d7ac0 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php @@ -48,6 +48,12 @@ final class ServiceLocatorTagPass extends AbstractRecursivePass if (!$v instanceof Reference) { throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set, "%s" found for key "%s".', $this->currentId, \is_object($v) ? \get_class($v) : \gettype($v), $k)); } + + if (\is_int($k)) { + unset($arguments[0][$k]); + + $k = (string) $v; + } $arguments[0][$k] = new ServiceClosureArgument($v); } ksort($arguments[0]); @@ -91,7 +97,11 @@ final class ServiceLocatorTagPass extends AbstractRecursivePass ->setPublic(false) ->addTag('container.service_locator'); - if (!$container->has($id = 'service_locator.'.ContainerBuilder::hash($locator))) { + if (null !== $callerId && $container->hasDefinition($callerId)) { + $locator->setBindings($container->getDefinition($callerId)->getBindings()); + } + + if (!$container->hasDefinition($id = 'service_locator.'.ContainerBuilder::hash($locator))) { $container->setDefinition($id, $locator); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ServiceLocatorTagPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ServiceLocatorTagPassTest.php new file mode 100644 index 0000000000..27ee7db533 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ServiceLocatorTagPassTest.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition; +use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition1; +use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition2; + +require_once __DIR__.'/../Fixtures/includes/classes.php'; + +class ServiceLocatorTagPassTest extends TestCase +{ + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Invalid definition for service "foo": an array of references is expected as first argument when the "container.service_locator" tag is set. + */ + public function testNoServices() + { + $container = new ContainerBuilder(); + + $container->register('foo', ServiceLocator::class) + ->addTag('container.service_locator') + ; + + (new ServiceLocatorTagPass())->process($container); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Invalid definition for service "foo": an array of references is expected as first argument when the "container.service_locator" tag is set, "string" found for key "0". + */ + public function testInvalidServices() + { + $container = new ContainerBuilder(); + + $container->register('foo', ServiceLocator::class) + ->setArguments([[ + 'dummy', + ]]) + ->addTag('container.service_locator') + ; + + (new ServiceLocatorTagPass())->process($container); + } + + public function testProcessValue() + { + $container = new ContainerBuilder(); + + $container->register('bar', CustomDefinition::class); + $container->register('baz', CustomDefinition::class); + + $container->register('foo', ServiceLocator::class) + ->setArguments([[ + new Reference('bar'), + new Reference('baz'), + 'some.service' => new Reference('bar'), + ]]) + ->addTag('container.service_locator') + ; + + (new ServiceLocatorTagPass())->process($container); + + /** @var ServiceLocator $locator */ + $locator = $container->get('foo'); + + $this->assertSame(CustomDefinition::class, \get_class($locator('bar'))); + $this->assertSame(CustomDefinition::class, \get_class($locator('baz'))); + $this->assertSame(CustomDefinition::class, \get_class($locator('some.service'))); + } + + public function testServiceWithKeyOverwritesPreviousInheritedKey() + { + $container = new ContainerBuilder(); + + $container->register('bar', TestDefinition1::class); + $container->register('baz', TestDefinition2::class); + + $container->register('foo', ServiceLocator::class) + ->setArguments([[ + new Reference('bar'), + 'bar' => new Reference('baz'), + ]]) + ->addTag('container.service_locator') + ; + + (new ServiceLocatorTagPass())->process($container); + + /** @var ServiceLocator $locator */ + $locator = $container->get('foo'); + + $this->assertSame(TestDefinition2::class, \get_class($locator('bar'))); + } + + public function testInheritedKeyOverwritesPreviousServiceWithKey() + { + $container = new ContainerBuilder(); + + $container->register('bar', TestDefinition1::class); + $container->register('baz', TestDefinition2::class); + + $container->register('foo', ServiceLocator::class) + ->setArguments([[ + 'bar' => new Reference('baz'), + new Reference('bar'), + ]]) + ->addTag('container.service_locator') + ; + + (new ServiceLocatorTagPass())->process($container); + + /** @var ServiceLocator $locator */ + $locator = $container->get('foo'); + + $this->assertSame(TestDefinition1::class, \get_class($locator('bar'))); + } + + public function testBindingsAreCopied() + { + $container = new ContainerBuilder(); + + $container->register('foo') + ->setBindings(['foo' => 'foo']); + + $locator = ServiceLocatorTagPass::register($container, ['foo' => new Reference('foo')], 'foo'); + $locator = $container->getDefinition($locator); + $locator = $container->getDefinition($locator->getFactory()[0]); + + $this->assertSame(['foo'], array_keys($locator->getBindings())); + $this->assertInstanceOf(BoundArgument::class, $locator->getBindings()['foo']); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/TestDefinition2.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/TestDefinition2.php new file mode 100644 index 0000000000..2ec8f9cf86 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/TestDefinition2.php @@ -0,0 +1,9 @@ + Date: Wed, 22 May 2019 09:57:24 +0200 Subject: [PATCH 2/8] fix phpdoc --- .../Http/Authorization/AccessDeniedHandlerInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.php b/src/Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.php index aea901181f..871c877f57 100644 --- a/src/Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.php +++ b/src/Symfony/Component/Security/Http/Authorization/AccessDeniedHandlerInterface.php @@ -26,7 +26,7 @@ interface AccessDeniedHandlerInterface /** * Handles an access denied failure. * - * @return Response may return null + * @return Response|null */ public function handle(Request $request, AccessDeniedException $accessDeniedException); } From 13ee1fa2b7be83e77cd9d3ebdd44da747b1999fe Mon Sep 17 00:00:00 2001 From: martijn Date: Wed, 1 May 2019 18:49:52 +0200 Subject: [PATCH 3/8] Use absolute URL for when the profiler's domain differs from the controller's domain which initialises the profiler. --- .../Bundle/WebProfilerBundle/Controller/ProfilerController.php | 2 +- .../Resources/views/Profiler/toolbar_item.html.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php index 4333c74d2f..55f343806a 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php @@ -164,7 +164,7 @@ class ProfilerController $url = null; try { - $url = $this->generator->generate('_profiler', ['token' => $token]); + $url = $this->generator->generate('_profiler', ['token' => $token], UrlGeneratorInterface::ABSOLUTE_URL); } catch (\Exception $e) { // the profiler is not enabled } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_item.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_item.html.twig index 69872418cf..d81e877977 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_item.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_item.html.twig @@ -1,5 +1,5 @@
- {% if link is not defined or link %}{% endif %} + {% if link is not defined or link %}{% endif %}
{{ icon|default('') }}
{% if link|default(false) %}
{% endif %}
{{ text|default('') }}
From 6b9ee1e1c569f61d1a871671c9e2d1cdffea217b Mon Sep 17 00:00:00 2001 From: mshavliuk Date: Wed, 22 May 2019 02:21:35 +0300 Subject: [PATCH 4/8] [Process] Fix infinite waiting for stopped process --- src/Symfony/Component/Process/Process.php | 1 + .../Process/Tests/ErrorProcessInitiator.php | 36 +++++++++++++++++++ .../Component/Process/Tests/ProcessTest.php | 9 +++++ 3 files changed, 46 insertions(+) create mode 100755 src/Symfony/Component/Process/Tests/ErrorProcessInitiator.php diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 75395b66c5..68cc6c65ae 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -427,6 +427,7 @@ class Process implements \IteratorAggregate } while ($running); while ($this->isRunning()) { + $this->checkTimeout(); usleep(1000); } diff --git a/src/Symfony/Component/Process/Tests/ErrorProcessInitiator.php b/src/Symfony/Component/Process/Tests/ErrorProcessInitiator.php new file mode 100755 index 0000000000..c37aeb5c8f --- /dev/null +++ b/src/Symfony/Component/Process/Tests/ErrorProcessInitiator.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Tests; + +use Symfony\Component\Process\Exception\ProcessTimedOutException; +use Symfony\Component\Process\Process; + +require \dirname(__DIR__).'/vendor/autoload.php'; + +list('e' => $php) = getopt('e:') + ['e' => 'php']; + +try { + $process = new Process("exec $php -r \"echo 'ready'; trigger_error('error', E_USER_ERROR);\""); + $process->start(); + $process->setTimeout(0.5); + while (false === strpos($process->getOutput(), 'ready')) { + usleep(1000); + } + $process->signal(SIGSTOP); + $process->wait(); + + return $process->getExitCode(); +} catch (ProcessTimedOutException $t) { + echo $t->getMessage().PHP_EOL; + + return 1; +} diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index a9ecbe8043..18fef4ff5f 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -1551,6 +1551,15 @@ EOTXT; $this->assertSame($env, $p->getEnv()); } + public function testWaitStoppedDeadProcess() + { + $process = $this->getProcess(self::$phpBin.' '.__DIR__.'/ErrorProcessInitiator.php -e '.self::$phpBin); + $process->start(); + $process->setTimeout(2); + $process->wait(); + $this->assertFalse($process->isRunning()); + } + /** * @param string $commandline * @param string|null $cwd From 721915f8ec3b4ae8bf9bfc37ee7ddc03dd6d3a16 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Wed, 22 May 2019 18:32:44 +0200 Subject: [PATCH 5/8] minor: fix phpdocs in the ldap component --- src/Symfony/Component/Ldap/Exception/ConnectionException.php | 2 +- .../Component/Ldap/Exception/DriverNotFoundException.php | 2 +- src/Symfony/Component/Ldap/Exception/LdapException.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Ldap/Exception/ConnectionException.php b/src/Symfony/Component/Ldap/Exception/ConnectionException.php index cded4cf2a3..7fa8e89f6f 100644 --- a/src/Symfony/Component/Ldap/Exception/ConnectionException.php +++ b/src/Symfony/Component/Ldap/Exception/ConnectionException.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Ldap\Exception; /** - * ConnectionException is throw if binding to ldap can not be established. + * ConnectionException is thrown if binding to ldap can not be established. * * @author Grégoire Pineau */ diff --git a/src/Symfony/Component/Ldap/Exception/DriverNotFoundException.php b/src/Symfony/Component/Ldap/Exception/DriverNotFoundException.php index 40258435bb..382cdf5ca6 100644 --- a/src/Symfony/Component/Ldap/Exception/DriverNotFoundException.php +++ b/src/Symfony/Component/Ldap/Exception/DriverNotFoundException.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Ldap\Exception; /** - * LdapException is throw if php ldap module is not loaded. + * LdapException is thrown if php ldap module is not loaded. * * @author Charles Sarrazin */ diff --git a/src/Symfony/Component/Ldap/Exception/LdapException.php b/src/Symfony/Component/Ldap/Exception/LdapException.php index 4045f32cf4..df8eabfbcb 100644 --- a/src/Symfony/Component/Ldap/Exception/LdapException.php +++ b/src/Symfony/Component/Ldap/Exception/LdapException.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Ldap\Exception; /** - * LdapException is throw if php ldap module is not loaded. + * LdapException is thrown if php ldap module is not loaded. * * @author Grégoire Pineau */ From 2a9816f0b63b798ec99f3586e763414b03ba00dc Mon Sep 17 00:00:00 2001 From: mmokhi Date: Thu, 23 May 2019 12:47:28 +0200 Subject: [PATCH 6/8] Make tempfile path unique The temp-file that the test currently creates is `/tmp/log`. This may exist on many platforms already (including `platform.sh` app containers). With the proposed patch way the collision will be less likely. Sponsored-by: Platform.sh --- src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php index 7354000b16..17865203f2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php @@ -34,7 +34,7 @@ class LoggerTest extends TestCase protected function setUp() { - $this->tmpFile = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'log'; + $this->tmpFile = tempnam(sys_get_temp_dir(), 'log'); $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile); } From 9b558fe1856f2cad369df45207baa18905191bb8 Mon Sep 17 00:00:00 2001 From: Saif Eddin G <29315886+azjezz@users.noreply.github.com> Date: Fri, 24 May 2019 13:25:55 +0100 Subject: [PATCH 7/8] [Finder] fix wrong method call casing --- src/Symfony/Component/Finder/Iterator/SortableIterator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Finder/Iterator/SortableIterator.php b/src/Symfony/Component/Finder/Iterator/SortableIterator.php index 53f8e31c6c..3c7157adb9 100644 --- a/src/Symfony/Component/Finder/Iterator/SortableIterator.php +++ b/src/Symfony/Component/Finder/Iterator/SortableIterator.php @@ -39,7 +39,7 @@ class SortableIterator implements \IteratorAggregate if (self::SORT_BY_NAME === $sort) { $this->sort = function ($a, $b) { - return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname()); + return strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); }; } elseif (self::SORT_BY_TYPE === $sort) { $this->sort = function ($a, $b) { @@ -49,7 +49,7 @@ class SortableIterator implements \IteratorAggregate return 1; } - return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname()); + return strcmp($a->getRealPath() ?: $a->getPathname(), $b->getRealPath() ?: $b->getPathname()); }; } elseif (self::SORT_BY_ACCESSED_TIME === $sort) { $this->sort = function ($a, $b) { From 35811ed22dc31a8d1d33c9336615088640e2e068 Mon Sep 17 00:00:00 2001 From: Ricardo de Vries Date: Fri, 24 May 2019 07:33:34 +0200 Subject: [PATCH 8/8] [github] Implement the new security policy. --- .github/SECURITY.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/SECURITY.md diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000000..60990950bf --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,10 @@ +Security Policy +=============== + +If you found any issues that might have security implications, +please send a report to security[at]symfony.com +DO NOT PUBLISH SECURITY REPORTS PUBLICLY. + +The full [Security Policy][1] is described in the official documentation. + + [1]: https://symfony.com/security