Browse Source

- 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).
pull/271/head
Derick Rethans 15 years ago
parent
commit
ac631dd580
  1. 31
      ext/date/lib/parse_date.c
  2. 31
      ext/date/lib/parse_date.re
  3. 12
      ext/date/lib/timelib.h
  4. 16
      ext/date/lib/tm2unixtime.c
  5. 94
      ext/date/php_date.c
  6. 2
      ext/date/php_date.h
  7. 100
      ext/date/tests/bug51223.phpt
  8. 3
      ext/date/tests/bug51994.phpt
  9. 11
      ext/date/tests/bug53502.phpt

31
ext/date/lib/parse_date.c

@ -1,4 +1,4 @@
/* Generated by re2c 0.13.5 on Sat Nov 26 16:43:35 2011 */
/* Generated by re2c 0.13.5 on Mon Dec 5 22:02:27 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);
}

31
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);
}

12
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 */

16
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)

94
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) {

2
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);

100
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) {
}

3
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--

11
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.
Loading…
Cancel
Save