diff options
Diffstat (limited to 'src/lua/lstate.c')
-rw-r--r-- | src/lua/lstate.c | 96 |
1 files changed, 30 insertions, 66 deletions
diff --git a/src/lua/lstate.c b/src/lua/lstate.c index 86b3761..4227429 100644 --- a/src/lua/lstate.c +++ b/src/lua/lstate.c | |||
@@ -76,7 +76,7 @@ static unsigned int luai_makeseed (lua_State *L) { | |||
76 | addbuff(buff, p, &h); /* local variable */ | 76 | addbuff(buff, p, &h); /* local variable */ |
77 | addbuff(buff, p, &lua_newstate); /* public function */ | 77 | addbuff(buff, p, &lua_newstate); /* public function */ |
78 | lua_assert(p == sizeof(buff)); | 78 | lua_assert(p == sizeof(buff)); |
79 | return luaS_hash(buff, p, h, 1); | 79 | return luaS_hash(buff, p, h); |
80 | } | 80 | } |
81 | 81 | ||
82 | #endif | 82 | #endif |
@@ -97,66 +97,14 @@ void luaE_setdebt (global_State *g, l_mem debt) { | |||
97 | 97 | ||
98 | 98 | ||
99 | LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) { | 99 | LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) { |
100 | global_State *g = G(L); | 100 | UNUSED(L); UNUSED(limit); |
101 | int ccalls; | 101 | return LUAI_MAXCCALLS; /* warning?? */ |
102 | luaE_freeCI(L); /* release unused CIs */ | ||
103 | ccalls = getCcalls(L); | ||
104 | if (limit >= 40000) | ||
105 | return 0; /* out of bounds */ | ||
106 | limit += CSTACKERR; | ||
107 | if (L != g-> mainthread) | ||
108 | return 0; /* only main thread can change the C stack */ | ||
109 | else if (ccalls <= CSTACKERR) | ||
110 | return 0; /* handling overflow */ | ||
111 | else { | ||
112 | int diff = limit - g->Cstacklimit; | ||
113 | if (ccalls + diff <= CSTACKERR) | ||
114 | return 0; /* new limit would cause an overflow */ | ||
115 | g->Cstacklimit = limit; /* set new limit */ | ||
116 | L->nCcalls += diff; /* correct 'nCcalls' */ | ||
117 | return limit - diff - CSTACKERR; /* success; return previous limit */ | ||
118 | } | ||
119 | } | ||
120 | |||
121 | |||
122 | /* | ||
123 | ** Decrement count of "C calls" and check for overflows. In case of | ||
124 | ** a stack overflow, check appropriate error ("regular" overflow or | ||
125 | ** overflow while handling stack overflow). If 'nCcalls' is smaller | ||
126 | ** than CSTACKERR but larger than CSTACKMARK, it means it has just | ||
127 | ** entered the "overflow zone", so the function raises an overflow | ||
128 | ** error. If 'nCcalls' is smaller than CSTACKMARK (which means it is | ||
129 | ** already handling an overflow) but larger than CSTACKERRMARK, does | ||
130 | ** not report an error (to allow message handling to work). Otherwise, | ||
131 | ** report a stack overflow while handling a stack overflow (probably | ||
132 | ** caused by a repeating error in the message handling function). | ||
133 | */ | ||
134 | |||
135 | void luaE_enterCcall (lua_State *L) { | ||
136 | int ncalls = getCcalls(L); | ||
137 | L->nCcalls--; | ||
138 | if (ncalls <= CSTACKERR) { /* possible overflow? */ | ||
139 | luaE_freeCI(L); /* release unused CIs */ | ||
140 | ncalls = getCcalls(L); /* update call count */ | ||
141 | if (ncalls <= CSTACKERR) { /* still overflow? */ | ||
142 | if (ncalls <= CSTACKERRMARK) /* below error-handling zone? */ | ||
143 | luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ | ||
144 | else if (ncalls >= CSTACKMARK) { | ||
145 | /* not in error-handling zone; raise the error now */ | ||
146 | L->nCcalls = (CSTACKMARK - 1); /* enter error-handling zone */ | ||
147 | luaG_runerror(L, "C stack overflow"); | ||
148 | } | ||
149 | /* else stack is in the error-handling zone; | ||
150 | allow message handler to work */ | ||
151 | } | ||
152 | } | ||
153 | } | 102 | } |
154 | 103 | ||
155 | 104 | ||
156 | CallInfo *luaE_extendCI (lua_State *L) { | 105 | CallInfo *luaE_extendCI (lua_State *L) { |
157 | CallInfo *ci; | 106 | CallInfo *ci; |
158 | lua_assert(L->ci->next == NULL); | 107 | lua_assert(L->ci->next == NULL); |
159 | luaE_enterCcall(L); | ||
160 | ci = luaM_new(L, CallInfo); | 108 | ci = luaM_new(L, CallInfo); |
161 | lua_assert(L->ci->next == NULL); | 109 | lua_assert(L->ci->next == NULL); |
162 | L->ci->next = ci; | 110 | L->ci->next = ci; |
@@ -175,13 +123,11 @@ void luaE_freeCI (lua_State *L) { | |||
175 | CallInfo *ci = L->ci; | 123 | CallInfo *ci = L->ci; |
176 | CallInfo *next = ci->next; | 124 | CallInfo *next = ci->next; |
177 | ci->next = NULL; | 125 | ci->next = NULL; |
178 | L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ | ||
179 | while ((ci = next) != NULL) { | 126 | while ((ci = next) != NULL) { |
180 | next = ci->next; | 127 | next = ci->next; |
181 | luaM_free(L, ci); | 128 | luaM_free(L, ci); |
182 | L->nci--; | 129 | L->nci--; |
183 | } | 130 | } |
184 | L->nCcalls -= L->nci; /* adjust result */ | ||
185 | } | 131 | } |
186 | 132 | ||
187 | 133 | ||
@@ -194,7 +140,6 @@ void luaE_shrinkCI (lua_State *L) { | |||
194 | CallInfo *next; | 140 | CallInfo *next; |
195 | if (ci == NULL) | 141 | if (ci == NULL) |
196 | return; /* no extra elements */ | 142 | return; /* no extra elements */ |
197 | L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ | ||
198 | while ((next = ci->next) != NULL) { /* two extra elements? */ | 143 | while ((next = ci->next) != NULL) { /* two extra elements? */ |
199 | CallInfo *next2 = next->next; /* next's next */ | 144 | CallInfo *next2 = next->next; /* next's next */ |
200 | ci->next = next2; /* remove next from the list */ | 145 | ci->next = next2; /* remove next from the list */ |
@@ -207,19 +152,39 @@ void luaE_shrinkCI (lua_State *L) { | |||
207 | ci = next2; /* continue */ | 152 | ci = next2; /* continue */ |
208 | } | 153 | } |
209 | } | 154 | } |
210 | L->nCcalls -= L->nci; /* adjust result */ | 155 | } |
156 | |||
157 | |||
158 | /* | ||
159 | ** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS. | ||
160 | ** If equal, raises an overflow error. If value is larger than | ||
161 | ** LUAI_MAXCCALLS (which means it is handling an overflow) but | ||
162 | ** not much larger, does not report an error (to allow overflow | ||
163 | ** handling to work). | ||
164 | */ | ||
165 | void luaE_checkcstack (lua_State *L) { | ||
166 | if (getCcalls(L) == LUAI_MAXCCALLS) | ||
167 | luaG_runerror(L, "C stack overflow"); | ||
168 | else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) | ||
169 | luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ | ||
170 | } | ||
171 | |||
172 | |||
173 | LUAI_FUNC void luaE_incCstack (lua_State *L) { | ||
174 | L->nCcalls++; | ||
175 | if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) | ||
176 | luaE_checkcstack(L); | ||
211 | } | 177 | } |
212 | 178 | ||
213 | 179 | ||
214 | static void stack_init (lua_State *L1, lua_State *L) { | 180 | static void stack_init (lua_State *L1, lua_State *L) { |
215 | int i; CallInfo *ci; | 181 | int i; CallInfo *ci; |
216 | /* initialize stack array */ | 182 | /* initialize stack array */ |
217 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, StackValue); | 183 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); |
218 | L1->stacksize = BASIC_STACK_SIZE; | ||
219 | for (i = 0; i < BASIC_STACK_SIZE; i++) | 184 | for (i = 0; i < BASIC_STACK_SIZE; i++) |
220 | setnilvalue(s2v(L1->stack + i)); /* erase new stack */ | 185 | setnilvalue(s2v(L1->stack + i)); /* erase new stack */ |
221 | L1->top = L1->stack; | 186 | L1->top = L1->stack; |
222 | L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; | 187 | L1->stack_last = L1->stack + BASIC_STACK_SIZE; |
223 | /* initialize first ci */ | 188 | /* initialize first ci */ |
224 | ci = &L1->base_ci; | 189 | ci = &L1->base_ci; |
225 | ci->next = ci->previous = NULL; | 190 | ci->next = ci->previous = NULL; |
@@ -240,7 +205,7 @@ static void freestack (lua_State *L) { | |||
240 | L->ci = &L->base_ci; /* free the entire 'ci' list */ | 205 | L->ci = &L->base_ci; /* free the entire 'ci' list */ |
241 | luaE_freeCI(L); | 206 | luaE_freeCI(L); |
242 | lua_assert(L->nci == 0); | 207 | lua_assert(L->nci == 0); |
243 | luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ | 208 | luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */ |
244 | } | 209 | } |
245 | 210 | ||
246 | 211 | ||
@@ -290,7 +255,6 @@ static void preinit_thread (lua_State *L, global_State *g) { | |||
290 | L->stack = NULL; | 255 | L->stack = NULL; |
291 | L->ci = NULL; | 256 | L->ci = NULL; |
292 | L->nci = 0; | 257 | L->nci = 0; |
293 | L->stacksize = 0; | ||
294 | L->twups = L; /* thread has no upvalues */ | 258 | L->twups = L; /* thread has no upvalues */ |
295 | L->errorJmp = NULL; | 259 | L->errorJmp = NULL; |
296 | L->hook = NULL; | 260 | L->hook = NULL; |
@@ -335,7 +299,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { | |||
335 | setthvalue2s(L, L->top, L1); | 299 | setthvalue2s(L, L->top, L1); |
336 | api_incr_top(L); | 300 | api_incr_top(L); |
337 | preinit_thread(L1, g); | 301 | preinit_thread(L1, g); |
338 | L1->nCcalls = getCcalls(L); | 302 | L1->nCcalls = 0; |
339 | L1->hookmask = L->hookmask; | 303 | L1->hookmask = L->hookmask; |
340 | L1->basehookcount = L->basehookcount; | 304 | L1->basehookcount = L->basehookcount; |
341 | L1->hook = L->hook; | 305 | L1->hook = L->hook; |
@@ -396,7 +360,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
396 | preinit_thread(L, g); | 360 | preinit_thread(L, g); |
397 | g->allgc = obj2gco(L); /* by now, only object is the main thread */ | 361 | g->allgc = obj2gco(L); /* by now, only object is the main thread */ |
398 | L->next = NULL; | 362 | L->next = NULL; |
399 | g->Cstacklimit = L->nCcalls = LUAI_MAXCSTACK + CSTACKERR; | 363 | L->nCcalls = 0; |
400 | incnny(L); /* main thread is always non yieldable */ | 364 | incnny(L); /* main thread is always non yieldable */ |
401 | g->frealloc = f; | 365 | g->frealloc = f; |
402 | g->ud = ud; | 366 | g->ud = ud; |