Fix lazy proxy calling magic methods twice#18039
Fix lazy proxy calling magic methods twice#18039arnaud-lb wants to merge 3 commits intophp:PHP-8.4from
Conversation
Zend/zend_object_handlers.c
Outdated
| && ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)); | ||
| } | ||
|
|
||
| static zend_always_inline zval *forward_write_to_lazy_object(zend_object *zobj, |
There was a problem hiding this comment.
I don't know if it's worth to always_inline this?
There was a problem hiding this comment.
Indeed, I will check if it makes a noticeable difference
There was a problem hiding this comment.
I've removed the always inline attribute
| var_dump($obj->prop); | ||
|
|
||
| ?> | ||
| --EXPECTF-- |
There was a problem hiding this comment.
I don't understand why the __get function should get called before instantiating the object? I.e. why does "C::__get" appear before "init"?
There was a problem hiding this comment.
It’s how lazy objects are supposed to behave: we interact primarily with the proxy (we execute the proxy’s code), but any access to its state is forwarded to the real instance.
So here we execute the getter, which tries to access a property. This triggers initialization before the access is forwarded.
There was a problem hiding this comment.
Okay I see, not what I intuitively expected but it makes sense
There was a problem hiding this comment.
I suppose there's also an implicit assumption here that the initialized properties does not contain dynamic properties. If it does, the initializer would need to be called before __get, to ensure that the property is actually still does not exist after the initializer has been called.
iluuu1994
left a comment
There was a problem hiding this comment.
I didn't find any other issues. If the aforementioned dynamic property behavior is correct, then this LGTM.
In GH-18039 we guard the underlying property before forwarding access to the real instance of a lazy proxy. When the real instance lacks magic methods, the assertion zobj->ce->ce_flags & ZEND_ACC_USE_GUARDS fails in zend_get_property_guard(). Fix by checking that the real instance uses guards. Fixes GH-20504 Closes GH-21093
…azy proxies zend_std_get_property_ptr_ptr() was the only property handler that did not propagate the IN_GET guard to the underlying object when forwarding from a lazy proxy after initialization. This caused __get to be called on the underlying object when it shouldn't be, leading to assertion failures. The same guard-copying pattern already existed in read_property, write_property, unset_property, and has_property since commit 26f5009 (phpGH-18039). Also fixes phpGH-20873 and phpGH-20854. Closes phpGH-20875
…azy proxies zend_std_get_property_ptr_ptr() was the only property handler that did not propagate the IN_GET guard to the underlying object when forwarding from a lazy proxy after initialization. This caused __get to be called on the underlying object when it shouldn't be, leading to assertion failures. The same guard-copying pattern already existed in read_property, write_property, unset_property, and has_property since commit 26f5009 (phpGH-18039). Also fixes phpGH-20873 and phpGH-20854. Closes phpGH-20875
… proxies zend_std_get_property_ptr_ptr() was the only property handler that did not propagate the IN_GET guard to the underlying object when forwarding from a lazy proxy after initialization. This caused __get to be called on the underlying object when it shouldn't be, leading to assertion failures. The same guard-copying pattern already existed in read_property, write_property, unset_property, and has_property since commit 26f5009 (GH-18039). Also fixes GH-20873 and GH-20854. Closes GH-20875
Fixes GH-18038.
Guard the underlying property, so that the forwarded operation accesses the property directly.