From 070211b3e3b2fc20247e761e3bf2a81b50b6e007 Mon Sep 17 00:00:00 2001 From: jhdxr Date: Fri, 22 Sep 2017 02:15:22 +0800 Subject: [PATCH] Fixed bug #68406 calling var_dump on a DateTimeZone object modifies it --- NEWS | 2 + ext/date/php_date.c | 41 +++++++++++++++++++ ext/date/tests/DateTimeZone_clone_basic3.phpt | 32 +++++++-------- ext/date/tests/bug68406.phpt | 34 +++++++++++++++ 4 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 ext/date/tests/bug68406.phpt diff --git a/NEWS b/NEWS index b1082fb1c6..0235d36d52 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS . Fixed bug #75857 (Timezone gets truncated when formatted). (carusogabriel) . Fixed bug #75928 (Argument 2 for `DateTimeZone::listIdentifiers()` should accept `null`). (Pedro Lacerda) + . Fixed bug #68406 (calling var_dump on a DateTimeZone object modifies it). + (jhdxr) - PGSQL: . Fixed #75838 (Memory leak in pg_escape_bytea()). (ard_1 at mail dot ru) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 277736505d..5b07f1e232 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -655,6 +655,7 @@ static HashTable *date_object_get_gc_period(zval *object, zval **table, int *n); static HashTable *date_object_get_properties_period(zval *object); static HashTable *date_object_get_properties_timezone(zval *object); static HashTable *date_object_get_gc_timezone(zval *object, zval **table, int *n); +static HashTable *date_object_get_debug_info_timezone(zval *object, int *is_temp); zval *date_interval_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv); void date_interval_write_property(zval *object, zval *member, zval *value, void **cache_slot); @@ -2100,6 +2101,7 @@ static void date_register_classes(void) /* {{{ */ date_object_handlers_timezone.clone_obj = date_object_clone_timezone; date_object_handlers_timezone.get_properties = date_object_get_properties_timezone; date_object_handlers_timezone.get_gc = date_object_get_gc_timezone; + date_object_handlers_timezone.get_debug_info = date_object_get_debug_info_timezone; #define REGISTER_TIMEZONE_CLASS_CONST_STRING(const_name, value) \ zend_declare_class_constant_long(date_ce_timezone, const_name, sizeof(const_name)-1, value); @@ -2377,6 +2379,45 @@ static HashTable *date_object_get_properties_timezone(zval *object) /* {{{ */ return props; } /* }}} */ +static HashTable *date_object_get_debug_info_timezone(zval *object, int *is_temp) /* {{{ */ +{ + HashTable *ht, *props; + zval zv; + php_timezone_obj *tzobj; + + tzobj = Z_PHPTIMEZONE_P(object); + props = zend_std_get_properties(object); + + *is_temp = 1; + ht = zend_array_dup(props); + + ZVAL_LONG(&zv, tzobj->type); + zend_hash_str_update(ht, "timezone_type", sizeof("timezone_type")-1, &zv); + + switch (tzobj->type) { + case TIMELIB_ZONETYPE_ID: + ZVAL_STRING(&zv, tzobj->tzi.tz->name); + break; + case TIMELIB_ZONETYPE_OFFSET: { + zend_string *tmpstr = zend_string_alloc(sizeof("UTC+05:00")-1, 0); + + ZSTR_LEN(tmpstr) = snprintf(ZSTR_VAL(tmpstr), sizeof("+05:00"), "%c%02d:%02d", + tzobj->tzi.utc_offset > 0 ? '-' : '+', + abs(tzobj->tzi.utc_offset / 60), + abs((tzobj->tzi.utc_offset % 60))); + + ZVAL_NEW_STR(&zv, tmpstr); + } + break; + case TIMELIB_ZONETYPE_ABBR: + ZVAL_STRING(&zv, tzobj->tzi.z.abbr); + break; + } + zend_hash_str_update(ht, "timezone", sizeof("timezone")-1, &zv); + + return ht; +} /* }}} */ + static inline zend_object *date_object_new_interval_ex(zend_class_entry *class_type, int init_props) /* {{{ */ { php_interval_obj *intern; diff --git a/ext/date/tests/DateTimeZone_clone_basic3.phpt b/ext/date/tests/DateTimeZone_clone_basic3.phpt index 128c8ff40b..f9be4e417e 100644 --- a/ext/date/tests/DateTimeZone_clone_basic3.phpt +++ b/ext/date/tests/DateTimeZone_clone_basic3.phpt @@ -39,34 +39,30 @@ object(DateTimeZone)#%d (2) { -- Add some properties -- object(DateTimeZone)#%d (4) { - ["timezone_type"]=> - int(3) - ["timezone"]=> - string(13) "Europe/London" ["property1"]=> int(99) ["property2"]=> string(5) "Hello" -} - --- clone it -- -object(DateTimeZone)#%d (4) { ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/London" +} + +-- clone it -- +object(DateTimeZone)#%d (4) { ["property1"]=> int(99) ["property2"]=> string(5) "Hello" -} - --- Add some more properties -- -object(DateTimeZone)#%d (6) { ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/London" +} + +-- Add some more properties -- +object(DateTimeZone)#%d (6) { ["property1"]=> int(99) ["property2"]=> @@ -75,14 +71,14 @@ object(DateTimeZone)#%d (6) { bool(true) ["property4"]=> float(10.5) -} - --- clone it -- -object(DateTimeZone)#%d (6) { ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/London" +} + +-- clone it -- +object(DateTimeZone)#%d (6) { ["property1"]=> int(99) ["property2"]=> @@ -91,5 +87,9 @@ object(DateTimeZone)#%d (6) { bool(true) ["property4"]=> float(10.5) + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/London" } ===DONE=== diff --git a/ext/date/tests/bug68406.phpt b/ext/date/tests/bug68406.phpt new file mode 100644 index 0000000000..a6a41c1078 --- /dev/null +++ b/ext/date/tests/bug68406.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #68406 calling var_dump on a DateTimeZone object modifies it +--INI-- +date.timezone=UTC +--FILE-- +getTimezone(), $tz2); + +if($tz2 == $d->getTimezone()) { + echo "yes"; +} +else { + echo "no"; +} + +--EXPECT-- +object(DateTimeZone)#4 (2) { + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/Berlin" +} +object(DateTimeZone)#2 (2) { + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/Berlin" +} +yes -- 2.49.0