From 4f9eedfcf79c1c76ecea90332aa6978eca7ed9dc Mon Sep 17 00:00:00 2001 From: YaFou <33806646+YaFou@users.noreply.github.com> Date: Wed, 20 Jan 2021 20:59:41 +0100 Subject: [PATCH 1/6] [RateLimiter] Fix infinite values with NoLimiter --- .../RateLimiter/Policy/NoLimiter.php | 4 +-- .../Tests/Policy/NoLimiterTest.php | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/RateLimiter/Tests/Policy/NoLimiterTest.php diff --git a/src/Symfony/Component/RateLimiter/Policy/NoLimiter.php b/src/Symfony/Component/RateLimiter/Policy/NoLimiter.php index 03d4e54331..88efa5f5e0 100644 --- a/src/Symfony/Component/RateLimiter/Policy/NoLimiter.php +++ b/src/Symfony/Component/RateLimiter/Policy/NoLimiter.php @@ -29,12 +29,12 @@ final class NoLimiter implements LimiterInterface { public function reserve(int $tokens = 1, ?float $maxTime = null): Reservation { - return new Reservation(time(), new RateLimit(\INF, new \DateTimeImmutable(), true, \INF)); + return new Reservation(time(), new RateLimit(\PHP_INT_MAX, new \DateTimeImmutable(), true, \PHP_INT_MAX)); } public function consume(int $tokens = 1): RateLimit { - return new RateLimit(\INF, new \DateTimeImmutable(), true, \INF); + return new RateLimit(\PHP_INT_MAX, new \DateTimeImmutable(), true, \PHP_INT_MAX); } public function reset(): void diff --git a/src/Symfony/Component/RateLimiter/Tests/Policy/NoLimiterTest.php b/src/Symfony/Component/RateLimiter/Tests/Policy/NoLimiterTest.php new file mode 100644 index 0000000000..ecfc9400e2 --- /dev/null +++ b/src/Symfony/Component/RateLimiter/Tests/Policy/NoLimiterTest.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\RateLimiter\Tests\Policy; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\RateLimiter\Policy\NoLimiter; +use Symfony\Component\RateLimiter\RateLimit; +use Symfony\Component\RateLimiter\Reservation; + +class NoLimiterTest extends TestCase +{ + public function testConsume() + { + $limiter = new NoLimiter(); + $this->assertInstanceOf(RateLimit::class, $limiter->consume()); + } + + public function testReserve() + { + $limiter = new NoLimiter(); + $this->assertInstanceOf(Reservation::class, $limiter->reserve()); + } +} From cde0ffdc83fa6fa2284f819037876014fc722673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Wed, 20 Jan 2021 18:20:41 +0100 Subject: [PATCH 2/6] Allow relative path to composer cache --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index cef6c98c29..648c9523dc 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -157,6 +157,18 @@ $COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') ? ('#!/usr/bin/env php' === file_get_contents($COMPOSER, false, null, 0, 18) ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang : 'composer'; +$prevCacheDir = getenv('COMPOSER_CACHE_DIR'); +if ($prevCacheDir) { + if (false === $absoluteCacheDir = realpath($prevCacheDir)) { + @mkdir($prevCacheDir, 0777, true); + $absoluteCacheDir = realpath($prevCacheDir); + } + if ($absoluteCacheDir) { + putenv("COMPOSER_CACHE_DIR=$absoluteCacheDir"); + } else { + $prevCacheDir = false; + } +} $SYMFONY_PHPUNIT_REMOVE = $getEnvVar('SYMFONY_PHPUNIT_REMOVE', 'phpspec/prophecy'.($PHPUNIT_VERSION < 6.0 ? ' symfony/yaml' : '')); $configurationHash = md5(implode(\PHP_EOL, [md5_file(__FILE__), $SYMFONY_PHPUNIT_REMOVE, (int) $PHPUNIT_REMOVE_RETURN_TYPEHINT])); $PHPUNIT_VERSION_DIR = sprintf('phpunit-%s-%d', $PHPUNIT_VERSION, $PHPUNIT_REMOVE_RETURN_TYPEHINT); @@ -239,6 +251,9 @@ if (!file_exists("$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR/phpunit") || $configurationH // --no-suggest is not in the list to keep compat with composer 1.0, which is shipped with Ubuntu 16.04LTS $exit = proc_close(proc_open("$q$COMPOSER install --no-dev --prefer-dist --no-progress $q", [], $p, getcwd())); putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : '')); + if ($prevCacheDir) { + putenv("COMPOSER_CACHE_DIR=$prevCacheDir"); + } if ($exit) { exit($exit); } From 31817b48e23bf2705ac8fa076c7e690779a9f2ad Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 22 Jan 2021 17:56:23 +0100 Subject: [PATCH 3/6] [HttpKernel] Configure the ErrorHandler even when it is overriden --- .../HttpKernel/EventListener/DebugHandlersListener.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php index f4781ccd8e..cfc277e330 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/DebugHandlersListener.php @@ -33,6 +33,7 @@ use Symfony\Component\HttpKernel\KernelEvents; */ class DebugHandlersListener implements EventSubscriberInterface { + private $earlyHandler; private $exceptionHandler; private $logger; private $levels; @@ -53,6 +54,10 @@ class DebugHandlersListener implements EventSubscriberInterface */ public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, $fileLinkFormat = null, bool $scope = true) { + $handler = set_exception_handler('var_dump'); + $this->earlyHandler = \is_array($handler) ? $handler[0] : null; + restore_exception_handler(); + $this->exceptionHandler = $exceptionHandler; $this->logger = $logger; $this->levels = null === $levels ? \E_ALL : $levels; @@ -79,6 +84,10 @@ class DebugHandlersListener implements EventSubscriberInterface $handler = \is_array($handler) ? $handler[0] : null; restore_exception_handler(); + if (!$handler instanceof ErrorHandler && !$handler instanceof LegacyErrorHandler) { + $handler = $this->earlyHandler; + } + if ($this->logger || null !== $this->throwAt) { if ($handler instanceof ErrorHandler || $handler instanceof LegacyErrorHandler) { if ($this->logger) { From a5505c4dfa6115025c213ac740bce9203769ac38 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 23 Jan 2021 14:21:25 +0100 Subject: [PATCH 4/6] check parent types for label_format and translation_domain --- .../ViolationMapper/ViolationMapper.php | 14 +++++- .../ViolationMapper/ViolationMapperTest.php | 44 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php index 2f4a3a6a5a..48284d8d73 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -154,7 +154,11 @@ class ViolationMapper implements ViolationMapperInterface $messageTemplate = $violation->getMessageTemplate(); if (false !== strpos($message, '{{ label }}') || false !== strpos($messageTemplate, '{{ label }}')) { - $labelFormat = $scope->getConfig()->getOption('label_format'); + $form = $scope; + + do { + $labelFormat = $form->getConfig()->getOption('label_format'); + } while (null === $labelFormat && null !== $form = $form->getParent()); if (null !== $labelFormat) { $label = str_replace( @@ -180,10 +184,16 @@ class ViolationMapper implements ViolationMapperInterface } if (null !== $this->translator) { + $form = $scope; + + do { + $translationDomain = $form->getConfig()->getOption('translation_domain'); + } while (null === $translationDomain && null !== $form = $form->getParent()); + $label = $this->translator->trans( $label, $scope->getConfig()->getOption('label_translation_parameters', []), - $scope->getConfig()->getOption('translation_domain') + $translationDomain ); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 2a8f92fb49..d636f9fe40 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -1742,6 +1742,50 @@ class ViolationMapperTest extends TestCase } } + public function testLabelFormatDefinedByParentType() + { + $form = $this->getForm('', null, null, [], false, true, [ + 'label_format' => 'form.%name%', + ]); + $child = $this->getForm('foo', 'foo'); + $form->add($child); + + $violation = new ConstraintViolation('Message "{{ label }}"', null, [], null, 'data.foo', null); + $this->mapper->mapViolation($violation, $form); + + $errors = iterator_to_array($child->getErrors()); + + $this->assertCount(1, $errors, $child->getName().' should have an error, but has none'); + $this->assertSame('Message "form.foo"', $errors[0]->getMessage()); + } + + public function testLabelPlaceholderTranslatedWithTranslationDomainDefinedByParentType() + { + $translator = $this->createMock(TranslatorInterface::class); + $translator->expects($this->any()) + ->method('trans') + ->with('foo', [], 'domain') + ->willReturn('translated foo label') + ; + $this->mapper = new ViolationMapper(null, $translator); + + $form = $this->getForm('', null, null, [], false, true, [ + 'translation_domain' => 'domain', + ]); + $child = $this->getForm('foo', 'foo', null, [], false, true, [ + 'label' => 'foo', + ]); + $form->add($child); + + $violation = new ConstraintViolation('Message "{{ label }}"', null, [], null, 'data.foo', null); + $this->mapper->mapViolation($violation, $form); + + $errors = iterator_to_array($child->getErrors()); + + $this->assertCount(1, $errors, $child->getName().' should have an error, but has none'); + $this->assertSame('Message "translated foo label"', $errors[0]->getMessage()); + } + public function testTranslatorNotCalledWithoutLabel() { $renderer = $this->getMockBuilder(FormRenderer::class) From 1eb13767fcaff7394dc841c32b330fdd2b3b2c41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Fr=C3=A9mont?= Date: Fri, 22 Jan 2021 11:02:15 +0100 Subject: [PATCH 5/6] [Validator] Fix DebugCommand --- src/Symfony/Component/Validator/Command/DebugCommand.php | 2 +- src/Symfony/Component/Validator/Tests/Dummy/TraitPass.php | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Validator/Tests/Dummy/TraitPass.php diff --git a/src/Symfony/Component/Validator/Command/DebugCommand.php b/src/Symfony/Component/Validator/Command/DebugCommand.php index 8eb1fa5e2e..96d33cf71d 100644 --- a/src/Symfony/Component/Validator/Command/DebugCommand.php +++ b/src/Symfony/Component/Validator/Command/DebugCommand.php @@ -181,7 +181,7 @@ EOF $namespace = $matches[1] ?? null; - if (false === preg_match('/class +([^{ ]+)/', $fileContent, $matches)) { + if (!preg_match('/class +([^{ ]+)/', $fileContent, $matches)) { // no class found continue; } diff --git a/src/Symfony/Component/Validator/Tests/Dummy/TraitPass.php b/src/Symfony/Component/Validator/Tests/Dummy/TraitPass.php new file mode 100644 index 0000000000..5ce54a7e0f --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Dummy/TraitPass.php @@ -0,0 +1,7 @@ + Date: Sat, 23 Jan 2021 20:10:32 +0100 Subject: [PATCH 6/6] [Uid] fix checking for valid UUIDs --- src/Symfony/Component/Uid/BinaryUtil.php | 14 ++++++++++---- src/Symfony/Component/Uid/Ulid.php | 2 +- src/Symfony/Component/Uid/Uuid.php | 16 +++++----------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Uid/BinaryUtil.php b/src/Symfony/Component/Uid/BinaryUtil.php index 082346cd15..32e7e0dff3 100644 --- a/src/Symfony/Component/Uid/BinaryUtil.php +++ b/src/Symfony/Component/Uid/BinaryUtil.php @@ -40,7 +40,7 @@ class BinaryUtil // 0x01b21dd213814000 is the number of 100-ns intervals between the // UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00. private const TIME_OFFSET_INT = 0x01b21dd213814000; - private const TIME_OFFSET_COM = "\xfe\x4d\xe2\x2d\xec\x7e\xc0\x00"; + private const TIME_OFFSET_COM2 = "\xfe\x4d\xe2\x2d\xec\x7e\xc0\x00"; public static function toBase(string $bytes, array $map): string { @@ -121,9 +121,15 @@ class BinaryUtil } $time = str_pad(hex2bin($time), 8, "\0", \STR_PAD_LEFT); - $time = self::add($time, self::TIME_OFFSET_COM); - $time[0] = $time[0] & "\x7F"; + $time = self::add($time, self::TIME_OFFSET_COM2); - return self::toBase($time, self::BASE10) / 10000000; + if ($time >= self::TIME_OFFSET_COM2) { + $time = -1 * self::toBase($time ^ "\xff\xff\xff\xff\xff\xff\xff\xff", self::BASE10); + } else { + $time[0] = $time[0] & "\x7F"; + $time = self::toBase($time, self::BASE10); + } + + return $time / 10000000; } } diff --git a/src/Symfony/Component/Uid/Ulid.php b/src/Symfony/Component/Uid/Ulid.php index b467f9be2b..5ff31bb398 100644 --- a/src/Symfony/Component/Uid/Ulid.php +++ b/src/Symfony/Component/Uid/Ulid.php @@ -153,7 +153,7 @@ class Ulid extends AbstractUid if (\PHP_INT_SIZE >= 8) { $time = base_convert($time, 10, 32); } else { - $time = bin2hex(BinaryUtil::fromBase($time, BinaryUtil::BASE10)); + $time = str_pad(bin2hex(BinaryUtil::fromBase($time, BinaryUtil::BASE10)), 12, '0', \STR_PAD_LEFT); $time = sprintf('%s%04s%04s', base_convert(substr($time, 0, 2), 16, 32), base_convert(substr($time, 2, 5), 16, 32), diff --git a/src/Symfony/Component/Uid/Uuid.php b/src/Symfony/Component/Uid/Uuid.php index 87a285b9c3..a9fbbc2158 100644 --- a/src/Symfony/Component/Uid/Uuid.php +++ b/src/Symfony/Component/Uid/Uuid.php @@ -22,11 +22,7 @@ class Uuid extends AbstractUid public function __construct(string $uuid) { - try { - $type = uuid_type($uuid); - } catch (\ValueError $e) { - throw new \InvalidArgumentException(sprintf('Invalid UUID%s: "%s".', static::TYPE ? 'v'.static::TYPE : '', $uuid), 0, $e); - } + $type = uuid_is_valid($uuid) ? uuid_type($uuid) : false; if (false === $type || \UUID_TYPE_INVALID === $type || (static::TYPE ?: $type) !== $type) { throw new \InvalidArgumentException(sprintf('Invalid UUID%s: "%s".', static::TYPE ? 'v'.static::TYPE : '', $uuid)); @@ -59,13 +55,11 @@ class Uuid extends AbstractUid return new static($uuid); } - try { - $type = uuid_type($uuid); - } catch (\ValueError $e) { - throw new \InvalidArgumentException(sprintf('Invalid UUID%s: "%s".', static::TYPE ? 'v'.static::TYPE : '', $uuid), 0, $e); + if (!uuid_is_valid($uuid)) { + throw new \InvalidArgumentException(sprintf('Invalid UUID%s: "%s".', static::TYPE ? 'v'.static::TYPE : '', $uuid)); } - switch ($type) { + switch (uuid_type($uuid)) { case UuidV1::TYPE: return new UuidV1($uuid); case UuidV3::TYPE: return new UuidV3($uuid); case UuidV4::TYPE: return new UuidV4($uuid); @@ -114,7 +108,7 @@ class Uuid extends AbstractUid return uuid_is_valid($uuid); } - return static::TYPE === uuid_type($uuid); + return uuid_is_valid($uuid) && static::TYPE === uuid_type($uuid); } public function toBinary(): string