@@ -179,9 +179,11 @@ PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};
179179 QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
180180 workaround will no longer be needed when Qt 5.6.1 and earlier are
181181 obsolete, say in the year 2021. */
182+ #ifndef WORK_AROUND_QTBUG_53071
182183enum
183184{
184185WORK_AROUND_QTBUG_53071 = true};
186+ #endif
185187
186188static int charcnt ;
187189static bool errors ;
@@ -1924,12 +1926,6 @@ atcomp(const void *avp, const void *bvp)
19241926 return (a < b ) ? -1 : (a > b );
19251927}
19261928
1927- static bool
1928- is32 (const zic_t x )
1929- {
1930- return x == ((zic_t ) ((int32 ) x ));
1931- }
1932-
19331929static void
19341930swaptypes (int i , int j )
19351931{
@@ -1983,7 +1979,12 @@ writezone(const char *const name, const char *const string, char version,
19831979 zic_t one = 1 ;
19841980 zic_t y2038_boundary = one << 31 ;
19851981 ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071 ;
1986- zic_t * ats = emalloc (size_product (nats , sizeof * ats + 1 ));
1982+
1983+ /*
1984+ * Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
1985+ * faster.
1986+ */
1987+ zic_t * ats = emalloc (MAXALIGN (size_product (nats , sizeof * ats + 1 )));
19871988 void * typesptr = ats + nats ;
19881989 unsigned char * types = typesptr ;
19891990
@@ -2041,20 +2042,6 @@ writezone(const char *const name, const char *const string, char version,
20412042 types [i ] = attypes [i ].type ;
20422043 }
20432044
2044- /*
2045- * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
2046- * inserting a no-op transition at time y2038_boundary - 1. This works
2047- * only for timestamps before the boundary, which should be good enough in
2048- * practice as QTBUG-53071 should be long-dead by 2038.
2049- */
2050- if (WORK_AROUND_QTBUG_53071 && timecnt != 0
2051- && ats [timecnt - 1 ] < y2038_boundary - 1 && strchr (string , '<' ))
2052- {
2053- ats [timecnt ] = y2038_boundary - 1 ;
2054- types [timecnt ] = types [timecnt - 1 ];
2055- timecnt ++ ;
2056- }
2057-
20582045 /*
20592046 * Correct for leap seconds.
20602047 */
@@ -2069,32 +2056,48 @@ writezone(const char *const name, const char *const string, char version,
20692056 }
20702057 }
20712058
2059+ /*
2060+ * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
2061+ * inserting a no-op transition at time y2038_boundary - 1. This works
2062+ * only for timestamps before the boundary, which should be good enough in
2063+ * practice as QTBUG-53071 should be long-dead by 2038. Do this after
2064+ * correcting for leap seconds, as the idea is to insert a transition just
2065+ * before 32-bit pg_time_t rolls around, and this occurs at a slightly
2066+ * different moment if transitions are leap-second corrected.
2067+ */
2068+ if (WORK_AROUND_QTBUG_53071 && timecnt != 0
2069+ && ats [timecnt - 1 ] < y2038_boundary - 1 && strchr (string , '<' ))
2070+ {
2071+ ats [timecnt ] = y2038_boundary - 1 ;
2072+ types [timecnt ] = types [timecnt - 1 ];
2073+ timecnt ++ ;
2074+ }
2075+
20722076 /*
20732077 * Figure out 32-bit-limited starts and counts.
20742078 */
20752079 timecnt32 = timecnt ;
20762080 timei32 = 0 ;
20772081 leapcnt32 = leapcnt ;
20782082 leapi32 = 0 ;
2079- while (timecnt32 > 0 && ! is32 ( ats [timecnt32 - 1 ]) )
2083+ while (0 < timecnt32 && PG_INT32_MAX < ats [timecnt32 - 1 ])
20802084 -- timecnt32 ;
2081- while (timecnt32 > 0 && !is32 (ats [timei32 ]))
2085+ while (1 < timecnt32 && ats [timei32 ] < PG_INT32_MIN
2086+ && ats [timei32 + 1 ] <= PG_INT32_MIN )
20822087 {
2088+ /*
2089+ * Discard too-low transitions, except keep any last too-low
2090+ * transition if no transition is exactly at PG_INT32_MIN. The kept
2091+ * transition will be output as an PG_INT32_MIN "transition"
2092+ * appropriate for buggy 32-bit clients that do not use time type 0
2093+ * for timestamps before the first transition; see below.
2094+ */
20832095 -- timecnt32 ;
20842096 ++ timei32 ;
20852097 }
2086-
2087- /*
2088- * Output an INT32_MIN "transition" if appropriate; see below.
2089- */
2090- if (timei32 > 0 && ats [timei32 ] > PG_INT32_MIN )
2091- {
2092- -- timei32 ;
2093- ++ timecnt32 ;
2094- }
2095- while (leapcnt32 > 0 && !is32 (trans [leapcnt32 - 1 ]))
2098+ while (0 < leapcnt32 && PG_INT32_MAX < trans [leapcnt32 - 1 ])
20962099 -- leapcnt32 ;
2097- while (leapcnt32 > 0 && ! is32 ( trans [leapi32 ]) )
2100+ while (0 < leapcnt32 && trans [leapi32 ] < PG_INT32_MIN )
20982101 {
20992102 -- leapcnt32 ;
21002103 ++ leapi32 ;
@@ -2327,7 +2330,8 @@ writezone(const char *const name, const char *const string, char version,
23272330 if (pass == 1 )
23282331
23292332 /*
2330- * Output an INT32_MIN "transition" if appropriate; see above.
2333+ * Output an PG_INT32_MIN "transition" if appropriate; see
2334+ * above.
23312335 */
23322336 puttzcode (((ats [i ] < PG_INT32_MIN ) ?
23332337 PG_INT32_MIN : ats [i ]), fp );
0 commit comments