[tz] [PROPOSED] Relax leap-second pickiness
Paul Eggert
eggert at cs.ucla.edu
Fri Sep 10 23:15:49 UTC 2021
* localtime.c (tzloadbody): Relax requirements on the leap second
table in a TZif file, to accommodate truncation at the start that
is less than 28 days before a leap second, or (unlikely, though
theoretically possible) expiration less than 28 days after the
last leap second.
---
localtime.c | 23 ++++++++++-------------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/localtime.c b/localtime.c
index e4f1a87..5f362d4 100644
--- a/localtime.c
+++ b/localtime.c
@@ -436,7 +436,7 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
for (stored = 4; stored <= 8; stored *= 2) {
int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
- int_fast64_t prevtr = 0;
+ int_fast64_t prevtr = -1;
int_fast32_t prevcorr;
int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
@@ -526,24 +526,21 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
int_fast32_t corr = detzcode(p + stored);
p += stored + 4;
- /* Leap seconds cannot occur before the Epoch. */
- if (tr < 0)
+ /* Leap seconds cannot occur before the Epoch,
+ or out of order. */
+ if (tr <= prevtr)
return EINVAL;
if (tr <= TIME_T_MAX) {
- /* Leap seconds cannot occur more than once per UTC month,
- and UTC months are at least 28 days long (minus 1
- second for a negative leap second). Each leap second's
+ /* To avoid other botches in this code, each leap second's
correction must differ from the previous one's by 1
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
- || ((timecnt == 0 || sp->ats[0] < tr)
- && ! (i == 0
- || (prevcorr < corr
- ? corr == prevcorr + 1
- : (corr == prevcorr
- || corr == prevcorr - 1)))))
+ if (! (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.31.1
More information about the tz
mailing list