Skip to content

Commit a7d70c6

Browse files
committed
Protect against recursive instantiation
1 parent c4ac008 commit a7d70c6

File tree

2 files changed

+91
-4
lines changed

2 files changed

+91
-4
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
--TEST--
2+
new recursion in property default value
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public $test = new Test;
8+
}
9+
10+
try {
11+
new Test;
12+
} catch (Error $e) {
13+
echo $e->getMessage(), "\n";
14+
}
15+
16+
class Test2 {
17+
// Check property name unmangling.
18+
private $test = new Test2;
19+
}
20+
21+
try {
22+
new Test2;
23+
} catch (Error $e) {
24+
echo $e->getMessage(), "\n";
25+
}
26+
27+
// Check mutual recursion.
28+
class Test3 {
29+
public $test4 = new Test4;
30+
}
31+
class Test4 {
32+
public $test3 = new Test3;
33+
}
34+
35+
try {
36+
new Test3;
37+
} catch (Error $e) {
38+
echo $e->getMessage(), "\n";
39+
}
40+
try {
41+
new Test4;
42+
} catch (Error $e) {
43+
echo $e->getMessage(), "\n";
44+
}
45+
46+
// Mutual recursion through constructor.
47+
class Test5 {
48+
public $test6 = new Test6;
49+
}
50+
class Test6 {
51+
public function __construct() {
52+
new Test5;
53+
}
54+
}
55+
56+
try {
57+
new Test5;
58+
} catch (Error $e) {
59+
echo $e->getMessage(), "\n";
60+
}
61+
try {
62+
new Test6;
63+
} catch (Error $e) {
64+
echo $e->getMessage(), "\n";
65+
}
66+
67+
?>
68+
--EXPECT--
69+
Trying to recursively instantiate Test while evaluating default value for Test::$test
70+
Trying to recursively instantiate Test2 while evaluating default value for Test2::$test
71+
Trying to recursively instantiate Test3 while evaluating default value for Test3::$test4
72+
Trying to recursively instantiate Test4 while evaluating default value for Test4::$test3
73+
Trying to recursively instantiate Test5 while evaluating default value for Test5::$test6
74+
Trying to recursively instantiate Test5 while evaluating default value for Test5::$test6

Zend/zend_API.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,11 +1477,24 @@ static zend_always_inline zend_result _object_properties_init(zend_object *objec
14771477
ZVAL_COPY_PROP(dst, src);
14781478
if (Z_TYPE_P(dst) == IS_CONSTANT_AST) {
14791479
zend_property_info *prop_info = zend_get_property_info_for_slot(object, dst);
1480-
if (zval_update_constant_ex(dst, prop_info->ce) == FAILURE
1481-
|| (ZEND_TYPE_IS_SET(prop_info->type)
1482-
&& !zend_verify_property_type(prop_info, dst, /* strict */ 1))) {
1483-
zval_ptr_dtor_nogc(dst);
1480+
if (Z_EXTRA_P(src)) {
1481+
zend_throw_error(NULL,
1482+
"Trying to recursively instantiate %s "
1483+
"while evaluating default value for %s::$%s",
1484+
ZSTR_VAL(class_type->name), ZSTR_VAL(prop_info->ce->name),
1485+
zend_get_unmangled_property_name(prop_info->name));
1486+
goto failure;
1487+
}
1488+
1489+
Z_EXTRA_P(src) = 1;
1490+
zend_result result = zval_update_constant_ex(dst, prop_info->ce);
1491+
Z_EXTRA_P(src) = 0;
1492+
1493+
if (result == FAILURE || (ZEND_TYPE_IS_SET(prop_info->type)
1494+
&& !zend_verify_property_type(prop_info, dst, /* strict */ 1))) {
1495+
failure:
14841496
/* On failure, initialize the remaining properties with UNDEF. */
1497+
zval_ptr_dtor_nogc(dst);
14851498
do {
14861499
ZVAL_UNDEF(dst);
14871500
src++;

0 commit comments

Comments
 (0)