Skip to content

[Serializer] Cache error normalizing anonymous class #36589

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ndench opened this issue Apr 27, 2020 · 1 comment · Fixed by #37937
Closed

[Serializer] Cache error normalizing anonymous class #36589

ndench opened this issue Apr 27, 2020 · 1 comment · Fixed by #37937

Comments

@ndench
Copy link
Contributor

ndench commented Apr 27, 2020

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:

@michaelzangerle
Copy link
Contributor

I experience the same problem when serializing anonymous classes. @xabbuh Is the suggested solution the way to go?

nicolas-grekas added a commit that referenced this issue Aug 31, 2020
…us classes (michaelzangerle)

This PR was squashed before being merged into the 4.4 branch.

Discussion
----------

[Serializer] fixed fix encoding of cache keys with anonymous classes

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #36589
| License       | MIT
| Doc PR        | -

Commits
-------

3a46753 [Serializer] fixed fix encoding of cache keys with anonymous classes
hultberg pushed a commit to hultberg/symfony that referenced this issue Sep 17, 2021
…anonymous classes (michaelzangerle)

This PR was squashed before being merged into the 4.4 branch.

Discussion
----------

[Serializer] fixed fix encoding of cache keys with anonymous classes

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix symfony#36589
| License       | MIT
| Doc PR        | -

Commits
-------

3a46753 [Serializer] fixed fix encoding of cache keys with anonymous classes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants