Pārlūkot izejas kodu

separated control over C recursion level

Roberto Ierusalimschy 23 gadi atpakaļ
vecāks
revīzija
2d2d45976c
4 mainītis faili ar 40 papildinājumiem un 18 dzēšanām
  1. 19 12
      ldo.c
  2. 16 3
      llimits.h
  3. 2 1
      lstate.c
  4. 3 2
      lstate.h

+ 19 - 12
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
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 ** 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) {
 void luaD_reallocCI (lua_State *L, int newsize) {
   CallInfo *oldci = L->base_ci;
   CallInfo *oldci = L->base_ci;
   luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);
   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->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;
 }
 }
@@ -288,15 +288,18 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
 ** function position.
 ** function position.
 */ 
 */ 
 void luaD_call (lua_State *L, StkId func, int nResults) {
 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);
   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;
   lu_byte old_allowhooks;
   lua_lock(L);
   lua_lock(L);
   old_allowhooks = L->allowhook;
   old_allowhooks = L->allowhook;
-  lua_assert(L->errfunc == 0);
+  lua_assert(L->errfunc == 0 && L->nCcalls == 0);
   status = luaD_rawrunprotected(L, resume, &nargs);
   status = luaD_rawrunprotected(L, resume, &nargs);
   if (status != 0) {  /* error? */
   if (status != 0) {  /* error? */
     L->ci = L->base_ci;  /* go back to initial level */
     L->ci = L->base_ci;  /* go back to initial level */
     L->base = L->ci->base;
     L->base = L->ci->base;
+    L->nCcalls = 0;
     luaF_close(L, L->base);  /* close eventual pending closures */
     luaF_close(L, L->base);  /* close eventual pending closures */
     seterrorobj(L, status, L->base);
     seterrorobj(L, status, L->base);
     L->allowhook = old_allowhooks;
     L->allowhook = old_allowhooks;
@@ -356,6 +360,8 @@ LUA_API int lua_yield (lua_State *L, int nresults) {
   CallInfo *ci;
   CallInfo *ci;
   lua_lock(L);
   lua_lock(L);
   ci = L->ci;
   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->state & CI_C) {  /* usual yield */
     if ((ci-1)->state & CI_C)
     if ((ci-1)->state & CI_C)
       luaG_runerror(L, "cannot yield a C function");
       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);
         setobjs2s(L->base + i, L->top - nresults + i);
       L->top = L->base + nresults;
       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;
   ci->state |= CI_YIELD;
   lua_unlock(L);
   lua_unlock(L);
   return -1;
   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) {
 int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) {
   struct CallS c;
   struct CallS c;
   int status;
   int status;
+  unsigned short oldnCcalls = L->nCcalls;
   ptrdiff_t old_top = savestack(L, L->top);
   ptrdiff_t old_top = savestack(L, L->top);
   ptrdiff_t old_ci = saveci(L, L->ci);
   ptrdiff_t old_ci = saveci(L, L->ci);
   lu_byte old_allowhooks = L->allowhook;
   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);
     StkId oldtop = restorestack(L, old_top) - (nargs+1);
     luaF_close(L, oldtop);  /* close eventual pending closures */
     luaF_close(L, oldtop);  /* close eventual pending closures */
     seterrorobj(L, status, oldtop);
     seterrorobj(L, status, oldtop);
+    L->nCcalls = oldnCcalls;
     L->ci = restoreci(L, old_ci);
     L->ci = restoreci(L, old_ci);
     L->base = L->ci->base;
     L->base = L->ci->base;
     L->allowhook = old_allowhooks;
     L->allowhook = old_allowhooks;

+ 16 - 3
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
 ** Limits, basic types, and some other `installation-dependent' definitions
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -119,12 +119,22 @@ typedef LUA_UACNUMBER l_uacNumber;
 typedef unsigned long Instruction;
 typedef unsigned long Instruction;
 
 
 
 
-/* maximum depth for calls */
+/* maximum depth for calls (unsigned short) */
 #ifndef LUA_MAXCALLS
 #ifndef LUA_MAXCALLS
 #define LUA_MAXCALLS        4096
 #define LUA_MAXCALLS        4096
 #endif
 #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 */
 /* maximum size for the C stack */
 #ifndef LUA_MAXCSTACK
 #ifndef LUA_MAXCSTACK
 #define LUA_MAXCSTACK        2048
 #define LUA_MAXCSTACK        2048
@@ -165,7 +175,10 @@ typedef unsigned long Instruction;
 #endif
 #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
 #ifndef LUA_MAXPARSERLEVEL
 #define LUA_MAXPARSERLEVEL	200
 #define LUA_MAXPARSERLEVEL	200
 #endif
 #endif

+ 2 - 1
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
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -130,6 +130,7 @@ static void preinit_state (lua_State *L) {
   resethookcount(L);
   resethookcount(L);
   L->openupval = NULL;
   L->openupval = NULL;
   L->size_ci = 0;
   L->size_ci = 0;
+  L->nCcalls = 0;
   L->base_ci = L->ci = NULL;
   L->base_ci = L->ci = NULL;
   L->errfunc = 0;
   L->errfunc = 0;
   setnilvalue(gt(L));
   setnilvalue(gt(L));

+ 3 - 2
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
 ** Global State
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -138,7 +138,8 @@ struct lua_State {
   int stacksize;
   int stacksize;
   CallInfo *end_ci;  /* points after end of ci array*/
   CallInfo *end_ci;  /* points after end of ci array*/
   CallInfo *base_ci;  /* array of CallInfo's */
   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 hookmask;
   lu_byte allowhook;
   lu_byte allowhook;
   lu_byte hookinit;
   lu_byte hookinit;