diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2010-11-30 00:38:59 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2010-11-30 00:38:59 +0000 |
commit | 41c476b7264833498877ab51e45a79e5ba822888 (patch) | |
tree | 59d4badbd1a69d918d91c356cda46ef25133f4d5 | |
parent | 8bf0a4ae48ed06c5ab317da4f038c05e2ba87b76 (diff) |
replace a large stack buffer with a malloc call, with help from matthew.
ok deraadt
[passed upstream to the tz list as well]
-rw-r--r-- | lib/libc/time/localtime.c | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/lib/libc/time/localtime.c b/lib/libc/time/localtime.c index 0471d0a25f1..0ba6a578230 100644 --- a/lib/libc/time/localtime.c +++ b/lib/libc/time/localtime.c @@ -1,4 +1,4 @@ -/* $OpenBSD: localtime.c,v 1.35 2010/08/23 22:35:34 millert Exp $ */ +/* $OpenBSD: localtime.c,v 1.36 2010/11/30 00:38:58 tedu Exp $ */ /* ** This file is in the public domain, so clarified as of ** 1996-06-05 by Arthur David Olson. @@ -340,7 +340,7 @@ register const int doextend; char buf[2 * sizeof(struct tzhead) + 2 * sizeof *sp + 4 * TZ_MAX_TIMES]; - } u; + } *u; sp->goback = sp->goahead = FALSE; if (name != NULL && issetugid() != 0) @@ -383,28 +383,33 @@ register const int doextend; if ((fid = open(name, OPEN_MODE)) == -1) return -1; } - nread = read(fid, u.buf, sizeof u.buf); - if (close(fid) < 0 || nread <= 0) + u = malloc(sizeof(*u)); + if (!u) { + close(fid); return -1; + } + nread = read(fid, u->buf, sizeof u->buf); + if (close(fid) < 0 || nread <= 0) + goto bad; for (stored = 4; stored <= 8; stored *= 2) { int ttisstdcnt; int ttisgmtcnt; - ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt); - ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt); - sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt); - sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt); - sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt); - sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt); - p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt; + ttisstdcnt = (int) detzcode(u->tzhead.tzh_ttisstdcnt); + ttisgmtcnt = (int) detzcode(u->tzhead.tzh_ttisgmtcnt); + sp->leapcnt = (int) detzcode(u->tzhead.tzh_leapcnt); + sp->timecnt = (int) detzcode(u->tzhead.tzh_timecnt); + sp->typecnt = (int) detzcode(u->tzhead.tzh_typecnt); + sp->charcnt = (int) detzcode(u->tzhead.tzh_charcnt); + p = u->tzhead.tzh_charcnt + sizeof u->tzhead.tzh_charcnt; if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS || sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES || sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES || sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS || (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) || (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0)) - return -1; - if (nread - (p - u.buf) < + goto bad; + if (nread - (p - u->buf) < sp->timecnt * stored + /* ats */ sp->timecnt + /* types */ sp->typecnt * 6 + /* ttinfos */ @@ -412,7 +417,7 @@ register const int doextend; sp->leapcnt * (stored + 4) + /* lsinfos */ ttisstdcnt + /* ttisstds */ ttisgmtcnt) /* ttisgmts */ - return -1; + goto bad; for (i = 0; i < sp->timecnt; ++i) { sp->ats[i] = (stored == 4) ? detzcode(p) : detzcode64(p); @@ -421,7 +426,7 @@ register const int doextend; for (i = 0; i < sp->timecnt; ++i) { sp->types[i] = (unsigned char) *p++; if (sp->types[i] >= sp->typecnt) - return -1; + goto bad; } for (i = 0; i < sp->typecnt; ++i) { register struct ttinfo * ttisp; @@ -431,11 +436,11 @@ register const int doextend; p += 4; ttisp->tt_isdst = (unsigned char) *p++; if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1) - return -1; + goto bad; ttisp->tt_abbrind = (unsigned char) *p++; if (ttisp->tt_abbrind < 0 || ttisp->tt_abbrind > sp->charcnt) - return -1; + goto bad; } for (i = 0; i < sp->charcnt; ++i) sp->chars[i] = *p++; @@ -460,7 +465,7 @@ register const int doextend; ttisp->tt_ttisstd = *p++; if (ttisp->tt_ttisstd != TRUE && ttisp->tt_ttisstd != FALSE) - return -1; + goto bad; } } for (i = 0; i < sp->typecnt; ++i) { @@ -473,7 +478,7 @@ register const int doextend; ttisp->tt_ttisgmt = *p++; if (ttisp->tt_ttisgmt != TRUE && ttisp->tt_ttisgmt != FALSE) - return -1; + goto bad; } } /* @@ -506,11 +511,11 @@ register const int doextend; /* ** If this is an old file, we're done. */ - if (u.tzhead.tzh_version[0] == '\0') + if (u->tzhead.tzh_version[0] == '\0') break; - nread -= p - u.buf; + nread -= p - u->buf; for (i = 0; i < nread; ++i) - u.buf[i] = p[i]; + u->buf[i] = p[i]; /* ** If this is a narrow integer time_t system, we're done. */ @@ -518,13 +523,13 @@ register const int doextend; break; } if (doextend && nread > 2 && - u.buf[0] == '\n' && u.buf[nread - 1] == '\n' && + u->buf[0] == '\n' && u->buf[nread - 1] == '\n' && sp->typecnt + 2 <= TZ_MAX_TYPES) { struct state ts; register int result; - u.buf[nread - 1] = '\0'; - result = tzparse(&u.buf[1], &ts, FALSE); + u->buf[nread - 1] = '\0'; + result = tzparse(&u->buf[1], &ts, FALSE); if (result == 0 && ts.typecnt == 2 && sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { for (i = 0; i < 2; ++i) @@ -568,7 +573,11 @@ register const int doextend; break; } } + free(u); return 0; +bad: + free(u); + return -1; } static int |