diff options
author | Derick Rethans <derick@php.net> | 2011-12-06 06:21:08 +0000 |
---|---|---|
committer | Derick Rethans <derick@php.net> | 2011-12-06 06:21:08 +0000 |
commit | 4c9fad8b362a7d2b6a94b4961e4b2dc037b2766d (patch) | |
tree | e4ad9273ebdabcb4b5ccc0957f38f3ed243ae6db | |
parent | 48f3cb3e2ed28a2e00ddf62fc791a3482fd908b4 (diff) | |
download | php-git-4c9fad8b362a7d2b6a94b4961e4b2dc037b2766d.tar.gz |
- Fixed bug #53502 (strtotime with timezone memory leak).
- Fixed bug #52062 (large timestamps with DateTime::getTimestamp and
DateTime::setTimestamp).
- Fixed bug #51994 (date_parse_from_format is parsing invalid date using 'yz'
format).
- Fixed bug #51223 (Seg fault while creating (by unserialization)
DatePeriod).
-rw-r--r-- | ext/date/lib/parse_date.c | 31 | ||||
-rw-r--r-- | ext/date/lib/parse_date.re | 31 | ||||
-rw-r--r-- | ext/date/lib/timelib.h | 12 | ||||
-rw-r--r-- | ext/date/lib/tm2unixtime.c | 16 | ||||
-rw-r--r-- | ext/date/php_date.c | 94 | ||||
-rw-r--r-- | ext/date/php_date.h | 2 | ||||
-rw-r--r-- | ext/date/tests/bug51223.phpt | 100 | ||||
-rw-r--r-- | ext/date/tests/bug51994.phpt | 3 | ||||
-rw-r--r-- | ext/date/tests/bug53502.phpt | 11 |
9 files changed, 245 insertions, 55 deletions
diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c index a13eaa70a6..4020e7b9f7 100644 --- a/ext/date/lib/parse_date.c +++ b/ext/date/lib/parse_date.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Sat Nov 26 10:23:33 2011 */ +/* Generated by re2c 0.13.5 on Mon Dec 5 22:02:39 2011 */ #line 1 "ext/date/lib/parse_date.re" /* +----------------------------------------------------------------------+ @@ -785,7 +785,7 @@ static long timelib_lookup_zone(char **ptr, int *dst, char **tz_abbr, int *found return value; } -static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb) +static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_wrapper) { timelib_tzinfo *res; long retval = 0; @@ -834,7 +834,7 @@ static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_ #endif /* If we have a TimeZone identifier to start with, use it */ if (strstr(tz_abbr, "/") || strcmp(tz_abbr, "UTC") == 0) { - if ((res = timelib_parse_tzfile(tz_abbr, tzdb)) != NULL) { + if ((res = tz_wrapper(tz_abbr, tzdb)) != NULL) { t->tz_info = res; t->zone_type = TIMELIB_ZONETYPE_ID; found++; @@ -863,7 +863,7 @@ static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_ } \ } -static int scan(Scanner *s) +static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) { uchar *cursor = s->cur; char *str, *ptr = NULL; @@ -1040,7 +1040,7 @@ yy4: DEBUG_OUTPUT("tzcorrection | tz"); TIMELIB_INIT; TIMELIB_HAVE_TZ(); - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -4502,7 +4502,7 @@ yy223: } if (*ptr != '\0') { - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -9832,7 +9832,7 @@ yy491: } if (*ptr != '\0') { - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -12107,7 +12107,7 @@ yy701: s->time->h = timelib_get_nr((char **) &ptr, 2); s->time->i = timelib_get_nr((char **) &ptr, 2); s->time->s = timelib_get_nr((char **) &ptr, 2); - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -13498,7 +13498,7 @@ yy843: if (*ptr == '.') { s->time->f = timelib_get_frac_nr((char **) &ptr, 9); if (*ptr) { /* timezone is optional */ - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -15847,7 +15847,7 @@ yy1076: s->time->s = timelib_get_nr((char **) &ptr, 2); if (*ptr != '\0') { - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -24770,7 +24770,7 @@ yy1537: #define YYMAXFILL 31 -timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, const timelib_tzdb *tzdb) +timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper) { Scanner in; int t; @@ -24825,7 +24825,7 @@ timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container in.time->zone_type = 0; do { - t = scan(&in); + t = scan(&in, tz_get_wrapper); #ifdef DEBUG_PARSER printf("%d\n", t); #endif @@ -24880,7 +24880,7 @@ static void timelib_time_reset_unset_fields(timelib_time *time) if (time->f == TIMELIB_UNSET ) time->f = 0.0; } -timelib_time *timelib_parse_from_format(char *format, char *string, int len, timelib_error_container **errors, const timelib_tzdb *tzdb) +timelib_time *timelib_parse_from_format(char *format, char *string, int len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper) { char *fptr = format; char *ptr = string; @@ -24942,13 +24942,14 @@ timelib_time *timelib_parse_from_format(char *format, char *string, int len, tim case 'S': /* day suffix, ignored, nor checked */ timelib_skip_day_suffix((char **) &ptr); break; - case 'z': /* day of year - resets month (0 based) */ + case 'z': /* day of year - resets month (0 based) - also initializes everything else to !TIMELIB_UNSET */ TIMELIB_CHECK_NUMBER; if ((tmp = timelib_get_nr((char **) &ptr, 3)) == TIMELIB_UNSET) { add_pbf_error(s, "A three digit day-of-year could not be found", string, begin); } else { s->time->m = 1; s->time->d = tmp + 1; + timelib_do_normalize(s->time); } break; @@ -25077,7 +25078,7 @@ timelib_time *timelib_parse_from_format(char *format, char *string, int len, tim case 'O': /* timezone */ { int tz_not_found; - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_pbf_error(s, "The timezone could not be found in the database", string, begin); } diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re index a777dbd8e4..16c45a2119 100644 --- a/ext/date/lib/parse_date.re +++ b/ext/date/lib/parse_date.re @@ -783,7 +783,7 @@ static long timelib_lookup_zone(char **ptr, int *dst, char **tz_abbr, int *found return value; } -static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb) +static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_found, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_wrapper) { timelib_tzinfo *res; long retval = 0; @@ -832,7 +832,7 @@ static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_ #endif /* If we have a TimeZone identifier to start with, use it */ if (strstr(tz_abbr, "/") || strcmp(tz_abbr, "UTC") == 0) { - if ((res = timelib_parse_tzfile(tz_abbr, tzdb)) != NULL) { + if ((res = tz_wrapper(tz_abbr, tzdb)) != NULL) { t->tz_info = res; t->zone_type = TIMELIB_ZONETYPE_ID; found++; @@ -861,7 +861,7 @@ static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_ } \ } -static int scan(Scanner *s) +static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) { uchar *cursor = s->cur; char *str, *ptr = NULL; @@ -1194,7 +1194,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of } if (*ptr != '\0') { - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -1235,7 +1235,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of s->time->h = timelib_get_nr((char **) &ptr, 2); s->time->i = timelib_get_nr((char **) &ptr, 2); s->time->s = 0; - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, s->tzdb, tz_get_wrapper); break; case 1: s->time->y = timelib_get_nr((char **) &ptr, 4); @@ -1260,7 +1260,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of s->time->s = timelib_get_nr((char **) &ptr, 2); if (*ptr != '\0') { - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -1462,7 +1462,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of if (*ptr == '.') { s->time->f = timelib_get_frac_nr((char **) &ptr, 9); if (*ptr) { /* timezone is optional */ - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -1565,7 +1565,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of s->time->h = timelib_get_nr((char **) &ptr, 2); s->time->i = timelib_get_nr((char **) &ptr, 2); s->time->s = timelib_get_nr((char **) &ptr, 2); - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -1678,7 +1678,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of DEBUG_OUTPUT("tzcorrection | tz"); TIMELIB_INIT; TIMELIB_HAVE_TZ(); - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -1731,7 +1731,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of } if (*ptr != '\0') { - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_error(s, "The timezone could not be found in the database"); } @@ -1777,7 +1777,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfull|dayabbr) space 'of /*!max:re2c */ -timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, const timelib_tzdb *tzdb) +timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper) { Scanner in; int t; @@ -1832,7 +1832,7 @@ timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container in.time->zone_type = 0; do { - t = scan(&in); + t = scan(&in, tz_get_wrapper); #ifdef DEBUG_PARSER printf("%d\n", t); #endif @@ -1887,7 +1887,7 @@ static void timelib_time_reset_unset_fields(timelib_time *time) if (time->f == TIMELIB_UNSET ) time->f = 0.0; } -timelib_time *timelib_parse_from_format(char *format, char *string, int len, timelib_error_container **errors, const timelib_tzdb *tzdb) +timelib_time *timelib_parse_from_format(char *format, char *string, int len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper) { char *fptr = format; char *ptr = string; @@ -1949,13 +1949,14 @@ timelib_time *timelib_parse_from_format(char *format, char *string, int len, tim case 'S': /* day suffix, ignored, nor checked */ timelib_skip_day_suffix((char **) &ptr); break; - case 'z': /* day of year - resets month (0 based) */ + case 'z': /* day of year - resets month (0 based) - also initializes everything else to !TIMELIB_UNSET */ TIMELIB_CHECK_NUMBER; if ((tmp = timelib_get_nr((char **) &ptr, 3)) == TIMELIB_UNSET) { add_pbf_error(s, "A three digit day-of-year could not be found", string, begin); } else { s->time->m = 1; s->time->d = tmp + 1; + timelib_do_normalize(s->time); } break; @@ -2084,7 +2085,7 @@ timelib_time *timelib_parse_from_format(char *format, char *string, int len, tim case 'O': /* timezone */ { int tz_not_found; - s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb); + s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper); if (tz_not_found) { add_pbf_error(s, "The timezone could not be found in the database", string, begin); } diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index 48a952e790..9667fa2dae 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -26,12 +26,14 @@ #include <limits.h> #endif -#define TIMELIB_VERSION 201101 +#define TIMELIB_VERSION 201102 #define TIMELIB_NONE 0x00 #define TIMELIB_OVERRIDE_TIME 0x01 #define TIMELIB_NO_CLONE 0x02 +#define TIMELIB_UNSET -99999 + #define TIMELIB_SPECIAL_WEEKDAY 0x01 #define TIMELIB_SPECIAL_DAY_OF_WEEK_IN_MONTH 0x02 #define TIMELIB_SPECIAL_LAST_DAY_OF_WEEK_IN_MONTH 0x03 @@ -52,6 +54,9 @@ #define strncasecmp strnicmp #endif +/* Function pointers */ +typedef timelib_tzinfo* (*timelib_tz_get_wrapper)(char *tzname, const timelib_tzdb *tzdb); + /* From dow.c */ timelib_sll timelib_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d); timelib_sll timelib_iso_day_of_week(timelib_sll y, timelib_sll m, timelib_sll d); @@ -63,8 +68,8 @@ int timelib_valid_time(timelib_sll h, timelib_sll i, timelib_sll s); int timelib_valid_date(timelib_sll y, timelib_sll m, timelib_sll d); /* From parse_date.re */ -timelib_time *timelib_strtotime(char *s, int len, timelib_error_container **errors, const timelib_tzdb *tzdb); -timelib_time *timelib_parse_from_format(char *format, char *s, int len, timelib_error_container **errors, const timelib_tzdb *tzdb); +timelib_time *timelib_strtotime(char *s, int len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper); +timelib_time *timelib_parse_from_format(char *format, char *s, int len, timelib_error_container **errors, const timelib_tzdb *tzdb, timelib_tz_get_wrapper tz_get_wrapper); void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options); char *timelib_timezone_id_from_abbr(const char *abbr, long gmtoffset, int isdst); const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void); @@ -78,6 +83,7 @@ void timelib_strtointerval(char *s, int len, /* From tm2unixtime.c */ void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi); +void timelib_do_normalize(timelib_time *base); void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt); /* From unixtime2tm.c */ diff --git a/ext/date/lib/tm2unixtime.c b/ext/date/lib/tm2unixtime.c index f2b7493ed4..c4830bbef0 100644 --- a/ext/date/lib/tm2unixtime.c +++ b/ext/date/lib/tm2unixtime.c @@ -179,11 +179,11 @@ void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt) do {} while (do_range_limit(0, 12, 12, &rt->m, &rt->y)); } -static void do_normalize(timelib_time* time) +void timelib_do_normalize(timelib_time* time) { - do {} while (do_range_limit(0, 60, 60, &time->s, &time->i)); - do {} while (do_range_limit(0, 60, 60, &time->i, &time->h)); - do {} while (do_range_limit(0, 24, 24, &time->h, &time->d)); + if (time->s != TIMELIB_UNSET) do {} while (do_range_limit(0, 60, 60, &time->s, &time->i)); + if (time->s != TIMELIB_UNSET) do {} while (do_range_limit(0, 60, 60, &time->i, &time->h)); + if (time->s != TIMELIB_UNSET) do {} while (do_range_limit(0, 24, 24, &time->h, &time->d)); do {} while (do_range_limit(1, 13, 12, &time->m, &time->y)); do {} while (do_range_limit_days(&time->y, &time->m, &time->d)); @@ -195,7 +195,7 @@ static void do_adjust_relative(timelib_time* time) if (time->relative.have_weekday_relative) { do_adjust_for_weekday(time); } - do_normalize(time); + timelib_do_normalize(time); if (time->have_relative) { time->s += time->relative.s; @@ -215,7 +215,7 @@ static void do_adjust_relative(timelib_time* time) time->m++; break; } - do_normalize(time); + timelib_do_normalize(time); } static void do_adjust_special_weekday(timelib_time* time) @@ -280,7 +280,7 @@ static void do_adjust_special(timelib_time* time) break; } } - do_normalize(time); + timelib_do_normalize(time); memset(&(time->relative.special), 0, sizeof(time->relative.special)); } @@ -300,7 +300,7 @@ static void do_adjust_special_early(timelib_time* time) break; } } - do_normalize(time); + timelib_do_normalize(time); } static timelib_sll do_years(timelib_sll year) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index c1fb5a9f30..ab4488f82d 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -463,6 +463,8 @@ const zend_function_entry date_funcs_timezone[] = { const zend_function_entry date_funcs_interval[] = { PHP_ME(DateInterval, __construct, arginfo_date_interval_construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC) + PHP_ME(DateInterval, __wakeup, NULL, ZEND_ACC_PUBLIC) + PHP_ME(DateInterval, __set_state, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_ME_MAPPING(format, date_interval_format, arginfo_date_method_interval_format, 0) PHP_ME_MAPPING(createFromDateString, date_interval_create_from_date_string, arginfo_date_interval_create_from_date_string, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) PHP_FE_END @@ -832,6 +834,12 @@ static timelib_tzinfo *php_date_parse_tzfile(char *formal_tzname, const timelib_ } return tzi; } + +timelib_tzinfo *php_date_parse_tzfile_wrapper(char *formal_tzname, const timelib_tzdb *tzdb) +{ + TSRMLS_FETCH(); + return php_date_parse_tzfile(formal_tzname, tzdb TSRMLS_CC); +} /* }}} */ /* {{{ Helper functions */ @@ -1294,7 +1302,7 @@ PHPAPI signed long php_parse_date(char *string, signed long *now) int error2; signed long retval; - parsed_time = timelib_strtotime(string, strlen(string), &error, DATE_TIMEZONEDB); + parsed_time = timelib_strtotime(string, strlen(string), &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); if (error->error_count) { timelib_error_container_dtor(error); return -1; @@ -1331,7 +1339,7 @@ PHP_FUNCTION(strtotime) initial_ts = emalloc(25); snprintf(initial_ts, 24, "@%ld UTC", preset_ts); - t = timelib_strtotime(initial_ts, strlen(initial_ts), NULL, DATE_TIMEZONEDB); /* we ignore the error here, as this should never fail */ + t = timelib_strtotime(initial_ts, strlen(initial_ts), NULL, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); /* we ignore the error here, as this should never fail */ timelib_update_ts(t, tzi); now->tz_info = tzi; now->zone_type = TIMELIB_ZONETYPE_ID; @@ -1353,7 +1361,7 @@ PHP_FUNCTION(strtotime) RETURN_FALSE; } - t = timelib_strtotime(times, time_len, &error, DATE_TIMEZONEDB); + t = timelib_strtotime(times, time_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); error1 = error->error_count; timelib_error_container_dtor(error); timelib_fill_holes(t, now, TIMELIB_NO_CLONE); @@ -2318,9 +2326,9 @@ PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str, timelib_time_dtor(dateobj->time); } if (format) { - dateobj->time = timelib_parse_from_format(format, time_str_len ? time_str : "", time_str_len ? time_str_len : 0, &err, DATE_TIMEZONEDB); + dateobj->time = timelib_parse_from_format(format, time_str_len ? time_str : "", time_str_len ? time_str_len : 0, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); } else { - dateobj->time = timelib_strtotime(time_str_len ? time_str : "now", time_str_len ? time_str_len : sizeof("now") -1, &err, DATE_TIMEZONEDB); + dateobj->time = timelib_strtotime(time_str_len ? time_str : "now", time_str_len ? time_str_len : sizeof("now") -1, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); } /* update last errors and warnings */ @@ -2654,7 +2662,7 @@ PHP_FUNCTION(date_parse) RETURN_FALSE; } - parsed_time = timelib_strtotime(date, date_len, &error, DATE_TIMEZONEDB); + parsed_time = timelib_strtotime(date, date_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAM_PASSTHRU, parsed_time, error); } /* }}} */ @@ -2673,7 +2681,7 @@ PHP_FUNCTION(date_parse_from_format) RETURN_FALSE; } - parsed_time = timelib_parse_from_format(format, date, date_len, &error, DATE_TIMEZONEDB); + parsed_time = timelib_parse_from_format(format, date, date_len, &error, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAM_PASSTHRU, parsed_time, error); } /* }}} */ @@ -2715,7 +2723,7 @@ PHP_FUNCTION(date_modify) dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); DATE_CHECK_INITIALIZED(dateobj->time, DateTime); - tmp_time = timelib_strtotime(modify, modify_len, &err, DATE_TIMEZONEDB); + tmp_time = timelib_strtotime(modify, modify_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); /* update last errors and warnings */ update_errors_warnings(err TSRMLS_CC); @@ -3536,6 +3544,70 @@ 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); + (*intobj)->initialized = 1; + + return 0; +} + +/* {{{ proto DateInterval::__set_state() +*/ +PHP_METHOD(DateInterval, __set_state) +{ + php_interval_obj *intobj; + zval *array; + HashTable *myht; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &array) == FAILURE) { + RETURN_FALSE; + } + + myht = HASH_OF(array); + + php_date_instantiate(date_ce_interval, return_value TSRMLS_CC); + intobj = (php_interval_obj *) zend_object_store_get_object(return_value TSRMLS_CC); + php_date_interval_initialize_from_hash(&return_value, &intobj, myht TSRMLS_CC); +} +/* }}} */ + +/* {{{ proto DateInterval::__wakeup() +*/ +PHP_METHOD(DateInterval, __wakeup) +{ + zval *object = getThis(); + php_interval_obj *intobj; + HashTable *myht; + + intobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC); + + myht = Z_OBJPROP_P(object); + + php_date_interval_initialize_from_hash(&return_value, &intobj, myht TSRMLS_CC); +} +/* }}} */ /* {{{ proto DateInterval date_interval_create_from_date_string(string time) Uses the normal date parsers and sets up a DateInterval from the relative parts of the parsed string */ @@ -3553,7 +3625,7 @@ PHP_FUNCTION(date_interval_create_from_date_string) php_date_instantiate(date_ce_interval, return_value TSRMLS_CC); - time = timelib_strtotime(time_str, time_str_len, &err, DATE_TIMEZONEDB); + time = timelib_strtotime(time_str, time_str_len, &err, DATE_TIMEZONEDB, php_date_parse_tzfile_wrapper); diobj = (php_interval_obj *) zend_object_store_get_object(return_value TSRMLS_CC); diobj->diff = timelib_rel_time_clone(&time->relative); diobj->initialized = 1; @@ -3591,8 +3663,8 @@ static char *date_interval_format(char *format, int format_len, timelib_rel_time case 'I': length = slprintf(buffer, 32, "%02d", (int) t->i); break; case 'i': length = slprintf(buffer, 32, "%d", (int) t->i); break; - case 'S': length = slprintf(buffer, 32, "%02d", (int) t->s); break; - case 's': length = slprintf(buffer, 32, "%d", (int) t->s); break; + case 'S': length = slprintf(buffer, 32, "%02ld", (long) t->s); break; + case 's': length = slprintf(buffer, 32, "%ld", (long) t->s); break; case 'a': { if ((int) t->days != -99999) { diff --git a/ext/date/php_date.h b/ext/date/php_date.h index 3f84d8242a..11df91a52a 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -82,6 +82,8 @@ PHP_FUNCTION(timezone_abbreviations_list); PHP_FUNCTION(timezone_version_get); PHP_METHOD(DateInterval, __construct); +PHP_METHOD(DateInterval, __wakeup); +PHP_METHOD(DateInterval, __set_state); PHP_FUNCTION(date_interval_format); PHP_FUNCTION(date_interval_create_from_date_string); diff --git a/ext/date/tests/bug51223.phpt b/ext/date/tests/bug51223.phpt new file mode 100644 index 0000000000..cb91d1d99b --- /dev/null +++ b/ext/date/tests/bug51223.phpt @@ -0,0 +1,100 @@ +--TEST-- +Bug #52113: Seg fault while creating (by unserialization) DatePeriod +--FILE-- +<?php +$start = new DateTime('2003-01-02 08:00:00'); +$end = new DateTime('2003-01-02 12:00:00'); +$diff = $start->diff($end); +$p = new DatePeriod($start, $diff, 2); +$diff_s = serialize($diff); +var_dump($diff, $diff_s); +var_export($diff); + +$diff_un = unserialize($diff_s); +$p = new DatePeriod($start, $diff_un, 2); +var_dump($diff_un, $p); + +$unser = DateInterval::__set_state(array( + 'y' => 7, + 'm' => 6, + 'd' => 5, + 'h' => 4, + 'i' => 3, + 's' => 2, + 'invert' => 1, + 'days' => 2400, +)); + +$p = new DatePeriod($start, $diff_un, 2); +var_dump($unser, $p); + +?> +--EXPECT-- +object(DateInterval)#3 (8) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(0) + ["h"]=> + int(4) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + 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;}" +DateInterval::__set_state(array( + 'y' => 0, + 'm' => 0, + 'd' => 0, + 'h' => 4, + 'i' => 0, + 's' => 0, + 'invert' => 0, + 'days' => 0, +))object(DateInterval)#5 (8) { + ["y"]=> + int(0) + ["m"]=> + int(0) + ["d"]=> + int(0) + ["h"]=> + int(4) + ["i"]=> + int(0) + ["s"]=> + int(0) + ["invert"]=> + int(0) + ["days"]=> + int(0) +} +object(DatePeriod)#6 (0) { +} +object(DateInterval)#4 (8) { + ["y"]=> + int(7) + ["m"]=> + int(6) + ["d"]=> + int(5) + ["h"]=> + int(4) + ["i"]=> + int(3) + ["s"]=> + int(2) + ["invert"]=> + int(1) + ["days"]=> + int(2400) +} +object(DatePeriod)#7 (0) { +} diff --git a/ext/date/tests/bug51994.phpt b/ext/date/tests/bug51994.phpt index fb0fe46d89..2c456ba6e3 100644 --- a/ext/date/tests/bug51994.phpt +++ b/ext/date/tests/bug51994.phpt @@ -1,12 +1,9 @@ --TEST-- Bug #51994 (date_parse_from_format is parsing invalid date using 'yz' format) ---XFAIL-- -Bug #51994 isn't fixed yet --FILE-- <?php $trans_date = '10153'; // 152nd day of year 2010 -> 03.06.2010 $a_date = date_parse_from_format('yz', $trans_date); - var_dump($a_date); ?> --EXPECTF-- diff --git a/ext/date/tests/bug53502.phpt b/ext/date/tests/bug53502.phpt new file mode 100644 index 0000000000..6c17078090 --- /dev/null +++ b/ext/date/tests/bug53502.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #53502: strtotime with timezone memory leak +--FILE-- +<?php +for ($i = 0; $i < 1000; $i++) { + strtotime('Monday 00:00 Europe/Paris'); // Memory leak +} +echo "Nothing, test only makes sense through valgrind.\n"; +?> +--EXPECT-- +Nothing, test only makes sense through valgrind. |