Skip to content

Commit ded87a9

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Fixed bug #78904: Don't call any magic for uninitialized typed properties
2 parents 734932e + 84354c6 commit ded87a9

File tree

6 files changed

+38
-2
lines changed

6 files changed

+38
-2
lines changed

Zend/tests/type_declarations/typed_properties_040.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Foo {
1414

1515
$foo = new Foo();
1616

17+
unset($foo->bar);
1718
var_dump($foo->bar);
1819
?>
1920
--EXPECTF--

Zend/tests/type_declarations/typed_properties_072.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class Test {
1212
}
1313

1414
$test = new Test;
15+
unset($test->val);
1516
var_dump($test);
1617
var_dump($test->val);
1718

Zend/tests/type_declarations/typed_properties_073.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class Test {
1313
}
1414

1515
$test = new Test;
16+
unset($test->val);
1617
var_dump($test);
1718
var_dump($val = &$test->val);
1819
var_dump($test);

Zend/tests/type_declarations/typed_properties_074.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Test {
1414

1515
$test = new Test;
1616
$dummyRef = &$test->prop;
17+
unset($test->val);
1718
var_dump($test);
1819
try {
1920
var_dump($test->val);

Zend/tests/type_declarations/typed_properties_magic_set.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,29 @@ __set() should not be invoked when setting an uninitialized typed property
55

66
class Test {
77
public int $foo;
8+
public function __get($name) {
9+
echo "__get ", $name, "\n";
10+
return null;
11+
}
812
public function __set($name, $value) {
913
echo "__set ", $name, " = ", $value, "\n";
1014
}
15+
public function __isset($name) {
16+
echo "__isset ", $name, "\n";
17+
return true;
18+
}
19+
public function __unset($name) {
20+
echo "__unset ", $name, "\n";
21+
}
1122
}
1223

1324
$test = new Test;
25+
try {
26+
var_dump($test->foo);
27+
} catch (Error $e) {
28+
echo $e->getMessage(), "\n";
29+
}
30+
var_dump(isset($test->foo));
1431
$test->foo = 42;
1532
var_dump($test->foo);
1633

@@ -44,6 +61,8 @@ $test->foo = 42;
4461

4562
?>
4663
--EXPECT--
64+
Typed property Test::$foo must not be accessed before initialization
65+
bool(false)
4766
int(42)
4867
__set foo = 42
4968
__set foo = 42

Zend/zend_object_handlers.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,10 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
668668
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
669669
goto exit;
670670
}
671+
if (UNEXPECTED(Z_PROP_FLAG_P(retval) == IS_PROP_UNINIT)) {
672+
/* Skip __get() for uninitialized typed properties */
673+
goto uninit_error;
674+
}
671675
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
672676
if (EXPECTED(zobj->properties != NULL)) {
673677
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(property_offset)) {
@@ -771,6 +775,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
771775
}
772776
}
773777

778+
uninit_error:
774779
if (type != BP_VAR_IS) {
775780
if (UNEXPECTED(prop_info)) {
776781
zend_throw_error(NULL, "Typed property %s::$%s must not be accessed before initialization",
@@ -1085,8 +1090,11 @@ ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void
10851090
}
10861091
return;
10871092
}
1088-
/* Reset the IS_PROP_UNINIT flag, if it exists. */
1089-
Z_PROP_FLAG_P(slot) = 0;
1093+
if (UNEXPECTED(Z_PROP_FLAG_P(slot) == IS_PROP_UNINIT)) {
1094+
/* Reset the IS_PROP_UNINIT flag, if it exists and bypass __unset(). */
1095+
Z_PROP_FLAG_P(slot) = 0;
1096+
return;
1097+
}
10901098
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))
10911099
&& EXPECTED(zobj->properties != NULL)) {
10921100
if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
@@ -1674,6 +1682,11 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has
16741682
if (Z_TYPE_P(value) != IS_UNDEF) {
16751683
goto found;
16761684
}
1685+
if (UNEXPECTED(Z_PROP_FLAG_P(value) == IS_PROP_UNINIT)) {
1686+
/* Skip __isset() for uninitialized typed properties */
1687+
result = 0;
1688+
goto exit;
1689+
}
16771690
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
16781691
if (EXPECTED(zobj->properties != NULL)) {
16791692
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(property_offset)) {

0 commit comments

Comments
 (0)