aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-07-15 14:26:14 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2009-07-15 14:26:14 -0300
commitf76f4cb79d84af4a7be9e0d75553bbe05a3ae90c (patch)
treedd9d1f8f3fb8c69f7617fe5688d7b1178bb7190e
parentabb85fc059a5d6427b9dc36edee1619f2c7a1da8 (diff)
downloadlua-f76f4cb79d84af4a7be9e0d75553bbe05a3ae90c.tar.gz
lua-f76f4cb79d84af4a7be9e0d75553bbe05a3ae90c.tar.bz2
lua-f76f4cb79d84af4a7be9e0d75553bbe05a3ae90c.zip
new way to control stack overflow, controling only total size of the stack
-rw-r--r--lapi.c17
-rw-r--r--lauxlib.c25
-rw-r--r--ldo.c68
-rw-r--r--ldo.h3
-rw-r--r--llimits.h6
-rw-r--r--lstate.c19
-rw-r--r--lstate.h3
-rw-r--r--ltests.c3
-rw-r--r--lua.h4
-rw-r--r--luaconf.h30
10 files changed, 100 insertions, 78 deletions
diff --git a/lapi.c b/lapi.c
index 6f33c950..1873bec3 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 2.83 2009/06/18 18:59:18 roberto Exp roberto $ 2** $Id: lapi.c,v 2.84 2009/06/19 14:21:23 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -86,14 +86,15 @@ LUA_API int lua_checkstack (lua_State *L, int size) {
86 int res = 1; 86 int res = 1;
87 CallInfo *ci = L->ci; 87 CallInfo *ci = L->ci;
88 lua_lock(L); 88 lua_lock(L);
89 if (size > LUAI_MAXCSTACK || 89 if (L->stack_last - L->top <= size) { /* need to grow stack? */
90 (L->top - (ci->func + 1) + size) > LUAI_MAXCSTACK) 90 int inuse = L->top - L->stack + EXTRA_STACK;
91 res = 0; /* stack overflow */ 91 if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */
92 else if (size > 0) { 92 res = 0; /* no */
93 luaD_checkstack(L, size); 93 else
94 if (ci->top < L->top + size) 94 luaD_growstack(L, size);
95 ci->top = L->top + size;
96 } 95 }
96 if (res && ci->top < L->top + size)
97 ci->top = L->top + size; /* adjust frame top */
97 lua_unlock(L); 98 lua_unlock(L);
98 return res; 99 return res;
99} 100}
diff --git a/lauxlib.c b/lauxlib.c
index f021686a..0ba32e1e 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.c,v 1.187 2009/06/18 18:59:58 roberto Exp roberto $ 2** $Id: lauxlib.c,v 1.188 2009/06/19 14:21:57 roberto Exp roberto $
3** Auxiliary functions for building Lua libraries 3** Auxiliary functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -106,9 +106,16 @@ static void pushfuncname (lua_State *L, lua_Debug *ar) {
106 106
107static int countlevels (lua_State *L) { 107static int countlevels (lua_State *L) {
108 lua_Debug ar; 108 lua_Debug ar;
109 int level = 1; 109 int li = 1, le = 1;
110 while (lua_getstack(L, level, &ar)) level++; 110 /* find an upper bound */
111 return level; 111 while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
112 /* do a binary search */
113 while (li < le) {
114 int m = (li + le)/2;
115 if (lua_getstack(L, m, &ar)) li = m + 1;
116 else le = m;
117 }
118 return le - 1;
112} 119}
113 120
114 121
@@ -263,9 +270,13 @@ LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
263} 270}
264 271
265 272
266LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { 273LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
267 if (!lua_checkstack(L, space)) 274 if (!lua_checkstack(L, space)) {
268 luaL_error(L, "stack overflow (%s)", mes); 275 if (msg)
276 luaL_error(L, "stack overflow (%s)", msg);
277 else
278 luaL_error(L, "stack overflow");
279 }
269} 280}
270 281
271 282
diff --git a/ldo.c b/ldo.c
index dc9112a1..e93f68e3 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.64 2009/05/21 20:06:11 roberto Exp roberto $ 2** $Id: ldo.c,v 2.65 2009/06/01 19:09:26 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -70,12 +70,6 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
70} 70}
71 71
72 72
73static void restore_stack_limit (lua_State *L) {
74 if (L->nci >= LUAI_MAXCALLS) /* stack overflow? */
75 luaE_freeCI(L); /* erase all extras CIs */
76}
77
78
79void luaD_throw (lua_State *L, int errcode) { 73void luaD_throw (lua_State *L, int errcode) {
80 if (L->errorJmp) { /* thread has an error handler? */ 74 if (L->errorJmp) { /* thread has an error handler? */
81 L->errorJmp->status = errcode; /* set status */ 75 L->errorJmp->status = errcode; /* set status */
@@ -130,25 +124,63 @@ static void correctstack (lua_State *L, TValue *oldstack) {
130} 124}
131 125
132 126
127/* some space for error handling */
128#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
129
130
133void luaD_reallocstack (lua_State *L, int newsize) { 131void luaD_reallocstack (lua_State *L, int newsize) {
134 TValue *oldstack = L->stack; 132 TValue *oldstack = L->stack;
135 int lim = L->stacksize; 133 int lim = L->stacksize;
136 int realsize = newsize + 1 + EXTRA_STACK; 134 lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
137 lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); 135 lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
138 luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); 136 luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue);
139 for (; lim < realsize; lim++) 137 for (; lim < newsize; lim++)
140 setnilvalue(L->stack + lim); /* erase new segment */ 138 setnilvalue(L->stack + lim); /* erase new segment */
141 L->stacksize = realsize; 139 L->stacksize = newsize;
142 L->stack_last = L->stack+newsize; 140 L->stack_last = L->stack + newsize - EXTRA_STACK;
143 correctstack(L, oldstack); 141 correctstack(L, oldstack);
144} 142}
145 143
146 144
147void luaD_growstack (lua_State *L, int n) { 145void luaD_growstack (lua_State *L, int n) {
148 if (n <= L->stacksize) /* double size is enough? */ 146 int size = L->stacksize;
149 luaD_reallocstack(L, 2*L->stacksize); 147 if (size > LUAI_MAXSTACK) /* error after extra size? */
148 luaD_throw(L, LUA_ERRERR);
149 else {
150 int needed = L->top - L->stack + n + EXTRA_STACK;
151 int newsize = 2 * size;
152 if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
153 if (newsize < needed) newsize = needed;
154 if (newsize > LUAI_MAXSTACK) { /* stack overflow? */
155 luaD_reallocstack(L, ERRORSTACKSIZE);
156 luaG_runerror(L, "stack overflow");
157 }
158 else
159 luaD_reallocstack(L, newsize);
160 }
161}
162
163
164static int stackinuse (lua_State *L) {
165 CallInfo *ci;
166 StkId lim = L->top;
167 for (ci = L->ci; ci != NULL; ci = ci->previous) {
168 lua_assert(ci->top <= L->stack_last);
169 if (lim < ci->top) lim = ci->top;
170 }
171 return cast_int(lim - L->stack) + 1; /* part of stack in use */
172}
173
174
175void luaD_shrinkstack (lua_State *L) {
176 int inuse = stackinuse(L);
177 int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK;
178 if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK;
179 if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */
180 goodsize >= L->stacksize) /* would grow instead of shrink? */
181 condmovestack(L); /* don't change stack (change only for debugging) */
150 else 182 else
151 luaD_reallocstack(L, L->stacksize + n); 183 luaD_reallocstack(L, goodsize); /* shrink it */
152} 184}
153 185
154 186
@@ -427,7 +459,7 @@ static int recover (lua_State *L, int status) {
427 L->ci = ci; 459 L->ci = ci;
428 L->allowhook = ci->u.c.old_allowhook; 460 L->allowhook = ci->u.c.old_allowhook;
429 L->nny = 0; /* should be zero to be yieldable */ 461 L->nny = 0; /* should be zero to be yieldable */
430 restore_stack_limit(L); 462 luaD_shrinkstack(L);
431 L->errfunc = ci->u.c.old_errfunc; 463 L->errfunc = ci->u.c.old_errfunc;
432 ci->callstatus |= CIST_STAT; /* call has error status */ 464 ci->callstatus |= CIST_STAT; /* call has error status */
433 ci->u.c.status = status; /* (here it is) */ 465 ci->u.c.status = status; /* (here it is) */
@@ -499,7 +531,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
499 L->ci = old_ci; 531 L->ci = old_ci;
500 L->allowhook = old_allowhooks; 532 L->allowhook = old_allowhooks;
501 L->nny = old_nny; 533 L->nny = old_nny;
502 restore_stack_limit(L); 534 luaD_shrinkstack(L);
503 } 535 }
504 L->errfunc = old_errfunc; 536 L->errfunc = old_errfunc;
505 return status; 537 return status;
diff --git a/ldo.h b/ldo.h
index 6cd9fdca..7f12ff85 100644
--- a/ldo.h
+++ b/ldo.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.h,v 2.13 2009/06/08 19:35:59 roberto Exp roberto $ 2** $Id: ldo.h,v 2.14 2009/07/08 16:06:51 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -37,6 +37,7 @@ LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);
37LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); 37LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);
38LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); 38LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
39LUAI_FUNC void luaD_growstack (lua_State *L, int n); 39LUAI_FUNC void luaD_growstack (lua_State *L, int n);
40LUAI_FUNC void luaD_shrinkstack (lua_State *L);
40 41
41LUAI_FUNC void luaD_throw (lua_State *L, int errcode); 42LUAI_FUNC void luaD_throw (lua_State *L, int errcode);
42LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); 43LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
diff --git a/llimits.h b/llimits.h
index 5f254f72..c4220d67 100644
--- a/llimits.h
+++ b/llimits.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: llimits.h,v 1.71 2009/06/08 19:35:59 roberto Exp roberto $ 2** $Id: llimits.h,v 1.72 2009/07/01 16:14:15 roberto Exp roberto $
3** Limits, basic types, and some other `installation-dependent' definitions 3** Limits, basic types, and some other `installation-dependent' definitions
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -122,8 +122,8 @@ typedef lu_int32 Instruction;
122#ifndef HARDSTACKTESTS 122#ifndef HARDSTACKTESTS
123#define condmovestack(L) ((void)0) 123#define condmovestack(L) ((void)0)
124#else 124#else
125#define condmovestack(L) /* realloc stack keeping its size */ \ 125/* realloc stack keeping its size */
126 luaD_reallocstack((L), (L)->stacksize - EXTRA_STACK - 1) 126#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize)
127#endif 127#endif
128 128
129#endif 129#endif
diff --git a/lstate.c b/lstate.c
index 3268209e..0b9bb671 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.55 2009/06/01 19:09:26 roberto Exp roberto $ 2** $Id: lstate.c,v 2.56 2009/06/18 18:59:18 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -52,12 +52,6 @@ CallInfo *luaE_extendCI (lua_State *L) {
52 L->ci->next = ci; 52 L->ci->next = ci;
53 ci->previous = L->ci; 53 ci->previous = L->ci;
54 ci->next = NULL; 54 ci->next = NULL;
55 if (++L->nci >= LUAI_MAXCALLS) {
56 if (L->nci == LUAI_MAXCALLS) /* overflow? */
57 luaG_runerror(L, "stack overflow");
58 if (L->nci >= LUAI_MAXCALLS + LUAI_EXTRACALLS) /* again? */
59 luaD_throw(L, LUA_ERRERR); /* error while handling overflow */
60 }
61 return ci; 55 return ci;
62} 56}
63 57
@@ -69,7 +63,6 @@ void luaE_freeCI (lua_State *L) {
69 while ((ci = next) != NULL) { 63 while ((ci = next) != NULL) {
70 next = ci->next; 64 next = ci->next;
71 luaM_free(L, ci); 65 luaM_free(L, ci);
72 L->nci--;
73 } 66 }
74} 67}
75 68
@@ -77,12 +70,12 @@ void luaE_freeCI (lua_State *L) {
77static void stack_init (lua_State *L1, lua_State *L) { 70static void stack_init (lua_State *L1, lua_State *L) {
78 int i; 71 int i;
79 /* initialize stack array */ 72 /* initialize stack array */
80 L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); 73 L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue);
81 L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; 74 L1->stacksize = BASIC_STACK_SIZE;
82 for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) 75 for (i = 0; i < BASIC_STACK_SIZE; i++)
83 setnilvalue(L1->stack + i); /* erase new stack */ 76 setnilvalue(L1->stack + i); /* erase new stack */
84 L1->top = L1->stack; 77 L1->top = L1->stack;
85 L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; 78 L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK;
86 /* initialize first ci */ 79 /* initialize first ci */
87 L1->ci->func = L1->top; 80 L1->ci->func = L1->top;
88 setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ 81 setnilvalue(L1->top++); /* 'function' entry for this 'ci' */
@@ -94,7 +87,6 @@ static void stack_init (lua_State *L1, lua_State *L) {
94static void freestack (lua_State *L) { 87static void freestack (lua_State *L) {
95 L->ci = &L->base_ci; /* reset 'ci' list */ 88 L->ci = &L->base_ci; /* reset 'ci' list */
96 luaE_freeCI(L); 89 luaE_freeCI(L);
97 lua_assert(L->nci == 0);
98 luaM_freearray(L, L->stack, L->stacksize); 90 luaM_freearray(L, L->stack, L->stacksize);
99} 91}
100 92
@@ -131,7 +123,6 @@ static void preinit_state (lua_State *L, global_State *g) {
131 L->status = LUA_OK; 123 L->status = LUA_OK;
132 L->base_ci.next = L->base_ci.previous = NULL; 124 L->base_ci.next = L->base_ci.previous = NULL;
133 L->ci = &L->base_ci; 125 L->ci = &L->base_ci;
134 L->nci = 0;
135 L->errfunc = 0; 126 L->errfunc = 0;
136 setnilvalue(gt(L)); 127 setnilvalue(gt(L));
137} 128}
diff --git a/lstate.h b/lstate.h
index 783e51cf..2ddffaf1 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.44 2009/06/01 19:09:26 roberto Exp roberto $ 2** $Id: lstate.h,v 2.45 2009/06/18 18:59:18 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -163,7 +163,6 @@ struct lua_State {
163 StkId top; /* first free slot in the stack */ 163 StkId top; /* first free slot in the stack */
164 global_State *l_G; 164 global_State *l_G;
165 CallInfo *ci; /* call info for current function */ 165 CallInfo *ci; /* call info for current function */
166 int nci; /* number of total CallInfo structures linked */
167 const Instruction *oldpc; /* last pc traced */ 166 const Instruction *oldpc; /* last pc traced */
168 StkId stack_last; /* last free slot in the stack */ 167 StkId stack_last; /* last free slot in the stack */
169 StkId stack; /* stack base */ 168 StkId stack; /* stack base */
diff --git a/ltests.c b/ltests.c
index bc5a21e0..cfa14c21 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.65 2009/06/15 19:51:31 roberto Exp roberto $ 2** $Id: ltests.c,v 2.66 2009/06/17 17:53:14 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -570,7 +570,6 @@ static int stacklevel (lua_State *L) {
570 unsigned long a = 0; 570 unsigned long a = 0;
571 lua_pushinteger(L, (L->top - L->stack)); 571 lua_pushinteger(L, (L->top - L->stack));
572 lua_pushinteger(L, (L->stack_last - L->stack)); 572 lua_pushinteger(L, (L->stack_last - L->stack));
573 lua_pushinteger(L, L->nci);
574 lua_pushinteger(L, (unsigned long)&a); 573 lua_pushinteger(L, (unsigned long)&a);
575 return 5; 574 return 5;
576} 575}
diff --git a/lua.h b/lua.h
index edeafe7a..5887d16c 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.239 2009/06/17 17:49:44 roberto Exp roberto $ 2** $Id: lua.h,v 1.240 2009/06/18 18:59:18 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** Lua.org, PUC-Rio, Brazil (http://www.lua.org) 4** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
5** See Copyright Notice at the end of this file 5** See Copyright Notice at the end of this file
@@ -33,7 +33,7 @@
33/* 33/*
34** pseudo-indices 34** pseudo-indices
35*/ 35*/
36#define LUA_REGISTRYINDEX (-(LUAI_MCS_AUX) - 1) 36#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX
37#define LUA_ENVIRONINDEX (LUA_REGISTRYINDEX - 1) 37#define LUA_ENVIRONINDEX (LUA_REGISTRYINDEX - 1)
38#define LUA_GLOBALSINDEX (LUA_ENVIRONINDEX - 1) 38#define LUA_GLOBALSINDEX (LUA_ENVIRONINDEX - 1)
39#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) 39#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
diff --git a/luaconf.h b/luaconf.h
index 96dacdda..d8bcc2ba 100644
--- a/luaconf.h
+++ b/luaconf.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: luaconf.h,v 1.105 2009/06/18 18:19:36 roberto Exp roberto $ 2** $Id: luaconf.h,v 1.106 2009/07/01 16:16:40 roberto Exp roberto $
3** Configuration file for Lua 3** Configuration file for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -417,31 +417,19 @@
417 417
418 418
419/* 419/*
420@@ LUAI_MAXCALLS limits the number of nested calls. 420@@ LUAI_MAXSTACK limits the size of the Lua stack.
421** CHANGE it if you need really deep recursive calls. This limit is
422** arbitrary; its only purpose is to stop infinite recursion before
423** exhausting memory.
424*/
425#define LUAI_MAXCALLS 20000
426
427
428/*
429@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function
430@* can use.
431** CHANGE it if you need a different limit. This limit is arbitrary; 421** CHANGE it if you need a different limit. This limit is arbitrary;
432** its only purpose is to stop C functions to consume unlimited stack 422** its only purpose is to stop Lua to consume unlimited stack
433** space. 423** space (and to reserve some numbers for pseudo-indices).
434*/ 424*/
435/* life is simpler if stack size fits in an int (16 is an estimate 425#if LUAI_BITSINT >= 32
436 for the size of a Lua value) */ 426#define LUAI_MAXSTACK 1000000
437#if SHRT_MAX < (INT_MAX / 16)
438#define LUAI_MCS_AUX SHRT_MAX
439#else 427#else
440#define LUAI_MCS_AUX (INT_MAX / 16) 428#define LUAI_MAXSTACK 15000
441#endif 429#endif
442 430
443/* reserve some space for pseudo-indices */ 431/* reserve some space for error handling */
444#define LUAI_MAXCSTACK (LUAI_MCS_AUX - 1000) 432#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000)
445 433
446 434
447 435