@@ -167,9 +167,11 @@ PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};
167167 QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
168168 workaround will no longer be needed when Qt 5.6.1 and earlier are
169169 obsolete, say in the year 2021. */
170+ #ifndef WORK_AROUND_QTBUG_53071
170171enum
171172{
172173WORK_AROUND_QTBUG_53071 = true};
174+ #endif
173175
174176static int charcnt ;
175177static bool errors ;
@@ -1912,12 +1914,6 @@ atcomp(const void *avp, const void *bvp)
19121914 return (a < b ) ? -1 : (a > b );
19131915}
19141916
1915- static bool
1916- is32 (const zic_t x )
1917- {
1918- return x == ((zic_t ) ((int32 ) x ));
1919- }
1920-
19211917static void
19221918swaptypes (int i , int j )
19231919{
@@ -1971,7 +1967,12 @@ writezone(const char *const name, const char *const string, char version,
19711967 zic_t one = 1 ;
19721968 zic_t y2038_boundary = one << 31 ;
19731969 ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071 ;
1974- zic_t * ats = emalloc (size_product (nats , sizeof * ats + 1 ));
1970+
1971+ /*
1972+ * Allocate the ATS and TYPES arrays via a single malloc, as this is a bit
1973+ * faster.
1974+ */
1975+ zic_t * ats = emalloc (MAXALIGN (size_product (nats , sizeof * ats + 1 )));
19751976 void * typesptr = ats + nats ;
19761977 unsigned char * types = typesptr ;
19771978
@@ -2029,20 +2030,6 @@ writezone(const char *const name, const char *const string, char version,
20292030 types [i ] = attypes [i ].type ;
20302031 }
20312032
2032- /*
2033- * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
2034- * inserting a no-op transition at time y2038_boundary - 1. This works
2035- * only for timestamps before the boundary, which should be good enough in
2036- * practice as QTBUG-53071 should be long-dead by 2038.
2037- */
2038- if (WORK_AROUND_QTBUG_53071 && timecnt != 0
2039- && ats [timecnt - 1 ] < y2038_boundary - 1 && strchr (string , '<' ))
2040- {
2041- ats [timecnt ] = y2038_boundary - 1 ;
2042- types [timecnt ] = types [timecnt - 1 ];
2043- timecnt ++ ;
2044- }
2045-
20462033 /*
20472034 * Correct for leap seconds.
20482035 */
@@ -2057,32 +2044,48 @@ writezone(const char *const name, const char *const string, char version,
20572044 }
20582045 }
20592046
2047+ /*
2048+ * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
2049+ * inserting a no-op transition at time y2038_boundary - 1. This works
2050+ * only for timestamps before the boundary, which should be good enough in
2051+ * practice as QTBUG-53071 should be long-dead by 2038. Do this after
2052+ * correcting for leap seconds, as the idea is to insert a transition just
2053+ * before 32-bit pg_time_t rolls around, and this occurs at a slightly
2054+ * different moment if transitions are leap-second corrected.
2055+ */
2056+ if (WORK_AROUND_QTBUG_53071 && timecnt != 0
2057+ && ats [timecnt - 1 ] < y2038_boundary - 1 && strchr (string , '<' ))
2058+ {
2059+ ats [timecnt ] = y2038_boundary - 1 ;
2060+ types [timecnt ] = types [timecnt - 1 ];
2061+ timecnt ++ ;
2062+ }
2063+
20602064 /*
20612065 * Figure out 32-bit-limited starts and counts.
20622066 */
20632067 timecnt32 = timecnt ;
20642068 timei32 = 0 ;
20652069 leapcnt32 = leapcnt ;
20662070 leapi32 = 0 ;
2067- while (timecnt32 > 0 && ! is32 ( ats [timecnt32 - 1 ]) )
2071+ while (0 < timecnt32 && PG_INT32_MAX < ats [timecnt32 - 1 ])
20682072 -- timecnt32 ;
2069- while (timecnt32 > 0 && !is32 (ats [timei32 ]))
2073+ while (1 < timecnt32 && ats [timei32 ] < PG_INT32_MIN
2074+ && ats [timei32 + 1 ] <= PG_INT32_MIN )
20702075 {
2076+ /*
2077+ * Discard too-low transitions, except keep any last too-low
2078+ * transition if no transition is exactly at PG_INT32_MIN. The kept
2079+ * transition will be output as an PG_INT32_MIN "transition"
2080+ * appropriate for buggy 32-bit clients that do not use time type 0
2081+ * for timestamps before the first transition; see below.
2082+ */
20712083 -- timecnt32 ;
20722084 ++ timei32 ;
20732085 }
2074-
2075- /*
2076- * Output an INT32_MIN "transition" if appropriate; see below.
2077- */
2078- if (timei32 > 0 && ats [timei32 ] > PG_INT32_MIN )
2079- {
2080- -- timei32 ;
2081- ++ timecnt32 ;
2082- }
2083- while (leapcnt32 > 0 && !is32 (trans [leapcnt32 - 1 ]))
2086+ while (0 < leapcnt32 && PG_INT32_MAX < trans [leapcnt32 - 1 ])
20842087 -- leapcnt32 ;
2085- while (leapcnt32 > 0 && ! is32 ( trans [leapi32 ]) )
2088+ while (0 < leapcnt32 && trans [leapi32 ] < PG_INT32_MIN )
20862089 {
20872090 -- leapcnt32 ;
20882091 ++ leapi32 ;
@@ -2315,7 +2318,8 @@ writezone(const char *const name, const char *const string, char version,
23152318 if (pass == 1 )
23162319
23172320 /*
2318- * Output an INT32_MIN "transition" if appropriate; see above.
2321+ * Output an PG_INT32_MIN "transition" if appropriate; see
2322+ * above.
23192323 */
23202324 puttzcode (((ats [i ] < PG_INT32_MIN ) ?
23212325 PG_INT32_MIN : ats [i ]), fp );
0 commit comments