diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index df1c16754d..b4347c2009 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -508,7 +508,7 @@ class PropertyAccessor implements PropertyAccessorInterface */ private function getReadAccessInfo($class, $property) { - $key = (false !== strpos($class, '@') ? rawurlencode($class) : $class).'..'.$property; + $key = false !== strpbrk($key = $class.'..'.$property, '{}()/@:') ? rawurlencode($key) : $key; if (isset($this->readPropertyCache[$key])) { return $this->readPropertyCache[$key]; @@ -687,7 +687,7 @@ class PropertyAccessor implements PropertyAccessorInterface */ private function getWriteAccessInfo($class, $property, $value) { - $key = (false !== strpos($class, '@') ? rawurlencode($class) : $class).'..'.$property; + $key = false !== strpbrk($key = $class.'..'.$property, '{}()/@:') ? rawurlencode($key) : $key; if (isset($this->writePropertyCache[$key])) { return $this->writePropertyCache[$key]; @@ -868,7 +868,8 @@ class PropertyAccessor implements PropertyAccessorInterface } if ($this->cacheItemPool) { - $item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_PROPERTY_PATH.$propertyPath); + $key = false !== strpbrk($propertyPath, '{}()/@:') ? rawurlencode($propertyPath) : $propertyPath; + $item = $this->cacheItemPool->getItem(self::CACHE_PREFIX_PROPERTY_PATH.str_replace('\\', '.', $key)); if ($item->isHit()) { return $this->propertyPathCache[$propertyPath] = $item->get(); } diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index ef60e26dcd..8536a6615e 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -582,6 +582,15 @@ class PropertyAccessorTest extends TestCase $this->assertEquals('baz', $propertyAccessor->getValue($obj, 'publicGetSetter')); } + public function testAttributeWithSpecialChars() + { + $obj = new \stdClass(); + $obj->{'@foo'} = 'bar'; + + $propertyAccessor = new PropertyAccessor(false, false, new ArrayAdapter()); + $this->assertSame('bar', $propertyAccessor->getValue($obj, '@foo')); + } + /** * @expectedException \Symfony\Component\PropertyAccess\Exception\InvalidArgumentException * @expectedExceptionMessage Expected argument of type "Countable", "string" given