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
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 9f67dc6..c40569c 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -506,37 +506,41 @@
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 @@
// 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