From b83a98a13cf636d79c709e2f008529abdaf86f45 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 25 Oct 2019 14:37:11 +0200 Subject: [PATCH 1/2] Fix #78751: Serialising DatePeriod converts DateTimeImmutable When getting the properties of a DatePeriod instance we have to retain the proper classes, and when restoring a DatePeriod instance we have to cater to DateTimeImmutable instances as well. --- ext/date/php_date.c | 12 ++++++------ ext/date/tests/bug78751.phpt | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 ext/date/tests/bug78751.phpt diff --git a/ext/date/php_date.c b/ext/date/php_date.c index b76c4c9a7ed83..49302c3685ff5 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -5203,7 +5203,7 @@ static HashTable *date_object_get_properties_period(zval *object) /* {{{ */ if (period_obj->start) { php_date_obj *date_obj; - object_init_ex(&zv, date_ce_date); + object_init_ex(&zv, period_obj->start_ce); date_obj = Z_PHPDATE_P(&zv); date_obj->time = timelib_time_clone(period_obj->start); } else { @@ -5213,7 +5213,7 @@ static HashTable *date_object_get_properties_period(zval *object) /* {{{ */ if (period_obj->current) { php_date_obj *date_obj; - object_init_ex(&zv, date_ce_date); + object_init_ex(&zv, period_obj->start_ce); date_obj = Z_PHPDATE_P(&zv); date_obj->time = timelib_time_clone(period_obj->current); } else { @@ -5223,7 +5223,7 @@ static HashTable *date_object_get_properties_period(zval *object) /* {{{ */ if (period_obj->end) { php_date_obj *date_obj; - object_init_ex(&zv, date_ce_date); + object_init_ex(&zv, period_obj->start_ce); date_obj = Z_PHPDATE_P(&zv); date_obj->time = timelib_time_clone(period_obj->end); } else { @@ -5260,7 +5260,7 @@ static int php_date_period_initialize_from_hash(php_period_obj *period_obj, Hash ht_entry = zend_hash_str_find(myht, "start", sizeof("start")-1); if (ht_entry) { - if (Z_TYPE_P(ht_entry) == IS_OBJECT && Z_OBJCE_P(ht_entry) == date_ce_date) { + if (Z_TYPE_P(ht_entry) == IS_OBJECT && (Z_OBJCE_P(ht_entry) == date_ce_date || Z_OBJCE_P(ht_entry) == date_ce_immutable)) { php_date_obj *date_obj; date_obj = Z_PHPDATE_P(ht_entry); period_obj->start = timelib_time_clone(date_obj->time); @@ -5274,7 +5274,7 @@ static int php_date_period_initialize_from_hash(php_period_obj *period_obj, Hash ht_entry = zend_hash_str_find(myht, "end", sizeof("end")-1); if (ht_entry) { - if (Z_TYPE_P(ht_entry) == IS_OBJECT && Z_OBJCE_P(ht_entry) == date_ce_date) { + if (Z_TYPE_P(ht_entry) == IS_OBJECT && (Z_OBJCE_P(ht_entry) == date_ce_date || Z_OBJCE_P(ht_entry) == date_ce_immutable)) { php_date_obj *date_obj; date_obj = Z_PHPDATE_P(ht_entry); period_obj->end = timelib_time_clone(date_obj->time); @@ -5287,7 +5287,7 @@ static int php_date_period_initialize_from_hash(php_period_obj *period_obj, Hash ht_entry = zend_hash_str_find(myht, "current", sizeof("current")-1); if (ht_entry) { - if (Z_TYPE_P(ht_entry) == IS_OBJECT && Z_OBJCE_P(ht_entry) == date_ce_date) { + if (Z_TYPE_P(ht_entry) == IS_OBJECT && (Z_OBJCE_P(ht_entry) == date_ce_date || Z_OBJCE_P(ht_entry) == date_ce_immutable)) { php_date_obj *date_obj; date_obj = Z_PHPDATE_P(ht_entry); period_obj->current = timelib_time_clone(date_obj->time); diff --git a/ext/date/tests/bug78751.phpt b/ext/date/tests/bug78751.phpt new file mode 100644 index 0000000000000..6021b9f6aec80 --- /dev/null +++ b/ext/date/tests/bug78751.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #78751 (Serialising DatePeriod converts DateTimeImmutable) +--FILE-- +modify('+1 day')); +$oDays = unserialize(serialize($oDays)); +var_dump( + $oDays->start instanceof DateTimeImmutable, + $oDays->end instanceof DateTimeImmutable +); +?> +--EXPECT-- +bool(true) +bool(true) From accc53e476022d525fa0263edf04d354c6c85c65 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 25 Oct 2019 15:43:38 +0200 Subject: [PATCH 2/2] Generalize to DateTimeInterface check --- ext/date/php_date.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 49302c3685ff5..f049ae2526633 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -5260,7 +5260,7 @@ static int php_date_period_initialize_from_hash(php_period_obj *period_obj, Hash ht_entry = zend_hash_str_find(myht, "start", sizeof("start")-1); if (ht_entry) { - if (Z_TYPE_P(ht_entry) == IS_OBJECT && (Z_OBJCE_P(ht_entry) == date_ce_date || Z_OBJCE_P(ht_entry) == date_ce_immutable)) { + if (Z_TYPE_P(ht_entry) == IS_OBJECT && instanceof_function(Z_OBJCE_P(ht_entry), date_ce_interface)) { php_date_obj *date_obj; date_obj = Z_PHPDATE_P(ht_entry); period_obj->start = timelib_time_clone(date_obj->time); @@ -5274,7 +5274,7 @@ static int php_date_period_initialize_from_hash(php_period_obj *period_obj, Hash ht_entry = zend_hash_str_find(myht, "end", sizeof("end")-1); if (ht_entry) { - if (Z_TYPE_P(ht_entry) == IS_OBJECT && (Z_OBJCE_P(ht_entry) == date_ce_date || Z_OBJCE_P(ht_entry) == date_ce_immutable)) { + if (Z_TYPE_P(ht_entry) == IS_OBJECT && instanceof_function(Z_OBJCE_P(ht_entry), date_ce_interface)) { php_date_obj *date_obj; date_obj = Z_PHPDATE_P(ht_entry); period_obj->end = timelib_time_clone(date_obj->time); @@ -5287,7 +5287,7 @@ static int php_date_period_initialize_from_hash(php_period_obj *period_obj, Hash ht_entry = zend_hash_str_find(myht, "current", sizeof("current")-1); if (ht_entry) { - if (Z_TYPE_P(ht_entry) == IS_OBJECT && (Z_OBJCE_P(ht_entry) == date_ce_date || Z_OBJCE_P(ht_entry) == date_ce_immutable)) { + if (Z_TYPE_P(ht_entry) == IS_OBJECT && instanceof_function(Z_OBJCE_P(ht_entry), date_ce_interface)) { php_date_obj *date_obj; date_obj = Z_PHPDATE_P(ht_entry); period_obj->current = timelib_time_clone(date_obj->time);