Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Serializer] Serializer tries to access initializer property when serializing a Doctrine Proxy object #44273

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

Closed
IonBazan opened this issue Nov 25, 2021 · 9 comments · Fixed by #44295

Comments

@IonBazan
Copy link
Contributor

IonBazan commented Nov 25, 2021

Symfony version(s) affected

5.3.11

Description

After upgrading symfony/serializer from 5.3.10 to 5.3.11 Seralizer starts to access special $initializer<id> property in proxies generated by Doctrine instead of letting the proxy initialize with actual objects.

How to reproduce

Edit: Use this repository to reproduce: https://github.com/IonBazan/serializer-proxy-bug

When Serializing a Doctrine ODM document with ReferenceMany or ReferenceOne, PropertyAccessor is trying to access a special $initializer<id> property.

Create 2 documents and make one of them reference the other. Now try to serialize the referencing document.
Following error should occur:

Undefined property: App\Domain\Document\Security\User::$initializer426f5 in /<redacted>/vendor/symfony/property-access/PropertyAccessor.php on line 473
ErrorException:
User Notice: Undefined property: App\Domain\Document\Security\User::$initializer426f5 in /<redacted>/vendor/symfony/property-access/PropertyAccessor.php on line 473

  at var/cache/dev/doctrine/odm/mongodb/Proxies/MongoDBODMProxies__PM__AppDomainDocumentSecurityUserGenerated0ca55a35e3ea298c1fbe2a3466d2e5dc.php:210
  at MongoDBODMProxies\__PM__\App\Domain\Document\Security\User\Generated0ca55a35e3ea298c1fbe2a3466d2e5dc->__get('initializer426f5')
     (vendor/symfony/property-access/PropertyAccessor.php:473)
  at Symfony\Component\PropertyAccess\PropertyAccessor->readProperty(array(object(Generated0ca55a35e3ea298c1fbe2a3466d2e5dc)), 'initializer426f5', false)
     (vendor/symfony/property-access/PropertyAccessor.php:154)
  at Symfony\Component\PropertyAccess\PropertyAccessor->getValue(object(Generated0ca55a35e3ea298c1fbe2a3466d2e5dc), 'initializer426f5')
     (vendor/symfony/serializer/Normalizer/ObjectNormalizer.php:148)
  at Symfony\Component\Serializer\Normalizer\ObjectNormalizer->getAttributeValue(object(Generated0ca55a35e3ea298c1fbe2a3466d2e5dc), 'initializer426f5', 'json', array('cache_key' => '8bae177454fb7ad4c74be899646036e2', 'circular_reference_limit_counters' => array('00000000046ab22e000000000059cf16' => 1, '00000000046a84a4000000000059cf16' => 1)))
     (vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:179)
  at Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->normalize(object(Generated0ca55a35e3ea298c1fbe2a3466d2e5dc), 'json', array('cache_key' => '8bae177454fb7ad4c74be899646036e2', 'circular_reference_limit_counters' => array('00000000046ab22e000000000059cf16' => 1, '00000000046a84a4000000000059cf16' => 1)))
     (vendor/symfony/serializer/Serializer.php:154)
  at Symfony\Component\Serializer\Serializer->normalize(object(Generated0ca55a35e3ea298c1fbe2a3466d2e5dc), 'json', array('cache_key' => '8bae177454fb7ad4c74be899646036e2', 'circular_reference_limit_counters' => array('00000000046ab22e000000000059cf16' => 1)))
     (vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:207)
  at Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer->normalize(object(Log), 'json', array('cache_key' => '8bae177454fb7ad4c74be899646036e2', 'circular_reference_limit_counters' => array('00000000046ab22e000000000059cf16' => 1)))
     (vendor/symfony/serializer/Serializer.php:154)
  at Symfony\Component\Serializer\Serializer->normalize(object(Log), 'json', array())
     (vendor/symfony/serializer/Serializer.php:168)
  at Symfony\Component\Serializer\Serializer->normalize(array(object(Log), object(Log), object(Log), object(Log), object(Log), object(Log), object(Log), object(Log), object(Log), object(Log)), 'json', array())
     (vendor/symfony/serializer/Serializer.php:127)
  at Symfony\Component\Serializer\Serializer->serialize(array(object(Log), object(Log), object(Log), object(Log), object(Log), object(Log), object(Log), object(Log), object(Log), object(Log)), 'json')
     (src/Http/Controller/DashboardController.php:20)
  at App\Http\Controller\DashboardController->__invoke(object(LogRepository), object(Serializer))
     (vendor/symfony/http-kernel/HttpKernel.php:156)
  at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:78)
  at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:199)
  at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
     (vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:37)
  at Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner->run()
     (vendor/autoload_runtime.php:35)

Possible Solution

No response

Additional Context

No response

@nicolas-grekas
Copy link
Member

Can you please try the following patch? Does it help?

--- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
+++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
@@ -470,6 +470,10 @@ class PropertyAccessor implements PropertyAccessorInterface
                         throw $e;
                     }
                 } elseif (PropertyReadInfo::TYPE_PROPERTY === $type) {
+                    if (!method_exists($object, '__get') && !\array_key_exists($name, (array) $object) && (\PHP_VERSION_ID < 70400 || !(new \ReflectionProperty($class, $name))->hasType())) {
+                        throw new UninitializedPropertyException(sprintf('The property "%s::$%s" is not initialized.', $class, $name));
+                    }
+
                     $result[self::VALUE] = $object->$name;
 
                     if (isset($zval[self::REF]) && $access->canBeReference()) {

@nicolas-grekas
Copy link
Member

Whether the patch fixes the issue or not, can you please try submitting a failing test case? That'd help a lot :)

@IonBazan
Copy link
Contributor Author

IonBazan commented Nov 25, 2021

This patch did not fix the issue. I will try to provide a minimal reproduceable test tomorrow.

Edit: I don't think PropertyAccessor causes that problem. It only occurs when I upgrade the Serializer component.

@IonBazan
Copy link
Contributor Author

While I'm working on the test case, I can confirm that reverting #44121 fixes the problem for me.

@IonBazan
Copy link
Contributor Author

It seems to be caused because calling __get on Doctrine Proxy checks for target object property existence:

if (! $realInstanceReflection->hasProperty($name)) {
            $targetObject = $this;

            $backtrace = debug_backtrace(false, 1);
            trigger_error(
                sprintf(
                    'Undefined property: %s::$%s in %s on line %s',
                    $realInstanceReflection->getName(),
                    $name,
                    $backtrace[0]['file'],
                    $backtrace[0]['line']
                ),
                \E_USER_NOTICE
            );
            return $targetObject->$name;
        }

I don't have any better idea than checking if object implements ProxyManager\Proxy\LazyLoadingInterface and triggering initialization there.

@IonBazan
Copy link
Contributor Author

@nicolas-grekas I created a minimal project to reproduce the error: https://github.com/IonBazan/serializer-proxy-bug

@nicolas-grekas
Copy link
Member

Thanks for the reproducer.
#44295 should fix it (for 4.4, 5.3 coming after merging up).

@nicolas-grekas nicolas-grekas linked a pull request Nov 26, 2021 that will close this issue
nicolas-grekas added a commit that referenced this issue Nov 28, 2021
…s-grekas)

This PR was merged into the 4.4 branch.

Discussion
----------

[Serializer] fix support for lazy/unset properties

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #44273 #44283
| License       | MIT
| Doc PR        | -

This basically backports #43469 into 4.4, which is the way to go to fix #44273.
The code that exists to handle uninitialized properties is broken anyway (it was before the recent changes.)

Commits
-------

db043aa [Serializer] fix support for lazy/unset properties
@cyildirim
Copy link

cyildirim commented Jul 22, 2023

I get the same error with 6.3.0 with MongoDB ODM while pulling Document with User associated with referenceOne. Do you mind if we reopen the issue or should i create new issue ? @nicolas-grekas

@xabbuh
Copy link
Member

xabbuh commented Nov 15, 2023

please open a new issue and provide an example application that allows to reproduce it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants