* 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