summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/date/lib/parse_tz.c297
-rw-r--r--ext/date/lib/timelib.h8
-rw-r--r--ext/date/lib/timelib_private.h2
-rw-r--r--ext/date/php_date.c10
4 files changed, 177 insertions, 140 deletions
diff --git a/ext/date/lib/parse_tz.c b/ext/date/lib/parse_tz.c
index 5986cd6468..c8e501151f 100644
--- a/ext/date/lib/parse_tz.c
+++ b/ext/date/lib/parse_tz.c
@@ -51,17 +51,37 @@ static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
{
return value;
}
+
+static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
+{
+ return value;
+}
#else
static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
{
- return ((value & 0x000000ff) << 24) +
- ((value & 0x0000ff00) << 8) +
- ((value & 0x00ff0000) >> 8) +
+ return
+ ((value & 0x000000ff) << 24) +
+ ((value & 0x0000ff00) << 8) +
+ ((value & 0x00ff0000) >> 8) +
((value & 0xff000000) >> 24);
}
+
+static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
+{
+ return
+ ((value & 0x00000000000000ff) << 56) +
+ ((value & 0x000000000000ff00) << 40) +
+ ((value & 0x0000000000ff0000) << 24) +
+ ((value & 0x00000000ff000000) << 8) +
+ ((value & 0x000000ff00000000) >> 8) +
+ ((value & 0x0000ff0000000000) >> 24) +
+ ((value & 0x00ff000000000000) >> 40) +
+ ((value & 0xff00000000000000) >> 56);
+}
#endif
#define timelib_conv_int_signed(value) ((int32_t) timelib_conv_int_unsigned((int32_t) value))
+#define timelib_conv_int64_signed(value) ((int64_t) timelib_conv_int64_unsigned((int64_t) value))
static int read_php_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
{
@@ -132,56 +152,49 @@ static int read_preamble(const unsigned char **tzf, timelib_tzinfo *tz, unsigned
}
}
-static void read_header(const unsigned char **tzf, timelib_tzinfo *tz)
+static void read_32bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
{
uint32_t buffer[6];
memcpy(&buffer, *tzf, sizeof(buffer));
- tz->bit32.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
- tz->bit32.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
- tz->bit32.leapcnt = timelib_conv_int_unsigned(buffer[2]);
- tz->bit32.timecnt = timelib_conv_int_unsigned(buffer[3]);
- tz->bit32.typecnt = timelib_conv_int_unsigned(buffer[4]);
- tz->bit32.charcnt = timelib_conv_int_unsigned(buffer[5]);
- *tzf += sizeof(buffer);
-}
+ tz->_bit32.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
+ tz->_bit32.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
+ tz->_bit32.leapcnt = timelib_conv_int_unsigned(buffer[2]);
+ tz->_bit32.timecnt = timelib_conv_int_unsigned(buffer[3]);
+ tz->_bit32.typecnt = timelib_conv_int_unsigned(buffer[4]);
+ tz->_bit32.charcnt = timelib_conv_int_unsigned(buffer[5]);
-static void skip_64bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
-{
- if (tz->bit64.timecnt) {
- *tzf += (sizeof(int64_t) * tz->bit64.timecnt);
- *tzf += (sizeof(unsigned char) * tz->bit64.timecnt);
- }
+ *tzf += sizeof(buffer);
}
-static int read_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
+static int read_64bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
{
- int32_t *buffer = NULL;
+ int64_t *buffer = NULL;
uint32_t i;
unsigned char *cbuffer = NULL;
- if (tz->bit32.timecnt) {
- buffer = (int32_t*) timelib_malloc(tz->bit32.timecnt * sizeof(int32_t));
+ if (tz->bit64.timecnt) {
+ buffer = (int64_t*) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
if (!buffer) {
return TIMELIB_ERROR_CANNOT_ALLOCATE;
}
- memcpy(buffer, *tzf, sizeof(int32_t) * tz->bit32.timecnt);
- *tzf += (sizeof(int32_t) * tz->bit32.timecnt);
- for (i = 0; i < tz->bit32.timecnt; i++) {
- buffer[i] = timelib_conv_int_signed(buffer[i]);
+ memcpy(buffer, *tzf, sizeof(int64_t) * tz->bit64.timecnt);
+ *tzf += (sizeof(int64_t) * tz->bit64.timecnt);
+ for (i = 0; i < tz->bit64.timecnt; i++) {
+ buffer[i] = timelib_conv_int64_signed(buffer[i]);
/* Sanity check to see whether TS is just increasing */
if (i > 0 && !(buffer[i] > buffer[i - 1])) {
return TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE;
}
}
- cbuffer = (unsigned char*) timelib_malloc(tz->bit32.timecnt * sizeof(unsigned char));
+ cbuffer = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
if (!cbuffer) {
timelib_free(buffer);
return TIMELIB_ERROR_CANNOT_ALLOCATE;
}
- memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->bit32.timecnt);
- *tzf += sizeof(unsigned char) * tz->bit32.timecnt;
+ memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->bit64.timecnt);
+ *tzf += sizeof(unsigned char) * tz->bit64.timecnt;
}
tz->trans = buffer;
@@ -190,41 +203,35 @@ static int read_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
return 0;
}
-static void skip_64bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
+static void skip_32bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
{
- *tzf += sizeof(unsigned char) * 6 * tz->bit64.typecnt;
- *tzf += sizeof(char) * tz->bit64.charcnt;
- if (tz->bit64.leapcnt) {
- *tzf += sizeof(int64_t) * tz->bit64.leapcnt * 2;
- }
- if (tz->bit64.ttisstdcnt) {
- *tzf += sizeof(unsigned char) * tz->bit64.ttisstdcnt;
- }
- if (tz->bit64.ttisgmtcnt) {
- *tzf += sizeof(unsigned char) * tz->bit64.ttisgmtcnt;
+ if (tz->_bit32.timecnt) {
+ *tzf += (sizeof(int32_t) * tz->_bit32.timecnt);
+ *tzf += sizeof(unsigned char) * tz->_bit32.timecnt;
}
}
-static int read_types(const unsigned char **tzf, timelib_tzinfo *tz)
+static int read_64bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
{
unsigned char *buffer;
int32_t *leap_buffer;
unsigned int i, j;
- buffer = (unsigned char*) timelib_malloc(tz->bit32.typecnt * sizeof(unsigned char) * 6);
+ /* Offset Types */
+ buffer = (unsigned char*) timelib_malloc(tz->bit64.typecnt * sizeof(unsigned char) * 6);
if (!buffer) {
return TIMELIB_ERROR_CANNOT_ALLOCATE;
}
- memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->bit32.typecnt);
- *tzf += sizeof(unsigned char) * 6 * tz->bit32.typecnt;
+ memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->bit64.typecnt);
+ *tzf += sizeof(unsigned char) * 6 * tz->bit64.typecnt;
- tz->type = (ttinfo*) timelib_malloc(tz->bit32.typecnt * sizeof(ttinfo));
+ tz->type = (ttinfo*) timelib_malloc(tz->bit64.typecnt * sizeof(ttinfo));
if (!tz->type) {
timelib_free(buffer);
return TIMELIB_ERROR_CANNOT_ALLOCATE;
}
- for (i = 0; i < tz->bit32.typecnt; i++) {
+ for (i = 0; i < tz->bit64.typecnt; i++) {
j = i * 6;
tz->type[i].offset = 0;
tz->type[i].offset += (int32_t) (((uint32_t) buffer[j]) << 24) + (buffer[j + 1] << 16) + (buffer[j + 2] << 8) + tz->type[i].offset + buffer[j + 3];
@@ -233,56 +240,60 @@ static int read_types(const unsigned char **tzf, timelib_tzinfo *tz)
}
timelib_free(buffer);
- tz->timezone_abbr = (char*) timelib_malloc(tz->bit32.charcnt);
+ /* Abbreviations */
+ tz->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
if (!tz->timezone_abbr) {
return TIMELIB_ERROR_CORRUPT_NO_ABBREVIATION;
}
- memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->bit32.charcnt);
- *tzf += sizeof(char) * tz->bit32.charcnt;
+ memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->bit64.charcnt);
+ *tzf += sizeof(char) * tz->bit64.charcnt;
- if (tz->bit32.leapcnt) {
- leap_buffer = (int32_t *) timelib_malloc(tz->bit32.leapcnt * 2 * sizeof(int32_t));
+ /* Leap seconds (only use in 'right/') format */
+ if (tz->bit64.leapcnt) {
+ leap_buffer = (int32_t *) timelib_malloc(tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
if (!leap_buffer) {
return TIMELIB_ERROR_CANNOT_ALLOCATE;
}
- memcpy(leap_buffer, *tzf, sizeof(int32_t) * tz->bit32.leapcnt * 2);
- *tzf += sizeof(int32_t) * tz->bit32.leapcnt * 2;
+ memcpy(leap_buffer, *tzf, tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
+ *tzf += tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t));
- tz->leap_times = (tlinfo*) timelib_malloc(tz->bit32.leapcnt * sizeof(tlinfo));
+ tz->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
if (!tz->leap_times) {
timelib_free(leap_buffer);
return TIMELIB_ERROR_CANNOT_ALLOCATE;
}
- for (i = 0; i < tz->bit32.leapcnt; i++) {
- tz->leap_times[i].trans = timelib_conv_int_signed(leap_buffer[i * 2]);
- tz->leap_times[i].offset = timelib_conv_int_signed(leap_buffer[i * 2 + 1]);
+ for (i = 0; i < tz->bit64.leapcnt; i++) {
+ tz->leap_times[i].trans = timelib_conv_int64_signed(leap_buffer[i * 3 + 1] * 4294967296 + leap_buffer[i * 3]);
+ tz->leap_times[i].offset = timelib_conv_int_signed(leap_buffer[i * 3 + 2]);
}
timelib_free(leap_buffer);
}
- if (tz->bit32.ttisstdcnt) {
- buffer = (unsigned char*) timelib_malloc(tz->bit32.ttisstdcnt * sizeof(unsigned char));
+ /* Standard/Wall Indicators (unused) */
+ if (tz->bit64.ttisstdcnt) {
+ buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisstdcnt * sizeof(unsigned char));
if (!buffer) {
return TIMELIB_ERROR_CANNOT_ALLOCATE;
}
- memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit32.ttisstdcnt);
- *tzf += sizeof(unsigned char) * tz->bit32.ttisstdcnt;
+ memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisstdcnt);
+ *tzf += sizeof(unsigned char) * tz->bit64.ttisstdcnt;
- for (i = 0; i < tz->bit32.ttisstdcnt; i++) {
+ for (i = 0; i < tz->bit64.ttisstdcnt; i++) {
tz->type[i].isstdcnt = buffer[i];
}
timelib_free(buffer);
}
- if (tz->bit32.ttisgmtcnt) {
- buffer = (unsigned char*) timelib_malloc(tz->bit32.ttisgmtcnt * sizeof(unsigned char));
+ /* UT/Local Time Indicators (unused) */
+ if (tz->bit64.ttisgmtcnt) {
+ buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisgmtcnt * sizeof(unsigned char));
if (!buffer) {
return TIMELIB_ERROR_CANNOT_ALLOCATE;
}
- memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit32.ttisgmtcnt);
- *tzf += sizeof(unsigned char) * tz->bit32.ttisgmtcnt;
+ memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisgmtcnt);
+ *tzf += sizeof(unsigned char) * tz->bit64.ttisgmtcnt;
- for (i = 0; i < tz->bit32.ttisgmtcnt; i++) {
+ for (i = 0; i < tz->bit64.ttisgmtcnt; i++) {
tz->type[i].isgmtcnt = buffer[i];
}
timelib_free(buffer);
@@ -291,6 +302,30 @@ static int read_types(const unsigned char **tzf, timelib_tzinfo *tz)
return 0;
}
+static void skip_32bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
+{
+ /* Offset Types */
+ *tzf += sizeof(unsigned char) * 6 * tz->_bit32.typecnt;
+
+ /* Abbreviations */
+ *tzf += sizeof(char) * tz->_bit32.charcnt;
+
+ /* Leap seconds (only use in 'right/') format */
+ if (tz->_bit32.leapcnt) {
+ *tzf += sizeof(int32_t) * tz->_bit32.leapcnt * 2;
+ }
+
+ /* Standard/Wall Indicators (unused) */
+ if (tz->_bit32.ttisstdcnt) {
+ *tzf += sizeof(unsigned char) * tz->_bit32.ttisstdcnt;
+ }
+
+ /* UT/Local Time Indicators (unused) */
+ if (tz->_bit32.ttisgmtcnt) {
+ *tzf += sizeof(unsigned char) * tz->_bit32.ttisgmtcnt;
+ }
+}
+
static void skip_posix_string(const unsigned char **tzf, timelib_tzinfo *tz)
{
int n_count = 0;
@@ -339,14 +374,16 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
printf("Geo Location: %f,%f\n", tz->location.latitude, tz->location.longitude);
printf("Comments:\n%s\n", tz->location.comments);
printf("BC: %s\n", tz->bc ? "" : "yes");
- printf("UTC/Local count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.ttisgmtcnt);
- printf("Std/Wall count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.ttisstdcnt);
- printf("Leap.sec. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.leapcnt);
- printf("Trans. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.timecnt);
- printf("Local types count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.typecnt);
- printf("Zone Abbr. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit32.charcnt);
-
- printf ("%8s (%12s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
+
+ printf("\n64-bit:\n");
+ printf("UTC/Local count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisgmtcnt);
+ printf("Std/Wall count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisstdcnt);
+ printf("Leap.sec. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.leapcnt);
+ printf("Trans. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.timecnt);
+ printf("Local types count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.typecnt);
+ printf("Zone Abbr. count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.charcnt);
+
+ printf ("%16s (%20s) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
"", "", 0,
(long int) tz->type[0].offset,
tz->type[0].isdst,
@@ -355,8 +392,8 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
tz->type[0].isstdcnt,
tz->type[0].isgmtcnt
);
- for (i = 0; i < tz->bit32.timecnt; i++) {
- printf ("%08X (%12d) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
+ for (i = 0; i < tz->bit64.timecnt; i++) {
+ printf ("%016lX (%20ld) = %3d [%5ld %1d %3d '%s' (%d,%d)]\n",
tz->trans[i], tz->trans[i], tz->trans_idx[i],
(long int) tz->type[tz->trans_idx[i]].offset,
tz->type[tz->trans_idx[i]].isdst,
@@ -366,8 +403,8 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
tz->type[tz->trans_idx[i]].isgmtcnt
);
}
- for (i = 0; i < tz->bit32.leapcnt; i++) {
- printf ("%08X (%12ld) = %d\n",
+ for (i = 0; i < tz->bit64.leapcnt; i++) {
+ printf ("%016lX (%20ld) = %d\n",
tz->leap_times[i].trans,
(long) tz->leap_times[i].trans,
tz->leap_times[i].offset);
@@ -470,31 +507,35 @@ timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb, i
timelib_tzinfo_dtor(tmp);
return NULL;
}
+ if (version < 2 || version > 3) {
+ *error_code = TIMELIB_ERROR_UNSUPPORTED_VERSION;
+ timelib_tzinfo_dtor(tmp);
+ return NULL;
+ }
//printf("- timezone: %s, version: %0d\n", timezone, version);
- read_header(&tzf, tmp);
- if ((transitions_result = read_transitions(&tzf, tmp)) != 0) {
+ read_32bit_header(&tzf, tmp);
+ skip_32bit_transitions(&tzf, tmp);
+ skip_32bit_types(&tzf, tmp);
+
+ if (!skip_64bit_preamble(&tzf, tmp)) {
+ /* 64 bit preamble is not in place */
+ *error_code = TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE;
+ return NULL;
+ }
+ read_64bit_header(&tzf, tmp);
+ if ((transitions_result = read_64bit_transitions(&tzf, tmp)) != 0) {
/* Corrupt file as transitions do not increase */
*error_code = transitions_result;
timelib_tzinfo_dtor(tmp);
return NULL;
}
- if ((types_result = read_types(&tzf, tmp)) != 0) {
+ if ((types_result = read_64bit_types(&tzf, tmp)) != 0) {
*error_code = types_result;
timelib_tzinfo_dtor(tmp);
return NULL;
}
- if (version == 2 || version == 3) {
- if (!skip_64bit_preamble(&tzf, tmp)) {
- /* 64 bit preamble is not in place */
- *error_code = TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE;
- return NULL;
- }
- read_64bit_header(&tzf, tmp);
- skip_64bit_transitions(&tzf, tmp);
- skip_64bit_types(&tzf, tmp);
- skip_posix_string(&tzf, tmp);
- }
+ skip_posix_string(&tzf, tmp);
if (type == TIMELIB_TZINFO_PHP) {
read_location(&tzf, tmp);
@@ -525,29 +566,35 @@ void timelib_tzinfo_dtor(timelib_tzinfo *tz)
timelib_tzinfo *timelib_tzinfo_clone(timelib_tzinfo *tz)
{
timelib_tzinfo *tmp = timelib_tzinfo_ctor(tz->name);
- tmp->bit32.ttisgmtcnt = tz->bit32.ttisgmtcnt;
- tmp->bit32.ttisstdcnt = tz->bit32.ttisstdcnt;
- tmp->bit32.leapcnt = tz->bit32.leapcnt;
- tmp->bit32.timecnt = tz->bit32.timecnt;
- tmp->bit32.typecnt = tz->bit32.typecnt;
- tmp->bit32.charcnt = tz->bit32.charcnt;
-
- if (tz->bit32.timecnt) {
- tmp->trans = (int32_t *) timelib_malloc(tz->bit32.timecnt * sizeof(int32_t));
- tmp->trans_idx = (unsigned char*) timelib_malloc(tz->bit32.timecnt * sizeof(unsigned char));
- memcpy(tmp->trans, tz->trans, tz->bit32.timecnt * sizeof(int32_t));
- memcpy(tmp->trans_idx, tz->trans_idx, tz->bit32.timecnt * sizeof(unsigned char));
+ tmp->_bit32.ttisgmtcnt = tz->_bit32.ttisgmtcnt;
+ tmp->_bit32.ttisstdcnt = tz->_bit32.ttisstdcnt;
+ tmp->_bit32.leapcnt = tz->_bit32.leapcnt;
+ tmp->_bit32.timecnt = tz->_bit32.timecnt;
+ tmp->_bit32.typecnt = tz->_bit32.typecnt;
+ tmp->_bit32.charcnt = tz->_bit32.charcnt;
+ tmp->bit64.ttisgmtcnt = tz->bit64.ttisgmtcnt;
+ tmp->bit64.ttisstdcnt = tz->bit64.ttisstdcnt;
+ tmp->bit64.leapcnt = tz->bit64.leapcnt;
+ tmp->bit64.timecnt = tz->bit64.timecnt;
+ tmp->bit64.typecnt = tz->bit64.typecnt;
+ tmp->bit64.charcnt = tz->bit64.charcnt;
+
+ if (tz->bit64.timecnt) {
+ tmp->trans = (int64_t *) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
+ tmp->trans_idx = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
+ memcpy(tmp->trans, tz->trans, tz->bit64.timecnt * sizeof(int64_t));
+ memcpy(tmp->trans_idx, tz->trans_idx, tz->bit64.timecnt * sizeof(unsigned char));
}
- tmp->type = (ttinfo*) timelib_malloc(tz->bit32.typecnt * sizeof(ttinfo));
- memcpy(tmp->type, tz->type, tz->bit32.typecnt * sizeof(ttinfo));
+ tmp->type = (ttinfo*) timelib_malloc(tz->bit64.typecnt * sizeof(ttinfo));
+ memcpy(tmp->type, tz->type, tz->bit64.typecnt * sizeof(ttinfo));
- tmp->timezone_abbr = (char*) timelib_malloc(tz->bit32.charcnt);
- memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->bit32.charcnt);
+ tmp->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
+ memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->bit64.charcnt);
- if (tz->bit32.leapcnt) {
- tmp->leap_times = (tlinfo*) timelib_malloc(tz->bit32.leapcnt * sizeof(tlinfo));
- memcpy(tmp->leap_times, tz->leap_times, tz->bit32.leapcnt * sizeof(tlinfo));
+ if (tz->bit64.leapcnt) {
+ tmp->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
+ memcpy(tmp->leap_times, tz->leap_times, tz->bit64.leapcnt * sizeof(tlinfo));
}
return tmp;
@@ -559,9 +606,9 @@ static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib
/* If there is no transition time, we pick the first one, if that doesn't
* exist we return NULL */
- if (!tz->bit32.timecnt || !tz->trans) {
+ if (!tz->bit64.timecnt || !tz->trans) {
*transition_time = 0;
- if (tz->bit32.typecnt == 1) {
+ if (tz->bit64.typecnt == 1) {
return &(tz->type[0]);
}
return NULL;
@@ -572,40 +619,30 @@ static ttinfo* fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib
* one in case there are only DST entries. Not sure which smartass came up
* with this idea in the first though :) */
if (ts < tz->trans[0]) {
- uint32_t j;
-
- *transition_time = 0;
- j = 0;
- while (j < tz->bit32.timecnt && tz->type[tz->trans_idx[j]].isdst) {
- ++j;
- }
- if (j == tz->bit32.timecnt) {
- j = 0;
- }
- return &(tz->type[tz->trans_idx[j]]);
+ return &(tz->type[0]);
}
/* In all other cases we loop through the available transition times to find
* the correct entry */
- for (i = 0; i < tz->bit32.timecnt; i++) {
+ for (i = 0; i < tz->bit64.timecnt; i++) {
if (ts < tz->trans[i]) {
*transition_time = tz->trans[i - 1];
return &(tz->type[tz->trans_idx[i - 1]]);
}
}
- *transition_time = tz->trans[tz->bit32.timecnt - 1];
- return &(tz->type[tz->trans_idx[tz->bit32.timecnt - 1]]);
+ *transition_time = tz->trans[tz->bit64.timecnt - 1];
+ return &(tz->type[tz->trans_idx[tz->bit64.timecnt - 1]]);
}
static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
{
int i;
- if (!tz->bit32.leapcnt || !tz->leap_times) {
+ if (!tz->bit64.leapcnt || !tz->leap_times) {
return NULL;
}
- for (i = tz->bit32.leapcnt - 1; i > 0; i--) {
+ for (i = tz->bit64.leapcnt - 1; i > 0; i--) {
if (ts > tz->leap_times[i].trans) {
return &(tz->leap_times[i]);
}
diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h
index 537c75a695..72f81992fc 100644
--- a/ext/date/lib/timelib.h
+++ b/ext/date/lib/timelib.h
@@ -153,7 +153,7 @@ typedef struct _timelib_tzinfo
uint32_t timecnt;
uint32_t typecnt;
uint32_t charcnt;
- } bit32;
+ } _bit32;
struct {
uint64_t ttisgmtcnt;
uint64_t ttisstdcnt;
@@ -163,7 +163,7 @@ typedef struct _timelib_tzinfo
uint64_t charcnt;
} bit64;
- int32_t *trans;
+ int64_t *trans;
unsigned char *trans_idx;
ttinfo *type;
@@ -322,8 +322,8 @@ typedef struct _timelib_tzdb {
#endif
#define TIMELIB_VERSION 201801
-#define TIMELIB_EXTENDED_VERSION 20180104
-#define TIMELIB_ASCII_VERSION "2018.01RC2"
+#define TIMELIB_EXTENDED_VERSION 20180105
+#define TIMELIB_ASCII_VERSION "2018.01RC3"
#define TIMELIB_NONE 0x00
#define TIMELIB_OVERRIDE_TIME 0x01
diff --git a/ext/date/lib/timelib_private.h b/ext/date/lib/timelib_private.h
index ac75a46a28..b2116e63a2 100644
--- a/ext/date/lib/timelib_private.h
+++ b/ext/date/lib/timelib_private.h
@@ -123,7 +123,7 @@ struct _ttinfo
struct _tlinfo
{
- int32_t trans;
+ int64_t trans;
int32_t offset;
};
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index c152c71d3d..7b1836e938 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -4032,7 +4032,7 @@ PHP_FUNCTION(timezone_transitions_get)
add_assoc_string(&element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].abbr_idx]); \
add_next_index_zval(return_value, &element);
-#define add_last() add(tzobj->tzi.tz->bit32.timecnt - 1, timestamp_begin)
+#define add_last() add(tzobj->tzi.tz->bit64.timecnt - 1, timestamp_begin)
array_init(return_value);
@@ -4043,7 +4043,7 @@ PHP_FUNCTION(timezone_transitions_get)
} else {
begin = 0;
found = 0;
- if (tzobj->tzi.tz->bit32.timecnt > 0) {
+ if (tzobj->tzi.tz->bit64.timecnt > 0) {
do {
if (tzobj->tzi.tz->trans[begin] > timestamp_begin) {
if (begin > 0) {
@@ -4055,19 +4055,19 @@ PHP_FUNCTION(timezone_transitions_get)
break;
}
begin++;
- } while (begin < tzobj->tzi.tz->bit32.timecnt);
+ } while (begin < tzobj->tzi.tz->bit64.timecnt);
}
}
if (!found) {
- if (tzobj->tzi.tz->bit32.timecnt > 0) {
+ if (tzobj->tzi.tz->bit64.timecnt > 0) {
add_last();
} else {
add_nominal();
}
} else {
unsigned int i;
- for (i = begin; i < tzobj->tzi.tz->bit32.timecnt; ++i) {
+ for (i = begin; i < tzobj->tzi.tz->bit64.timecnt; ++i) {
if (tzobj->tzi.tz->trans[i] < timestamp_end) {
add(i, tzobj->tzi.tz->trans[i]);
}