]> granicus.if.org Git - php/commitdiff
Migrate ext/date to get_properties_for where appropriate
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 4 Oct 2018 14:51:52 +0000 (16:51 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 10 Oct 2018 08:39:10 +0000 (10:39 +0200)
This resolves the long-standing issue where var_dump
a DateTime (etc) object makes a number of additional properties
accessible, which may also change other behaviors as a side-effect.

ext/date/php_date.c
ext/date/tests/DateTime_clone_basic3.phpt
ext/date/tests/bug52113.phpt
ext/date/tests/bug75232.phpt [new file with mode: 0644]

index c5f6a3ff0b701a1c324af6d1c7e8f3af0e17f719..13c950d096a1d50bdd35ee8c97f19b66d4856087 100644 (file)
@@ -667,12 +667,12 @@ static zend_object *date_object_clone_period(zval *this_ptr);
 
 static int date_object_compare_date(zval *d1, zval *d2);
 static HashTable *date_object_get_gc(zval *object, zval **table, int *n);
-static HashTable *date_object_get_properties(zval *object);
+static HashTable *date_object_get_properties_for(zval *object, zend_prop_purpose purpose);
 static HashTable *date_object_get_gc_interval(zval *object, zval **table, int *n);
 static HashTable *date_object_get_properties_interval(zval *object);
 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_properties_for_timezone(zval *object, zend_prop_purpose purpose);
 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);
 static void php_timezone_to_string(php_timezone_obj *tzobj, zval *zv);
@@ -2123,7 +2123,7 @@ static void date_register_classes(void) /* {{{ */
        date_object_handlers_date.free_obj = date_object_free_storage_date;
        date_object_handlers_date.clone_obj = date_object_clone_date;
        date_object_handlers_date.compare_objects = date_object_compare_date;
-       date_object_handlers_date.get_properties = date_object_get_properties;
+       date_object_handlers_date.get_properties_for = date_object_get_properties_for;
        date_object_handlers_date.get_gc = date_object_get_gc;
        zend_class_implements(date_ce_date, 1, date_ce_interface);
 
@@ -2133,7 +2133,7 @@ static void date_register_classes(void) /* {{{ */
        memcpy(&date_object_handlers_immutable, &std_object_handlers, sizeof(zend_object_handlers));
        date_object_handlers_immutable.clone_obj = date_object_clone_date;
        date_object_handlers_immutable.compare_objects = date_object_compare_date;
-       date_object_handlers_immutable.get_properties = date_object_get_properties;
+       date_object_handlers_immutable.get_properties_for = date_object_get_properties_for;
        date_object_handlers_immutable.get_gc = date_object_get_gc;
        zend_class_implements(date_ce_immutable, 1, date_ce_interface);
 
@@ -2144,7 +2144,7 @@ static void date_register_classes(void) /* {{{ */
        date_object_handlers_timezone.offset = XtOffsetOf(php_timezone_obj, std);
        date_object_handlers_timezone.free_obj = date_object_free_storage_timezone;
        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_properties_for = date_object_get_properties_for_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;
 
@@ -2273,17 +2273,24 @@ static HashTable *date_object_get_gc_timezone(zval *object, zval **table, int *n
        return zend_std_get_properties(object);
 } /* }}} */
 
-static HashTable *date_object_get_properties(zval *object) /* {{{ */
+static HashTable *date_object_get_properties_for(zval *object, zend_prop_purpose purpose) /* {{{ */
 {
        HashTable *props;
        zval zv;
-       php_date_obj     *dateobj;
+       php_date_obj *dateobj;
 
+       switch (purpose) {
+               case ZEND_PROP_PURPOSE_DEBUG:
+               case ZEND_PROP_PURPOSE_SERIALIZE:
+               case ZEND_PROP_PURPOSE_VAR_EXPORT:
+               case ZEND_PROP_PURPOSE_JSON:
+                       break;
+               default:
+                       return zend_std_get_properties_for(object, purpose);
+       }
 
        dateobj = Z_PHPDATE_P(object);
-
-       props = zend_std_get_properties(object);
-
+       props = zend_array_dup(zend_std_get_properties(object));
        if (!dateobj->time) {
                return props;
        }
@@ -2387,16 +2394,24 @@ static void php_timezone_to_string(php_timezone_obj *tzobj, zval *zv)
        }
 }
 
-static HashTable *date_object_get_properties_timezone(zval *object) /* {{{ */
+static HashTable *date_object_get_properties_for_timezone(zval *object, zend_prop_purpose purpose) /* {{{ */
 {
        HashTable *props;
        zval zv;
-       php_timezone_obj     *tzobj;
-
-       tzobj = Z_PHPTIMEZONE_P(object);
+       php_timezone_obj *tzobj;
 
-       props = zend_std_get_properties(object);
+       switch (purpose) {
+               case ZEND_PROP_PURPOSE_DEBUG:
+               case ZEND_PROP_PURPOSE_SERIALIZE:
+               case ZEND_PROP_PURPOSE_VAR_EXPORT:
+               case ZEND_PROP_PURPOSE_JSON:
+                       break;
+               default:
+                       return zend_std_get_properties_for(object, purpose);
+       }
 
+       tzobj = Z_PHPTIMEZONE_P(object);
+       props = zend_array_dup(zend_std_get_properties(object));
        if (!tzobj->initialized) {
                return props;
        }
@@ -2468,12 +2483,10 @@ static HashTable *date_object_get_properties_interval(zval *object) /* {{{ */
 {
        HashTable *props;
        zval zv;
-       php_interval_obj     *intervalobj;
+       php_interval_obj *intervalobj;
 
        intervalobj = Z_PHPINTERVAL_P(object);
-
        props = zend_std_get_properties(object);
-
        if (!intervalobj->initialized) {
                return props;
        }
@@ -5094,9 +5107,7 @@ static HashTable *date_object_get_properties_period(zval *object) /* {{{ */
        php_period_obj  *period_obj;
 
        period_obj = Z_PHPPERIOD_P(object);
-
        props = zend_std_get_properties(object);
-
        if (!period_obj->start) {
                return props;
        }
index f3d9c142fb51574437c1568021ac27aa690741ef..ac117958699e64b64a0c58fa0fcb5b3de6ab164f 100644 (file)
@@ -41,40 +41,34 @@ object(DateTime)#%d (3) {
 
 -- Add some properties --
 object(DateTime)#%d (5) {
-  ["date"]=>
-  string(26) "2009-02-03 12:34:41.000000"
-  ["timezone_type"]=>
-  int(2)
-  ["timezone"]=>
-  string(3) "GMT"
   ["property1"]=>
   int(99)
   ["property2"]=>
   string(5) "Hello"
-}
-
--- clone it --
-object(DateTime)#%d (5) {
   ["date"]=>
   string(26) "2009-02-03 12:34:41.000000"
   ["timezone_type"]=>
   int(2)
   ["timezone"]=>
   string(3) "GMT"
+}
+
+-- clone it --
+object(DateTime)#%d (5) {
   ["property1"]=>
   int(99)
   ["property2"]=>
   string(5) "Hello"
-}
-
--- Add some more properties --
-object(DateTime)#%d (7) {
   ["date"]=>
   string(26) "2009-02-03 12:34:41.000000"
   ["timezone_type"]=>
   int(2)
   ["timezone"]=>
   string(3) "GMT"
+}
+
+-- Add some more properties --
+object(DateTime)#%d (7) {
   ["property1"]=>
   int(99)
   ["property2"]=>
@@ -83,16 +77,16 @@ object(DateTime)#%d (7) {
   bool(true)
   ["property4"]=>
   float(10.5)
-}
-
--- clone it --
-object(DateTime)#%d (7) {
   ["date"]=>
   string(26) "2009-02-03 12:34:41.000000"
   ["timezone_type"]=>
   int(2)
   ["timezone"]=>
   string(3) "GMT"
+}
+
+-- clone it --
+object(DateTime)#%d (7) {
   ["property1"]=>
   int(99)
   ["property2"]=>
@@ -101,5 +95,11 @@ object(DateTime)#%d (7) {
   bool(true)
   ["property4"]=>
   float(10.5)
+  ["date"]=>
+  string(26) "2009-02-03 12:34:41.000000"
+  ["timezone_type"]=>
+  int(2)
+  ["timezone"]=>
+  string(3) "GMT"
 }
 ===DONE===
index dfc7d6112d3539a5636c549f2275b221b0e74b11..f6d0962625db4e94fbcea2970c3b9fa011caaa12 100644 (file)
@@ -32,8 +32,8 @@ $p = new DatePeriod($start, $diff_un, 2);
 var_dump($unser, $p);
 
 ?>
---EXPECT--
-object(DateInterval)#3 (16) {
+--EXPECTF--
+object(DateInterval)#%d (16) {
   ["y"]=>
   int(0)
   ["m"]=>
@@ -85,7 +85,7 @@ DateInterval::__set_state(array(
    'special_amount' => 0,
    'have_weekday_relative' => 0,
    'have_special_relative' => 0,
-))object(DateInterval)#5 (16) {
+))object(DateInterval)#%d (16) {
   ["y"]=>
   int(0)
   ["m"]=>
@@ -119,9 +119,9 @@ DateInterval::__set_state(array(
   ["have_special_relative"]=>
   int(0)
 }
-object(DatePeriod)#6 (6) {
+object(DatePeriod)#%d (6) {
   ["start"]=>
-  object(DateTime)#4 (3) {
+  object(DateTime)#%d (3) {
     ["date"]=>
     string(26) "2003-01-02 08:00:00.000000"
     ["timezone_type"]=>
@@ -134,7 +134,7 @@ object(DatePeriod)#6 (6) {
   ["end"]=>
   NULL
   ["interval"]=>
-  object(DateInterval)#7 (16) {
+  object(DateInterval)#%d (16) {
     ["y"]=>
     int(0)
     ["m"]=>
@@ -173,7 +173,7 @@ object(DatePeriod)#6 (6) {
   ["include_start_date"]=>
   bool(true)
 }
-object(DateInterval)#8 (16) {
+object(DateInterval)#%d (16) {
   ["y"]=>
   int(7)
   ["m"]=>
@@ -207,9 +207,9 @@ object(DateInterval)#8 (16) {
   ["have_special_relative"]=>
   int(0)
 }
-object(DatePeriod)#9 (6) {
+object(DatePeriod)#%d (6) {
   ["start"]=>
-  object(DateTime)#6 (3) {
+  object(DateTime)#%d (3) {
     ["date"]=>
     string(26) "2003-01-02 08:00:00.000000"
     ["timezone_type"]=>
@@ -222,7 +222,7 @@ object(DatePeriod)#9 (6) {
   ["end"]=>
   NULL
   ["interval"]=>
-  object(DateInterval)#7 (16) {
+  object(DateInterval)#%d (16) {
     ["y"]=>
     int(0)
     ["m"]=>
diff --git a/ext/date/tests/bug75232.phpt b/ext/date/tests/bug75232.phpt
new file mode 100644 (file)
index 0000000..2873bb9
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+Bug #75232: print_r of DateTime creating side-effect
+--FILE--
+<?php
+
+$d1 = DateTime::createFromFormat("Ymd\THis\Z", '20170920T091600Z');
+echo $d1->date, "\n";
+
+$d2 = DateTime::createFromFormat("Ymd\THis\Z", '20170920T091600Z');
+print_r($d2);
+echo $d2->date, "\n";
+
+?>
+--EXPECTF--
+Notice: Undefined property: DateTime::$date in %s on line %d
+
+DateTime Object
+(
+    [date] => 2017-09-20 09:16:00.000000
+    [timezone_type] => 3
+    [timezone] => UTC
+)
+
+Notice: Undefined property: DateTime::$date in %s on line %d