[tz] [PROPOSED PATCH 1/2] Mostly work around Qt bug 53071 by inserting dummy
Paul Eggert
eggert at cs.ucla.edu
Sun May 1 08:56:52 UTC 2016
Problem reported by Zhanibek Adilbekov in:
http://mm.icann.org/pipermail/tz/2016-April/023605.html
Also see the Qt bug report in:
https://bugreports.qt.io/browse/QTBUG-53071
* NEWS: Document this.
* zic.c (WORK_AROUND_QTBUG_53071): New constant.
(growalloc): Don't grow past INT_MAX - 1 if the bug is present,
since we add 1 at the end.
(writezone) [WORK_AROUND_QTBUG_53071]: Work around most of
QTBUG-53071, by inserting a dummy transition at time 2**31 - 1.
---
NEWS | 7 +++++++
zic.c | 30 +++++++++++++++++++++++++++---
2 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index e16f489..b5fb182 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,13 @@ Unreleased, experimental changes
Asia/Baku's 1992-09-27 transition from +04 (DST) to +04 (non-DST) was
at 03:00, not 23:00 the previous day. (Thanks to Michael Deckers.)
+ Changes to code
+
+ zic now outputs a dummy transition at time 2**31 - 1 in zones
+ whose POSIX-style TZ strings contain a '<'. This mostly works
+ around Qt bug 53071 <https://bugreports.qt.io/browse/QTBUG-53071>.
+ (Thanks to Zhanibek Adilbekov for reporting the Qt bug.)
+
Changes affecting documentation and commentary
tz-link.htm says why governments should give plenty of notice for
diff --git a/zic.c b/zic.c
index 0ec3359..3b32f9b 100644
--- a/zic.c
+++ b/zic.c
@@ -143,6 +143,13 @@ static bool yearistype(int year, const char * type);
/* Bound on length of what %z can expand to. */
enum { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1 };
+/* If true, work around a bug in Qt 5.6 and earlier, which mishandles
+ tzdata binary files whose POSIX-TZ-style strings contain '<'; see
+ QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
+ workaround will no longer be needed when Qt 5.6 is obsolete, say in
+ the year 2021. */
+enum { WORK_AROUND_QTBUG_53071 = true };
+
static int charcnt;
static bool errors;
static bool warnings;
@@ -420,7 +427,8 @@ growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
if (nitems < *nitems_alloc)
return ptr;
else {
- int amax = INT_MAX < SIZE_MAX ? INT_MAX : SIZE_MAX;
+ int nitems_max = INT_MAX - WORK_AROUND_QTBUG_53071;
+ int amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
if ((amax - 1) / 3 * 2 < *nitems_alloc)
memory_exhausted(_("int overflow"));
*nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1;
@@ -1616,8 +1624,11 @@ writezone(const char *const name, const char *const string, char version)
char * fullname;
static const struct tzhead tzh0;
static struct tzhead tzh;
- zic_t *ats = emalloc(size_product(timecnt, sizeof *ats + 1));
- void *typesptr = ats + timecnt;
+ zic_t one = 1;
+ zic_t y2038_boundary = one << 31;
+ int nats = timecnt + WORK_AROUND_QTBUG_53071;
+ zic_t *ats = emalloc(size_product(nats, sizeof *ats + 1));
+ void *typesptr = ats + nats;
unsigned char *types = typesptr;
/*
@@ -1661,6 +1672,19 @@ writezone(const char *const name, const char *const string, char version)
ats[i] = attypes[i].at;
types[i] = attypes[i].type;
}
+
+ /* Work around QTBUG-53071 for time stamps 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.
*/
--
2.7.4
More information about the tz
mailing list