summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-12-09 08:41:43 +0100
committerNikita Popov <nikita.ppv@gmail.com>2019-12-09 08:42:34 +0100
commitded87a9ea0f12107031e6cac6c0299c1f87ff233 (patch)
tree2ded41bb4c694dd6dadfc70b628263fa2f0fd326
parent734932ecbbddf18109e5c60701b1dc8ab97fc88c (diff)
parent84354c62b37a56816a695b18ebd898f9703a9ad2 (diff)
downloadphp-git-ded87a9ea0f12107031e6cac6c0299c1f87ff233.tar.gz
Merge branch 'PHP-7.4'
* PHP-7.4: Fixed bug #78904: Don't call any magic for uninitialized typed properties
-rw-r--r--Zend/tests/type_declarations/typed_properties_040.phpt1
-rw-r--r--Zend/tests/type_declarations/typed_properties_072.phpt1
-rw-r--r--Zend/tests/type_declarations/typed_properties_073.phpt1
-rw-r--r--Zend/tests/type_declarations/typed_properties_074.phpt1
-rw-r--r--Zend/tests/type_declarations/typed_properties_magic_set.phpt19
-rw-r--r--Zend/zend_object_handlers.c17
6 files changed, 38 insertions, 2 deletions
diff --git a/Zend/tests/type_declarations/typed_properties_040.phpt b/Zend/tests/type_declarations/typed_properties_040.phpt
index 0b47c92a87..d1931c5a11 100644
--- a/Zend/tests/type_declarations/typed_properties_040.phpt
+++ b/Zend/tests/type_declarations/typed_properties_040.phpt
@@ -14,6 +14,7 @@ class Foo {
$foo = new Foo();
+unset($foo->bar);
var_dump($foo->bar);
?>
--EXPECTF--
diff --git a/Zend/tests/type_declarations/typed_properties_072.phpt b/Zend/tests/type_declarations/typed_properties_072.phpt
index b56c5d632e..13fab7177e 100644
--- a/Zend/tests/type_declarations/typed_properties_072.phpt
+++ b/Zend/tests/type_declarations/typed_properties_072.phpt
@@ -12,6 +12,7 @@ class Test {
}
$test = new Test;
+unset($test->val);
var_dump($test);
var_dump($test->val);
diff --git a/Zend/tests/type_declarations/typed_properties_073.phpt b/Zend/tests/type_declarations/typed_properties_073.phpt
index 7f9b4ff2de..43cb0f507b 100644
--- a/Zend/tests/type_declarations/typed_properties_073.phpt
+++ b/Zend/tests/type_declarations/typed_properties_073.phpt
@@ -13,6 +13,7 @@ class Test {
}
$test = new Test;
+unset($test->val);
var_dump($test);
var_dump($val = &$test->val);
var_dump($test);
diff --git a/Zend/tests/type_declarations/typed_properties_074.phpt b/Zend/tests/type_declarations/typed_properties_074.phpt
index 5a84435550..5759505707 100644
--- a/Zend/tests/type_declarations/typed_properties_074.phpt
+++ b/Zend/tests/type_declarations/typed_properties_074.phpt
@@ -14,6 +14,7 @@ class Test {
$test = new Test;
$dummyRef = &$test->prop;
+unset($test->val);
var_dump($test);
try {
var_dump($test->val);
diff --git a/Zend/tests/type_declarations/typed_properties_magic_set.phpt b/Zend/tests/type_declarations/typed_properties_magic_set.phpt
index fd101cf24d..70a7d4fe6f 100644
--- a/Zend/tests/type_declarations/typed_properties_magic_set.phpt
+++ b/Zend/tests/type_declarations/typed_properties_magic_set.phpt
@@ -5,12 +5,29 @@ __set() should not be invoked when setting an uninitialized typed property
class Test {
public int $foo;
+ public function __get($name) {
+ echo "__get ", $name, "\n";
+ return null;
+ }
public function __set($name, $value) {
echo "__set ", $name, " = ", $value, "\n";
}
+ public function __isset($name) {
+ echo "__isset ", $name, "\n";
+ return true;
+ }
+ public function __unset($name) {
+ echo "__unset ", $name, "\n";
+ }
}
$test = new Test;
+try {
+ var_dump($test->foo);
+} catch (Error $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump(isset($test->foo));
$test->foo = 42;
var_dump($test->foo);
@@ -44,6 +61,8 @@ $test->foo = 42;
?>
--EXPECT--
+Typed property Test::$foo must not be accessed before initialization
+bool(false)
int(42)
__set foo = 42
__set foo = 42
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 3b0bec45a5..668a1ef9d3 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -668,6 +668,10 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
goto exit;
}
+ if (UNEXPECTED(Z_PROP_FLAG_P(retval) == IS_PROP_UNINIT)) {
+ /* Skip __get() for uninitialized typed properties */
+ goto uninit_error;
+ }
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
if (EXPECTED(zobj->properties != NULL)) {
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(property_offset)) {
@@ -771,6 +775,7 @@ call_getter:
}
}
+uninit_error:
if (type != BP_VAR_IS) {
if (UNEXPECTED(prop_info)) {
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
}
return;
}
- /* Reset the IS_PROP_UNINIT flag, if it exists. */
- Z_PROP_FLAG_P(slot) = 0;
+ if (UNEXPECTED(Z_PROP_FLAG_P(slot) == IS_PROP_UNINIT)) {
+ /* Reset the IS_PROP_UNINIT flag, if it exists and bypass __unset(). */
+ Z_PROP_FLAG_P(slot) = 0;
+ return;
+ }
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))
&& EXPECTED(zobj->properties != NULL)) {
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
if (Z_TYPE_P(value) != IS_UNDEF) {
goto found;
}
+ if (UNEXPECTED(Z_PROP_FLAG_P(value) == IS_PROP_UNINIT)) {
+ /* Skip __isset() for uninitialized typed properties */
+ result = 0;
+ goto exit;
+ }
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
if (EXPECTED(zobj->properties != NULL)) {
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(property_offset)) {