diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-09-08 11:23:09 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-09-08 11:23:09 -0300 |
commit | 0de2065f4e7cbbbe301b07835b9dd0b1bd1a4bbb (patch) | |
tree | 6f578771ff27c6a352b52ba721fbcf163c610945 | |
parent | ee165043ef917688d6e9151fc1a98d1e0f3e6ab1 (diff) | |
download | lua-0de2065f4e7cbbbe301b07835b9dd0b1bd1a4bbb.tar.gz lua-0de2065f4e7cbbbe301b07835b9dd0b1bd1a4bbb.tar.bz2 lua-0de2065f4e7cbbbe301b07835b9dd0b1bd1a4bbb.zip |
tighter tests for stack overflow
-rw-r--r-- | ldo.c | 34 | ||||
-rw-r--r-- | ldo.h | 6 | ||||
-rw-r--r-- | lgc.c | 17 | ||||
-rw-r--r-- | lstate.c | 4 |
4 files changed, 37 insertions, 24 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.7 2004/06/02 19:07:55 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.8 2004/09/03 15:48:56 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 | */ |
@@ -93,7 +93,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { | |||
93 | 93 | ||
94 | 94 | ||
95 | static void restore_stack_limit (lua_State *L) { | 95 | static void restore_stack_limit (lua_State *L) { |
96 | L->stack_last = L->stack+L->stacksize-1; | 96 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); |
97 | if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */ | 97 | if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */ |
98 | int inuse = (L->ci - L->base_ci); | 98 | int inuse = (L->ci - L->base_ci); |
99 | if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */ | 99 | if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */ |
@@ -121,9 +121,11 @@ static void correctstack (lua_State *L, TValue *oldstack) { | |||
121 | 121 | ||
122 | void luaD_reallocstack (lua_State *L, int newsize) { | 122 | void luaD_reallocstack (lua_State *L, int newsize) { |
123 | TValue *oldstack = L->stack; | 123 | TValue *oldstack = L->stack; |
124 | luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); | 124 | int realsize = newsize + 1 + EXTRA_STACK; |
125 | L->stacksize = newsize; | 125 | lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); |
126 | L->stack_last = L->stack+newsize-1-EXTRA_STACK; | 126 | luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); |
127 | L->stacksize = realsize; | ||
128 | L->stack_last = L->stack+newsize; | ||
127 | correctstack(L, oldstack); | 129 | correctstack(L, oldstack); |
128 | } | 130 | } |
129 | 131 | ||
@@ -133,7 +135,7 @@ void luaD_reallocCI (lua_State *L, int newsize) { | |||
133 | luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); | 135 | luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); |
134 | L->size_ci = cast(unsigned short, newsize); | 136 | L->size_ci = cast(unsigned short, newsize); |
135 | L->ci = (L->ci - oldci) + L->base_ci; | 137 | L->ci = (L->ci - oldci) + L->base_ci; |
136 | L->end_ci = L->base_ci + L->size_ci; | 138 | L->end_ci = L->base_ci + L->size_ci - 1; |
137 | } | 139 | } |
138 | 140 | ||
139 | 141 | ||
@@ -141,11 +143,11 @@ void luaD_growstack (lua_State *L, int n) { | |||
141 | if (n <= L->stacksize) /* double size is enough? */ | 143 | if (n <= L->stacksize) /* double size is enough? */ |
142 | luaD_reallocstack(L, 2*L->stacksize); | 144 | luaD_reallocstack(L, 2*L->stacksize); |
143 | else | 145 | else |
144 | luaD_reallocstack(L, L->stacksize + n + EXTRA_STACK); | 146 | luaD_reallocstack(L, L->stacksize + n); |
145 | } | 147 | } |
146 | 148 | ||
147 | 149 | ||
148 | static void luaD_growCI (lua_State *L) { | 150 | static CallInfo *luaD_growCI (lua_State *L) { |
149 | if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ | 151 | if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ |
150 | luaD_throw(L, LUA_ERRERR); | 152 | luaD_throw(L, LUA_ERRERR); |
151 | else { | 153 | else { |
@@ -153,6 +155,7 @@ static void luaD_growCI (lua_State *L) { | |||
153 | if (L->size_ci > LUA_MAXCALLS) | 155 | if (L->size_ci > LUA_MAXCALLS) |
154 | luaG_runerror(L, "stack overflow"); | 156 | luaG_runerror(L, "stack overflow"); |
155 | } | 157 | } |
158 | return ++L->ci; | ||
156 | } | 159 | } |
157 | 160 | ||
158 | 161 | ||
@@ -170,6 +173,7 @@ void luaD_callhook (lua_State *L, int event, int line) { | |||
170 | ar.i_ci = L->ci - L->base_ci; | 173 | ar.i_ci = L->ci - L->base_ci; |
171 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 174 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
172 | L->ci->top = L->top + LUA_MINSTACK; | 175 | L->ci->top = L->top + LUA_MINSTACK; |
176 | lua_assert(L->ci->top <= L->stack_last); | ||
173 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 177 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
174 | lua_unlock(L); | 178 | lua_unlock(L); |
175 | (*hook)(L, &ar); | 179 | (*hook)(L, &ar); |
@@ -232,14 +236,18 @@ static StkId tryfuncTM (lua_State *L, StkId func) { | |||
232 | } | 236 | } |
233 | 237 | ||
234 | 238 | ||
239 | |||
240 | #define inc_ci(L) \ | ||
241 | ((L->ci == L->end_ci) ? luaD_growCI(L) : \ | ||
242 | (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) | ||
243 | |||
244 | |||
235 | int luaD_precall (lua_State *L, StkId func, int nresults) { | 245 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
236 | LClosure *cl; | 246 | LClosure *cl; |
237 | ptrdiff_t funcr; | 247 | ptrdiff_t funcr; |
238 | if (!ttisfunction(func)) /* `func' is not a function? */ | 248 | if (!ttisfunction(func)) /* `func' is not a function? */ |
239 | func = tryfuncTM(L, func); /* check the `function' tag method */ | 249 | func = tryfuncTM(L, func); /* check the `function' tag method */ |
240 | funcr = savestack(L, func); | 250 | funcr = savestack(L, func); |
241 | if (L->ci + 1 == L->end_ci) luaD_growCI(L); | ||
242 | else condhardstacktests(luaD_reallocCI(L, L->size_ci)); | ||
243 | cl = &clvalue(func)->l; | 251 | cl = &clvalue(func)->l; |
244 | if (!cl->isC) { /* Lua function? prepare its call */ | 252 | if (!cl->isC) { /* Lua function? prepare its call */ |
245 | CallInfo *ci; | 253 | CallInfo *ci; |
@@ -256,10 +264,11 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
256 | func = restorestack(L, funcr); | 264 | func = restorestack(L, funcr); |
257 | base = func + 1; | 265 | base = func + 1; |
258 | } | 266 | } |
259 | ci = ++L->ci; /* now `enter' new function */ | 267 | ci = inc_ci(L); /* now `enter' new function */ |
260 | ci->func = func; | 268 | ci->func = func; |
261 | L->base = ci->base = base; | 269 | L->base = ci->base = base; |
262 | ci->top = L->base + p->maxstacksize; | 270 | ci->top = L->base + p->maxstacksize; |
271 | lua_assert(ci->top <= L->stack_last); | ||
263 | ci->savedpc = p->code; /* starting point */ | 272 | ci->savedpc = p->code; /* starting point */ |
264 | ci->tailcalls = 0; | 273 | ci->tailcalls = 0; |
265 | ci->nresults = nresults; | 274 | ci->nresults = nresults; |
@@ -272,10 +281,11 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
272 | CallInfo *ci; | 281 | CallInfo *ci; |
273 | int n; | 282 | int n; |
274 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 283 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
275 | ci = ++L->ci; /* now `enter' new function */ | 284 | ci = inc_ci(L); /* now `enter' new function */ |
276 | ci->func = restorestack(L, funcr); | 285 | ci->func = restorestack(L, funcr); |
277 | L->base = ci->base = ci->func + 1; | 286 | L->base = ci->base = ci->func + 1; |
278 | ci->top = L->top + LUA_MINSTACK; | 287 | ci->top = L->top + LUA_MINSTACK; |
288 | lua_assert(ci->top <= L->stack_last); | ||
279 | if (L->hookmask & LUA_MASKCALL) | 289 | if (L->hookmask & LUA_MASKCALL) |
280 | luaD_callhook(L, LUA_HOOKCALL, -1); | 290 | luaD_callhook(L, LUA_HOOKCALL, -1); |
281 | lua_unlock(L); | 291 | lua_unlock(L); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.h,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 2.2 2004/05/14 19:25:09 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 | */ |
@@ -17,7 +17,7 @@ | |||
17 | ** macro to control inclusion of some hard tests on stack reallocation | 17 | ** macro to control inclusion of some hard tests on stack reallocation |
18 | */ | 18 | */ |
19 | #ifndef HARDSTACKTESTS | 19 | #ifndef HARDSTACKTESTS |
20 | #define condhardstacktests(x) { /* empty */ } | 20 | #define condhardstacktests(x) ((void)0) |
21 | #else | 21 | #else |
22 | #define condhardstacktests(x) x | 22 | #define condhardstacktests(x) x |
23 | #endif | 23 | #endif |
@@ -26,7 +26,7 @@ | |||
26 | #define luaD_checkstack(L,n) \ | 26 | #define luaD_checkstack(L,n) \ |
27 | if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ | 27 | if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ |
28 | luaD_growstack(L, n); \ | 28 | luaD_growstack(L, n); \ |
29 | else condhardstacktests(luaD_reallocstack(L, L->stacksize)); | 29 | else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); |
30 | 30 | ||
31 | 31 | ||
32 | #define incr_top(L) {luaD_checkstack(L,1); L->top++;} | 32 | #define incr_top(L) {luaD_checkstack(L,1); L->top++;} |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.9 2004/08/24 20:12:06 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.10 2004/08/30 13:44:44 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -239,14 +239,17 @@ static void traverseclosure (global_State *g, Closure *cl) { | |||
239 | 239 | ||
240 | 240 | ||
241 | static void checkstacksizes (lua_State *L, StkId max) { | 241 | static void checkstacksizes (lua_State *L, StkId max) { |
242 | int used = L->ci - L->base_ci; /* number of `ci' in use */ | 242 | int ci_used = L->ci - L->base_ci; /* number of `ci' in use */ |
243 | if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) | 243 | int s_used = max - L->stack; /* part of stack in use */ |
244 | if (L->size_ci > LUA_MAXCALLS) /* handling overflow? */ | ||
245 | return; /* do not touch the stacks */ | ||
246 | if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) | ||
244 | luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ | 247 | luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ |
245 | else condhardstacktests(luaD_reallocCI(L, L->size_ci)); | 248 | condhardstacktests(luaD_reallocCI(L, ci_used + 1)); |
246 | used = max - L->stack; /* part of stack in use */ | 249 | if (4*s_used < L->stacksize && |
247 | if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) | 250 | 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) |
248 | luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ | 251 | luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ |
249 | else condhardstacktests(luaD_reallocstack(L, L->stacksize)); | 252 | condhardstacktests(luaD_reallocstack(L, s_used)); |
250 | } | 253 | } |
251 | 254 | ||
252 | 255 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.11 2004/08/24 20:12:06 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.12 2004/08/30 13:44:44 roberto Exp $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -62,7 +62,7 @@ static void stack_init (lua_State *L1, lua_State *L) { | |||
62 | L1->base = L1->ci->base = L1->top; | 62 | L1->base = L1->ci->base = L1->top; |
63 | L1->ci->top = L1->top + LUA_MINSTACK; | 63 | L1->ci->top = L1->top + LUA_MINSTACK; |
64 | L1->size_ci = BASIC_CI_SIZE; | 64 | L1->size_ci = BASIC_CI_SIZE; |
65 | L1->end_ci = L1->base_ci + L1->size_ci; | 65 | L1->end_ci = L1->base_ci + L1->size_ci - 1; |
66 | } | 66 | } |
67 | 67 | ||
68 | 68 | ||