From 0de2065f4e7cbbbe301b07835b9dd0b1bd1a4bbb Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 8 Sep 2004 11:23:09 -0300 Subject: [PATCH] tighter tests for stack overflow --- ldo.c | 34 ++++++++++++++++++++++------------ ldo.h | 6 +++--- lgc.c | 17 ++++++++++------- lstate.c | 4 ++-- 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/ldo.c b/ldo.c index 5aa6b5c0..19c57153 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.7 2004/06/02 19:07:55 roberto Exp roberto $ +** $Id: ldo.c,v 2.8 2004/09/03 15:48:56 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -93,7 +93,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { static void restore_stack_limit (lua_State *L) { - L->stack_last = L->stack+L->stacksize-1; + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); if (L->size_ci > LUA_MAXCALLS) { /* there was an overflow? */ int inuse = (L->ci - L->base_ci); if (inuse + 1 < LUA_MAXCALLS) /* can `undo' overflow? */ @@ -121,9 +121,11 @@ static void correctstack (lua_State *L, TValue *oldstack) { void luaD_reallocstack (lua_State *L, int newsize) { TValue *oldstack = L->stack; - luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); - L->stacksize = newsize; - L->stack_last = L->stack+newsize-1-EXTRA_STACK; + int realsize = newsize + 1 + EXTRA_STACK; + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + L->stacksize = realsize; + L->stack_last = L->stack+newsize; correctstack(L, oldstack); } @@ -133,7 +135,7 @@ void luaD_reallocCI (lua_State *L, int newsize) { luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); L->size_ci = cast(unsigned short, newsize); L->ci = (L->ci - oldci) + L->base_ci; - L->end_ci = L->base_ci + L->size_ci; + L->end_ci = L->base_ci + L->size_ci - 1; } @@ -141,11 +143,11 @@ void luaD_growstack (lua_State *L, int n) { if (n <= L->stacksize) /* double size is enough? */ luaD_reallocstack(L, 2*L->stacksize); else - luaD_reallocstack(L, L->stacksize + n + EXTRA_STACK); + luaD_reallocstack(L, L->stacksize + n); } -static void luaD_growCI (lua_State *L) { +static CallInfo *luaD_growCI (lua_State *L) { if (L->size_ci > LUA_MAXCALLS) /* overflow while handling overflow? */ luaD_throw(L, LUA_ERRERR); else { @@ -153,6 +155,7 @@ static void luaD_growCI (lua_State *L) { if (L->size_ci > LUA_MAXCALLS) luaG_runerror(L, "stack overflow"); } + return ++L->ci; } @@ -170,6 +173,7 @@ void luaD_callhook (lua_State *L, int event, int line) { ar.i_ci = L->ci - L->base_ci; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ L->ci->top = L->top + LUA_MINSTACK; + lua_assert(L->ci->top <= L->stack_last); L->allowhook = 0; /* cannot call hooks inside a hook */ lua_unlock(L); (*hook)(L, &ar); @@ -232,14 +236,18 @@ static StkId tryfuncTM (lua_State *L, StkId func) { } + +#define inc_ci(L) \ + ((L->ci == L->end_ci) ? luaD_growCI(L) : \ + (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) + + int luaD_precall (lua_State *L, StkId func, int nresults) { LClosure *cl; ptrdiff_t funcr; if (!ttisfunction(func)) /* `func' is not a function? */ func = tryfuncTM(L, func); /* check the `function' tag method */ funcr = savestack(L, func); - if (L->ci + 1 == L->end_ci) luaD_growCI(L); - else condhardstacktests(luaD_reallocCI(L, L->size_ci)); cl = &clvalue(func)->l; if (!cl->isC) { /* Lua function? prepare its call */ CallInfo *ci; @@ -256,10 +264,11 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { func = restorestack(L, funcr); base = func + 1; } - ci = ++L->ci; /* now `enter' new function */ + ci = inc_ci(L); /* now `enter' new function */ ci->func = func; L->base = ci->base = base; ci->top = L->base + p->maxstacksize; + lua_assert(ci->top <= L->stack_last); ci->savedpc = p->code; /* starting point */ ci->tailcalls = 0; ci->nresults = nresults; @@ -272,10 +281,11 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { CallInfo *ci; int n; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci = ++L->ci; /* now `enter' new function */ + ci = inc_ci(L); /* now `enter' new function */ ci->func = restorestack(L, funcr); L->base = ci->base = ci->func + 1; ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); if (L->hookmask & LUA_MASKCALL) luaD_callhook(L, LUA_HOOKCALL, -1); lua_unlock(L); diff --git a/ldo.h b/ldo.h index 8e2e026b..665934bd 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $ +** $Id: ldo.h,v 2.2 2004/05/14 19:25:09 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -17,7 +17,7 @@ ** macro to control inclusion of some hard tests on stack reallocation */ #ifndef HARDSTACKTESTS -#define condhardstacktests(x) { /* empty */ } +#define condhardstacktests(x) ((void)0) #else #define condhardstacktests(x) x #endif @@ -26,7 +26,7 @@ #define luaD_checkstack(L,n) \ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ luaD_growstack(L, n); \ - else condhardstacktests(luaD_reallocstack(L, L->stacksize)); + else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); #define incr_top(L) {luaD_checkstack(L,1); L->top++;} diff --git a/lgc.c b/lgc.c index 94d801ab..6beaa55b 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.9 2004/08/24 20:12:06 roberto Exp roberto $ +** $Id: lgc.c,v 2.10 2004/08/30 13:44:44 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -239,14 +239,17 @@ static void traverseclosure (global_State *g, Closure *cl) { static void checkstacksizes (lua_State *L, StkId max) { - int used = L->ci - L->base_ci; /* number of `ci' in use */ - if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) + int ci_used = L->ci - L->base_ci; /* number of `ci' in use */ + int s_used = max - L->stack; /* part of stack in use */ + if (L->size_ci > LUA_MAXCALLS) /* handling overflow? */ + return; /* do not touch the stacks */ + if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ - else condhardstacktests(luaD_reallocCI(L, L->size_ci)); - used = max - L->stack; /* part of stack in use */ - if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) + condhardstacktests(luaD_reallocCI(L, ci_used + 1)); + if (4*s_used < L->stacksize && + 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ - else condhardstacktests(luaD_reallocstack(L, L->stacksize)); + condhardstacktests(luaD_reallocstack(L, s_used)); } diff --git a/lstate.c b/lstate.c index 568d8e72..0a2eaefb 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.11 2004/08/24 20:12:06 roberto Exp roberto $ +** $Id: lstate.c,v 2.12 2004/08/30 13:44:44 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -62,7 +62,7 @@ static void stack_init (lua_State *L1, lua_State *L) { L1->base = L1->ci->base = L1->top; L1->ci->top = L1->top + LUA_MINSTACK; L1->size_ci = BASIC_CI_SIZE; - L1->end_ci = L1->base_ci + L1->size_ci; + L1->end_ci = L1->base_ci + L1->size_ci - 1; }