Module Name: src Committed By: christos Date: Tue Oct 14 20:35:40 UTC 2014
Modified Files: src/lib/libc/time: localtime.c Log Message: improve error checking (setting errno) To generate a diff of this commit: cvs rdiff -u -r1.87 -r1.88 src/lib/libc/time/localtime.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/time/localtime.c diff -u src/lib/libc/time/localtime.c:1.87 src/lib/libc/time/localtime.c:1.88 --- src/lib/libc/time/localtime.c:1.87 Tue Oct 7 17:51:03 2014 +++ src/lib/libc/time/localtime.c Tue Oct 14 16:35:40 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: localtime.c,v 1.87 2014/10/07 21:51:03 christos Exp $ */ +/* $NetBSD: localtime.c,v 1.88 2014/10/14 20:35:40 christos Exp $ */ /* ** This file is in the public domain, so clarified as of @@ -10,7 +10,7 @@ #if 0 static char elsieid[] = "@(#)localtime.c 8.17"; #else -__RCSID("$NetBSD: localtime.c,v 1.87 2014/10/07 21:51:03 christos Exp $"); +__RCSID("$NetBSD: localtime.c,v 1.88 2014/10/14 20:35:40 christos Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -250,6 +250,7 @@ tzgetname(const timezone_t sp, int isdst if (ttisp->tt_isdst == isdst) return &sp->chars[ttisp->tt_abbrind]; } + errno = ESRCH; return NULL; } @@ -1353,8 +1354,10 @@ localsub(struct state const *sp, time_t newt += seconds; else newt -= seconds; if (newt < sp->ats[0] || - newt > sp->ats[sp->timecnt - 1]) - return NULL; /* "cannot happen" */ + newt > sp->ats[sp->timecnt - 1]) { + errno = EINVAL; + return NULL; /* "cannot happen" */ + } result = localsub(sp, &newt, offset, tmp); if (result) { int_fast64_t newy; @@ -1363,8 +1366,10 @@ localsub(struct state const *sp, time_t if (t < sp->ats[0]) newy -= years; else newy += years; - if (! (INT_MIN <= newy && newy <= INT_MAX)) + if (! (INT_MIN <= newy && newy <= INT_MAX)) { + errno = EOVERFLOW; return NULL; + } result->tm_year = (int)newy; } return result; @@ -1398,7 +1403,7 @@ localsub(struct state const *sp, time_t tzname[result->tm_isdst] = __UNCONST(&sp->chars[ttisp->tt_abbrind]); #ifdef TM_ZONE - tmp->TM_ZONE = __UNCONST(&sp->chars[ttisp->tt_abbrind]); + result->TM_ZONE = __UNCONST(&sp->chars[ttisp->tt_abbrind]); #endif /* defined TM_ZONE */ } return result; @@ -1456,8 +1461,9 @@ gmtsub(struct state const *sp, const tim ** "UT+xxxx" or "UT-xxxx" if offset is non-zero, ** but this is no time for a treasure hunt. */ - tmp->TM_ZONE = offset ? __UNCONST(wildabbr) : gmtptr ? gmtptr->chars : - __UNCONST(gmt); + if (result) + result->TM_ZONE = offset ? __UNCONST(wildabbr) : gmtptr ? + gmtptr->chars : __UNCONST(gmt); #endif /* defined TM_ZONE */ return result; } @@ -1575,14 +1581,14 @@ timesub(time_t const *timep, int_fast32_ tdelta = tdays / DAYSPERLYEAR; if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta) && tdelta <= INT_MAX)) - return NULL; + goto overflow; _DIAGASSERT(__type_fit(int, tdelta)); idelta = (int)tdelta; if (idelta == 0) idelta = (tdays < 0) ? -1 : 1; newy = y; if (increment_overflow(&newy, idelta)) - return NULL; + goto overflow; leapdays = leaps_thru_end_of(newy - 1) - leaps_thru_end_of(y - 1); tdays -= ((time_t) newy - y) * DAYSPERNYEAR; @@ -1611,13 +1617,13 @@ timesub(time_t const *timep, int_fast32_ } while (idays < 0) { if (increment_overflow(&y, -1)) - return NULL; + goto overflow; idays += year_lengths[isleap(y)]; } while (idays >= year_lengths[isleap(y)]) { idays -= year_lengths[isleap(y)]; if (increment_overflow(&y, 1)) - return NULL; + goto overflow; } tmp->tm_year = y; if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE)) @@ -1652,6 +1658,9 @@ timesub(time_t const *timep, int_fast32_ tmp->TM_GMTOFF = offset; #endif /* defined TM_GMTOFF */ return tmp; +overflow: + errno = EOVERFLOW; + return NULL; } char * @@ -2131,7 +2140,6 @@ static time_t mktime_tzname(timezone_t sp, struct tm *tmp, bool setname) { if (sp) -/*###2133 [lint] warning argument has incompatible pointer type, arg #2 (pointer to function != pointer to function) [153]%%%*/ return time1(tmp, localsub, sp, setname); else { gmtcheck();