8000 minor #44122 [Serializer] fix reading unset properties (nicolas-grekas) · symfony/symfony@a598b82 · GitHub
[go: up one dir, main page]

Skip to content

Commit a598b82

Browse files
minor #44122 [Serializer] fix reading unset properties (nicolas-grekas)
This PR was merged into the 5. 10000 4 branch. Discussion ---------- [Serializer] fix reading unset properties | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | no | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Follows #44111 (comment) Commits ------- a86f586 [Serializer] fix reading unset properties
2 parents d81705f + a86f586 commit a598b82

File tree

3 files changed

+18
-28
lines changed

3 files changed

+18
-28
lines changed

src/Symfony/Component/PropertyAccess/PropertyAccessor.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,10 @@ private function readProperty(array $zval, string $property, bool $ignoreInvalid
470470
throw $e;
471471
}
472472
} elseif (PropertyReadInfo::TYPE_PROPERTY === $type) {
473+
if (!method_exists($object, '__get') && !\array_key_exists($name, (array) $object)) {
474+
throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not initialized.', $class, $name));
475+
}
476+
473477
$result[self::VALUE] = $object->$name;
474478

475479
if (isset($zval[self::REF]) && $access->canBeReference()) {

src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,6 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory
123123

124124
$this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] = array_merge($this->defaultContext[self::EXCLUDE_FROM_CACHE_KEY] ?? [], [self::CIRCULAR_REFERENCE_LIMIT_COUNTERS]);
125125

126-
if (\PHP_VERSION_ID >= 70400) {
127-
$this->defaultContext[self::SKIP_UNINITIALIZED_VALUES] = true;
128-
}
129-
130126
$this->propertyTypeExtractor = $propertyTypeExtractor;
131127

132128
if (null === $classDiscriminatorResolver && null !== $classMetadataFactory) {
@@ -194,12 +190,7 @@ public function normalize($object, string $format = null, array $context = [])
194190
try {
195191
$attributeValue = $this->getAttributeValue($object, $attribute, $format, $attributeContext);
196192
} catch (UninitializedPropertyException $e) {
197-
if ($this->shouldSkipUninitializedValues($context)) {
198-
continue;
199-
}
200-
throw $e;
201-
} catch (\Error $e) {
202-
if ($this->shouldSkipUninitializedValues($context) && $this->isUninitializedValueError($e)) {
193+
if ($context[self::SKIP_UNINITIALIZED_VALUES] ?? $this->defaultContext[self::SKIP_UNINITIALIZED_VALUES] ?? true) {
203194
continue;
204195
}
205196
throw $e;
@@ -733,22 +724,4 @@ private function getCacheKey(?string $format, array $context)
733724
return false;
734725
}
735726
}
736-
737-
private function shouldSkipUninitializedValues(array $context): bool
738-
{
739-
return $context[self::SKIP_UNINITIALIZED_VALUES]
740-
?? $this->defaultContext[self::SKIP_UNINITIALIZED_VALUES]
741-
?? false;
742-
}
743-
744-
/**
745-
* This error may occur when specific object normalizer implementation gets attribute value
746-
* by accessing a public uninitialized property or by calling a method accessing such property.
747-
*/
748-
private function isUninitializedValueError(\Error $e): bool
749-
{
750-
return \PHP_VERSION_ID >= 70400
751-
&& str_starts_with($e->getMessage(), 'Typed property')
752-
&& str_ends_with($e->getMessage(), 'must not be accessed before initialization');
753-
}
754727
}

src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\Serializer\Normalizer;
1313

14+
use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException;
15+
1416
/**
1517
* Converts between objects and arrays by mapping properties.
1618
*
@@ -131,6 +133,17 @@ protected function getAttributeValue(object $object, string $attribute, string $
131133
$reflectionProperty->setAccessible(true);
132134
}
133135

136+
if (!method_exists($object, '__get')) {
137+
$propertyValues = (array) $object;
138+
139+
if (($reflectionProperty->isPublic() && !\array_key_exists($reflectionProperty->name, $propertyValues))
140+
|| ($reflectionProperty->isProtected() && !\array_key_exists("\0*\0{$reflectionProperty->name}", $propertyValues))
141+
|| ($reflectionProperty->isPrivate() && !\array_key_exists("\0{$reflectionProperty->class}\0{$reflectionProperty->name}", $propertyValues))
142+
) {
143+
throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not initialized.', $reflectionProperty->class, $reflectionProperty->name));
144+
}
145+
}
146+
134147
return $reflectionProperty->getValue($object);
135148
}
136149

0 commit comments

Comments
 (0)
0