-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Description
Symfony version(s) affected: 4.4.7
Description
During phpunit tests with APP_DEBUG=1
, an anonymous class can be normalized by the NormalizerInterface
, however, with APP_DEBUG=0
the following error is produced:
Symfony\Component\Cache\Exception\InvalidArgumentException: Cache key "class@anonymous/app/tests/AnonymousClassTest.php:16$9c" contains reserved characters "{}()/\@:".
Full stack trace
Symfony\Component\Cache\Exception\InvalidArgumentException: Cache key "class@anonymous/app/tests/AnonymousClassTest.php:16$9c" contains reserved characters "{}()/\@:".
/app/vendor/symfony/cache/CacheItem.php:177
/app/vendor/symfony/cache/Traits/AbstractTrait.php:281
/app/vendor/symfony/cache/Traits/AbstractAdapterTrait.php:44
/app/vendor/symfony/cache/Adapter/PhpArrayAdapter.php:122
/app/vendor/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php:50
/app/vendor/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.php:50
/app/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:269
/app/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:164
/app/vendor/symfony/serializer/Serializer.php:152
/app/tests/AnonymousClassTest.php:19
How to reproduce
The error can be reproduced with the following test case:
<?php
namespace App\Tests;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
final class AnonymousClassTest extends KernelTestCase
{
public function testSerializeAnonymousClass(): void
{
static::bootKernel();
$normalizer = static::$container->get(NormalizerInterface::class);
$class = new class() {
};
$normalizer->normalize($class);
$this->addToAssertionCount(1);
}
}
Successful test run with APP_DEBUG=1
$ APP_DEBUG=1 vendor/bin/phpunit tests/AnonymousClassTest.php
PHPUnit 8.5.4 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 466 ms, Memory: 20.00 MB
OK (1 test, 1 assertion)
Failed test run with APP_DEBUG=0
$ APP_DEBUG=0 vendor/bin/phpunit tests/AnonymousClassTest.php
PHPUnit 8.5.4 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 216 ms, Memory: 18.00 MB
There was 1 error:
1) App\Tests\AnonymousClassTest::testSerializeAnonymousClass
Symfony\Component\Cache\Exception\InvalidArgumentException: Cache key "class@anonymous/app/tests/AnonymousClassTest.php:16$9c" contains reserved characters "{}()/\@:".
/app/vendor/symfony/cache/CacheItem.php:177
/app/vendor/symfony/cache/Traits/AbstractTrait.php:281
/app/vendor/symfony/cache/Traits/AbstractAdapterTrait.php:44
/app/vendor/symfony/cache/Adapter/PhpArrayAdapter.php:122
/app/vendor/symfony/serializer/Mapping/Factory/CacheClassMetadataFactory.php:50
/app/vendor/symfony/serializer/Mapping/ClassDiscriminatorFromClassMetadata.php:50
/app/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:269
/app/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:164
/app/vendor/symfony/serializer/Serializer.php:152
/app/tests/AnonymousClassTest.php:19
ERRORS!
Tests: 1, Assertions: 0, Errors: 1.
Possible Solution
It appears that an issue similar to this has appeared a few times in the past (linked issued below) and it was fixed with something like this in PropertyAccessor::getReadAccessInfo
and PropertyAccessor::getWriteAccessInfo
:
$key = false !== strpbrk($key = $class.'..'.$property, '{}()/@:') ? rawurlencode($key) : $key;
But this issue seems to be unrelated to the PropertyAccessor, so I adding the change to CacheClassMetadataFactory::getMetadataFor
and that makes the test pass successfully with APP_DEBUG=0
:
public function getMetadataFor($value)
{
$class = $this->getClass($value);
// Key cannot contain backslashes according to PSR-6
$key = strtr($class, '\\', '_');
+ $key = false !== strpbrk($key, '{}()/@:') ? rawurlencode($key) : $key;
$item = $this->cacheItemPool->getItem($key);
Not sure if this is the correct place to fix the issue, or if it has knock on affects elsewhere.
Additional context
I found a few older issues which may be related:
- [PropertyAccess] getReadAccessInfo can not be cached due naming restrictions when using Anonymous Class object #23136
- [Console] Remaining regressions due to #33897 #36565
- [Property Accessor] Error on reserved characters from CacheAdapter #29329
- Deserializing an Xml file into an Object can cause
Cache key "p@triggers" contains reserved characters {}()/\@:
#29293 - Cache key "email@address" contains reserved characters {}()/\@: #26313