summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2010-11-30 00:38:59 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2010-11-30 00:38:59 +0000
commit41c476b7264833498877ab51e45a79e5ba822888 (patch)
tree59d4badbd1a69d918d91c356cda46ef25133f4d5
parent8bf0a4ae48ed06c5ab317da4f038c05e2ba87b76 (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.c59
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