[tz] [PATCH 1/7] localtime.c is less finicky about leap seconds
Paul Eggert
eggert at cs.ucla.edu
Wed Mar 17 01:45:59 UTC 2021
* localtime.c (tzloadbody): Do not reject a TZif file merely
because its leap second table contains adjacent entries with
equal corrections, or contains a first entry with a correction
value other than +1 or -1.
* NEWS: Mention this.
---
NEWS | 5 +++++
localtime.c | 13 ++++++++++---
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/NEWS b/NEWS
index 0de05f3..d8676e6 100644
--- a/NEWS
+++ b/NEWS
@@ -39,6 +39,11 @@ Unreleased, experimental changes
seconds error than with an hour error, so zic -L no longer
truncates output in this way.
+ The TZif reader now allows the leap second table to begin with a
+ correction other than -1 or +1, and to contain adjacent
+ transitions with equal corrections. This supports possible
+ future extensions to the TZif format.
+
Fix bug that caused 'localtime' etc. to crash when TZ was
set to a all-year DST string like "EST5EDT4,0/0,J365/25" that does
not conform to POSIX but does conform to Internet RFC 8536.
diff --git a/localtime.c b/localtime.c
index 6627ff2..a086d4d 100644
--- a/localtime.c
+++ b/localtime.c
@@ -445,7 +445,7 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
int_fast64_t prevtr = 0;
- int_fast32_t prevcorr = 0;
+ int_fast32_t prevcorr;
int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
@@ -542,9 +542,16 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
and UTC months are at least 28 days long (minus 1
second for a negative leap second). Each leap second's
correction must differ from the previous one's by 1
- second. */
+ second or less, except that the first correction can be
+ any value; these requirements are more generous than
+ RFC 8536, to allow future RFC extensions. */
if (tr - prevtr < 28 * SECSPERDAY - 1
- || (corr != prevcorr - 1 && corr != prevcorr + 1))
+ || ((timecnt == 0 || sp->ats[0] < tr)
+ && ! (i == 0
+ || (prevcorr < corr
+ ? corr == prevcorr + 1
+ : (corr == prevcorr
+ || corr == prevcorr - 1)))))
return EINVAL;
sp->lsis[leapcnt].ls_trans = prevtr = tr;
sp->lsis[leapcnt].ls_corr = prevcorr = corr;
--
2.27.0
More information about the tz
mailing list