Skip to content

Commit 957aa22

Browse files
committed
Fixed location reading due to file format changes
1 parent 53c4999 commit 957aa22

File tree

2 files changed

+640
-587
lines changed

2 files changed

+640
-587
lines changed

ext/date/lib/parse_tz.c

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,12 @@
4949
#define timelib_conv_int(l) ((l & 0x000000ff) << 24) + ((l & 0x0000ff00) << 8) + ((l & 0x00ff0000) >> 8) + ((l & 0xff000000) >> 24)
5050
#endif
5151

52-
static void read_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
52+
static int read_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
5353
{
54-
/* skip ID */
54+
uint32_t version;
55+
56+
/* read ID */
57+
version = (*tzf)[3] - '0';
5558
*tzf += 4;
5659

5760
/* read BC flag */
@@ -63,8 +66,10 @@ static void read_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
6366
tz->location.country_code[2] = '\0';
6467
*tzf += 2;
6568

66-
/* skip read of preamble */
69+
/* skip rest of preamble */
6770
*tzf += 13;
71+
72+
return version;
6873
}
6974

7075
static void read_header(const unsigned char **tzf, timelib_tzinfo *tz)
@@ -81,6 +86,14 @@ static void read_header(const unsigned char **tzf, timelib_tzinfo *tz)
8186
*tzf += sizeof(buffer);
8287
}
8388

89+
static void skip_transistions_64bit(const unsigned char **tzf, timelib_tzinfo *tz)
90+
{
91+
if (tz->timecnt) {
92+
*tzf += (sizeof(int64_t) * (tz->timecnt + 1));
93+
*tzf += (sizeof(unsigned char) * (tz->timecnt + 1));
94+
}
95+
}
96+
8497
static void read_transistions(const unsigned char **tzf, timelib_tzinfo *tz)
8598
{
8699
int32_t *buffer = NULL;
@@ -111,6 +124,21 @@ static void read_transistions(const unsigned char **tzf, timelib_tzinfo *tz)
111124
tz->trans_idx = cbuffer;
112125
}
113126

127+
static void skip_types_64bit(const unsigned char **tzf, timelib_tzinfo *tz)
128+
{
129+
*tzf += sizeof(unsigned char) * 6 * tz->typecnt;
130+
*tzf += sizeof(char) * tz->charcnt;
131+
if (tz->leapcnt) {
132+
*tzf += sizeof(int64_t) * tz->leapcnt * 2;
133+
}
134+
if (tz->ttisstdcnt) {
135+
*tzf += sizeof(unsigned char) * tz->ttisstdcnt;
136+
}
137+
if (tz->ttisgmtcnt) {
138+
*tzf += sizeof(unsigned char) * tz->ttisgmtcnt;
139+
}
140+
}
141+
114142
static void read_types(const unsigned char **tzf, timelib_tzinfo *tz)
115143
{
116144
unsigned char *buffer;
@@ -194,6 +222,18 @@ static void read_types(const unsigned char **tzf, timelib_tzinfo *tz)
194222
}
195223
}
196224

225+
static void skip_posix_string(const unsigned char **tzf, timelib_tzinfo *tz)
226+
{
227+
int n_count = 0;
228+
229+
do {
230+
if (*tzf[0] == '\n') {
231+
n_count++;
232+
}
233+
(*tzf)++;
234+
} while (n_count < 2);
235+
}
236+
197237
static void read_location(const unsigned char **tzf, timelib_tzinfo *tz)
198238
{
199239
uint32_t buffer[3];
@@ -312,18 +352,31 @@ int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb)
312352
return (seek_to_tz_position(&tzf, timezone, tzdb));
313353
}
314354

355+
static void skip_2nd_header_and_data(const unsigned char **tzf, timelib_tzinfo *tz)
356+
{
357+
*tzf += 20; /* skip 2nd header (preamble) */
358+
*tzf += sizeof(int32_t) * 6; /* Counts */
359+
}
360+
315361
timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb)
316362
{
317363
const unsigned char *tzf;
318364
timelib_tzinfo *tmp;
365+
int version;
319366

320367
if (seek_to_tz_position(&tzf, timezone, tzdb)) {
321368
tmp = timelib_tzinfo_ctor(timezone);
322369

323-
read_preamble(&tzf, tmp);
370+
version = read_preamble(&tzf, tmp);
324371
read_header(&tzf, tmp);
325372
read_transistions(&tzf, tmp);
326373
read_types(&tzf, tmp);
374+
if (version == 2) {
375+
skip_2nd_header_and_data(&tzf, tmp);
376+
skip_transistions_64bit(&tzf, tmp);
377+
skip_types_64bit(&tzf, tmp);
378+
skip_posix_string(&tzf, tmp);
379+
}
327380
read_location(&tzf, tmp);
328381
} else {
329382
tmp = NULL;

0 commit comments

Comments
 (0)