From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id 3D8A2383F84B; Mon, 4 May 2020 09:20:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3D8A2383F84B 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.74 X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/master X-Git-Oldrev: 76d4d40b8b23d046473a5946cf6b83faa36ae7be X-Git-Newrev: 3f0c2ac96e7c493bbfc2bc1b0c1274445b756a9d Message-Id: <20200504092031.3D8A2383F84B@sourceware.org> Date: Mon, 4 May 2020 09:20:31 +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:20:31 -0000 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=3f0c2ac96e7c493bbfc2bc1b0c1274445b756a9d commit 3f0c2ac96e7c493bbfc2bc1b0c1274445b756a9d Author: Corinna Vinschen Date: Tue Apr 28 20:50:57 2020 +0200 localtime 1.74 Diff: --- winsup/cygwin/localtime.cc | 221 +++++++++++++++++++++++++++------------------ 1 file changed, 133 insertions(+), 88 deletions(-) diff --git a/winsup/cygwin/localtime.cc b/winsup/cygwin/localtime.cc index da446f101..a2749654e 100644 --- a/winsup/cygwin/localtime.cc +++ b/winsup/cygwin/localtime.cc @@ -1,4 +1,4 @@ -/* $NetBSD: localtime.c,v 1.73 2013/03/02 21:24:28 christos Exp $ */ +/* $NetBSD: localtime.c,v 1.74 2013/07/17 20:13:04 christos Exp $ */ /* ** This file is in the public domain, so clarified as of @@ -75,11 +75,11 @@ static char privatehid[] = "@(#)private.h 7.48"; /* Unlike 's isdigit, this also works if c < 0 | c > UCHAR_MAX. */ #define is_digit(c) ((unsigned)(c) - '0' <= 9) -#ifndef __pure +#ifndef ATTRIBUTE_PURE #if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__) -# define __pure __attribute__ ((__pure__)) +# define ATTRIBUTE_PURE __attribute__ ((__pure__)) #else -# define __pure /* empty */ +# define ATTRIBUTE_PURE /* empty */ #endif #endif @@ -401,7 +401,7 @@ static const char gmt[] = "GMT"; #endif /* !defined TZDEFDST */ struct ttinfo { /* time type information */ - long tt_gmtoff; /* UTC offset in seconds */ + int_fast32_t tt_gmtoff; /* UTC offset in seconds */ int tt_isdst; /* used to set tm_isdst */ int tt_abbrind; /* abbreviation list index */ int tt_ttisstd; /* TRUE if transition is std time */ @@ -410,7 +410,7 @@ struct ttinfo { /* time type information */ struct lsinfo { /* leap second information */ time_t ls_trans; /* transition time */ - long ls_corr; /* correction to apply */ + int_fast64_t ls_corr; /* correction to apply */ }; #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) @@ -435,6 +435,7 @@ struct __state { char chars[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))]; struct lsinfo lsis[TZ_MAX_LEAPS]; + int defaulttype; /* for early times or if no transitions */ }; struct rule { @@ -442,7 +443,7 @@ struct rule { int r_day; /* day number of rule */ int r_week; /* week number of rule */ int r_mon; /* month number of rule */ - long r_time; /* transition time of rule */ + int_fast32_t r_time; /* transition time of rule */ }; #define JULIAN_DAY 0 /* Jn - Julian day */ @@ -454,49 +455,50 @@ typedef struct __state *timezone_t; #endif typedef struct tm *(*subfun_t)(const timezone_t sp, const time_t *timep, - long offset, struct tm *tmp); + const int_fast32_t offset, struct tm *tmp); /* ** Prototypes for static functions. */ -static long detzcode(const char * codep); +static int_fast32_t detzcode(const char * codep); static time_t detzcode64(const char * codep); static int differ_by_repeat(time_t t1, time_t t0); -static const char * getzname(const char * strp) __pure; -static const char * getqzname(const char * strp, const int delim) __pure; +static const char * getzname(const char * strp) ATTRIBUTE_PURE; +static const char * getqzname(const char * strp, const int delim) ATTRIBUTE_PURE; static const char * getnum(const char * strp, int * nump, int min, int max); -static const char * getsecs(const char * strp, long * secsp); -static const char * getoffset(const char * strp, long * offsetp); +static const char * getsecs(const char * strp, int_fast32_t * secsp); +static const char * getoffset(const char * strp, int_fast32_t * offsetp); static const char * getrule(const char * strp, struct rule * rulep); static void gmtload(timezone_t sp); static struct tm * gmtsub(const timezone_t sp, const time_t *timep, - long offset, struct tm * tmp); + const int_fast32_t offset, struct tm * tmp); static struct tm * localsub(const timezone_t sp, const time_t *timep, - long offset, struct tm *tmp); + const int_fast32_t offset, struct tm *tmp); static int increment_overflow(int * number, int delta); -static int leaps_thru_end_of(int y) __pure; -static int long_increment_overflow(long * number, int delta); -static int long_normalize_overflow(long * tensptr, +static int leaps_thru_end_of(int y) ATTRIBUTE_PURE; +static int increment_overflow32(int_fast32_t * number, int delta); +static int normalize_overflow32(int_fast32_t * tensptr, int * unitsptr, int base); static int normalize_overflow(int * tensptr, int * unitsptr, int base); static void settzname(void); static time_t time1(const timezone_t sp, struct tm * const tmp, - subfun_t funcp, const long offset); + subfun_t funcp, const int_fast32_t offset); static time_t time2(const timezone_t sp, struct tm * const tmp, subfun_t funcp, - const long offset, int *const okayp); + const int_fast32_t offset, int *const okayp); static time_t time2sub(const timezone_t sp, struct tm * const tmp, - subfun_t funcp, const long offset, + subfun_t funcp, const int_fast32_t offset, int *const okayp, const int do_norm_secs); static struct tm * timesub(const timezone_t sp, const time_t * timep, - long offset, struct tm * tmp); + 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, long offset) __pure; + const struct rule * rulep, + const 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); @@ -507,7 +509,7 @@ extern "C" void tzset_unlocked(void); #else static void tzset_unlocked(void); #endif -static long leapcorr(const timezone_t sp, time_t * timep); +static int_fast64_t leapcorr(const timezone_t sp, time_t * timep); static timezone_t lclptr; static timezone_t gmtptr; @@ -561,13 +563,13 @@ int daylight; time_t altzone = 0; #endif /* defined ALTZONE */ -static long +static int_fast32_t detzcode(const char *const codep) { - long result; + int_fast32_t result; int i; - result = (codep[0] & 0x80) ? ~0L : 0; + result = (codep[0] & 0x80) ? -1 : 0; for (i = 0; i < 4; ++i) result = (result << 8) | (codep[i] & 0xff); return result; @@ -915,6 +917,40 @@ tzload(timezone_t sp, const char *name, const int doextend) break; } } + /* + ** If type 0 is is unused in transitions, + ** it's the type to use for early times. + */ + for (i = 0; i < sp->typecnt; ++i) + if (sp->types[i] == 0) + break; + i = (i >= sp->typecnt) ? 0 : -1; + /* + ** Absent the above, + ** if there are transition times + ** and the first transition is to a daylight time + ** find the standard type less than and closest to + ** the type of the first transition. + */ + if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) { + i = sp->types[0]; + while (--i >= 0) + if (!sp->ttis[i].tt_isdst) + break; + } + /* + ** If no result yet, find the first standard type. + ** If there is none, punt to type zero. + */ + if (i < 0) { + i = 0; + while (sp->ttis[i].tt_isdst) + if (++i >= sp->typecnt) { + i = 0; + break; + } + } + sp->defaulttype = i; free(up); /* ** Get latest zone offsets into tzinfo (for newlib). . . @@ -1045,7 +1081,7 @@ getnum(const char *strp, int *const nump, const int min, const int max) */ static const char * -getsecs(const char *strp, long *const secsp) +getsecs(const char *strp, int_fast32_t *const secsp) { int num; @@ -1058,7 +1094,7 @@ getsecs(const char *strp, long *const secsp) strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1); if (strp == NULL) return NULL; - *secsp = num * (long) SECSPERHOUR; + *secsp = num * (int_fast32_t) SECSPERHOUR; if (*strp == ':') { ++strp; strp = getnum(strp, &num, 0, MINSPERHOUR - 1); @@ -1085,7 +1121,7 @@ getsecs(const char *strp, long *const secsp) */ static const char * -getoffset(const char *strp, long *const offsetp) +getoffset(const char *strp, int_fast32_t *const offsetp) { int neg = 0; @@ -1163,7 +1199,7 @@ getrule(const char *strp, struct rule *const rulep) static time_t transtime(const time_t janfirst, const int year, const struct rule *const rulep, - const long offset) + const int_fast32_t offset) { int leapyear; time_t value; @@ -1256,14 +1292,14 @@ transtime(const time_t janfirst, const int year, const struct rule *const rulep, static int tzparse(timezone_t sp, const char *name, const int lastditch) { - const char * stdname; - const char * dstname; - size_t stdlen; - size_t dstlen; - long stdoffset; - long dstoffset; + const char * stdname; + const char * dstname; + size_t stdlen; + size_t dstlen; + int_fast32_t stdoffset; + int_fast32_t dstoffset; time_t * atp; - unsigned char * typep; + unsigned char * typep; char * cp; int load_result; @@ -1388,12 +1424,12 @@ tzparse(timezone_t sp, const char *name, const int lastditch) = -sp->ttis[0].tt_gmtoff; } } else { - long theirstdoffset; - long theirdstoffset; - long theiroffset; - int isdst; - int i; - int j; + int_fast32_t theirstdoffset; + int_fast32_t theirdstoffset; + int_fast32_t theiroffset; + int isdst; + int i; + int j; if (*name != '\0') return -1; @@ -1706,7 +1742,7 @@ tzset(void) /*ARGSUSED*/ static struct tm * -localsub(const timezone_t sp, const time_t * const timep, const long offset, +localsub(const timezone_t sp, const time_t * const timep, const int_fast32_t offset, struct tm *const tmp) { const struct ttinfo * ttisp; @@ -1755,12 +1791,7 @@ localsub(const timezone_t sp, const time_t * const timep, const long offset, return result; } if (sp->timecnt == 0 || t < sp->ats[0]) { - i = 0; - while (sp->ttis[i].tt_isdst) - if (++i >= sp->typecnt) { - i = 0; - break; - } + i = sp->defaulttype; } else { int lo = 1; int hi = sp->timecnt; @@ -1819,8 +1850,8 @@ localtime(const time_t *const timep) static NO_COPY muto gmt_guard; static struct tm * -gmtsub(const timezone_t sp, const time_t *const timep, const long offset, - struct tm *tmp) +gmtsub(const timezone_t sp, const time_t *const timep, + const int_fast32_t offset, struct tm *const tmp) { struct tm * result; @@ -1857,7 +1888,7 @@ gmtsub(const timezone_t sp, const time_t *const timep, const long offset, extern "C" struct tm * gmtime(const time_t *const timep) { - struct tm *tmp = gmtsub(NULL, timep, 0L, &tm); + struct tm *tmp = gmtsub(NULL, timep, 0, &tm); if (tmp == NULL) errno = EOVERFLOW; @@ -1872,7 +1903,7 @@ gmtime(const time_t *const timep) extern "C" struct tm * gmtime_r(const time_t *__restrict const timep, struct tm *__restrict tmp) { - tmp = gmtsub(NULL, timep, 0L, tmp); + tmp = gmtsub(NULL, timep, 0, tmp); if (tmp == NULL) errno = EOVERFLOW; @@ -1885,7 +1916,14 @@ gmtime_r(const time_t *__restrict const timep, struct tm *__restrict tmp) extern "C" struct tm * offtime(const time_t *const timep, long offset) { - struct tm *tmp = gmtsub(NULL, timep, offset, &tm); + struct tm *tmp; + + if ((offset > 0 && offset > INT_FAST32_MAX) || + (offset < 0 && offset > INT_FAST32_MIN)) { + errno = EOVERFLOW; + return NULL; + } + tmp = gmtsub(NULL, timep, (int_fast32_t)offset, &tm); if (tmp == NULL) errno = EOVERFLOW; @@ -1908,16 +1946,16 @@ leaps_thru_end_of(const int y) } static struct tm * -timesub(const timezone_t sp, const time_t *const timep, const long offset, - struct tm *const tmp) +timesub(const timezone_t sp, const time_t *const timep, + const int_fast32_t offset, struct tm *const tmp) { const struct lsinfo * lp; time_t tdays; int idays; /* unsigned would be so 2003 */ - long rem; + int_fast64_t rem; int y; const int * ip; - long corr; + int_fast64_t corr; int hit; int i; @@ -1946,7 +1984,7 @@ timesub(const timezone_t sp, const time_t *const timep, const long offset, } y = EPOCH_YEAR; tdays = (time_t)(*timep / SECSPERDAY); - rem = (long) (*timep - tdays * SECSPERDAY); + rem = (int_fast64_t) (*timep - tdays * SECSPERDAY); while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { int newy; time_t tdelta; @@ -1969,11 +2007,12 @@ timesub(const timezone_t sp, const time_t *const timep, const long offset, y = newy; } { - long seconds; + int_fast32_t seconds; + const time_t half_second = 0.5; - seconds = tdays * SECSPERDAY + 0.5; + seconds = (int_fast32_t)(tdays * SECSPERDAY + half_second); tdays = (time_t)(seconds / SECSPERDAY); - rem += (long) (seconds - tdays * SECSPERDAY); + rem += (int_fast64_t)(seconds - tdays * SECSPERDAY); } /* ** Given the range, we can now fearlessly cast... @@ -2095,11 +2134,11 @@ increment_overflow(int *const ip, int j) } static int -long_increment_overflow(long *const lp, int m) +increment_overflow32(int_fast32_t *const lp, int const m) { - long l = *lp; + int_fast32_t l = *lp; - if ((l >= 0) ? (m > LONG_MAX - l) : (m < LONG_MIN - l)) + if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l)) return TRUE; *lp += m; return FALSE; @@ -2118,7 +2157,7 @@ normalize_overflow(int *const tensptr, int *const unitsptr, const int base) } static int -long_normalize_overflow(long *const tensptr, int *const unitsptr, +normalize_overflow32(int_fast32_t *const tensptr, int *const unitsptr, const int base) { int tensdelta; @@ -2127,7 +2166,7 @@ long_normalize_overflow(long *const tensptr, int *const unitsptr, (*unitsptr / base) : (-1 - (-1 - *unitsptr) / base); *unitsptr -= tensdelta * base; - return long_increment_overflow(tensptr, tensdelta); + return increment_overflow32(tensptr, tensdelta); } static int @@ -2146,21 +2185,21 @@ tmcomp(const struct tm *const atmp, const struct tm *const btmp) static time_t time2sub(const timezone_t sp, struct tm *const tmp, subfun_t funcp, - const long offset, int *const okayp, const int do_norm_secs) + const int_fast32_t offset, int *const okayp, const int do_norm_secs) { int dir; int i, j; int saved_seconds; - long li; + int_fast32_t li; time_t lo; time_t hi; #ifdef NO_ERROR_IN_DST_GAP time_t ilo; #endif - long y; - time_t newt; - time_t t; - struct tm yourtm, mytm; + int_fast32_t y; + time_t newt; + time_t t; + struct tm yourtm, mytm; *okayp = FALSE; yourtm = *tmp; @@ -2177,16 +2216,16 @@ again: if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY)) goto overflow; y = yourtm.tm_year; - if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR)) + if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR)) goto overflow; /* ** Turn y into an actual year number for now. ** It is converted back to an offset from TM_YEAR_BASE later. */ - if (long_increment_overflow(&y, TM_YEAR_BASE)) + if (increment_overflow32(&y, TM_YEAR_BASE)) goto overflow; while (yourtm.tm_mday <= 0) { - if (long_increment_overflow(&y, -1)) + if (increment_overflow32(&y, -1)) goto overflow; li = y + (1 < yourtm.tm_mon); yourtm.tm_mday += year_lengths[isleap(li)]; @@ -2194,7 +2233,7 @@ again: while (yourtm.tm_mday > DAYSPERLYEAR) { li = y + (1 < yourtm.tm_mon); yourtm.tm_mday -= year_lengths[isleap(li)]; - if (long_increment_overflow(&y, 1)) + if (increment_overflow32(&y, 1)) goto overflow; } for ( ; ; ) { @@ -2204,11 +2243,11 @@ again: yourtm.tm_mday -= i; if (++yourtm.tm_mon >= MONSPERYEAR) { yourtm.tm_mon = 0; - if (long_increment_overflow(&y, 1)) + if (increment_overflow32(&y, 1)) goto overflow; } } - if (long_increment_overflow(&y, -TM_YEAR_BASE)) + if (increment_overflow32(&y, -TM_YEAR_BASE)) goto overflow; yourtm.tm_year = (int)y; if (yourtm.tm_year != y) @@ -2352,7 +2391,7 @@ invalid: static time_t time2(const timezone_t sp, struct tm *const tmp, subfun_t funcp, - const long offset, int *const okayp) + const int_fast32_t offset, int *const okayp) { time_t t; @@ -2367,7 +2406,7 @@ time2(const timezone_t sp, struct tm *const tmp, subfun_t funcp, static time_t time1(const timezone_t sp, struct tm *const tmp, subfun_t funcp, - const long offset) + const int_fast32_t offset) { time_t t; int samei, otheri; @@ -2468,18 +2507,23 @@ timegm(struct tm *const tmp) if (tmp != NULL) tmp->tm_isdst = 0; - t = time1(gmtptr, tmp, gmtsub, 0L); + t = time1(gmtptr, tmp, gmtsub, 0); return t; } extern "C" time_t -timeoff(struct tm *const tmp, const long offset) +timeoff(struct tm *const tmp, long offset) { time_t t; + if ((offset > 0 && offset > INT_FAST32_MAX) || + (offset < 0 && offset > INT_FAST32_MIN)) { + errno = EOVERFLOW; + return -1; + } if (tmp != NULL) tmp->tm_isdst = 0; - t = time1(gmtptr, tmp, gmtsub, offset); + t = time1(gmtptr, tmp, gmtsub, (int_fast32_t)offset); return t; } @@ -2492,7 +2536,8 @@ timeoff(struct tm *const tmp, const long offset) ** previous versions of the CMUCS runtime library. */ -extern "C" long +extern "C" +int_fast32_t gtime(struct tm *const tmp) { const time_t t = mktime(tmp); @@ -2518,7 +2563,7 @@ gtime(struct tm *const tmp) ** when exchanging timestamps with POSIX conforming systems. */ -static long +static int_fast64_t leapcorr(const timezone_t sp, time_t *timep) { struct lsinfo * lp;