Fix GH-21478: Forward read_property to real instance for initialized lazy proxies#21480
Fix GH-21478: Forward read_property to real instance for initialized lazy proxies#21480iliaal wants to merge 1 commit intophp:masterfrom
Conversation
|
@arnaud-lb this is your area. |
|
Thank you @iliaal! Unfortunately this breaks the assumption that when interacting with a proxy, the proxy's code is executed instead of the real instance: class Foo {
private $_;
public function __get($name) {
echo __CLASS__, " ", $name, "\n";
echo $this->{$name};
}
}
class Bar extends Foo {
public function __get($name) {
echo __CLASS__, " ", $name, "\n";
echo $this->{$name};
}
}
$rc = new ReflectionClass(Bar::class);
$proxy = $rc->newLazyProxy(function () {
return new Foo();
});
$rc->initializeLazyObject($proxy);
$proxy->x;This should print "Bar x", but now this prints "Foo x". |
…ed lazy proxies For initialized lazy proxies, the proxy and real instance have separate magic method guard slots. When the real instance's __get/__isset is running and code inside it accesses the proxy, the proxy's guard is clear, causing __get/__isset to fire on the proxy too (double invocation). Check whether the real instance's guard is already set before invoking magic methods on the proxy. If it is, forward to the real instance (we're inside a recursive call). If not, the proxy was accessed directly and its own magic methods should run as normal.
83b7358 to
d68fcd8
Compare
|
Good catch, the unconditional forward was too broad. I've narrowed it: before calling Your example prints "Bar x" now. Added it as a test ( I also updated |
Summary
zend_std_read_property()was calling__get/__isseton an initialized lazy proxy before forwarding to the real instance. This produced double magic method invocations when the real instance's__getaccessed the proxy -- the proxy's own guard was clear, so__getfired on the proxy too.For pure reads (
BP_VAR_R,BP_VAR_IS), forward directly to the real instance before attempting magic methods on the proxy. Write contexts (BP_VAR_W/RW) are excluded sinceread_propertywith those types is a fallback fromget_property_ptr_ptrfor reference operations.Also updates
gh18038-004andgh18038-007test expectations to match -- these tests previously asserted the double-call behavior that GH-21478 reports as a bug.Fixes #21478