[tz] [PATCH 3/7] Fix unlikely Y2038 leap second bug
Paul Eggert
eggert at cs.ucla.edu
Wed Mar 17 01:46:01 UTC 2021
* NEWS: Mention this.
* localtime.c (tzloadbody): Don’t misbehave if adding the
leap second correction overflows time_t.
---
NEWS | 4 ++++
localtime.c | 19 +++++++++----------
2 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/NEWS b/NEWS
index d8676e6..5b26bd2 100644
--- a/NEWS
+++ b/NEWS
@@ -52,6 +52,10 @@ Unreleased, experimental changes
set to a POSIX-conforming but unusual TZ string like
"EST5EDT4,0/0,J365/0", where almost all the year is DST.
+ Fix an unlikely bug that caused 'localtime' etc. to misbehave if
+ civil time changes a few seconds before time_t wraps around, when
+ leap seconds are enabled.
+
Fix bug in zic -r; in some cases, the dummy time type after the
last time transition disagreed with the TZ string, contrary to
Internet RFC 8563 section 3.3.
diff --git a/localtime.c b/localtime.c
index 5b8f278..0d34ead 100644
--- a/localtime.c
+++ b/localtime.c
@@ -639,19 +639,18 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
== sp->types[sp->timecnt - 2]))
sp->timecnt--;
- for (i = 0; i < ts->timecnt; i++)
- if (sp->timecnt == 0
- || (sp->ats[sp->timecnt - 1]
- < ts->ats[i] + leapcorr(sp, ts->ats[i])))
- break;
- while (i < ts->timecnt
- && sp->timecnt < TZ_MAX_TIMES) {
- sp->ats[sp->timecnt]
- = ts->ats[i] + leapcorr(sp, ts->ats[i]);
+ for (i = 0;
+ i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES;
+ i++) {
+ time_t t = ts->ats[i];
+ if (increment_overflow_time(&t, leapcorr(sp, t))
+ || (0 < sp->timecnt
+ && t <= sp->ats[sp->timecnt - 1]))
+ continue;
+ sp->ats[sp->timecnt] = t;
sp->types[sp->timecnt] = (sp->typecnt
+ ts->types[i]);
sp->timecnt++;
- i++;
}
for (i = 0; i < ts->typecnt; i++)
sp->ttis[sp->typecnt++] = ts->ttis[i];
--
2.27.0
More information about the tz
mailing list