summaryrefslogtreecommitdiff
path: root/src/timezone/zic.c
diff options
context:
space:
mode:
authorTom Lane2018-10-31 13:47:53 +0000
committerTom Lane2018-10-31 13:47:53 +0000
commit10bfda06176739faedf909c9aba9823cdd21165d (patch)
tree0591a69df56140968e4f620664164054035dc30f /src/timezone/zic.c
parent5c2e0ca5f0be780c5fa9c85f4cd4b1106ff747ab (diff)
Sync our copy of the timezone library with IANA release tzcode2018g.
This patch absorbs an upstream fix to "zic" for a recently-introduced bug that made it output data that some 32-bit clients couldn't read. Given the current source data, the bug only manifests in zones with leap seconds, which we don't generate, so that there's no actual change in our installed timezone data files from this. Still, in case somebody uses our copy of "zic" to do something else, it seems best to apply the fix promptly. Also, update the README's notes about converting upstream code to our conventions.
Diffstat (limited to 'src/timezone/zic.c')
-rw-r--r--src/timezone/zic.c74
1 files changed, 39 insertions, 35 deletions
diff --git a/src/timezone/zic.c b/src/timezone/zic.c
index ae61264364c..4613919afe4 100644
--- a/src/timezone/zic.c
+++ b/src/timezone/zic.c
@@ -167,9 +167,11 @@ PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};
QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
workaround will no longer be needed when Qt 5.6.1 and earlier are
obsolete, say in the year 2021. */
+#ifndef WORK_AROUND_QTBUG_53071
enum
{
WORK_AROUND_QTBUG_53071 = true};
+#endif
static int charcnt;
static bool errors;
@@ -1912,12 +1914,6 @@ atcomp(const void *avp, const void *bvp)
return (a < b) ? -1 : (a > b);
}
-static bool
-is32(const zic_t x)
-{
- return x == ((zic_t) ((int32) x));
-}
-
static void
swaptypes(int i, int j)
{
@@ -1971,7 +1967,12 @@ writezone(const char *const name, const char *const string, char version,
zic_t one = 1;
zic_t y2038_boundary = one << 31;
ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071;
- zic_t *ats = emalloc(size_product(nats, sizeof *ats + 1));
+
+ /*
+ * Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
+ * faster.
+ */
+ zic_t *ats = emalloc(MAXALIGN(size_product(nats, sizeof *ats + 1)));
void *typesptr = ats + nats;
unsigned char *types = typesptr;
@@ -2030,20 +2031,6 @@ writezone(const char *const name, const char *const string, char version,
}
/*
- * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
- * inserting a no-op transition at time y2038_boundary - 1. This works
- * only for timestamps before the boundary, which should be good enough in
- * practice as QTBUG-53071 should be long-dead by 2038.
- */
- if (WORK_AROUND_QTBUG_53071 && timecnt != 0
- && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<'))
- {
- ats[timecnt] = y2038_boundary - 1;
- types[timecnt] = types[timecnt - 1];
- timecnt++;
- }
-
- /*
* Correct for leap seconds.
*/
for (i = 0; i < timecnt; ++i)
@@ -2058,31 +2045,47 @@ writezone(const char *const name, const char *const string, char version,
}
/*
+ * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
+ * inserting a no-op transition at time y2038_boundary - 1. This works
+ * only for timestamps before the boundary, which should be good enough in
+ * practice as QTBUG-53071 should be long-dead by 2038. Do this after
+ * correcting for leap seconds, as the idea is to insert a transition just
+ * before 32-bit pg_time_t rolls around, and this occurs at a slightly
+ * different moment if transitions are leap-second corrected.
+ */
+ if (WORK_AROUND_QTBUG_53071 && timecnt != 0
+ && ats[timecnt - 1] < y2038_boundary - 1 && strchr(string, '<'))
+ {
+ ats[timecnt] = y2038_boundary - 1;
+ types[timecnt] = types[timecnt - 1];
+ timecnt++;
+ }
+
+ /*
* Figure out 32-bit-limited starts and counts.
*/
timecnt32 = timecnt;
timei32 = 0;
leapcnt32 = leapcnt;
leapi32 = 0;
- while (timecnt32 > 0 && !is32(ats[timecnt32 - 1]))
+ while (0 < timecnt32 && PG_INT32_MAX < ats[timecnt32 - 1])
--timecnt32;
- while (timecnt32 > 0 && !is32(ats[timei32]))
+ while (1 < timecnt32 && ats[timei32] < PG_INT32_MIN
+ && ats[timei32 + 1] <= PG_INT32_MIN)
{
+ /*
+ * Discard too-low transitions, except keep any last too-low
+ * transition if no transition is exactly at PG_INT32_MIN. The kept
+ * transition will be output as an PG_INT32_MIN "transition"
+ * appropriate for buggy 32-bit clients that do not use time type 0
+ * for timestamps before the first transition; see below.
+ */
--timecnt32;
++timei32;
}
-
- /*
- * Output an INT32_MIN "transition" if appropriate; see below.
- */
- if (timei32 > 0 && ats[timei32] > PG_INT32_MIN)
- {
- --timei32;
- ++timecnt32;
- }
- while (leapcnt32 > 0 && !is32(trans[leapcnt32 - 1]))
+ while (0 < leapcnt32 && PG_INT32_MAX < trans[leapcnt32 - 1])
--leapcnt32;
- while (leapcnt32 > 0 && !is32(trans[leapi32]))
+ while (0 < leapcnt32 && trans[leapi32] < PG_INT32_MIN)
{
--leapcnt32;
++leapi32;
@@ -2315,7 +2318,8 @@ writezone(const char *const name, const char *const string, char version,
if (pass == 1)
/*
- * Output an INT32_MIN "transition" if appropriate; see above.
+ * Output an PG_INT32_MIN "transition" if appropriate; see
+ * above.
*/
puttzcode(((ats[i] < PG_INT32_MIN) ?
PG_INT32_MIN : ats[i]), fp);