Parcourir la source

Don't mistruncate TZif files at leap seconds

Without this fix, zic mishandles the command
‘zic -L leapseconds -r @1706745601 etcetera’ when ‘leapseconds’
is generated from the test data file mentioned in:
https://mm.icann.org/pipermail/tz/2021-September/030385.html
The resulting, incorrect TZif file causes
‘TZ=Etc/GMT date -r 1706745601’ to output
"Thu Feb  1 00:00:01 GMT 2024" instead of the correct
"Thu Feb  1 00:00:00 GMT 2024", because localtime misinterprets
the leap second entry at 1706745601 to be a positive instead of a
negative leap second.
* NEWS: Mention the fix.
* zic.c (limitrange): When omitting leading leap seconds, do not
output a leap second table that starts with a positive leap second
with a nonpositive correction (or with a negative leap second with
a positive correction) as that will confuse TZif readers into
thinking the positive leap second is negative or vice versa.
Instead, keep otherwise-unnecessary leading leap seconds to
avoid the confusion.
Paul Eggert il y a 4 ans
Parent
commit
df12babf4e
2 fichiers modifiés avec 18 ajouts et 2 suppressions
  1. 6 0
      NEWS
  2. 12 2
      zic.c

+ 6 - 0
NEWS

@@ -139,6 +139,12 @@ Unreleased, experimental changes
     last time transition disagreed with the TZ string, contrary to
     Internet RFC 8563 section 3.3.
 
+    Fix a bug with 'zic -r @X' when X is a negative leap second that
+    has a nonnegative correction.  Without the fix, the output file
+    was truncated so that X appeared to be a positive leap second.
+    Fix a similar, even-less-likely bug when truncating at a positive
+    leap second that has a nonpositive correction.
+
     zic -r now reports an error if given rolling leap seconds, as this
     usage has never generally worked and is evidently unused.
 

+ 12 - 2
zic.c

@@ -1972,12 +1972,22 @@ limitrange(struct timerange r, bool locut, zic_t lo, zic_t hi,
     r.base++;
   }
 
-  /* Omit as many leap seconds < LO as possible, such that the first
-     leap second in the truncated list is <= LO.  */
+  /* Omit as many initial leap seconds as possible, such that the
+     first leap second in the truncated list is <= LO, and is a
+     positive leap second if and only if it has a positive correction.
+     This supports common TZif readers that assume that the first leap
+     second is positive if and only if its correction is positive.  */
   while (1 < r.leapcount && trans[r.leapbase + 1] <= lo) {
     r.leapcount--;
     r.leapbase++;
   }
+  while (0 < r.leapbase
+	 && ((corr[r.leapbase - 1] < corr[r.leapbase])
+	     != (0 < corr[r.leapbase]))) {
+    r.leapcount++;
+    r.leapbase--;
+  }
+
 
   /* Omit ordinary and leap second transitions greater than HI + 1.  */
   if (hi < ZIC_MAX) {