From 8a8b0c9bfcd80c67154ed2aca1e60d815c822acb Mon Sep 17 00:00:00 2001 From: Christopher Ferris Date: Wed, 14 May 2014 16:06:17 -0700 Subject: [PATCH] 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 --- libc/tzcode/localtime.c | 59 ++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c index 9f67dc6a8..c40569c47 100644 --- a/libc/tzcode/localtime.c +++ b/libc/tzcode/localtime.c @@ -506,37 +506,41 @@ tzload(register const char* name, register struct state* const sp, if (doextend && nread > 2 && up->buf[0] == '\n' && up->buf[nread - 1] == '\n' && sp->typecnt + 2 <= TZ_MAX_TYPES) { - struct state ts; + struct state * ts = malloc(sizeof *ts); register int result; + if (ts == NULL) + goto oops; + up->buf[nread - 1] = '\0'; - result = tzparse(&up->buf[1], &ts, FALSE); - if (result == 0 && ts.typecnt == 2 && - sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { + result = tzparse(&up->buf[1], ts, FALSE); + if (result == 0 && ts->typecnt == 2 && + sp->charcnt + ts->charcnt <= TZ_MAX_CHARS) { for (i = 0; i < 2; ++i) - ts.ttis[i].tt_abbrind += + ts->ttis[i].tt_abbrind += sp->charcnt; - for (i = 0; i < ts.charcnt; ++i) + for (i = 0; i < ts->charcnt; ++i) sp->chars[sp->charcnt++] = - ts.chars[i]; + ts->chars[i]; i = 0; - while (i < ts.timecnt && - ts.ats[i] <= + while (i < ts->timecnt && + ts->ats[i] <= sp->ats[sp->timecnt - 1]) ++i; - while (i < ts.timecnt && + while (i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES) { sp->ats[sp->timecnt] = - ts.ats[i]; + ts->ats[i]; sp->types[sp->timecnt] = sp->typecnt + - ts.types[i]; + ts->types[i]; ++sp->timecnt; ++i; } - sp->ttis[sp->typecnt++] = ts.ttis[0]; - sp->ttis[sp->typecnt++] = ts.ttis[1]; + sp->ttis[sp->typecnt++] = ts->ttis[0]; + sp->ttis[sp->typecnt++] = ts->ttis[1]; } + free(ts); } if (sp->timecnt > 1) { 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. time_t mktime_tz(struct tm* const tmp, const char* tz) { - struct state st; - if (__bionic_tzload_cached(tz, &st, TRUE) != 0) { + struct state* st = malloc(sizeof(*st)); + 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. - 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. void localtime_tz(const time_t* const timep, struct tm* tmp, const char* tz) { - struct state st; - if (__bionic_tzload_cached(tz, &st, TRUE) != 0) { + struct state* st = malloc(sizeof(*st)); + + 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. - gmtload(&st); + gmtload(st); } - localsub(timep, 0L, tmp, &st); + localsub(timep, 0L, tmp, st); + free(st); } // END android-added