]> granicus.if.org Git - php/commitdiff
Fix array access on undeclared properties in DateInterval
authorAnatol Belski <ab@php.net>
Mon, 9 Oct 2017 13:35:38 +0000 (15:35 +0200)
committerAnatol Belski <ab@php.net>
Mon, 9 Oct 2017 13:35:38 +0000 (15:35 +0200)
ext/date/php_date.c
ext/date/tests/date_interval_prop_dim.phpt [new file with mode: 0644]

index 00722d3c8e2399e7566204ed9373846998093907..f46167bf605f402d1e25819ace60c5b7602fbf76 100644 (file)
@@ -647,6 +647,7 @@ static HashTable *date_object_get_gc_timezone(zval *object, zval **table, int *n
 
 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);
+static zval *date_interval_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot);
 static zval *date_period_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv);
 static void date_period_write_property(zval *object, zval *member, zval *value, void **cache_slot);
 
@@ -2117,7 +2118,7 @@ static void date_register_classes(void) /* {{{ */
        date_object_handlers_interval.read_property = date_interval_read_property;
        date_object_handlers_interval.write_property = date_interval_write_property;
        date_object_handlers_interval.get_properties = date_object_get_properties_interval;
-       date_object_handlers_interval.get_property_ptr_ptr = NULL;
+       date_object_handlers_interval.get_property_ptr_ptr = date_interval_get_property_ptr_ptr;
        date_object_handlers_interval.get_gc = date_object_get_gc_interval;
 
        INIT_CLASS_ENTRY(ce_period, "DatePeriod", date_funcs_period);
@@ -4142,6 +4143,40 @@ void date_interval_write_property(zval *object, zval *member, zval *value, void
 }
 /* }}} */
 
+/* {{{ date_interval_get_property_ptr_ptr */
+static zval *date_interval_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot)
+{
+       zval tmp_member, *ret;
+
+       if (Z_TYPE_P(member) != IS_STRING) {
+               tmp_member = *member;
+               zval_copy_ctor(&tmp_member);
+               convert_to_string(&tmp_member);
+               member = &tmp_member;
+               cache_slot = NULL;
+       }
+
+       if(zend_binary_strcmp("y", sizeof("y") - 1, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0 ||
+               zend_binary_strcmp("m", sizeof("m") - 1, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0 ||
+               zend_binary_strcmp("d", sizeof("d") - 1, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0 ||
+               zend_binary_strcmp("h", sizeof("h") - 1, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0 ||
+               zend_binary_strcmp("i", sizeof("i") - 1, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0 ||
+               zend_binary_strcmp("s", sizeof("s") - 1, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0 ||
+               zend_binary_strcmp("days", sizeof("days") - 1, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0 ||
+               zend_binary_strcmp("invert", sizeof("invert") - 1, Z_STRVAL_P(member), Z_STRLEN_P(member)) == 0) {
+               /* Fallback to read_property. */
+               ret = NULL;
+       } else {
+               ret = (zend_get_std_object_handlers())->get_property_ptr_ptr(object, member, type, cache_slot);
+       }
+
+       if (member == &tmp_member) {
+               zval_dtor(member);
+       }
+
+       return ret;
+}
+/* }}} */
 
 /* {{{ proto DateInterval::__construct([string interval_spec])
    Creates new DateInterval object.
diff --git a/ext/date/tests/date_interval_prop_dim.phpt b/ext/date/tests/date_interval_prop_dim.phpt
new file mode 100644 (file)
index 0000000..3f9af6f
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+Test DateInterval props with dimension handling
+--FILE--
+<?php
+class Z extends DateInterval{}
+$z = new Z('P2Y4DT6H8M');
+$i = 0;
+$z->prop[1]=10;
+while ($i < 1026) {
+       $z->prop[$i] = $i;
+       $i++;
+}
+?>
+==NOCRASH==
+--EXPECT--
+==NOCRASH==