bug #20146 [Validator] Prevent infinite loop in PropertyMetadata (wesleylancel)

This PR was submitted for the master branch but it was merged into the 2.7 branch instead (closes #20146).

Discussion
----------

[Validator] Prevent infinite loop in PropertyMetadata

| Q             | A
| ------------- | ---
| Branch?       | 3.1
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |n/a
| License       | MIT
| Doc PR        | n/a

This commit fixes a possible infinite loop in PropertyMetadata when the PropertyMetadata class was constructed with an existing property of class and later used (after being serialized and cached) on that same class while that property no longer existing. `get_parent_class` will return false when there is no parent class and `property_existing` will then keeping return false causing the `while` loop to be infinite.

Commits
-------

c1ae7b6 Prevent infinite loop in PropertyMetadata
This commit is contained in:
Fabien Potencier 2016-10-13 07:00:51 -07:00
commit 705a4f7e91
2 changed files with 16 additions and 0 deletions

View File

@ -58,8 +58,14 @@ class PropertyMetadata extends MemberMetadata
*/
protected function newReflectionMember($objectOrClassName)
{
$originalClass = is_string($objectOrClassName) ? $objectOrClassName : get_class($objectOrClassName);
while (!property_exists($objectOrClassName, $this->getName())) {
$objectOrClassName = get_parent_class($objectOrClassName);
if (false === $objectOrClassName) {
throw new ValidatorException(sprintf('Property "%s" does not exist in class "%s"', $this->getName(), $originalClass));
}
}
$member = new \ReflectionProperty($objectOrClassName, $this->getName());

View File

@ -42,4 +42,14 @@ class PropertyMetadataTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($metadata->isPublic($entity));
$this->assertEquals('Overridden data', $metadata->getPropertyValue($entity));
}
public function testGetPropertyValueFromRemovedProperty()
{
$entity = new Entity('foobar');
$metadata = new PropertyMetadata(self::CLASSNAME, 'internal');
$metadata->name = 'test';
$this->setExpectedException('Symfony\Component\Validator\Exception\ValidatorException');
$metadata->getPropertyValue($entity);
}
}