[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