Partially reverts 846b647953: instead of
throwing, this skips uninitialized typed properties when serializing objects.

This makes serialize with __sleep() behave the same as serialize()
without __sleep().

As in the non-__sleep() case, unserialize(serialize($x)) identity
may not be preserved due to replacement of uninitialized/unset
properties with default values. Fixing this will require changes to
the serialization format.

Closes GH-5396.
This commit is contained in:
Nicolas Grekas 2020-04-16 00:11:38 +02:00 committed by Nikita Popov
parent c705079b12
commit 73d02c3b3e
3 changed files with 16 additions and 28 deletions

2
NEWS
View file

@ -40,6 +40,8 @@ PHP NEWS
- Standard:
. Fixed bug #79468 (SIGSEGV when closing stream handle with a stream filter
appended). (dinosaur)
. Fixed bug #79447 (Serializing uninitialized typed properties with __sleep
should not throw). (nicolas-grekas)
?? ??? ????, PHP 7.4.5

View file

@ -1,5 +1,5 @@
--TEST--
Referencing an uninitialized typed property in __sleep() should result in Error
Referencing an uninitialized typed property in __sleep() should be skipped
--FILE--
<?php
@ -18,39 +18,27 @@ class Test {
}
$t = new Test;
try {
serialize($t);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump(serialize($t));
var_dump(unserialize(serialize($t)) == $t);
$t->x = 1;
try {
serialize($t);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump(unserialize(serialize($t)) == $t);
$t->y = 2;
try {
serialize($t);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump(unserialize(serialize($t)) == $t);
$t->z = 3;
try {
var_dump(unserialize(serialize($t)));
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump(unserialize(serialize($t)) == $t);
var_dump($t);
?>
--EXPECT--
Typed property Test::$x must not be accessed before initialization (in __sleep)
Typed property Test::$y must not be accessed before initialization (in __sleep)
Typed property Test::$z must not be accessed before initialization (in __sleep)
object(Test)#3 (3) {
string(15) "O:4:"Test":0:{}"
bool(true)
bool(true)
bool(true)
bool(true)
object(Test)#1 (3) {
["x"]=>
int(1)
["y":protected]=>

View file

@ -784,9 +784,7 @@ static int php_var_serialize_try_add_sleep_prop(
if (Z_TYPE_P(val) == IS_UNDEF) {
zend_property_info *info = zend_get_typed_property_info_for_slot(Z_OBJ_P(struc), val);
if (info) {
zend_throw_error(NULL,
"Typed property %s::$%s must not be accessed before initialization (in __sleep)",
ZSTR_VAL(Z_OBJCE_P(struc)->name), ZSTR_VAL(error_name));
return SUCCESS;
}
return FAILURE;
}