Selaa lähdekoodia

tighter tests for stack overflow

Roberto Ierusalimschy 21 vuotta sitten
vanhempi
commit
0de2065f4e
4 muutettua tiedostoa jossa 37 lisäystä ja 24 poistoa
  1. 22 12
      ldo.c
  2. 3 3
      ldo.h
  3. 10 7
      lgc.c
  4. 2 2
      lstate.c

+ 22 - 12
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);

+ 3 - 3
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++;}

+ 10 - 7
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));
 }
 
 

+ 2 - 2
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;
 }