8000 Cache key "email@address" contains reserved characters {}()/\@: · Issue #26313 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Cache key "email@address" contains reserved characters {}()/\@: #26313

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
dadepl opened this issue Feb 26, 2018 · 24 comments
Closed

Cache key "email@address" contains reserved characters {}()/\@: #26313

dadepl opened this issue Feb 26, 2018 · 24 comments
Labels
Bug Cache Good first issue Ideal for your first contribution! (some Symfony experience may be required) Status: Reviewed Validator

Comments

@dadepl
Copy link
dadepl commented Feb 26, 2018
Q A
Bug report? maybe
Feature request? no
BC Break report? no
RFC? no
Symfony version 3.4.4

Hi,

I have problem when submitting user form. I use FOSUserBundle and there's simple form with only two fields:
->add('name', TextType::class, [ 'label' => 'name and surname', ])
->add('department', TextType::class, [ 'label' => 'department', ])

It's also standard in controller:
$editForm = $this->createForm('Company\AdminBundle\Form\UserEditType', $user);
$editForm->handleRequest($request);

When I submit form in production env I get error in prod.log:
[2018-02-26 08:50:35] request.CRITICAL: Uncaught PHP Exception Symfony\Component\Cache\Exception\InvalidArgumentException: "Cache key "email@address" contains reserved characters {}()/\@:" at /Users/local/Sites/projectname/vendor/symfony/cache/CacheItem.php line 162 {"exception":"[object] (Symfony\\Component\\Cache\\Exception\\InvalidArgumentException(code: 0): Cache key \"email@address\" contains reserved characters {}()/\\@: at /Users/local/Sites/projectname/vendor/symfony/cache/CacheItem.php:162)"} []

As far as I can check, the problem occurs on handleRequest($request) in controller and later on Symfony Form class when dispatches POST_SUBMIT
$dispatcher->dispatch(FormEvents::POST_SUBMIT, $event);
and then in ValidationListener class when running
$violations = $this->validator->validate($form);

I do not use any custom cache bundles / vendors and it's first time I have such problem. Just don't know why. I understand error itself, that there's problem with "@" character in cache and with PSR-6, but have no idea what to check or change.

Thank you for help.

@nicolas-grekas
Copy link
Member

can you dump the full stack trace of that exception please?

@dadepl
Copy link
Author
dadepl commented Feb 26, 2018
[2018-02-26 09:16:01] request.INFO: Matched route "admin_user_edit". {"route":"admin_user_edit","route_parameters":{"_controller":"Company\\AdminBundle\\Controller\\UserController::editAction","id":"1","_route":"admin_user_edit"},"request_uri":"http://projectname.test/admin/user/1/edit","method":"POST"} []`
`[2018-02-26 09:16:01] security.DEBUG: Read existing security token from the session. {"key":"_security_admin","token_class":"Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken"} []`
`[2018-02-26 09:16:01] security.DEBUG: User was reloaded from a user provider. {"provider":"FOS\\UserBundle\\Security\\EmailUserProvider","username":"dade"} []`
`[2018-02-26 09:16:01] request.CRITICAL: Uncaught PHP Exception Symfony\Component\Cache\Exception\InvalidArgumentException: "Cache key "email@address" contains reserved characters {}()/\@:" at /Users/local/Sites/projectname/vendor/symfony/cache/CacheItem.php line 162 {"exception":"[object] (Symfony\\Component\\Cache\\Exception\\InvalidArgumentException(code: 0): Cache key \"email@address\" contains reserved characters {}()/\\@: at /Users/local/Sites/projectname/vendor/symfony/cache/CacheItem.php:162)"} []`
`[2018-02-26 09:16:01] security.DEBUG: Stored the security token in the session. {"key":"_security_admin"} []

@nicolas-grekas
Copy link
Member

We'd need to know where the invalid key is used.
To do so, we'd need to get the full stack trace, which is something you could get by eg opening vendor/symfony/cache/CacheItem.php and inserting echo new \Exception(); just before the exception is thrown. (don't forget to remove the line once you copy/pasted the output)

@dadepl
Copy link
Author
dadepl commented Feb 26, 2018

echoing new exception just before throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters {}()/\@:', $key)); results in:

Exception in /Users/local/Sites/project/vendor/symfony/cache/CacheItem.php:162 Stack trace: #0 
/Users/local/Sites/project/vendor/symfony/cache/Traits/AbstractTrait.php(232): Symfony\Component\Cache\CacheItem::validateKey('firstname.lastna...') #1 
/Users/local/Sites/project/vendor/symfony/cache/Adapter/AbstractAdapter.php(148): Symfony\Component\Cache\Adapter\AbstractAdapter->getId('firstname.lastna...') #2 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator
8000
/Mapping/Cache/Psr6Cache.php(44): Symfony\Component\Cache\Adapter\AbstractAdapter->getItem('firstname.lastna...') #3 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Mapping/Factory/LazyLoadingMetadataFactory.php(91): Symfony\Component\Validator\Mapping\Cache\Psr6Cache->read('firstname.lastna...') #4 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php(328): Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory->getMetadataFor('firstname.lastna...') #5 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php(724): Symfony\Component\Validator\Validator\RecursiveContextualValidator->validateObject('firstname.lastna...', 'data.email', Array, 1, Object(Symfony\Component\Validator\Context\ExecutionContext)) #6 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php(577): Symfony\Component\Validator\Validator\RecursiveContextualValidator->validateGenericNode('firstname.lastna...', Object(Client\AppBundle\Entity\User), '000000002c28ba2...', Object(Symfony\Component\Validator\Mapping\PropertyMetadata), 'data.email', Array, Array, 1, Object(Symfony\Component\Validator\Context\ExecutionContext)) #7 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php(347): Symfony\Component\Validator\Validator\RecursiveContextualValidator->validateClassNode(Object(Client\AppBundle\Entity\User), '000000002c28ba2...', Object(Symfony\Component\Validator\Mapping\ClassMetadata), 'data', Array, NULL, 1, Object(Symfony\Component\Validator\Context\ExecutionContext)) #8 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php(139): Symfony\Component\Validator\Validator\RecursiveContextualValidator->validateObject(Object(Client\AppBundle\Entity\User), 'data', Array, 1, Object(Symfony\Component\Validator\Context\ExecutionContext)) #9 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php(52): Symfony\Component\Validator\Validator\RecursiveContextualValidator->validate(Object(Client\AppBundle\Entity\User), NULL, Array) #10 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php(829): Symfony\Component\Form\Extension\Validator\Constraints\FormValidator->validate(Object(Symfony\Component\Form\Form), Object(Symfony\Component\Form\Extension\Validator\Constraints\Form)) #11 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php(542): Symfony\Component\Validator\Validator\RecursiveContextualValidator->validateInGroup(Object(Symfony\Component\Form\Form), '000000002c28bac...', Object(Symfony\Component\Validator\Mapping\ClassMetadata), 'Default', Object(Symfony\Component\Validator\Context\ExecutionContext)) #12 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php(347): Symfony\Component\Validator\Validator\RecursiveContextualValidator->validateClassNode(Object(Symfony\Component\Form\Form), '000000002c28bac...', Object(Symfony\Component\Validator\Mapping\ClassMetadata), '', Array, NULL, 1, Object(Symfony\Component\Validator\Context\ExecutionContext)) #13 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php(139): Symfony\Component\Validator\Validator\RecursiveContextualValidator->validateObject(Object(Symfony\Component\Form\Form), '', Array, 1, Object(Symfony\Component\Validator\Context\ExecutionContext)) #14 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Validator/Validator/RecursiveValidator.php(100): Symfony\Component\Validator\Validator\RecursiveContextualValidator->validate(Object(Symfony\Component\Form\Form), NULL, Array) #15 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Validator/EventListener/ValidationListener.php(55): Symfony\Component\Validator\Validator\RecursiveValidator->validate(Object(Symfony\Component\Form\Form)) #16 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php(212): Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener->validateForm(Object(Symfony\Component\Form\FormEvent), 'form.post_bind', Object(Symfony\Component\EventDispatcher\EventDispatcher)) #17 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php(44): Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(Array, 'form.post_bind', Object(Symfony\Component\Form\FormEvent)) #18 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/ImmutableEventDispatcher.php(33): Symfony\Component\EventDispatcher\EventDispatcher->dispatch('form.post_bind', Object(Symfony\Component\Form\FormEvent)) #19 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Form/Form.php(665): Symfony\Component\EventDispatcher\ImmutableEventDispatcher->dispatch('form.post_bind', Object(Symfony\Component\Form\FormEvent)) #20 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php(108): Symfony\Component\Form\Form->submit(Array, true) #21 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/Form/Form.php(498): Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler->handleRequest(Object(Symfony\Component\Form\Form), Object(Symfony\Component\HttpFoundation\Request)) #22 
/Users/local/Sites/project/src/Company/AdminBundle/Controller/UserController.php(138): Symfony\Component\Form\Form->handleRequest(Object(Symfony\Component\HttpFoundation\Request)) #23 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php(151): Client\AdminBundle\Controller\UserController->editAction(Object(Client\AppBundle\Entity\User), Object(Symfony\Component\HttpFoundation\Request)) #24 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #25 
/Users/local/Sites/project/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(202): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #26 
/Users/local/Sites/project/web/app.php(20): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #27 
{main}

@nicolas-grekas
Copy link
Member

Are you sure you put that echo inside the "if"? The trace tells about key firstname.lastna..., but your report is about about email@address. Can you get a trace with the failing key also?

@dadepl
Copy link
Author
dadepl commented Feb 26, 2018

Yes, echo exception is within this if, before throwing InvalidArgumentException:
if (false !== strpbrk($key, '{}()/\@:')) {
echo new \Exception();
throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters {}()/\@:', $key));
}
Sorry for inconvenience, firstname.lastna is placeholder for my e-mail address that is visible in original stack trace.

@xabbuh
Copy link
Member
xabbuh commented Feb 26, 2018

For some reason, the metadata factory in the Validator component is called with an e-mail address which is then treated as a class name there. Would you be able to provide a small example application that allows to reproduce your issue?

@dadepl
Copy link
Author
dadepl commented Feb 26, 2018

Source code or as www?

@xabbuh
Copy link
Member
xabbuh commented Feb 26, 2018

The source code :) The best is a small application that you push to GitHub.

@dadepl
Copy link
Author
dadepl commented Feb 26, 2018

Repo, cut to minimum: https://github.com/dadepl/sfusertest
Install, create db and user account with fos:user:create and promote it to ROLE_ADMIN, go to /admin and then through link to user edit form. It gives me 500 when saving form and "reserved characters" exception in prod.log (dev env is ok).

@xabbuh
Copy link
Member
xabbuh commented Feb 26, 2018

Are you sure that you cleared the cache properly?

@dadepl
Copy link
Author
dadepl commented Feb 26, 2018

If by "properly" you mean running bin/console cache:clear --env=prod then yes, I have cleared the cache for both, prod and dev environments.
I have same cache exception results when running project online on shared hosting.
If this helps somehow, I'm running Apache localhost with php 7.1 on OSX.

@dmaicher
Copy link
Contributor
dmaicher commented Feb 26, 2018

@xabbuh could this be the problem?

https://github.com/dadepl/sfusertest/blob/master/src/Company/AppBundle/Entity/User.php#L40

So somehow it treats the email as an object and tries to get the metadata for it? 🙈

@dadepl what if you change that to @Assert\Email?

@dadepl
Copy link
Author
dadepl commented Feb 26, 2018

@dmaicher Thanks! It helped when I removed @Assert\Valid or changed it to @Assert\Email()!
Other case is I don't know why there was such behaviour and despite of that, I will have to investigate why I had such code in my entity file ;)

Thanks one more time!

@xabbuh
Copy link
Member
xabbuh commented Feb 26, 2018

@dmaicher Great catch 👍 not sure though why this didn't fail for me. So this does not look like an error in the Cache component, but we need to investigate why using the Valid constraint here doesn't fail earlier.

@dmaicher
Copy link
Contributor
dmaicher commented Feb 28, 2018

@xabbuh I checked a bit and actually here

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php#L717

The Validator just passes any scalar value and treats it as an object. So it tries to fetch the meta data here:

https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php#L328

And the value is then passed through to the Psr6Cache which is not properly escaping it?

@nicolas-grekas nicolas-grekas added Good first issue Ideal for your first contribution! (some Symfony experience may be required) Status: Reviewed and removed Status: Needs Review Status: Waiting feedback labels Apr 3, 2018
8000
@pmontoya
Copy link
pmontoya commented Apr 4, 2018

Maybe i could have a try for my first issue?

@xabbuh
Copy link
Member
xabbuh commented Apr 4, 2018

@pmontoya That would be great! 👍

@pmontoya
Copy link
pmontoya commented Apr 4, 2018

Ok, it's for me! 🤞

@stof
Copy link
Member
stof commented Apr 4, 2018

And the value is then passed through to the Psr6Cache which is not properly escaping it?

the escaping is done assuming the fact that metadata are loaded for a class name, which cannot contain a @.

but the class_exists check in the factory is done after trying to read from the cache rather than before:

if (!class_exists($class) && !interface_exists($class)) {

@dmaicher
Copy link
Contributor
dmaicher commented Apr 4, 2018

@stof indeed 👍 Should be fine to move this check before trying to retrieve something from the cache then

nicolas-grekas added a commit that referenced this issue Apr 9, 2018
…for non classname if tested values isn't existing class (Pascal Montoya, pmontoya)

This PR was merged into the 2.7 branch.

Discussion
----------

[Validator] Fix LazyLoadingMetadataFactory with PSR6Cache for non classname if tested values isn't existing class

| Q             | A
| ------------- | ---
| Branch?       | 2.7
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #26313
| License       | MIT

If @Assert\Valid is applied to a string value, the value is searched in metadata cache and some characters aren't allowed in this cache. This create an unexpected exception.

Class existence is now tested before cache read.

Commits
-------

5198f43 Disable autoloader call on interface_exists check
cd91420 [Validator] Fix LazyLoadingMetadataFactory with PSR6Cache for non classname if tested values isn't an existing class
@xabbuh xabbuh closed this as completed Apr 10, 2018
@abelardolg
Copy link
abelardolg commented May 5, 2022

This issue happens again.
This is my setup:

Symfony cli version 5.4.7

My composer.json contains:
"extra": {
"symfony": {
"allow-contrib": false,
"require": "4.4.*"
}
}

PHP Version: 7.4
OS Version: Windows 10 Home

The message is:
image

Cache and log dirs were deleted.

Point of my code where this error starts:
image

Point of my code where this message is showed:
image

How could I solve this issue, please?
This link https://github.com/dadepl/sfusertest/blob/master/src/Company/AppBundle/Entity/User.php#L40
is 404.

Best regards.

@xabbuh
Copy link
Member
xabbuh commented May 5, 2022

This is probably related to an update of Doctrine packages. You now need to access the repository using the FQCN instead of the alias like this:

$user = $em->getRepository(User::class)->findOneBy(['email' => $email);

@abelardolg
Copy link

Thanks, Christian. @xabbuh

< 5FBB /p>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Cache Good first issue Ideal for your first contribution! (some Symfony experience may be required) Status: Reviewed Validator
Projects
None yet
Development

No branches or pull requests

8 participants
0