Do not keep struct state on the stack.

This structure is huge (~18000 bytes on arm64) and can blow out
the stack very easily.
Modify the code to allocate these structures instead of leaving them
on the stack.

Bug: 14468519
Change-Id: I774f71235d896d32a14ab1af06f95ca9ef819f52
This commit is contained in:
Christopher Ferris 2014-05-14 16:06:17 -07:00
parent 6897b7b8b9
commit 8a8b0c9bfc

View File

@ -506,37 +506,41 @@ tzload(register const char* name, register struct state* const sp,
if (doextend && nread > 2 && if (doextend && nread > 2 &&
up->buf[0] == '\n' && up->buf[nread - 1] == '\n' && up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
sp->typecnt + 2 <= TZ_MAX_TYPES) { sp->typecnt + 2 <= TZ_MAX_TYPES) {
struct state ts; struct state * ts = malloc(sizeof *ts);
register int result; register int result;
if (ts == NULL)
goto oops;
up->buf[nread - 1] = '\0'; up->buf[nread - 1] = '\0';
result = tzparse(&up->buf[1], &ts, FALSE); result = tzparse(&up->buf[1], ts, FALSE);
if (result == 0 && ts.typecnt == 2 && if (result == 0 && ts->typecnt == 2 &&
sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { sp->charcnt + ts->charcnt <= TZ_MAX_CHARS) {
for (i = 0; i < 2; ++i) for (i = 0; i < 2; ++i)
ts.ttis[i].tt_abbrind += ts->ttis[i].tt_abbrind +=
sp->charcnt; sp->charcnt;
for (i = 0; i < ts.charcnt; ++i) for (i = 0; i < ts->charcnt; ++i)
sp->chars[sp->charcnt++] = sp->chars[sp->charcnt++] =
ts.chars[i]; ts->chars[i];
i = 0; i = 0;
while (i < ts.timecnt && while (i < ts->timecnt &&
ts.ats[i] <= ts->ats[i] <=
sp->ats[sp->timecnt - 1]) sp->ats[sp->timecnt - 1])
++i; ++i;
while (i < ts.timecnt && while (i < ts->timecnt &&
sp->timecnt < TZ_MAX_TIMES) { sp->timecnt < TZ_MAX_TIMES) {
sp->ats[sp->timecnt] = sp->ats[sp->timecnt] =
ts.ats[i]; ts->ats[i];
sp->types[sp->timecnt] = sp->types[sp->timecnt] =
sp->typecnt + sp->typecnt +
ts.types[i]; ts->types[i];
++sp->timecnt; ++sp->timecnt;
++i; ++i;
} }
sp->ttis[sp->typecnt++] = ts.ttis[0]; sp->ttis[sp->typecnt++] = ts->ttis[0];
sp->ttis[sp->typecnt++] = ts.ttis[1]; sp->ttis[sp->typecnt++] = ts->ttis[1];
} }
free(ts);
} }
if (sp->timecnt > 1) { if (sp->timecnt > 1) {
for (i = 1; i < sp->timecnt; ++i) for (i = 1; i < sp->timecnt; ++i)
@ -2280,22 +2284,33 @@ static int __bionic_tzload_cached(const char* name, struct state* const sp, cons
// Non-standard API: mktime(3) but with an explicit timezone parameter. // Non-standard API: mktime(3) but with an explicit timezone parameter.
time_t mktime_tz(struct tm* const tmp, const char* tz) { time_t mktime_tz(struct tm* const tmp, const char* tz) {
struct state st; struct state* st = malloc(sizeof(*st));
if (__bionic_tzload_cached(tz, &st, TRUE) != 0) { time_t return_value;
if (st == NULL)
return 0;
if (__bionic_tzload_cached(tz, st, TRUE) != 0) {
// TODO: not sure what's best here, but for now, we fall back to gmt. // TODO: not sure what's best here, but for now, we fall back to gmt.
gmtload(&st); gmtload(st);
} }
return time1(tmp, localsub, 0L, &st);
return_value = time1(tmp, localsub, 0L, st);
free(st);
return return_value;
} }
// Non-standard API: localtime(3) but with an explicit timezone parameter. // Non-standard API: localtime(3) but with an explicit timezone parameter.
void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) { void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) {
struct state st; struct state* st = malloc(sizeof(*st));
if (__bionic_tzload_cached(tz, &st, TRUE) != 0) {
if (st == NULL)
return;
if (__bionic_tzload_cached(tz, st, TRUE) != 0) {
// TODO: not sure what's best here, but for now, we fall back to gmt. // TODO: not sure what's best here, but for now, we fall back to gmt.
gmtload(&st); gmtload(st);
} }
localsub(timep, 0L, tmp, &st); localsub(timep, 0L, tmp, st);
free(st);
} }
// END android-added // END android-added