From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id 8D7B8383E82C; Mon, 4 May 2020 09:21:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8D7B8383E82C Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] localtime 1.81 X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/master X-Git-Oldrev: 9e29639ca01208a4a8bac5b9d0f6491b34b1017e X-Git-Newrev: 3003c3dacd157c11f5e035bc18bdd30631800720 Message-Id: <20200504092106.8D7B8383E82C@sourceware.org> Date: Mon, 4 May 2020 09:21:06 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 04 May 2020 09:21:06 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=3003c3dacd157c11f5e035bc18bdd30631800720 commit 3003c3dacd157c11f5e035bc18bdd30631800720 Author: Corinna Vinschen Date: Tue Apr 28 21:26:45 2020 +0200 localtime 1.81 Diff: --- winsup/cygwin/localtime.cc | 205 ++++++++++++++++++++++----------------------- 1 file changed, 101 insertions(+), 104 deletions(-) diff --git a/winsup/cygwin/localtime.cc b/winsup/cygwin/localtime.cc index b0a1a4f2d..7324fbd98 100644 --- a/winsup/cygwin/localtime.cc +++ b/winsup/cygwin/localtime.cc @@ -1,4 +1,4 @@ -/* $NetBSD: localtime.c,v 1.80 2013/12/13 10:37:24 christos Exp $ */ +/* $NetBSD: localtime.c,v 1.81 2013/12/26 18:34:28 christos Exp $ */ /* ** This file is in the public domain, so clarified as of @@ -88,7 +88,7 @@ static char privatehid[] = "@(#)private.h 7.48"; #if 0 static char elsieid[] = "@(#)localtime.cc 8.17"; #else -__RCSID("$NetBSD: localtime.c,v 1.80 2013/12/13 10:37:24 christos Exp $"); +__RCSID("$NetBSD: localtime.c,v 1.81 2013/12/26 18:34:28 christos Exp $"); #endif /* @@ -480,7 +480,7 @@ typedef struct tm *(*subfun_t)(const timezone_t sp, const time_t *timep, */ static int_fast32_t detzcode(const char * codep); -static time_t detzcode64(const char * codep); +static int_fast64_t detzcode64(const char * codep); static int differ_by_repeat(time_t t1, time_t t0); static const char * getzname(const char * strp) ATTRIBUTE_PURE; static const char * getqzname(const char * strp, const int delim) ATTRIBUTE_PURE; @@ -496,6 +496,7 @@ static struct tm * localsub(const timezone_t sp, const time_t *timep, const int_fast32_t offset, struct tm *tmp); static int increment_overflow(int * number, int delta); static int increment_overflow32(int_fast32_t * number, int delta); +static int increment_overflow_time(time_t *t, int_fast32_t delta); static int leaps_thru_end_of(int y) ATTRIBUTE_PURE; static int normalize_overflow(int * tensptr, int * unitsptr, int base); @@ -514,9 +515,9 @@ static struct tm * timesub(const timezone_t sp, const time_t * timep, const int_fast32_t offset, struct tm * tmp); static int tmcomp(const struct tm * atmp, const struct tm * btmp); -static time_t transtime(time_t janfirst, int year, - const struct rule * rulep, - const int_fast32_t offset) ATTRIBUTE_PURE; +static int_fast32_t transtime(int year, const struct rule * rulep, + int_fast32_t offset) + ATTRIBUTE_PURE; static int typesequiv(const timezone_t sp, int a, int b); static int tzload(timezone_t sp, const char * name, int doextend); @@ -578,7 +579,7 @@ int daylight; #endif /* defined USG_COMPAT */ #ifdef ALTZONE -time_t altzone = 0; +long altzone = 0; #endif /* defined ALTZONE */ static int_fast32_t @@ -593,15 +594,15 @@ detzcode(const char *const codep) return result; } -static time_t +static int_fast64_t detzcode64(const char *const codep) { - time_t result; + int_fast64_t result; int i; - result = (time_t)((codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0); + result = (codep[0] & 0x80) ? -1 : 0; for (i = 0; i < 8; ++i) - result = result * 256 + (codep[i] & 0xff); + result = (result << 8) | (codep[i] & 0xff); return result; } @@ -742,6 +743,7 @@ tzload(timezone_t sp, const char *name, const int doextend) for (stored = 4; stored <= 8; stored *= 2) { int ttisstdcnt; int ttisgmtcnt; + int timecnt; ttisstdcnt = (int) detzcode(up->tzhead.tzh_ttisstdcnt); ttisgmtcnt = (int) detzcode(up->tzhead.tzh_ttisgmtcnt); @@ -766,15 +768,36 @@ tzload(timezone_t sp, const char *name, const int doextend) ttisstdcnt + /* ttisstds */ ttisgmtcnt) /* ttisgmts */ goto oops; + timecnt = 0; for (i = 0; i < sp->timecnt; ++i) { - sp->ats[i] = (time_t)((stored == 4) ? - detzcode(p) : detzcode64(p)); + int_fast64_t at + = stored == 4 ? detzcode(p) : detzcode64(p); + sp->types[i] = ((TYPE_SIGNED(time_t) + ? time_t_min <= at + : 0 <= at) + && at <= time_t_max); + if (sp->types[i]) { + if (i && !timecnt && at != time_t_min) { + /* + ** Keep the earlier record, but tweak + ** it so that it starts with the + ** minimum time_t value. + */ + sp->types[i - 1] = 1; + sp->ats[timecnt++] = time_t_min; + } + //_DIAGASSERT(__type_fit(time_t, at)); + sp->ats[timecnt++] = (time_t)at; + } p += stored; } + timecnt = 0; for (i = 0; i < sp->timecnt; ++i) { - sp->types[i] = (unsigned char) *p++; - if (sp->types[i] >= sp->typecnt) + unsigned char typ = *p++; + if (sp->typecnt <= typ) goto oops; + if (sp->types[i]) + sp->types[timecnt++] = typ; } for (i = 0; i < sp->typecnt; ++i) { struct ttinfo * ttisp; @@ -830,44 +853,6 @@ tzload(timezone_t sp, const char *name, const int doextend) } } /* - ** Out-of-sort ats should mean we're running on a - ** signed time_t system but using a data file with - ** unsigned values (or vice versa). - */ - for (i = 0; i < sp->timecnt; ++i) - if ((i < sp->timecnt - 1 && - sp->ats[i] > sp->ats[i + 1]) || - (i == sp->timecnt - 1 && !TYPE_SIGNED(time_t) && - sp->ats[i] > - ((stored == 4) ? INT32_MAX : INT64_MAX))) { - if (TYPE_SIGNED(time_t)) { - /* - ** Ignore the end (easy). - */ - sp->timecnt = i + 1; - } else { - /* - ** Ignore the beginning (harder). - */ - int j; - - /* - ** Keep the record right before the - ** epoch boundary, - ** but tweak it so that it starts - ** right with the epoch - ** (thanks to Doug Bailey). - */ - sp->ats[i] = 0; - for (j = 0; j + i < sp->timecnt; ++j) { - sp->ats[j] = sp->ats[j + i]; - sp->types[j] = sp->types[j + i]; - } - sp->timecnt = j; - } - break; - } - /* ** If this is an old file, we're done. */ if (up->tzhead.tzh_version[0] == '\0') @@ -876,9 +861,9 @@ tzload(timezone_t sp, const char *name, const int doextend) for (i = 0; i < nread; ++i) up->buf[i] = p[i]; /* - ** If this is a narrow time_t system, we're done. + ** If this is a signed narrow time_t system, we're done. */ - if (stored >= (int) sizeof(time_t)) + if (TYPE_SIGNED(time_t) && stored >= (int) sizeof(time_t)) break; } if (doextend && nread > 2 && @@ -1207,17 +1192,16 @@ getrule(const char *strp, struct rule *const rulep) } /* -** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the -** year, a rule, and the offset from UT at the time that rule takes effect, -** calculate the Epoch-relative time that rule takes effect. +** Given a year, a rule, and the offset from UT at the time that rule takes +** effect, calculate the year-relative time that rule takes effect. */ -static time_t -transtime(const time_t janfirst, const int year, const struct rule *const rulep, - const int_fast32_t offset) +static int_fast32_t +transtime(const int year, const struct rule *const rulep, + const int_fast32_t offset) { int leapyear; - time_t value; + int_fast32_t value; int i; int d, m1, yy0, yy1, yy2, dow; @@ -1233,7 +1217,7 @@ transtime(const time_t janfirst, const int year, const struct rule *const rulep, ** add SECSPERDAY times the day number-1 to the time of ** January 1, midnight, to get the day. */ - value = (time_t)(janfirst + (rulep->r_day - 1) * SECSPERDAY); + value = (rulep->r_day - 1) * SECSPERDAY; if (leapyear && rulep->r_day >= 60) value += SECSPERDAY; break; @@ -1244,16 +1228,13 @@ transtime(const time_t janfirst, const int year, const struct rule *const rulep, ** Just add SECSPERDAY times the day number to the time of ** January 1, midnight, to get the day. */ - value = (time_t)(janfirst + rulep->r_day * SECSPERDAY); + value = rulep->r_day * SECSPERDAY; break; case MONTH_NTH_DAY_OF_WEEK: /* ** Mm.n.d - nth "dth day" of month m. */ - value = janfirst; - for (i = 0; i < rulep->r_mon - 1; ++i) - value += (time_t)(mon_lengths[leapyear][i] * SECSPERDAY); /* ** Use Zeller's Congruence to get day-of-week of first day of @@ -1286,17 +1267,19 @@ transtime(const time_t janfirst, const int year, const struct rule *const rulep, /* ** "d" is the day-of-month (zero-origin) of the day we want. */ - value += (time_t)(d * SECSPERDAY); + value = d * SECSPERDAY; + for (i = 0; i < rulep->r_mon - 1; ++i) + value += mon_lengths[leapyear][i] * SECSPERDAY; break; } /* - ** "value" is the Epoch-relative time of 00:00:00 UT on the day in - ** question. To get the Epoch-relative time of the specified local + ** "value" is the year-relative time of 00:00:00 UT on the day in + ** question. To get the year-relative time of the specified local ** time on that day, add the transition time and the current offset ** from UT. */ - return (time_t)(value + rulep->r_time + offset); + return value + rulep->r_time + offset; } /* @@ -1313,8 +1296,6 @@ tzparse(timezone_t sp, const char *name, const int lastditch) size_t dstlen; int_fast32_t stdoffset; int_fast32_t dstoffset; - time_t * atp; - unsigned char * typep; char * cp; int load_result; @@ -1373,9 +1354,8 @@ tzparse(timezone_t sp, const char *name, const int lastditch) struct rule end; int year; int yearlim; + int timecnt; time_t janfirst; - time_t starttime; - time_t endtime; ++name; if ((name = getrule(name, &start)) == NULL) @@ -1397,43 +1377,44 @@ tzparse(timezone_t sp, const char *name, const int lastditch) sp->ttis[1].tt_gmtoff = -stdoffset; sp->ttis[1].tt_isdst = 0; sp->ttis[1].tt_abbrind = 0; - atp = sp->ats; - typep = sp->types; + timecnt = 0; janfirst = 0; sp->timecnt = 0; yearlim = EPOCH_YEAR + YEARSPERREPEAT; for (year = EPOCH_YEAR; year < yearlim; year++) { - int_fast32_t yearsecs; - - starttime = transtime(janfirst, year, &start, - stdoffset); - endtime = transtime(janfirst, year, &end, - dstoffset); - yearsecs = (year_lengths[isleap(year)] - * SECSPERDAY); - if (starttime > endtime + int_fast32_t + starttime = transtime(year, &start, stdoffset), + endtime = transtime(year, &end, dstoffset); + int_fast32_t + yearsecs = (year_lengths[isleap(year)] + * SECSPERDAY); + int reversed = endtime < starttime; + if (reversed) { + int_fast32_t swap = starttime; + starttime = endtime; + endtime = swap; + } + if (reversed || (starttime < endtime && (endtime - starttime < (yearsecs + (stdoffset - dstoffset))))) { - if (&sp->ats[TZ_MAX_TIMES - 2] < atp) + if (TZ_MAX_TIMES - 2 < timecnt) break; yearlim = year + YEARSPERREPEAT + 1; - if (starttime > endtime) { - *atp++ = endtime; - *typep++ = 1; /* DST ends */ - *atp++ = starttime; - *typep++ = 0; /* DST begins */ - } else { - *atp++ = starttime; - *typep++ = 0; /* DST begins */ - *atp++ = endtime; - *typep++ = 1; /* DST ends */ - } + sp->ats[timecnt] = janfirst; + if (increment_overflow_time + (&sp->ats[timecnt], starttime)) + break; + sp->types[timecnt++] = reversed; + sp->ats[timecnt] = janfirst; + if (increment_overflow_time + (&sp->ats[timecnt], endtime)) + break; + sp->types[timecnt++] = !reversed; } - if (time_t_max - janfirst < yearsecs) + if (increment_overflow_time(&janfirst, yearsecs)) break; - janfirst += (time_t)yearsecs; } /* ** Get zone offsets into tzinfo (for newlib). . . @@ -1445,9 +1426,8 @@ tzparse(timezone_t sp, const char *name, const int lastditch) __gettzinfo ()->__tzrule[1].offset = -sp->ttis[0].tt_gmtoff; } - //_DIAGASSERT(__type_fit(int, atp - sp->ats)); - sp->timecnt = (int)(atp - sp->ats); - if (!sp->timecnt) + sp->timecnt = timecnt; + if (!timecnt) sp->typecnt = 1; /* Perpetual DST. */ } else { int_fast32_t theirstdoffset; @@ -2013,7 +1993,8 @@ timesub(const timezone_t sp, const time_t *const timep, if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta) && tdelta <= INT_MAX)) return NULL; - idelta = tdelta; + //_DIAGASSERT(__type_fit(int, tdelta)); + idelta = (int)tdelta; if (idelta == 0) idelta = (tdays < 0) ? -1 : 1; newy = y; @@ -2162,6 +2143,22 @@ increment_overflow32(int_fast32_t *const lp, int const m) return FALSE; } +static int +increment_overflow_time(time_t *tp, int_fast32_t j) +{ + /* + ** This is like + ** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...', + ** except that it does the right thing even if *tp + j would overflow. + */ + if (! (j < 0 + ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp) + : *tp <= time_t_max - j)) + return TRUE; + *tp += j; + return FALSE; +} + static int normalize_overflow(int *const tensptr, int *const unitsptr, const int base) {