diff options
Diffstat (limited to 'ext')
30 files changed, 1133 insertions, 100 deletions
diff --git a/ext/date/php_date.c b/ext/date/php_date.c index e27be7d81e..75bdf33121 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -39,6 +39,20 @@ static __inline __int64_t php_date_llabs( __int64_t i ) { return i >= 0 ? i : -i static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i; } #endif +#ifdef PHP_WIN32 +#define DATE_I64_BUF_LEN 65 +# define DATE_I64A(i, s, len) _i64toa_s(i, s, len, 10) +# define DATE_A64I(i, s) i = _atoi64(s) +#else +#define DATE_I64_BUF_LEN 65 +# define DATE_I64A(i, s, len) \ + do { \ + int st = snprintf(s, len, "%lld", i); \ + s[st] = '\0'; \ + } while (0); +# define DATE_A64I(i, s) i = atoll(s) +#endif + /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo_date, 0, 0, 1) ZEND_ARG_INFO(0, format) @@ -472,6 +486,8 @@ const zend_function_entry date_funcs_interval[] = { const zend_function_entry date_funcs_period[] = { PHP_ME(DatePeriod, __construct, arginfo_date_period_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC) + PHP_ME(DatePeriod, __wakeup, NULL, ZEND_ACC_PUBLIC) + PHP_ME(DatePeriod, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_FE_END }; @@ -565,9 +581,12 @@ static zend_object_value date_object_clone_period(zval *this_ptr TSRMLS_DC); static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC); static HashTable *date_object_get_properties(zval *object TSRMLS_DC); static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC); +static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC); zval *date_interval_read_property(zval *object, zval *member, int type TSRMLS_DC); void date_interval_write_property(zval *object, zval *member, zval *value TSRMLS_DC); +static zval *date_period_read_property(zval *object, zval *member, int type TSRMLS_DC); +static void date_period_write_property(zval *object, zval *member, zval *value TSRMLS_DC); /* {{{ Module struct */ zend_module_entry date_module_entry = { @@ -2015,6 +2034,10 @@ static void date_register_classes(TSRMLS_D) zend_class_implements(date_ce_period TSRMLS_CC, 1, zend_ce_traversable); memcpy(&date_object_handlers_period, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); date_object_handlers_period.clone_obj = date_object_clone_period; + date_object_handlers_period.get_properties = date_object_get_properties_period; + date_object_handlers_period.get_property_ptr_ptr = NULL; + date_object_handlers_period.read_property = date_period_read_property; + date_object_handlers_period.write_property = date_period_write_property; #define REGISTER_PERIOD_CLASS_CONST_STRING(const_name, value) \ zend_declare_class_constant_long(date_ce_period, const_name, sizeof(const_name)-1, value TSRMLS_CC); @@ -2250,7 +2273,6 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) zval *zv; php_interval_obj *intervalobj; - intervalobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC); props = zend_std_get_properties(object TSRMLS_CC); @@ -2261,7 +2283,7 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) #define PHP_DATE_INTERVAL_ADD_PROPERTY(n,f) \ MAKE_STD_ZVAL(zv); \ - ZVAL_LONG(zv, intervalobj->diff->f); \ + ZVAL_LONG(zv, (long)intervalobj->diff->f); \ zend_hash_update(props, n, strlen(n) + 1, &zv, sizeof(zval), NULL); PHP_DATE_INTERVAL_ADD_PROPERTY("y", y); @@ -2270,6 +2292,9 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) PHP_DATE_INTERVAL_ADD_PROPERTY("h", h); PHP_DATE_INTERVAL_ADD_PROPERTY("i", i); PHP_DATE_INTERVAL_ADD_PROPERTY("s", s); + PHP_DATE_INTERVAL_ADD_PROPERTY("weekday", weekday); + PHP_DATE_INTERVAL_ADD_PROPERTY("weekday_behavior", weekday_behavior); + PHP_DATE_INTERVAL_ADD_PROPERTY("first_last_day_of", first_last_day_of); PHP_DATE_INTERVAL_ADD_PROPERTY("invert", invert); if (intervalobj->diff->days != -99999) { PHP_DATE_INTERVAL_ADD_PROPERTY("days", days); @@ -2278,6 +2303,10 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC) ZVAL_FALSE(zv); zend_hash_update(props, "days", 5, &zv, sizeof(zval), NULL); } + PHP_DATE_INTERVAL_ADD_PROPERTY("special_type", special.type); + PHP_DATE_INTERVAL_ADD_PROPERTY("special_amount", special.amount); + PHP_DATE_INTERVAL_ADD_PROPERTY("have_weekday_relative", have_weekday_relative); + PHP_DATE_INTERVAL_ADD_PROPERTY("have_special_relative", have_special_relative); return props; } @@ -2380,6 +2409,7 @@ PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC) object_init_ex(object, pce); Z_SET_REFCOUNT_P(object, 1); Z_UNSET_ISREF_P(object); + return object; } @@ -3649,30 +3679,48 @@ PHP_METHOD(DateInterval, __construct) } /* }}} */ -static long php_date_long_from_hash_element(HashTable *myht, char *element, size_t size) -{ - zval **z_arg = NULL; - - if (zend_hash_find(myht, element, size + 1, (void**) &z_arg) == SUCCESS) { - convert_to_long(*z_arg); - return Z_LVAL_PP(z_arg); - } else { - return -1; - } -} static int php_date_interval_initialize_from_hash(zval **return_value, php_interval_obj **intobj, HashTable *myht TSRMLS_DC) { (*intobj)->diff = timelib_rel_time_ctor(); - (*intobj)->diff->y = php_date_long_from_hash_element(myht, "y", 1); - (*intobj)->diff->m = php_date_long_from_hash_element(myht, "m", 1); - (*intobj)->diff->d = php_date_long_from_hash_element(myht, "d", 1); - (*intobj)->diff->h = php_date_long_from_hash_element(myht, "h", 1); - (*intobj)->diff->i = php_date_long_from_hash_element(myht, "i", 1); - (*intobj)->diff->s = php_date_long_from_hash_element(myht, "s", 1); - (*intobj)->diff->invert = php_date_long_from_hash_element(myht, "invert", 6); - (*intobj)->diff->days = php_date_long_from_hash_element(myht, "days", 4); +#define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \ + do { \ + zval **z_arg = NULL; \ + if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \ + convert_to_long(*z_arg); \ + (*intobj)->diff->member = (itype)Z_LVAL_PP(z_arg); \ + } else { \ + (*intobj)->diff->member = (itype)def; \ + } \ + } while (0); + +#define PHP_DATE_INTERVAL_READ_PROPERTY_I64(element, member) \ + do { \ + zval **z_arg = NULL; \ + if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \ + convert_to_string(*z_arg); \ + DATE_A64I((*intobj)->diff->member, Z_STRVAL_PP(z_arg)); \ + } else { \ + (*intobj)->diff->member = -1LL; \ + } \ + } while (0); + + PHP_DATE_INTERVAL_READ_PROPERTY("y", y, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("m", m, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("d", d, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("h", h, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("i", i, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("s", s, timelib_sll, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("weekday", weekday, int, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("weekday_behavior", weekday_behavior, int, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("first_last_day_of", first_last_day_of, int, -1) + PHP_DATE_INTERVAL_READ_PROPERTY("invert", invert, int, 0); + PHP_DATE_INTERVAL_READ_PROPERTY_I64("days", days); + PHP_DATE_INTERVAL_READ_PROPERTY("special_type", special.type, unsigned int, 0); + PHP_DATE_INTERVAL_READ_PROPERTY_I64("special_amount", special.amount); + PHP_DATE_INTERVAL_READ_PROPERTY("have_weekday_relative", have_weekday_relative, unsigned int, 0); + PHP_DATE_INTERVAL_READ_PROPERTY("have_special_relative", have_special_relative, unsigned int, 0); (*intobj)->initialized = 1; return 0; @@ -4276,6 +4324,223 @@ PHP_FUNCTION(date_sun_info) timelib_time_dtor(t2); } /* }}} */ + + +static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC) +{ + HashTable *props; + zval *zv; + php_period_obj *period_obj; + + period_obj = zend_object_store_get_object(object TSRMLS_CC); + + props = zend_std_get_properties(object TSRMLS_CC); + + if (!period_obj->start) { + return props; + } + + MAKE_STD_ZVAL(zv); + if (period_obj->start) { + php_date_obj *date_obj; + object_init_ex(zv, date_ce_date); + date_obj = zend_object_store_get_object(zv TSRMLS_CC); + date_obj->time = timelib_time_clone(period_obj->start); + } else { + ZVAL_NULL(zv); + } + zend_hash_update(props, "start", sizeof("start"), &zv, sizeof(zv), NULL); + + MAKE_STD_ZVAL(zv); + if (period_obj->current) { + php_date_obj *date_obj; + object_init_ex(zv, date_ce_date); + date_obj = zend_object_store_get_object(zv TSRMLS_CC); + date_obj->time = timelib_time_clone(period_obj->current); + } else { + ZVAL_NULL(zv); + } + zend_hash_update(props, "current", sizeof("current"), &zv, sizeof(zv), NULL); + + MAKE_STD_ZVAL(zv); + if (period_obj->end) { + php_date_obj *date_obj; + object_init_ex(zv, date_ce_date); + date_obj = zend_object_store_get_object(zv TSRMLS_CC); + date_obj->time = timelib_time_clone(period_obj->end); + } else { + ZVAL_NULL(zv); + } + zend_hash_update(props, "end", sizeof("end"), &zv, sizeof(zv), NULL); + + MAKE_STD_ZVAL(zv); + if (period_obj->interval) { + php_interval_obj *interval_obj; + object_init_ex(zv, date_ce_interval); + interval_obj = zend_object_store_get_object(zv TSRMLS_CC); + interval_obj->diff = timelib_rel_time_clone(period_obj->interval); + interval_obj->initialized = 1; + } else { + ZVAL_NULL(zv); + } + zend_hash_update(props, "interval", sizeof("interval"), &zv, sizeof(zv), NULL); + + /* converted to larger type (int->long); must check when unserializing */ + MAKE_STD_ZVAL(zv); + ZVAL_LONG(zv, (long) period_obj->recurrences); + zend_hash_update(props, "recurrences", sizeof("recurrences"), &zv, sizeof(zv), NULL); + + MAKE_STD_ZVAL(zv); + ZVAL_BOOL(zv, period_obj->include_start_date); + zend_hash_update(props, "include_start_date", sizeof("include_start_date"), &zv, sizeof(zv), NULL); + + return props; +} + +static int php_date_period_initialize_from_hash(php_period_obj *period_obj, HashTable *myht TSRMLS_DC) +{ + zval **ht_entry; + + /* this function does no rollback on error */ + + if (zend_hash_find(myht, "start", sizeof("start"), (void**) &ht_entry) == SUCCESS) { + if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) { + php_date_obj *date_obj; + date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC); + period_obj->start = timelib_time_clone(date_obj->time); + } else if (Z_TYPE_PP(ht_entry) != IS_NULL) { + return 0; + } + } else { + return 0; + } + + if (zend_hash_find(myht, "end", sizeof("end"), (void**) &ht_entry) == SUCCESS) { + if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) { + php_date_obj *date_obj; + date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC); + period_obj->end = timelib_time_clone(date_obj->time); + } else if (Z_TYPE_PP(ht_entry) != IS_NULL) { + return 0; + } + } else { + return 0; + } + + if (zend_hash_find(myht, "current", sizeof("current"), (void**) &ht_entry) == SUCCESS) { + if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_date) { + php_date_obj *date_obj; + date_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC); + period_obj->current = timelib_time_clone(date_obj->time); + } else if (Z_TYPE_PP(ht_entry) != IS_NULL) { + return 0; + } + } else { + return 0; + } + + if (zend_hash_find(myht, "interval", sizeof("interval"), (void**) &ht_entry) == SUCCESS) { + if (Z_TYPE_PP(ht_entry) == IS_OBJECT && Z_OBJCE_PP(ht_entry) == date_ce_interval) { + php_interval_obj *interval_obj; + interval_obj = zend_object_store_get_object(*ht_entry TSRMLS_CC); + period_obj->interval = timelib_rel_time_clone(interval_obj->diff); + } else { /* interval is required */ + return 0; + } + } else { + return 0; + } + + if (zend_hash_find(myht, "recurrences", sizeof("recurrences"), (void**) &ht_entry) == SUCCESS && + Z_TYPE_PP(ht_entry) == IS_LONG && Z_LVAL_PP(ht_entry) >= 0 && Z_LVAL_PP(ht_entry) <= INT_MAX) { + period_obj->recurrences = Z_LVAL_PP(ht_entry); + } else { + return 0; + } + + if (zend_hash_find(myht, "include_start_date", sizeof("include_start_date"), (void**) &ht_entry) == SUCCESS && + Z_TYPE_PP(ht_entry) == IS_BOOL) { + period_obj->include_start_date = Z_BVAL_PP(ht_entry); + } else { + return 0; + } + + period_obj->initialized = 1; + + return 1; +} + +/* {{{ proto DatePeriod::__set_state() +*/ +PHP_METHOD(DatePeriod, __set_state) +{ + php_period_obj *period_obj; + zval *array; + HashTable *myht; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + RETURN_FALSE; + } + + myht = Z_ARRVAL_P(array); + + object_init_ex(return_value, date_ce_period); + period_obj = zend_object_store_get_object(return_value TSRMLS_CC); + if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) { + php_error(E_ERROR, "Invalid serialization data for DatePeriod object"); + } +} +/* }}} */ + +/* {{{ proto DatePeriod::__wakeup() +*/ +PHP_METHOD(DatePeriod, __wakeup) +{ + zval *object = getThis(); + php_period_obj *period_obj; + HashTable *myht; + + period_obj = zend_object_store_get_object(object TSRMLS_CC); + + myht = Z_OBJPROP_P(object); + + if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) { + php_error(E_ERROR, "Invalid serialization data for DatePeriod object"); + } +} +/* }}} */ + +/* {{{ date_period_read_property */ +static zval *date_period_read_property(zval *object, zval *member, int type TSRMLS_DC) +{ + zval *zv; + if (type != BP_VAR_IS && type != BP_VAR_R) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Retrieval of DatePeriod properties for modification is unsupported"); + } + + Z_OBJPROP_P(object); /* build properties hash table */ + + zv = std_object_handlers.read_property(object, member, type TSRMLS_CC); + if (Z_TYPE_P(zv) == IS_OBJECT && Z_OBJ_HANDLER_P(zv, clone_obj)) { + /* defensive copy */ + zend_object_value zov = Z_OBJ_HANDLER_P(zv, clone_obj)(zv TSRMLS_CC); + MAKE_STD_ZVAL(zv); + Z_TYPE_P(zv) = IS_OBJECT; + Z_OBJVAL_P(zv) = zov; + } + + return zv; +} +/* }}} */ + +/* {{{ date_period_write_property */ +static void date_period_write_property(zval *object, zval *member, zval *value TSRMLS_DC) +{ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Writing to DatePeriod properties is unsupported"); +} +/* }}} */ + + /* * Local variables: * tab-width: 4 diff --git a/ext/date/php_date.h b/ext/date/php_date.h index a86d6c7e70..16837df2a9 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -88,6 +88,8 @@ PHP_FUNCTION(date_interval_format); PHP_FUNCTION(date_interval_create_from_date_string); PHP_METHOD(DatePeriod, __construct); +PHP_METHOD(DatePeriod, __wakeup); +PHP_METHOD(DatePeriod, __set_state); /* Options and Configuration */ PHP_FUNCTION(date_default_timezone_set); diff --git a/ext/date/tests/bug45682.phpt b/ext/date/tests/bug45682.phpt index d8bbfc5a04..ea8fa94706 100644 --- a/ext/date/tests/bug45682.phpt +++ b/ext/date/tests/bug45682.phpt @@ -11,8 +11,8 @@ $other = new DateTime("31-July-2008"); $diff = date_diff($date, $other); var_dump($diff); ---EXPECT-- -object(DateInterval)#3 (8) { +--EXPECTF-- +object(DateInterval)#%d (15) { ["y"]=> int(0) ["m"]=> @@ -25,8 +25,22 @@ object(DateInterval)#3 (8) { int(0) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> int(3) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } diff --git a/ext/date/tests/bug48678.phpt b/ext/date/tests/bug48678.phpt index e2cb724f76..253cb84ce6 100644 --- a/ext/date/tests/bug48678.phpt +++ b/ext/date/tests/bug48678.phpt @@ -15,8 +15,15 @@ DateInterval Object [h] => 12 [i] => 30 [s] => 5 + [weekday] => 0 + [weekday_behavior] => 0 + [first_last_day_of] => 0 [invert] => 0 - [days] =>%s + [days] => + [special_type] => 0 + [special_amount] => 0 + [have_weekday_relative] => 0 + [have_special_relative] => 0 ) DateInterval Object ( @@ -26,6 +33,13 @@ DateInterval Object [h] => 12 [i] => 30 [s] => 5 + [weekday] => 0 + [weekday_behavior] => 0 + [first_last_day_of] => 0 [invert] => 0 - [days] =>%s + [days] => 0 + [special_type] => 0 + [special_amount] => 0 + [have_weekday_relative] => 0 + [have_special_relative] => 0 ) diff --git a/ext/date/tests/bug49081.phpt b/ext/date/tests/bug49081.phpt index f4f02903d1..31f7351481 100644 --- a/ext/date/tests/bug49081.phpt +++ b/ext/date/tests/bug49081.phpt @@ -17,6 +17,13 @@ DateInterval Object [h] => 4 [i] => 0 [s] => 0 + [weekday] => 0 + [weekday_behavior] => 0 + [first_last_day_of] => 0 [invert] => 0 [days] => 30 + [special_type] => 0 + [special_amount] => 0 + [have_weekday_relative] => 0 + [have_special_relative] => 0 ) diff --git a/ext/date/tests/bug49778.phpt b/ext/date/tests/bug49778.phpt index 67c8e27f91..2062d69168 100644 --- a/ext/date/tests/bug49778.phpt +++ b/ext/date/tests/bug49778.phpt @@ -8,7 +8,7 @@ echo $i->format("%d"), "\n"; echo $i->format("%a"), "\n"; ?> --EXPECT-- -object(DateInterval)#1 (8) { +object(DateInterval)#1 (15) { ["y"]=> int(0) ["m"]=> @@ -21,10 +21,24 @@ object(DateInterval)#1 (8) { int(0) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> bool(false) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } 7 (unknown) diff --git a/ext/date/tests/bug52113.phpt b/ext/date/tests/bug52113.phpt index a7d9339d13..f4730c6a44 100644 --- a/ext/date/tests/bug52113.phpt +++ b/ext/date/tests/bug52113.phpt @@ -32,7 +32,7 @@ var_dump($unser, $p); ?> --EXPECT-- -object(DateInterval)#3 (8) { +object(DateInterval)#3 (15) { ["y"]=> int(0) ["m"]=> @@ -45,12 +45,26 @@ object(DateInterval)#3 (8) { int(0) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> int(0) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } -string(128) "O:12:"DateInterval":8:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:6:"invert";i:0;s:4:"days";i:0;}" +string(320) "O:12:"DateInterval":15:{s:1:"y";i:0;s:1:"m";i:0;s:1:"d";i:0;s:1:"h";i:4;s:1:"i";i:0;s:1:"s";i:0;s:7:"weekday";i:0;s:16:"weekday_behavior";i:0;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";i:0;s:12:"special_type";i:0;s:14:"special_amount";i:0;s:21:"have_weekday_relative";i:0;s:21:"have_special_relative";i:0;}" DateInterval::__set_state(array( 'y' => 0, 'm' => 0, @@ -58,9 +72,16 @@ DateInterval::__set_state(array( 'h' => 4, 'i' => 0, 's' => 0, + 'weekday' => 0, + 'weekday_behavior' => 0, + 'first_last_day_of' => 0, 'invert' => 0, 'days' => 0, -))object(DateInterval)#5 (8) { + 'special_type' => 0, + 'special_amount' => 0, + 'have_weekday_relative' => 0, + 'have_special_relative' => 0, +))object(DateInterval)#5 (15) { ["y"]=> int(0) ["m"]=> @@ -73,14 +94,78 @@ DateInterval::__set_state(array( int(0) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> int(0) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } -object(DatePeriod)#6 (0) { +object(DatePeriod)#6 (6) { + ["start"]=> + object(DateTime)#4 (3) { + ["date"]=> + string(19) "2003-01-02 08:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#7 (15) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(0) + ["h"]=> + int(4) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(0) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) + } + ["recurrences"]=> + int(3) + ["include_start_date"]=> + bool(true) } -object(DateInterval)#4 (8) { +object(DateInterval)#8 (15) { ["y"]=> int(7) ["m"]=> @@ -93,10 +178,74 @@ object(DateInterval)#4 (8) { int(3) ["s"]=> int(2) + ["weekday"]=> + int(-1) + ["weekday_behavior"]=> + int(-1) + ["first_last_day_of"]=> + int(-1) ["invert"]=> int(1) ["days"]=> int(2400) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(-1) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } -object(DatePeriod)#7 (0) { +object(DatePeriod)#9 (6) { + ["start"]=> + object(DateTime)#6 (3) { + ["date"]=> + string(19) "2003-01-02 08:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["current"]=> + NULL + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#7 (15) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(0) + ["h"]=> + int(4) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(0) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) + } + ["recurrences"]=> + int(3) + ["include_start_date"]=> + bool(true) } diff --git a/ext/date/tests/bug52738.phpt b/ext/date/tests/bug52738.phpt index fc1b6029e9..ea219f7c7c 100644 --- a/ext/date/tests/bug52738.phpt +++ b/ext/date/tests/bug52738.phpt @@ -27,6 +27,13 @@ di Object [h] => 0 [i] => 0 [s] => 0 + [weekday] => 0 + [weekday_behavior] => 0 + [first_last_day_of] => 0 [invert] => 0 [days] => + [special_type] => 0 + [special_amount] => 0 + [have_weekday_relative] => 0 + [have_special_relative] => 0 ) diff --git a/ext/date/tests/bug52808.phpt b/ext/date/tests/bug52808.phpt index e031ac6ee3..1f0fc84cd7 100644 --- a/ext/date/tests/bug52808.phpt +++ b/ext/date/tests/bug52808.phpt @@ -25,7 +25,7 @@ foreach($intervals as $iv) { echo "==DONE==\n"; ?> --EXPECTF-- -object(DateInterval)#%d (8) { +object(DateInterval)#%d (15) { ["y"]=> int(1) ["m"]=> @@ -38,12 +38,26 @@ object(DateInterval)#%d (8) { int(30) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(1) ["days"]=> int(437) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } -object(DateInterval)#%d (8) { +object(DateInterval)#%d (15) { ["y"]=> int(0) ["m"]=> @@ -56,12 +70,26 @@ object(DateInterval)#%d (8) { int(30) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> int(294) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } -object(DateInterval)#%d (8) { +object(DateInterval)#%d (15) { ["y"]=> int(0) ["m"]=> @@ -74,10 +102,24 @@ object(DateInterval)#%d (8) { int(30) ["s"]=> int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> int(294) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } DateInterval::__construct(): Failed to parse interval (2007-05-11T15:30:00Z/) DateInterval::__construct(): Failed to parse interval (2007-05-11T15:30:00Z) diff --git a/ext/date/tests/bug53437.phpt b/ext/date/tests/bug53437.phpt index f089866538..2ea091453f 100644 --- a/ext/date/tests/bug53437.phpt +++ b/ext/date/tests/bug53437.phpt @@ -1,7 +1,5 @@ --TEST-- -Bug #53437 (Crash when using unserialized DatePeriod instance) ---XFAIL-- -Bug #53437 Not fixed yet +Bug #53437 (Crash when using unserialized DatePeriod instance), variation 1 --FILE-- <?php $dp = new DatePeriod(new DateTime('2010-01-01 UTC'), new DateInterval('P1D'), 2); @@ -20,9 +18,137 @@ $dpu = unserialize($ser); // $dpu has invalid values??? var_dump($dpu); echo "Unserialized:\r\n"; -// ???which leads to CRASH: foreach($dpu as $dt) { echo $dt->format('Y-m-d H:i:s')."\r\n"; } ?> +==DONE== --EXPECT-- +Original: +2010-01-01 00:00:00 +2010-01-02 00:00:00 +2010-01-03 00:00:00 + +object(DatePeriod)#1 (6) { + ["start"]=> + object(DateTime)#2 (3) { + ["date"]=> + string(19) "2010-01-01 00:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["current"]=> + object(DateTime)#4 (3) { + ["date"]=> + string(19) "2010-01-04 00:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#5 (15) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(1) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) + } + ["recurrences"]=> + int(3) + ["include_start_date"]=> + bool(true) +} +object(DatePeriod)#5 (6) { + ["start"]=> + object(DateTime)#10 (3) { + ["date"]=> + string(19) "2010-01-01 00:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["current"]=> + object(DateTime)#7 (3) { + ["date"]=> + string(19) "2010-01-04 00:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" + } + ["end"]=> + NULL + ["interval"]=> + object(DateInterval)#8 (15) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(1) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(0) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) + } + ["recurrences"]=> + int(3) + ["include_start_date"]=> + bool(true) +} +Unserialized: +2010-01-01 00:00:00 +2010-01-02 00:00:00 +2010-01-03 00:00:00 +==DONE== diff --git a/ext/date/tests/bug53437_var1.phpt b/ext/date/tests/bug53437_var1.phpt new file mode 100644 index 0000000000..f1f9843d5e --- /dev/null +++ b/ext/date/tests/bug53437_var1.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #53437 (Crash when using unserialized DatePeriod instance), variation 2 +--FILE-- +<?php +$s = 'O:10:"DatePeriod":0:{}'; + +$dp = unserialize($s); + +var_dump($dp); +?> +==DONE== +--EXPECTF-- +Fatal error: Invalid serialization data for DatePeriod object in %sbug53437_var1.php on line %d diff --git a/ext/date/tests/bug53437_var2.phpt b/ext/date/tests/bug53437_var2.phpt new file mode 100644 index 0000000000..50aebda57c --- /dev/null +++ b/ext/date/tests/bug53437_var2.phpt @@ -0,0 +1,80 @@ +--TEST-- +Bug #53437 DateInterval basic serialization +--FILE-- +<?php +$di0 = new DateInterval('P2Y4DT6H8M'); + +$s = serialize($di0); + +$di1 = unserialize($s); + +var_dump($di0, $di1); + +?> +==DONE== +--EXPECT-- +object(DateInterval)#1 (15) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(4) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + bool(false) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) +} +object(DateInterval)#2 (15) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(4) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(0) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) +} +==DONE== diff --git a/ext/date/tests/bug53437_var3.phpt b/ext/date/tests/bug53437_var3.phpt new file mode 100644 index 0000000000..82b90f559b --- /dev/null +++ b/ext/date/tests/bug53437_var3.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug #53437 DateInterval unserialize bad data, 32 bit +--SKIPIF-- +<?php if (PHP_INT_SIZE != 4) { die('skip 32 bit only'); } ?> +--FILE-- +<?php +$s = 'O:12:"DateInterval":15:{s:1:"y";s:1:"2";s:1:"m";s:1:"0";s:1:"d";s:3:"bla";s:1:"h";s:1:"6";s:1:"i";s:1:"8";s:1:"s";s:1:"0";s:7:"weekday";i:10;s:16:"weekday_behavior";i:10;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";s:4:"aoeu";s:12:"special_type";i:0;s:14:"special_amount";s:21:"234523452345234532455";s:21:"have_weekday_relative";i:21474836489;s:21:"have_special_relative";s:3:"bla";}'; + +$di = unserialize($s); +var_dump($di); + +?> +==DONE== +--EXPECTF-- +object(DateInterval)#%d (15) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(0) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["weekday"]=> + int(10) + ["weekday_behavior"]=> + int(10) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(0) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(-1) + ["have_weekday_relative"]=> + int(9) + ["have_special_relative"]=> + int(0) +} +==DONE== diff --git a/ext/date/tests/bug53437_var4.phpt b/ext/date/tests/bug53437_var4.phpt new file mode 100644 index 0000000000..88fd81c9db --- /dev/null +++ b/ext/date/tests/bug53437_var4.phpt @@ -0,0 +1,64 @@ +--TEST-- +Bug #53437 (Check that var_dump out is the same using the whole object or it's single properties), variation 4 +--INI-- +date.timezone = Europe/Berlin +--FILE-- +<?php +$dt = new DateTime('2009-10-11'); + +$df = $dt->diff(new DateTime('2009-10-13')); + +var_dump($df, + $df->y, + $df->m, + $df->d, + $df->h, + $df->i, + $df->s, + $df->invert, + $df->days); + +?> +==DONE== +--EXPECTF-- +object(DateInterval)#%d (15) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(2) + ["h"]=> + int(0) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(2) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) +} +int(0) +int(0) +int(2) +int(0) +int(0) +int(0) +int(0) +int(2) +==DONE== diff --git a/ext/date/tests/bug53437_var5.phpt b/ext/date/tests/bug53437_var5.phpt new file mode 100644 index 0000000000..e95fcdae96 --- /dev/null +++ b/ext/date/tests/bug53437_var5.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug #53437 DateInterval unserialize bad data, 64 bit +--SKIPIF-- +<?php if (PHP_INT_SIZE != 8) { die('skip true 64 bit only'); } ?> +--FILE-- +<?php +$s = 'O:12:"DateInterval":15:{s:1:"y";s:1:"2";s:1:"m";s:1:"0";s:1:"d";s:3:"bla";s:1:"h";s:1:"6";s:1:"i";s:1:"8";s:1:"s";s:1:"0";s:7:"weekday";i:10;s:16:"weekday_behavior";i:10;s:17:"first_last_day_of";i:0;s:6:"invert";i:0;s:4:"days";s:4:"aoeu";s:12:"special_type";i:0;s:14:"special_amount";s:21:"234523452345234532455";s:21:"have_weekday_relative";i:21474836489;s:21:"have_special_relative";s:3:"bla";}'; + +$di = unserialize($s); +var_dump($di); + +?> +==DONE== +--EXPECTF-- +object(DateInterval)#%d (15) { + ["y"]=> + int(2) + ["m"]=> + int(0) + ["d"]=> + int(0) + ["h"]=> + int(6) + ["i"]=> + int(8) + ["s"]=> + int(0) + ["weekday"]=> + int(10) + ["weekday_behavior"]=> + int(10) + ["first_last_day_of"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(0) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(9223372036854775807) + ["have_weekday_relative"]=> + int(9) + ["have_special_relative"]=> + int(0) +} +==DONE== diff --git a/ext/date/tests/date_diff1.phpt b/ext/date/tests/date_diff1.phpt index cf32fcbf3b..a908cdba75 100644 --- a/ext/date/tests/date_diff1.phpt +++ b/ext/date/tests/date_diff1.phpt @@ -28,7 +28,7 @@ object(DateTime)#2 (3) { ["timezone"]=> string(3) "EDT" } -object(DateInterval)#3 (8) { +object(DateInterval)#3 (15) { ["y"]=> int(0) ["m"]=> @@ -41,8 +41,22 @@ object(DateInterval)#3 (8) { int(19) ["s"]=> int(40) + ["weekday"]=> + int(0) + ["weekday_behavior"]=> + int(0) + ["first_last_day_of"]=> + int(0) ["invert"]=> int(0) ["days"]=> int(33) + ["special_type"]=> + int(0) + ["special_amount"]=> + int(0) + ["have_weekday_relative"]=> + int(0) + ["have_special_relative"]=> + int(0) } diff --git a/ext/pdo_pgsql/tests/copy_from.phpt b/ext/pdo_pgsql/tests/copy_from.phpt index 2858905d0c..10967b0fe9 100644 --- a/ext/pdo_pgsql/tests/copy_from.phpt +++ b/ext/pdo_pgsql/tests/copy_from.phpt @@ -110,8 +110,10 @@ $db->rollback(); echo "Exception! at line ", $e->getLine(), "\n"; var_dump($e->getMessage()); } -if(isset($filename)) { - @unlink($filename); + +// Clean up +foreach (array($filename, $filenameWithDifferentNullValues, $filenameWithDifferentNullValuesAndSelectedFields) as $f) { + @unlink($f); } ?> --EXPECT-- @@ -383,4 +385,4 @@ array(6) { NULL } Testing pgsqlCopyFromFile() with error -bool(false)
\ No newline at end of file +bool(false) diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index a0faed1424..c5d9a4ab1c 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -4875,7 +4875,7 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z } smart_str_appends(&querystr, - "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotNULL, a.atthasdef, a.attndims " + "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotnull, a.atthasdef, a.attndims, t.typtype = 'e' " "FROM pg_class as c, pg_attribute a, pg_type t, pg_namespace n " "WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '"); tmp_name2 = php_addslashes(tmp_name2, strlen(tmp_name2), &new_len, 0 TSRMLS_CC); @@ -4921,6 +4921,12 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z add_assoc_bool(elem, "has default", 0); } add_assoc_long(elem, "array dims", atoi(PQgetvalue(pg_result,i,6))); + if (!strcmp(PQgetvalue(pg_result,i,7), "t")) { + add_assoc_bool(elem, "is enum", 1); + } + else { + add_assoc_bool(elem, "is enum", 0); + } name = PQgetvalue(pg_result,i,0); add_assoc_zval(meta, name, elem); } @@ -4954,7 +4960,18 @@ PHP_FUNCTION(pg_meta_data) zval_dtor(return_value); /* destroy array */ RETURN_FALSE; } -} + else { + HashPosition pos; + zval **val; + + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(return_value), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_P(return_value), (void **)&val, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_P(return_value), &pos)) { + /* delete newly added entry, in order to keep BC */ + zend_hash_del_key_or_index(Z_ARRVAL_PP(val), "is enum", sizeof("is enum"), 0, HASH_DEL_KEY); + } + } +} /* }}} */ /* {{{ php_pgsql_get_data_type @@ -5136,8 +5153,9 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con char *field = NULL; uint field_len = -1; ulong num_idx = -1; - zval *meta, **def, **type, **not_null, **has_default, **val, *new_val; + zval *meta, **def, **type, **not_null, **has_default, **is_enum, **val, *new_val; int new_len, key_type, err = 0, skip_field; + php_pgsql_data_type data_type; assert(pg_link != NULL); assert(Z_TYPE_P(values) == IS_ARRAY); @@ -5188,17 +5206,30 @@ PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, con php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'has default'"); err = 1; } + if (!err && zend_hash_find(Z_ARRVAL_PP(def), "is enum", sizeof("is enum"), (void **)&is_enum) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'is enum'"); + err = 1; + } if (!err && (Z_TYPE_PP(val) == IS_ARRAY || Z_TYPE_PP(val) == IS_OBJECT || Z_TYPE_PP(val) == IS_CONSTANT_ARRAY)) { - php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scaler values as field values"); + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scalar values as field values"); err = 1; } if (err) { break; /* break out for() */ } ALLOC_INIT_ZVAL(new_val); - switch(php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type))) + + if (Z_BVAL_PP(is_enum)) { + /* enums need to be treated like strings */ + data_type = PG_TEXT; + } + else { + data_type = php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type)); + } + + switch(data_type) { case PG_BOOL: switch (Z_TYPE_PP(val)) { diff --git a/ext/pgsql/tests/10pg_convert_85.phpt b/ext/pgsql/tests/10pg_convert_85.phpt index 4f1c92bf1a..8b1cc8f538 100644 --- a/ext/pgsql/tests/10pg_convert_85.phpt +++ b/ext/pgsql/tests/10pg_convert_85.phpt @@ -12,6 +12,7 @@ error_reporting(E_ALL); include 'config.inc'; $db = pg_connect($conn_str); +pg_query($db, "SET standard_conforming_strings = 0"); $fields = array('num'=>'1234', 'str'=>'AAA', 'bin'=>'BBB'); $converted = pg_convert($db, $table_name, $fields); diff --git a/ext/pgsql/tests/12pg_insert_85.phpt b/ext/pgsql/tests/12pg_insert_85.phpt index a85dea0363..5fbbe4b7af 100644 --- a/ext/pgsql/tests/12pg_insert_85.phpt +++ b/ext/pgsql/tests/12pg_insert_85.phpt @@ -12,6 +12,8 @@ error_reporting(E_ALL); include 'config.inc'; $db = pg_connect($conn_str); +pg_query($db, "SET standard_conforming_strings = 0"); + $fields = array('num'=>'1234', 'str'=>'AAA', 'bin'=>'BBB'); pg_insert($db, $table_name, $fields) or print "Error in test 1\n"; diff --git a/ext/pgsql/tests/14pg_update_85.phpt b/ext/pgsql/tests/14pg_update_85.phpt index f1c77eac1d..06ca8c3de9 100644 --- a/ext/pgsql/tests/14pg_update_85.phpt +++ b/ext/pgsql/tests/14pg_update_85.phpt @@ -12,6 +12,8 @@ error_reporting(E_ALL); include 'config.inc'; $db = pg_connect($conn_str); +pg_query($db, "SET standard_conforming_strings = 0"); + $fields = array('num'=>'1234', 'str'=>'ABC', 'bin'=>'XYZ'); $ids = array('num'=>'1234'); diff --git a/ext/pgsql/tests/18pg_escape_bytea.phpt b/ext/pgsql/tests/18pg_escape_bytea.phpt index 43f98c4467..5f52a17d97 100644 --- a/ext/pgsql/tests/18pg_escape_bytea.phpt +++ b/ext/pgsql/tests/18pg_escape_bytea.phpt @@ -8,10 +8,11 @@ PostgreSQL pg_escape_bytea() functions include('config.inc'); +$db = pg_connect($conn_str); + $image = file_get_contents(dirname(__FILE__) . '/php.gif'); $esc_image = pg_escape_bytea($image); -$db = pg_connect($conn_str); pg_query($db, 'INSERT INTO '.$table_name.' (num, bin) VALUES (9876, \''.$esc_image.'\');'); $result = pg_query($db, 'SELECT * FROM '.$table_name.' WHERE num = 9876'); $rows = pg_fetch_all($result); diff --git a/ext/pgsql/tests/bug64609.phpt b/ext/pgsql/tests/bug64609.phpt new file mode 100644 index 0000000000..0df63012da --- /dev/null +++ b/ext/pgsql/tests/bug64609.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #64609 (pg_convert enum type support) +--SKIPIF-- +<?php +include("skipif.inc"); +skip_server_version('8.3', '<'); +?> +--FILE-- +<?php +error_reporting(E_ALL); + +include 'config.inc'; + +$db = pg_connect($conn_str); +pg_query("BEGIN"); +pg_query("CREATE TYPE t_enum AS ENUM ('ok', 'ko')"); +pg_query("CREATE TABLE test_enum (a t_enum)"); + +$fields = array('a' => 'ok'); +$converted = pg_convert($db, 'test_enum', $fields); + +pg_query("ROLLBACK"); + +var_dump($converted); +?> +--EXPECT-- +array(1) { + ["a"]=> + string(4) "'ok'" +} diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 91f7c8eb7b..cd0af8fbc5 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -1025,12 +1025,12 @@ static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object * obje zend_replace_error_handling(EH_THROW, spl_ce_UnexpectedValueException, &error_handling TSRMLS_CC); if (data && *data) { RETVAL_ZVAL(*data, 1, 0); - } - if (Z_TYPE_P(return_value) == IS_ARRAY) { - zval_dtor(return_value); - ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1, 1); - } else { - convert_to_string(return_value); + if (Z_TYPE_P(return_value) == IS_ARRAY) { + zval_dtor(return_value); + ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1, 1); + } else { + convert_to_string(return_value); + } } zend_restore_error_handling(&error_handling TSRMLS_CC); } @@ -1131,8 +1131,15 @@ SPL_METHOD(RecursiveTreeIterator, current) } } + INIT_ZVAL(prefix); + INIT_ZVAL(entry); spl_recursive_tree_iterator_get_prefix(object, &prefix TSRMLS_CC); spl_recursive_tree_iterator_get_entry(object, &entry TSRMLS_CC); + if (Z_TYPE(entry) != IS_STRING) { + zval_dtor(&prefix); + zval_dtor(&entry); + RETURN_NULL(); + } spl_recursive_tree_iterator_get_postfix(object, &postfix TSRMLS_CC); str_len = Z_STRLEN(prefix) + Z_STRLEN(entry) + Z_STRLEN(postfix); diff --git a/ext/standard/browscap.c b/ext/standard/browscap.c index 60949fc352..343ad2051c 100644 --- a/ext/standard/browscap.c +++ b/ext/standard/browscap.c @@ -451,6 +451,19 @@ static int browser_reg_compare(zval **browser TSRMLS_DC, int num_args, va_list a } /* }}} */ +static void browscap_zval_copy_ctor(zval **p) /* {{{ */ +{ + zval *new; + + ALLOC_ZVAL(new); + *new = **p; + + zval_copy_ctor(new); + + INIT_PZVAL(new); + *p = new; +} /* }}} */ + /* {{{ proto mixed get_browser([string browser_name [, bool return_array]]) Get information about the capabilities of a browser. If browser_name is omitted or null, HTTP_USER_AGENT is used. Returns an object by default; if return_array is true, returns an array. */ PHP_FUNCTION(get_browser) @@ -511,11 +524,11 @@ PHP_FUNCTION(get_browser) if (return_array) { array_init(return_value); - zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); + zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) browscap_zval_copy_ctor, (void *) &tmp_copy, sizeof(zval *)); } else { object_init(return_value); - zend_hash_copy(Z_OBJPROP_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); + zend_hash_copy(Z_OBJPROP_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) browscap_zval_copy_ctor, (void *) &tmp_copy, sizeof(zval *)); } while (zend_hash_find(Z_ARRVAL_PP(agent), "parent", sizeof("parent"), (void **) &z_agent_name) == SUCCESS) { @@ -524,10 +537,10 @@ PHP_FUNCTION(get_browser) } if (return_array) { - zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *), 0); + zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) browscap_zval_copy_ctor, (void *) &tmp_copy, sizeof(zval *), 0); } else { - zend_hash_merge(Z_OBJPROP_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *), 0); + zend_hash_merge(Z_OBJPROP_P(return_value), Z_ARRVAL_PP(agent), (copy_ctor_func_t) browscap_zval_copy_ctor, (void *) &tmp_copy, sizeof(zval *), 0); } } diff --git a/ext/standard/quot_print.c b/ext/standard/quot_print.c index 280b86a9a2..6627858989 100644 --- a/ext/standard/quot_print.c +++ b/ext/standard/quot_print.c @@ -151,7 +151,7 @@ PHPAPI unsigned char *php_quot_print_encode(const unsigned char *str, size_t len unsigned char c, *ret, *d; char *hex = "0123456789ABCDEF"; - ret = safe_emalloc(1, 3 * length + 3 * (((3 * length)/PHP_QPRINT_MAXL) + 1), 0); + ret = safe_emalloc(3, length + (((3 * length)/(PHP_QPRINT_MAXL-9)) + 1), 1); d = ret; while (length--) { diff --git a/ext/standard/tests/array/bug31158.phpt b/ext/standard/tests/array/bug31158.phpt index e672a10b28..da7a9ec907 100644 --- a/ext/standard/tests/array/bug31158.phpt +++ b/ext/standard/tests/array/bug31158.phpt @@ -1,5 +1,7 @@ --TEST-- Bug #31158 (array_splice on $GLOBALS crashes) +--INI-- +error_reporting = E_ALL --FILE-- <?php function __(){ diff --git a/ext/standard/tests/strings/bug64879.phpt b/ext/standard/tests/strings/bug64879.phpt new file mode 100644 index 0000000000..1df90c6d85 --- /dev/null +++ b/ext/standard/tests/strings/bug64879.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #64879: quoted_printable_encode() wrong size calculation (CVE-2013-2110) +--FILE-- +<?php + +quoted_printable_encode(str_repeat("\xf4", 1000)); +quoted_printable_encode(str_repeat("\xf4", 100000)); + +echo "Done\n"; +?> +--EXPECTF-- +Done diff --git a/ext/xml/tests/bug65236.phpt b/ext/xml/tests/bug65236.phpt new file mode 100644 index 0000000000..67b26d663f --- /dev/null +++ b/ext/xml/tests/bug65236.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #65236 (heap corruption in xml parser) +--SKIPIF-- +<?php +require_once("skipif.inc"); +?> +--FILE-- +<?php +xml_parse_into_struct(xml_parser_create_ns(), str_repeat("<blah>", 1000), $a); + +echo "Done\n"; +?> +--EXPECTF-- +Warning: xml_parse_into_struct(): Maximum depth exceeded - Results truncated in %s on line %d +Done diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 1f0480b6c7..9f0bc30d98 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -427,7 +427,7 @@ static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) } if (parser->ltags) { int inx; - for (inx = 0; inx < parser->level; inx++) + for (inx = 0; ((inx < parser->level) && (inx < XML_MAXLEVEL)); inx++) efree(parser->ltags[ inx ]); efree(parser->ltags); } @@ -905,45 +905,50 @@ void _xml_startElementHandler(void *userData, const XML_Char *name, const XML_Ch } if (parser->data) { - zval *tag, *atr; - int atcnt = 0; + if (parser->level <= XML_MAXLEVEL) { + zval *tag, *atr; + int atcnt = 0; - MAKE_STD_ZVAL(tag); - MAKE_STD_ZVAL(atr); + MAKE_STD_ZVAL(tag); + MAKE_STD_ZVAL(atr); - array_init(tag); - array_init(atr); + array_init(tag); + array_init(atr); - _xml_add_to_info(parser,((char *) tag_name) + parser->toffset); + _xml_add_to_info(parser,((char *) tag_name) + parser->toffset); - add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */ - add_assoc_string(tag,"type","open",1); - add_assoc_long(tag,"level",parser->level); + add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */ + add_assoc_string(tag,"type","open",1); + add_assoc_long(tag,"level",parser->level); - parser->ltags[parser->level-1] = estrdup(tag_name); - parser->lastwasopen = 1; + parser->ltags[parser->level-1] = estrdup(tag_name); + parser->lastwasopen = 1; - attributes = (const XML_Char **) attrs; + attributes = (const XML_Char **) attrs; - while (attributes && *attributes) { - att = _xml_decode_tag(parser, attributes[0]); - val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding); - - add_assoc_stringl(atr,att,val,val_len,0); + while (attributes && *attributes) { + att = _xml_decode_tag(parser, attributes[0]); + val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding); - atcnt++; - attributes += 2; + add_assoc_stringl(atr,att,val,val_len,0); - efree(att); - } + atcnt++; + attributes += 2; - if (atcnt) { - zend_hash_add(Z_ARRVAL_P(tag),"attributes",sizeof("attributes"),&atr,sizeof(zval*),NULL); - } else { - zval_ptr_dtor(&atr); - } + efree(att); + } + + if (atcnt) { + zend_hash_add(Z_ARRVAL_P(tag),"attributes",sizeof("attributes"),&atr,sizeof(zval*),NULL); + } else { + zval_ptr_dtor(&atr); + } - zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),(void *) &parser->ctag); + zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),(void *) &parser->ctag); + } else if (parser->level == (XML_MAXLEVEL + 1)) { + TSRMLS_FETCH(); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum depth exceeded - Results truncated"); + } } efree(tag_name); @@ -995,7 +1000,7 @@ void _xml_endElementHandler(void *userData, const XML_Char *name) efree(tag_name); - if (parser->ltags) { + if ((parser->ltags) && (parser->level <= XML_MAXLEVEL)) { efree(parser->ltags[parser->level-1]); } @@ -1079,18 +1084,23 @@ void _xml_characterDataHandler(void *userData, const XML_Char *s, int len) } } - MAKE_STD_ZVAL(tag); - - array_init(tag); - - _xml_add_to_info(parser,parser->ltags[parser->level-1] + parser->toffset); + if (parser->level <= XML_MAXLEVEL) { + MAKE_STD_ZVAL(tag); - add_assoc_string(tag,"tag",parser->ltags[parser->level-1] + parser->toffset,1); - add_assoc_string(tag,"value",decoded_value,0); - add_assoc_string(tag,"type","cdata",1); - add_assoc_long(tag,"level",parser->level); + array_init(tag); - zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL); + _xml_add_to_info(parser,parser->ltags[parser->level-1] + parser->toffset); + + add_assoc_string(tag,"tag",parser->ltags[parser->level-1] + parser->toffset,1); + add_assoc_string(tag,"value",decoded_value,0); + add_assoc_string(tag,"type","cdata",1); + add_assoc_long(tag,"level",parser->level); + + zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL); + } else if (parser->level == (XML_MAXLEVEL + 1)) { + TSRMLS_FETCH(); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Maximum depth exceeded - Results truncated"); + } } } else { efree(decoded_value); |
