. Fixed bug #78883 (fgets(STDIN) fails on Windows). (cmb)
. Fixed bug #78898 (call_user_func(['parent', ...]) fails while other
succeed). (Nikita)
+ . Fixed bug #78904 (Uninitialized property triggers __get()). (Nikita)
- GD:
. Fixed bug #78849 (GD build broken with -D SIGNED_COMPARE_SLOW). (cmb)
$foo = new Foo();
+unset($foo->bar);
var_dump($foo->bar);
?>
--EXPECTF--
string(3) "bar"
-Fatal error: Uncaught TypeError: Typed property Foo::$bar must be int, null used in %s:14
+Fatal error: Uncaught TypeError: Typed property Foo::$bar must be int, null used in %s:%d
Stack trace:
#0 {main}
- thrown in %s on line 14
+ thrown in %s on line %d
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);
?>
--EXPECT--
+Typed property Test::$foo must not be accessed before initialization
+bool(false)
int(42)
__set foo = 42
__set foo = 42
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)) {
}
}
+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",
}
goto exit;
}
- /* 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;
+ goto exit;
+ }
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))
&& EXPECTED(zobj->properties != NULL)) {
if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
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)) {