Skip to content

Commit 211ddac

Browse files
committed
Backup value
1 parent d9d3ed1 commit 211ddac

File tree

3 files changed

+81
-15
lines changed

3 files changed

+81
-15
lines changed

Zend/tests/lazy_objects/gh15999.phpt renamed to Zend/tests/lazy_objects/gh15999_001.phpt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Lazy Objects: GH-15999: Object is released during initialization
2+
Lazy Objects: GH-15999 001: Object is released during initialization
33
--FILE--
44
<?php
55

@@ -18,9 +18,10 @@ $o = $r->newLazyGhost(function ($obj) {
1818
global $o;
1919
$o = null;
2020
});
21+
$p = new stdClass;
2122

2223
try {
23-
$o->s = $o;
24+
$o->s = $p;
2425
} catch (Error $e) {
2526
printf("%s: %s\n", $e::class, $e->getMessage());
2627
}
@@ -32,9 +33,10 @@ $o = $r->newLazyProxy(function ($obj) {
3233
$o = null;
3334
return new C();
3435
});
36+
$p = new stdClass;
3537

3638
try {
37-
$o->s = $o;
39+
$o->s = $p;
3840
} catch (Error $e) {
3941
printf("%s: %s\n", $e::class, $e->getMessage());
4042
}
@@ -47,8 +49,9 @@ $o = $r->newLazyGhost(function ($obj) {
4749
$o = null;
4850
gc_collect_cycles();
4951
});
52+
$p = new stdClass;
5053

51-
$o->s = $o;
54+
$o->s = $p;
5255
gc_collect_cycles();
5356

5457
print "# Nested error (ghost):\n";
@@ -60,9 +63,10 @@ $o = $r->newLazyGhost(function ($obj) {
6063
$o = null;
6164
return new stdClass;
6265
});
66+
$p = new stdClass;
6367

6468
try {
65-
$o->s = $o;
69+
$o->s = $p;
6670
} catch (Error $e) {
6771
do {
6872
printf("%s: %s\n", $e::class, $e->getMessage());
@@ -78,9 +82,10 @@ $o = $r->newLazyProxy(function ($obj) {
7882
$o = null;
7983
return new stdClass;
8084
});
85+
$p = new stdClass;
8186

8287
try {
83-
$o->s = $o;
88+
$o->s = $p;
8489
} catch (Error $e) {
8590
do {
8691
printf("%s: %s\n", $e::class, $e->getMessage());
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
Lazy Objects: GH-15999 002: Assigned value is changed during lazy object initialization
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public $s;
8+
public function __destruct() {
9+
var_dump(__METHOD__);
10+
}
11+
}
12+
13+
print "# Ghost:\n";
14+
15+
$r = new ReflectionClass(C::class);
16+
17+
$o = $r->newLazyGhost(function ($obj) {
18+
global $p;
19+
$p = null;
20+
});
21+
22+
$p = new stdClass;
23+
var_dump($o->s = $p);
24+
var_dump($o->s);
25+
26+
print "# Proxy:\n";
27+
28+
$r = new ReflectionClass(C::class);
29+
30+
$o = $r->newLazyProxy(function ($obj) {
31+
global $p;
32+
$p = null;
33+
return new C();
34+
});
35+
36+
$p = new stdClass;
37+
var_dump($o->s = $p);
38+
var_dump($o->s);
39+
40+
?>
41+
==DONE==
42+
--EXPECTF--
43+
# Ghost:
44+
object(stdClass)#%d (0) {
45+
}
46+
object(stdClass)#%d (0) {
47+
}
48+
# Proxy:
49+
string(13) "C::__destruct"
50+
object(stdClass)#%d (0) {
51+
}
52+
object(stdClass)#%d (0) {
53+
}
54+
==DONE==
55+
string(13) "C::__destruct"

Zend/zend_object_handlers.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,16 +1184,22 @@ found:;
11841184
return variable_ptr;
11851185

11861186
lazy_init:
1187-
zobj = zend_lazy_object_init(zobj);
1188-
if (UNEXPECTED(!zobj)) {
1189-
variable_ptr = &EG(error_zval);
1190-
goto exit;
1191-
}
1192-
/* value may have changed during initialization */
1193-
if (UNEXPECTED(Z_ISREF_P(value))) {
1194-
value = Z_REFVAL_P(value);
1187+
{
1188+
/* backup value as it may change during initialization */
1189+
zval backup;
1190+
ZVAL_COPY(&backup, value);
1191+
1192+
zobj = zend_lazy_object_init(zobj);
1193+
if (UNEXPECTED(!zobj)) {
1194+
variable_ptr = &EG(error_zval);
1195+
zval_ptr_dtor(&backup);
1196+
goto exit;
1197+
}
1198+
1199+
variable_ptr = zend_std_write_property(zobj, name, &backup, cache_slot);
1200+
zval_ptr_dtor(&backup);
1201+
return variable_ptr;
11951202
}
1196-
return zend_std_write_property(zobj, name, value, cache_slot);
11971203
}
11981204
/* }}} */
11991205

0 commit comments

Comments
 (0)