-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
allow_extra_attributes does not throw an exception as documented #26534
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
Conversation
Hey @deviantintegral! Thanks for the report. IIRC, this is not working because there is no metadata. Right now, I'm not sure if we can do something. |
We may throw if this flag is set but the metadata are not loaded. WDYT? |
Could be a solution indeed. Perhaps triggering a deprecation first and throwing on 5.0 if we fear this might break some apps (that would mean the flag wasn't working anyway and they didn't noticed, but an exception at runtime would be worse I think). @deviantintegral: Would you like to work on this ? |
I would throw directly. Relying on a non-functional behavior like this one can lead to security vulnerabilities. |
But I don't see any security vulnerability here. If the flag is set without metadata factory, no Anyway, I'm fine with both. |
I'd expected that something was reflecting the target class, and looking for public properties or set methods. If neither of those existed for a given property in the data being deserialized, then an Is there any reason why we couldn't instantiate a default metadata providing this behaviour, if |
Status: needs work |
I see I need to add the legacy annotations or methods for exception tests. I will do that tomorrow. One question; if I try to deserialize into a class that only has a private field specified, with no setter, it is not set, but no exception is thrown as it's still in the list of allowed attributes. Is there a decorator class I missed to do field access checks when reflecting the target class? |
</person> | ||
EOF; | ||
|
||
$encoders = array(new XmlEncoder()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for the xml encoder & serializer for this test. It's just about the object normalizer. See above one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I used the full ObjectNormalizer class as I think we need it's implementations to reasonably test this. Should it be copied in as a dummy class or left as is?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine with the ObjectNormalizer to me :)
// If additional attributes are not allowed, use a default class metadata factory to check against | ||
// properties and methods. | ||
if (isset($context[static::ALLOW_EXTRA_ATTRIBUTES]) && !$context[static::ALLOW_EXTRA_ATTRIBUTES]) { | ||
$this->classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An issue I see with this might be performances, as there is no cache on contrary of the CacheClassMetadataFactory
used on production. If that's only for a convenience exception, it's a free penalty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could default to an array cache, or we could leave it to the docs to say "if you are using allow_extra_attributes in production, consider caching the metadata factory". Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Array cache wouldn't be useful actually. ClassMetadataFactory
already has its own in memory cache. So the performances impact might not be really significant in most cases actually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's why I'm for throwing instead.
Everything else in the component works this way. If someone want to use this feature, it must register properly a metadata factory (and use a cached one as much as possible).
b4c6539
to
e70ee3c
Compare
Can someone rebuild the appveyor build? It threw Failed to decode response: zlib_decode(): data error 69 during composer update. |
@deviantintegral : Done. |
ping @ogizanagi @dunglas, any decision about throwing or not? |
Alright, considering #26534 (comment), let's throw. The documentation should also benefit from a PR. |
Perfect. |
The appveyor failure is in the Process component, so I'm guessing it's unrelated to this PR. This should be ready for another review. |
Something went wrong here. @deviantintegral Can you rebase on current 3.4? |
60d6562
to
4283e74
Compare
The test failures are from
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@deviantintegral : Could you also submit a PR to the symfony-docs repository?
Would be great IMHO to add a note block to hint about this.
@@ -205,6 +205,10 @@ protected function handleCircularReference($object) | |||
protected function getAllowedAttributes($classOrObject, array $context, $attributesAsString = false) | |||
{ | |||
if (!$this->classMetadataFactory) { | |||
if (isset($context[static::ALLOW_EXTRA_ATTRIBUTES]) && !$context[static::ALLOW_EXTRA_ATTRIBUTES]) { | |||
throw new LogicException('A class metadata factory must be provided in the constructor when setting ALLOW_EXTRA_ATTRIBUTES to false.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually should rather use the ALLOW_EXTRA_ATTRIBUTE
const value here I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is that constant defined? I don't see that anywhere in the project, at least on the 3.4 and 4.1 branches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean static::ALLOW_EXTRA_ATTRIBUTES
. the one used in the isset
above ^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I get it - the docs and so on don't use the class constant, but the actual lowercase string. I'll update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's why I asked for using the const value. Here you're mentioning the constant in the error message :)
(rebase needed) |
d878b4c
to
b594ad8
Compare
Docs PR filed at symfony/symfony-docs#9948 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @deviantintegral
@@ -208,7 +208,7 @@ protected function getAllowedAttributes($classOrObject, array $context, $attribu | |||
{ | |||
if (!$this->classMetadataFactory) { | |||
if (isset($context[static::ALLOW_EXTRA_ATTRIBUTES]) && !$context[static::ALLOW_EXTRA_ATTRIBUTES]) { | |||
throw new LogicException('A class metadata factory must be provided in the constructor when setting ALLOW_EXTRA_ATTRIBUTES to false.'); | |||
throw new LogicException(sprintf('A class metadata factory must be provided in the constructor when setting %s to false.', static::ALLOW_EXTRA_ATTRIBUTES)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps just wrapping the const value with double quotes
53283c4
to
a67b650
Compare
Thanks @deviantintegral. |
…mented (deviantintegral) This PR was squashed before being merged into the 3.4 branch (closes #26534). Discussion ---------- allow_extra_attributes does not throw an exception as documented | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | none | License | MIT | Doc PR | none The example at [Deserializing an object](https://symfony.com/doc/current/components/serializer.html#deserializing-an-object) does not actually work. It looks like this is a bug and not a docs issue. #24783 reported the same bug, but it looks like the fix at #24816 isn't complete. Here's a failing test that copies the existing example. Commits ------- a67b650 allow_extra_attributes does not throw an exception as documented
…al, javiereguiluz) This PR was submitted for the master branch but it was merged into the 3.4 branch instead (closes #9948). Discussion ---------- Document the required ClassMetadataFactory Symfony PR at symfony/symfony#26534 Commits ------- bc011c0 Reword b05c1cc Codefence ClassMetadataFactory a4cb67a Document the required ClassMetadataFactory
The example at Deserializing an object does not actually work. It looks like this is a bug and not a docs issue. #24783 reported the same bug, but it looks like the fix at #24816 isn't complete.
Here's a failing test that copies the existing example.