Closed
Description
Bug description: when using the built-in PropertyAccessor service, accessing an array property containing /
in its key throws an error.
Example
- in a standalone
bin/test.php
file, in a working Symfony instance
<?php
$loader = require __DIR__.'/../vendor/autoload.php';
$kernel = new AppKernel('dev', true);
$kernel->boot();
var_dump($kernel->getContainer()->get('property_accessor')->getValue(['a/b' => 'ok'], '[a/b]'));
- execution and stack
$ php bin/test.php
PHP Fatal error: Uncaught Symfony\Component\Cache\Exception\InvalidArgumentException: Cache key "p[a/b]" contains reserved characters {}()/\@: in /var/www/current/vendor/symfony/symfony/src/Symfony/Component/Cache/CacheItem.php:162
Stack trace:
#0 /var/www/current/vendor/symfony/symfony/src/Symfony/Component/Cache/Traits/ArrayTrait.php(45): Symfony\Component\Cache\CacheItem::validateKey('p[a/b]')
#1 /var/www/current/vendor/symfony/symfony/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php(56): Symfony\Component\Cache\Adapter\ArrayAdapter->hasItem('p[a/b]')
#2 /var/www/current/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php(875): Symfony\Component\Cache\Adapter\ArrayAdapter->getItem('p[a/b]')
#3 /var/www/current/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php(160): Symfony\Component\PropertyAccess\PropertyAccessor->getPropertyPath('[a/b]')
#4 /var/www/current/bin/test.php(8): Symfony\Component\PropertyAccess\PropertyAccessor->getValue(Array, '[a/b]')
#5 {main} in /var/www/current/vendor/symfony/symfony/src/Symfony/Component/Cache/CacheItem.php on line 162
Analysis
The PropertyAccessor component uses a standard PSR6 cache to increase it's performance, but the key is validated by Symfony\Component\Cache\CacheItem::validateKey
, and some characters are forbidden. The problem is that any of those characters are allowed as an array key (source). It means some properties can never be accessed through the property accessor.
As a quick workaround, we will disable the cache.
Side note: an empty array key is also not reachable (even if it's certainly a bad practice...)
Resolution proposals
- Hash the key (but should it be protected against collisions with a mapping ?)
- Catch the cache component error, add a warning and skip caching for those property (not ideal, but a quick and safe solution...)
- Find a way to escape those characters
Context
- Symfony 3.4
- PHP 7.2