commit 2d2d45976ce41de04e9007c8a78a8ba244d1fdc5
parent 0050d983fc2f3cc56442cadd73a93823643ac53d
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Fri, 22 Nov 2002 15:16:30 -0200
separated control over C recursion level
Diffstat:
4 files changed, 40 insertions(+), 18 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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;