Skip to content

Commit f49684f

Browse files
committed
Fix assertion failure when &__get forwards through initialized lazy proxy
1 parent 86a2c5b commit f49684f

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

Zend/tests/lazy_objects/gh20875.phpt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,6 @@ Warning: Undefined variable $a in %s on line %d
3131

3232
Warning: Undefined variable $v in %s on line %d
3333

34-
Notice: Indirect modification of overloaded property A::$b has no effect in %s on line %d
35-
36-
Warning: Undefined variable $x in %s on line %d
37-
38-
Notice: Object of class stdClass could not be converted to int in %s on line %d
39-
40-
Warning: Undefined variable $v in %s on line %d
41-
4234
Notice: Indirect modification of overloaded property A::$f has no effect in %s on line %d
4335

4436
Fatal error: Uncaught Error: Cannot assign by reference to overloaded object in %s:%d
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
GH-21478: No assertion failure when &__get forwards through initialized lazy proxy
3+
--FILE--
4+
<?php
5+
class Foo {
6+
public $_;
7+
8+
public function &__get($name) {
9+
global $proxy;
10+
printf("%s(\$%s) on %s\n", __METHOD__, $name, $this::class);
11+
return $proxy->{$name};
12+
}
13+
}
14+
15+
class Bar extends Foo {}
16+
17+
$rc = new ReflectionClass(Bar::class);
18+
$proxy = $rc->newLazyProxy(function () {
19+
echo "Init\n";
20+
return new Foo();
21+
});
22+
23+
$real = $rc->initializeLazyObject($proxy);
24+
$a = &$real->x;
25+
var_dump($a);
26+
?>
27+
--EXPECTF--
28+
Init
29+
Foo::__get($x) on Foo
30+
31+
Warning: Undefined property: Foo::$x in %s on line %d
32+
NULL

Zend/zend_object_handlers.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,12 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
898898
uint32_t guard_type = ((type == BP_VAR_IS) && zobj->ce->__isset)
899899
? IN_ISSET : IN_GET;
900900
if ((*instance_guard) & guard_type) {
901-
return zend_std_read_property(instance, name, type, cache_slot, rv);
901+
retval = zend_std_read_property(instance, name, type, cache_slot, rv);
902+
if (retval == &EG(uninitialized_zval)) {
903+
ZVAL_NULL(rv);
904+
retval = rv;
905+
}
906+
return retval;
902907
}
903908
}
904909
}

0 commit comments

Comments
 (0)