diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-07-15 14:26:14 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-07-15 14:26:14 -0300 |
commit | f76f4cb79d84af4a7be9e0d75553bbe05a3ae90c (patch) | |
tree | dd9d1f8f3fb8c69f7617fe5688d7b1178bb7190e /ldo.c | |
parent | abb85fc059a5d6427b9dc36edee1619f2c7a1da8 (diff) | |
download | lua-f76f4cb79d84af4a7be9e0d75553bbe05a3ae90c.tar.gz lua-f76f4cb79d84af4a7be9e0d75553bbe05a3ae90c.tar.bz2 lua-f76f4cb79d84af4a7be9e0d75553bbe05a3ae90c.zip |
new way to control stack overflow, controling only total size of the stack
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 68 |
1 files changed, 50 insertions, 18 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.64 2009/05/21 20:06:11 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.65 2009/06/01 19:09:26 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -70,12 +70,6 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { | |||
70 | } | 70 | } |
71 | 71 | ||
72 | 72 | ||
73 | static void restore_stack_limit (lua_State *L) { | ||
74 | if (L->nci >= LUAI_MAXCALLS) /* stack overflow? */ | ||
75 | luaE_freeCI(L); /* erase all extras CIs */ | ||
76 | } | ||
77 | |||
78 | |||
79 | void luaD_throw (lua_State *L, int errcode) { | 73 | void luaD_throw (lua_State *L, int errcode) { |
80 | if (L->errorJmp) { /* thread has an error handler? */ | 74 | if (L->errorJmp) { /* thread has an error handler? */ |
81 | L->errorJmp->status = errcode; /* set status */ | 75 | L->errorJmp->status = errcode; /* set status */ |
@@ -130,25 +124,63 @@ static void correctstack (lua_State *L, TValue *oldstack) { | |||
130 | } | 124 | } |
131 | 125 | ||
132 | 126 | ||
127 | /* some space for error handling */ | ||
128 | #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) | ||
129 | |||
130 | |||
133 | void luaD_reallocstack (lua_State *L, int newsize) { | 131 | void luaD_reallocstack (lua_State *L, int newsize) { |
134 | TValue *oldstack = L->stack; | 132 | TValue *oldstack = L->stack; |
135 | int lim = L->stacksize; | 133 | int lim = L->stacksize; |
136 | int realsize = newsize + 1 + EXTRA_STACK; | 134 | lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); |
137 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); | 135 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); |
138 | luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); | 136 | luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); |
139 | for (; lim < realsize; lim++) | 137 | for (; lim < newsize; lim++) |
140 | setnilvalue(L->stack + lim); /* erase new segment */ | 138 | setnilvalue(L->stack + lim); /* erase new segment */ |
141 | L->stacksize = realsize; | 139 | L->stacksize = newsize; |
142 | L->stack_last = L->stack+newsize; | 140 | L->stack_last = L->stack + newsize - EXTRA_STACK; |
143 | correctstack(L, oldstack); | 141 | correctstack(L, oldstack); |
144 | } | 142 | } |
145 | 143 | ||
146 | 144 | ||
147 | void luaD_growstack (lua_State *L, int n) { | 145 | void luaD_growstack (lua_State *L, int n) { |
148 | if (n <= L->stacksize) /* double size is enough? */ | 146 | int size = L->stacksize; |
149 | luaD_reallocstack(L, 2*L->stacksize); | 147 | if (size > LUAI_MAXSTACK) /* error after extra size? */ |
148 | luaD_throw(L, LUA_ERRERR); | ||
149 | else { | ||
150 | int needed = L->top - L->stack + n + EXTRA_STACK; | ||
151 | int newsize = 2 * size; | ||
152 | if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; | ||
153 | if (newsize < needed) newsize = needed; | ||
154 | if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ | ||
155 | luaD_reallocstack(L, ERRORSTACKSIZE); | ||
156 | luaG_runerror(L, "stack overflow"); | ||
157 | } | ||
158 | else | ||
159 | luaD_reallocstack(L, newsize); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | |||
164 | static int stackinuse (lua_State *L) { | ||
165 | CallInfo *ci; | ||
166 | StkId lim = L->top; | ||
167 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | ||
168 | lua_assert(ci->top <= L->stack_last); | ||
169 | if (lim < ci->top) lim = ci->top; | ||
170 | } | ||
171 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ | ||
172 | } | ||
173 | |||
174 | |||
175 | void luaD_shrinkstack (lua_State *L) { | ||
176 | int inuse = stackinuse(L); | ||
177 | int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; | ||
178 | if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; | ||
179 | if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ | ||
180 | goodsize >= L->stacksize) /* would grow instead of shrink? */ | ||
181 | condmovestack(L); /* don't change stack (change only for debugging) */ | ||
150 | else | 182 | else |
151 | luaD_reallocstack(L, L->stacksize + n); | 183 | luaD_reallocstack(L, goodsize); /* shrink it */ |
152 | } | 184 | } |
153 | 185 | ||
154 | 186 | ||
@@ -427,7 +459,7 @@ static int recover (lua_State *L, int status) { | |||
427 | L->ci = ci; | 459 | L->ci = ci; |
428 | L->allowhook = ci->u.c.old_allowhook; | 460 | L->allowhook = ci->u.c.old_allowhook; |
429 | L->nny = 0; /* should be zero to be yieldable */ | 461 | L->nny = 0; /* should be zero to be yieldable */ |
430 | restore_stack_limit(L); | 462 | luaD_shrinkstack(L); |
431 | L->errfunc = ci->u.c.old_errfunc; | 463 | L->errfunc = ci->u.c.old_errfunc; |
432 | ci->callstatus |= CIST_STAT; /* call has error status */ | 464 | ci->callstatus |= CIST_STAT; /* call has error status */ |
433 | ci->u.c.status = status; /* (here it is) */ | 465 | ci->u.c.status = status; /* (here it is) */ |
@@ -499,7 +531,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, | |||
499 | L->ci = old_ci; | 531 | L->ci = old_ci; |
500 | L->allowhook = old_allowhooks; | 532 | L->allowhook = old_allowhooks; |
501 | L->nny = old_nny; | 533 | L->nny = old_nny; |
502 | restore_stack_limit(L); | 534 | luaD_shrinkstack(L); |
503 | } | 535 | } |
504 | L->errfunc = old_errfunc; | 536 | L->errfunc = old_errfunc; |
505 | return status; | 537 | return status; |