diff options
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)) { |