diff --git a/ldo.c b/ldo.c index 45d820c7..84c244e6 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.206 2002/11/21 15:46:44 roberto Exp roberto $ +** $Id: ldo.c,v 1.207 2002/11/21 17:19:11 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -126,7 +126,7 @@ void luaD_reallocstack (lua_State *L, int newsize) { void luaD_reallocCI (lua_State *L, int newsize) { CallInfo *oldci = L->base_ci; luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); - L->size_ci = newsize; + L->size_ci = cast(unsigned short, newsize); L->ci = (L->ci - oldci) + L->base_ci; L->end_ci = L->base_ci + L->size_ci; } @@ -288,15 +288,18 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { ** function position. */ void luaD_call (lua_State *L, StkId func, int nResults) { - StkId firstResult = luaD_precall(L, func); - if (firstResult == NULL) { /* is a Lua function? */ - firstResult = luaV_execute(L); /* call it */ - if (firstResult == NULL) { - luaD_poscall(L, 0, L->top); - luaG_runerror(L, "attempt to yield across tag-method/C-call boundary"); - } + StkId firstResult; + if (++L->nCcalls >= LUA_MAXCCALLS) { + if (L->nCcalls == LUA_MAXCCALLS) + luaG_runerror(L, "stack overflow"); + else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ } + firstResult = luaD_precall(L, func); + if (firstResult == NULL) /* is a Lua function? */ + firstResult = luaV_execute(L); /* call it */ luaD_poscall(L, nResults, firstResult); + L->nCcalls--; } @@ -337,11 +340,12 @@ LUA_API int lua_resume (lua_State *L, int nargs) { lu_byte old_allowhooks; lua_lock(L); old_allowhooks = L->allowhook; - lua_assert(L->errfunc == 0); + lua_assert(L->errfunc == 0 && L->nCcalls == 0); status = luaD_rawrunprotected(L, resume, &nargs); if (status != 0) { /* error? */ L->ci = L->base_ci; /* go back to initial level */ L->base = L->ci->base; + L->nCcalls = 0; luaF_close(L, L->base); /* close eventual pending closures */ seterrorobj(L, status, L->base); L->allowhook = old_allowhooks; @@ -356,6 +360,8 @@ LUA_API int lua_yield (lua_State *L, int nresults) { CallInfo *ci; lua_lock(L); ci = L->ci; + if (L->nCcalls > 0) + luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); if (ci->state & CI_C) { /* usual yield */ if ((ci-1)->state & CI_C) luaG_runerror(L, "cannot yield a C function"); @@ -365,8 +371,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { setobjs2s(L->base + i, L->top - nresults + i); L->top = L->base + nresults; } - } - /* else it's an yield inside a hook: nothing to do */ + } /* else it's an yield inside a hook: nothing to do */ ci->state |= CI_YIELD; lua_unlock(L); return -1; @@ -391,6 +396,7 @@ static void f_call (lua_State *L, void *ud) { int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) { struct CallS c; int status; + unsigned short oldnCcalls = L->nCcalls; ptrdiff_t old_top = savestack(L, L->top); ptrdiff_t old_ci = saveci(L, L->ci); lu_byte old_allowhooks = L->allowhook; @@ -403,6 +409,7 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) { StkId oldtop = restorestack(L, old_top) - (nargs+1); luaF_close(L, oldtop); /* close eventual pending closures */ seterrorobj(L, status, oldtop); + L->nCcalls = oldnCcalls; L->ci = restoreci(L, old_ci); L->base = L->ci->base; L->allowhook = old_allowhooks; diff --git a/llimits.h b/llimits.h index c14e0203..1e6171f3 100644 --- a/llimits.h +++ b/llimits.h @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.47 2002/10/22 17:18:28 roberto Exp roberto $ +** $Id: llimits.h,v 1.48 2002/11/22 16:35:20 roberto Exp roberto $ ** Limits, basic types, and some other `installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -119,12 +119,22 @@ typedef LUA_UACNUMBER l_uacNumber; typedef unsigned long Instruction; -/* maximum depth for calls */ +/* maximum depth for calls (unsigned short) */ #ifndef LUA_MAXCALLS #define LUA_MAXCALLS 4096 #endif +/* +** maximum depth for C calls (unsigned short): Not too big, or may +** overflow the C stack... +*/ + +#ifndef LUA_MAXCCALLS +#define LUA_MAXCCALLS 200 +#endif + + /* maximum size for the C stack */ #ifndef LUA_MAXCSTACK #define LUA_MAXCSTACK 2048 @@ -165,7 +175,10 @@ typedef unsigned long Instruction; #endif -/* maximum number of syntactical nested non-terminals */ +/* +** maximum number of syntactical nested non-terminals: Not too big, +** or may overflow the C stack... +*/ #ifndef LUA_MAXPARSERLEVEL #define LUA_MAXPARSERLEVEL 200 #endif diff --git a/lstate.c b/lstate.c index 5257c3e2..988ae13c 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 1.114 2002/11/21 14:14:42 roberto Exp roberto $ +** $Id: lstate.c,v 1.115 2002/11/21 15:16:04 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -130,6 +130,7 @@ static void preinit_state (lua_State *L) { resethookcount(L); L->openupval = NULL; L->size_ci = 0; + L->nCcalls = 0; L->base_ci = L->ci = NULL; L->errfunc = 0; setnilvalue(gt(L)); diff --git a/lstate.h b/lstate.h index 507de477..770c16ca 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.104 2002/11/21 15:16:04 roberto Exp roberto $ +** $Id: lstate.h,v 1.105 2002/11/21 15:46:44 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -138,7 +138,8 @@ struct lua_State { int stacksize; CallInfo *end_ci; /* points after end of ci array*/ CallInfo *base_ci; /* array of CallInfo's */ - int size_ci; /* size of array `base_ci' */ + unsigned short size_ci; /* size of array `base_ci' */ + unsigned short nCcalls; /* number of nested C calls */ lu_byte hookmask; lu_byte allowhook; lu_byte hookinit;