]> granicus.if.org Git - php/commitdiff
- Fixed bug #53502 (strtotime with timezone memory leak).
authorDerick Rethans <derick@php.net>
Tue, 6 Dec 2011 06:21:08 +0000 (06:21 +0000)
committerDerick Rethans <derick@php.net>
Tue, 6 Dec 2011 06:21:08 +0000 (06:21 +0000)
- 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).

ext/date/lib/parse_date.c
ext/date/lib/parse_date.re
ext/date/lib/timelib.h
ext/date/lib/tm2unixtime.c
ext/date/php_date.c
ext/date/php_date.h
ext/date/tests/bug51223.phpt [new file with mode: 0644]
ext/date/tests/bug51994.phpt
ext/date/tests/bug53502.phpt [new file with mode: 0644]

index c6ce621a713fa9c3fdd4ec4d2a52b47389c0f946..fbe330700b3a5845a5fae99f09751747e9e09fa2 100644 (file)
@@ -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);
                                        }
index a777dbd8e4ce42b3fbd7a0da14073679718cf350..16c45a2119829a51dad71b5a3f14777ef5ef79f4 100644 (file)
@@ -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);
                                        }
index 48a952e790175100a310d97c629911547fdb5928..9667fa2dae420db077b265b037c4d5dd4303f4f5 100644 (file)
 #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 */
index f2b7493ed481126b636d704487e000a2c84a324f..c4830bbef0c7b787fce9e555f5a04d6dd104809e 100644 (file)
@@ -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)
index c1fb5a9f30cdf249f15a8131e15ebe012c38a149..ab4488f82d7f65ddee461423a06546d10541957a 100644 (file)
@@ -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) {
index 3f84d8242a18228b3e5918e831fea71d2c7ddeee..11df91a52a9278e1e9b752b74a94cf14491ab6b5 100644 (file)
@@ -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 (file)
index 0000000..cb91d1d
--- /dev/null
@@ -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) {
+}
index fb0fe46d892adfc2783b68f4564455196a0e2641..2c456ba6e3a44704e07aeb4a0865b9cd7db18e3e 100644 (file)
@@ -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 (file)
index 0000000..6c17078
--- /dev/null
@@ -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.