From 11d493ae597f7f3e41afa441b93848aa2281209c Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 12 Jan 2017 08:34:21 -0800 Subject: [PATCH] Fix bug for pre-1970 POSIX DST, 32-bit time_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * localtime.c (tzparse): Fill in the table before 1970, if POSIX DST is specified. This is needed on 32-bit platforms, since they don’t have the time_t space for a 400-year repeat. This finishes the fix for the problem reported by Kees Dekker in: http://mm.icann.org/pipermail/tz/2017-January/024736.html --- localtime.c | 50 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/localtime.c b/localtime.c index 5f63801..3967e90 100644 --- a/localtime.c +++ b/localtime.c @@ -1080,6 +1080,8 @@ tzparse(const char *name, struct state *sp, bool lastditch) register int yearlim; register int timecnt; time_t janfirst; + int_fast32_t janoffset = 0; + int yearbeg; ++name; if ((name = getrule(name, &start)) == NULL) @@ -1099,8 +1101,20 @@ tzparse(const char *name, struct state *sp, bool lastditch) sp->defaulttype = 0; timecnt = 0; janfirst = 0; - yearlim = EPOCH_YEAR + YEARSPERREPEAT; - for (year = EPOCH_YEAR; year < yearlim; year++) { + yearbeg = EPOCH_YEAR; + + do { + int_fast32_t yearsecs + = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY; + yearbeg--; + if (increment_overflow_time(&janfirst, -yearsecs)) { + janoffset = -yearsecs; + break; + } + } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg); + + yearlim = yearbeg + YEARSPERREPEAT + 1; + for (year = yearbeg; year < yearlim; year++) { int_fast32_t starttime = transtime(year, &start, stdoffset), endtime = transtime(year, &end, dstoffset); @@ -1120,26 +1134,32 @@ tzparse(const char *name, struct state *sp, bool lastditch) + (stdoffset - dstoffset))))) { if (TZ_MAX_TIMES - 2 < timecnt) break; - yearlim = year + YEARSPERREPEAT + 1; sp->ats[timecnt] = janfirst; - if (increment_overflow_time - (&sp->ats[timecnt], starttime)) - break; - sp->types[timecnt++] = reversed; + if (! increment_overflow_time + (&sp->ats[timecnt], + janoffset + starttime)) + sp->types[timecnt++] = reversed; + else if (janoffset) + sp->defaulttype = reversed; sp->ats[timecnt] = janfirst; - if (increment_overflow_time - (&sp->ats[timecnt], endtime)) - break; - sp->types[timecnt++] = !reversed; + if (! increment_overflow_time + (&sp->ats[timecnt], + janoffset + endtime)) { + sp->types[timecnt++] = !reversed; + yearlim = year + YEARSPERREPEAT + 1; + } else if (janoffset) + sp->defaulttype = !reversed; } - if (increment_overflow_time(&janfirst, yearsecs)) + if (increment_overflow_time + (&janfirst, janoffset + yearsecs)) break; + janoffset = 0; } sp->timecnt = timecnt; - if (timecnt) - sp->goback = sp->goahead = true; - else + if (! timecnt) sp->typecnt = 1; /* Perpetual DST. */ + else if (YEARSPERREPEAT < year - yearbeg) + sp->goback = sp->goahead = true; } else { register int_fast32_t theirstdoffset; register int_fast32_t theirdstoffset; -- 2.9.3