Don't treat failed assignment as initialization

Only reset the uninitialized property flag once the type check
has succeeded. Previously the property was treated as unset rather
than uninitialized after a failed assignment.

Noticed this edge-case while working on accessors...
This commit is contained in:
Nikita Popov 2021-05-04 14:44:54 +02:00
parent 5ce0fa2129
commit 398cfb982e
2 changed files with 37 additions and 1 deletions

View File

@ -0,0 +1,36 @@
--TEST--
A failed assignment should not be considered an initialization
--FILE--
<?php
class Test {
public int $prop;
public function __get($name) {
echo "__get() called\n";
return 0;
}
}
$test = new Test;
try {
$test->prop;
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
$test->prop = "foo";
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
$test->prop;
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
?>
--EXPECT--
Typed property Test::$prop must not be accessed before initialization
Cannot assign string to property Test::$prop of type int
Typed property Test::$prop must not be accessed before initialization

View File

@ -728,7 +728,6 @@ found:
}
if (Z_PROP_FLAG_P(variable_ptr) == IS_PROP_UNINIT) {
/* Writes to uninitializde typed properties bypass __set(). */
Z_PROP_FLAG_P(variable_ptr) = 0;
goto write_std_property;
}
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
@ -783,6 +782,7 @@ write_std_property:
goto exit;
}
value = &tmp;
Z_PROP_FLAG_P(variable_ptr) = 0;
goto found; /* might have been updated via e.g. __toString() */
}