Skip to content

Commit a7f71aa

Browse files
Skip uninitialized typed properties when serializing objects
Partially reverts 846b647: instead of throwing, this skips uninitialized typed properties when serializing objects. This preserves the `unserialize(serialize($obj)) == $obj` identity. Fixes bug https://bugs.php.net/79447
1 parent 0a2fd0d commit a7f71aa

File tree

3 files changed

+20
-54
lines changed

3 files changed

+20
-54
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ PHP NEWS
66
- Core:
77
. Fixed bug #78434 (Generator yields no items after valid() call). (Nikita)
88
. Fixed bug #79477 (casting object into array creates references). (Nikita)
9+
. Fixed bug #79447 (Serializing uninitialized typed properties with __sleep should not throw). (nicolas-grekas)
910

1011
- DOM:
1112
. Fixed bug #78221 (DOMNode::normalize() doesn't remove empty text nodes).

ext/standard/tests/serialize/sleep_uninitialized_typed_prop.phpt

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Referencing an uninitialized typed property in __sleep() should result in Error
2+
Referencing an uninitialized typed property in __sleep() should be skipped
33
--FILE--
44
<?php
55

@@ -18,39 +18,27 @@ class Test {
1818
}
1919

2020
$t = new Test;
21-
try {
22-
serialize($t);
23-
} catch (Error $e) {
24-
echo $e->getMessage(), "\n";
25-
}
21+
var_dump(serialize($t));
22+
var_dump(unserialize(serialize($t)) == $t);
2623

2724
$t->x = 1;
28-
try {
29-
serialize($t);
30-
} catch (Error $e) {
31-
echo $e->getMessage(), "\n";
32-
}
25+
var_dump(unserialize(serialize($t)) == $t);
3326

3427
$t->y = 2;
35-
try {
36-
serialize($t);
37-
} catch (Error $e) {
38-
echo $e->getMessage(), "\n";
39-
}
28+
var_dump(unserialize(serialize($t)) == $t);
4029

4130
$t->z = 3;
42-
try {
43-
var_dump(unserialize(serialize($t)));
44-
} catch (Error $e) {
45-
echo $e->getMessage(), "\n";
46-
}
31+
var_dump(unserialize(serialize($t)) == $t);
4732

33+
var_dump($t);
4834
?>
4935
--EXPECT--
50-
Typed property Test::$x must not be accessed before initialization (in __sleep)
51-
Typed property Test::$y must not be accessed before initialization (in __sleep)
52-
Typed property Test::$z must not be accessed before initialization (in __sleep)
53-
object(Test)#3 (3) {
36+
string(15) "O:4:"Test":0:{}"
37+
bool(true)
38+
bool(true)
39+
bool(true)
40+
bool(true)
41+
object(Test)#1 (3) {
5442
["x"]=>
5543
int(1)
5644
["y":protected]=>

ext/standard/var.c

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -784,9 +784,7 @@ static int php_var_serialize_try_add_sleep_prop(
784784
if (Z_TYPE_P(val) == IS_UNDEF) {
785785
zend_property_info *info = zend_get_typed_property_info_for_slot(Z_OBJ_P(struc), val);
786786
if (info) {
787-
zend_throw_error(NULL,
788-
"Typed property %s::$%s must not be accessed before initialization (in __sleep)",
789-
ZSTR_VAL(Z_OBJCE_P(struc)->name), ZSTR_VAL(error_name));
787+
return SUCCESS;
790788
}
791789
return FAILURE;
792790
}
@@ -803,13 +801,12 @@ static int php_var_serialize_try_add_sleep_prop(
803801
}
804802
/* }}} */
805803

806-
static int php_var_serialize_get_sleep_props(
804+
static void php_var_serialize_get_sleep_props(
807805
HashTable *ht, zval *struc, HashTable *sleep_retval) /* {{{ */
808806
{
809807
zend_class_entry *ce = Z_OBJCE_P(struc);
810808
HashTable *props = zend_get_properties_for(struc, ZEND_PROP_PURPOSE_SERIALIZE);
811809
zval *name_val;
812-
int retval = SUCCESS;
813810

814811
zend_hash_init(ht, zend_hash_num_elements(sleep_retval), NULL, ZVAL_PTR_DTOR, 0);
815812
/* TODO: Rewrite this by fetching the property info instead of trying out different
@@ -829,12 +826,6 @@ static int php_var_serialize_get_sleep_props(
829826
continue;
830827
}
831828

832-
if (EG(exception)) {
833-
zend_tmp_string_release(tmp_name);
834-
retval = FAILURE;
835-
break;
836-
}
837-
838829
priv_name = zend_mangle_property_name(
839830
ZSTR_VAL(ce->name), ZSTR_LEN(ce->name),
840831
ZSTR_VAL(name), ZSTR_LEN(name), ce->type & ZEND_INTERNAL_CLASS);
@@ -845,12 +836,6 @@ static int php_var_serialize_get_sleep_props(
845836
}
846837
zend_string_release(priv_name);
847838

848-
if (EG(exception)) {
849-
zend_tmp_string_release(tmp_name);
850-
retval = FAILURE;
851-
break;
852-
}
853-
854839
prot_name = zend_mangle_property_name(
855840
"*", 1, ZSTR_VAL(name), ZSTR_LEN(name), ce->type & ZEND_INTERNAL_CLASS);
856841
if (php_var_serialize_try_add_sleep_prop(ht, props, prot_name, name, struc) == SUCCESS) {
@@ -860,20 +845,13 @@ static int php_var_serialize_get_sleep_props(
860845
}
861846
zend_string_release(prot_name);
862847

863-
if (EG(exception)) {
864-
zend_tmp_string_release(tmp_name);
865-
retval = FAILURE;
866-
break;
867-
}
868-
869848
php_error_docref(NULL, E_NOTICE,
870849
"\"%s\" returned as member variable from __sleep() but does not exist", ZSTR_VAL(name));
871850
zend_hash_add(ht, name, &EG(uninitialized_zval));
872851
zend_tmp_string_release(tmp_name);
873852
} ZEND_HASH_FOREACH_END();
874853

875854
zend_release_properties(props);
876-
return retval;
877855
}
878856
/* }}} */
879857

@@ -929,11 +907,10 @@ static void php_var_serialize_nested_data(smart_str *buf, zval *struc, HashTable
929907
static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_ptr, php_serialize_data_t var_hash) /* {{{ */
930908
{
931909
HashTable props;
932-
if (php_var_serialize_get_sleep_props(&props, struc, HASH_OF(retval_ptr)) == SUCCESS) {
933-
php_var_serialize_class_name(buf, struc);
934-
php_var_serialize_nested_data(
935-
buf, struc, &props, zend_hash_num_elements(&props), /* incomplete_class */ 0, var_hash);
936-
}
910+
php_var_serialize_get_sleep_props(&props, struc, HASH_OF(retval_ptr));
911+
php_var_serialize_class_name(buf, struc);
912+
php_var_serialize_nested_data(
913+
buf, struc, &props, zend_hash_num_elements(&props), /* incomplete_class */ 0, var_hash);
937914
zend_hash_destroy(&props);
938915
}
939916
/* }}} */

0 commit comments

Comments
 (0)