aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-02-28 16:45:15 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2003-02-28 16:45:15 -0300
commit69dd9461e5aeb98fe9bbc71f1e81859d03ec8a34 (patch)
treed9505d7a0e89940c55ff0a1fd3c13311b9084197
parent6b6bc532a4f5e335540e6f19914cfe8435d064ed (diff)
downloadlua-69dd9461e5aeb98fe9bbc71f1e81859d03ec8a34.tar.gz
lua-69dd9461e5aeb98fe9bbc71f1e81859d03ec8a34.tar.bz2
lua-69dd9461e5aeb98fe9bbc71f1e81859d03ec8a34.zip
bug: GC metamethod calls could mess C/Lua stack syncronization
-rw-r--r--bugs5
-rw-r--r--ldo.c18
-rw-r--r--lgc.h6
-rw-r--r--lstate.c11
-rw-r--r--lvm.c23
5 files changed, 44 insertions, 19 deletions
diff --git a/bugs b/bugs
index d87a158c..e39ae780 100644
--- a/bugs
+++ b/bugs
@@ -324,3 +324,8 @@ Thu Jan 23 11:29:06 UTC 2003
324>> protected 324>> protected
325(by Benoit Germain; since 5.0a) 325(by Benoit Germain; since 5.0a)
326 326
327** ldo.c (and others)
328Fri Feb 28 14:20:33 EST 2003
329>> GC metamethod calls could mess C/Lua stack syncronization
330(by Roberto; since 5.0b)
331
diff --git a/ldo.c b/ldo.c
index a285d6e1..985ab6e3 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 1.214 2003/02/27 11:52:30 roberto Exp roberto $ 2** $Id: ldo.c,v 1.215 2003/02/28 15:42:08 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*/
@@ -292,7 +292,6 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
292 while (wanted-- > 0) 292 while (wanted-- > 0)
293 setnilvalue(res++); 293 setnilvalue(res++);
294 L->top = res; 294 L->top = res;
295 luaC_checkGC(L);
296} 295}
297 296
298 297
@@ -304,9 +303,10 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
304*/ 303*/
305void luaD_call (lua_State *L, StkId func, int nResults) { 304void luaD_call (lua_State *L, StkId func, int nResults) {
306 StkId firstResult; 305 StkId firstResult;
306 lua_assert(!(L->ci->state & CI_CALLING));
307 if (++L->nCcalls >= LUA_MAXCCALLS) { 307 if (++L->nCcalls >= LUA_MAXCCALLS) {
308 if (L->nCcalls == LUA_MAXCCALLS) 308 if (L->nCcalls == LUA_MAXCCALLS)
309 luaG_runerror(L, "stack overflow"); 309 luaG_runerror(L, "C stack overflow");
310 else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3))) 310 else if (L->nCcalls >= (LUA_MAXCCALLS + (LUA_MAXCCALLS>>3)))
311 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ 311 luaD_throw(L, LUA_ERRERR); /* error while handing stack error */
312 } 312 }
@@ -315,6 +315,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
315 firstResult = luaV_execute(L); /* call it */ 315 firstResult = luaV_execute(L); /* call it */
316 luaD_poscall(L, nResults, firstResult); 316 luaD_poscall(L, nResults, firstResult);
317 L->nCcalls--; 317 L->nCcalls--;
318 luaC_checkGC(L);
318} 319}
319 320
320 321
@@ -428,10 +429,13 @@ struct SParser { /* data to `f_parser' */
428}; 429};
429 430
430static void f_parser (lua_State *L, void *ud) { 431static void f_parser (lua_State *L, void *ud) {
431 struct SParser *p = cast(struct SParser *, ud); 432 struct SParser *p;
432 Proto *tf = p->bin ? luaU_undump(L, p->z, &p->buff) : 433 Proto *tf;
433 luaY_parser(L, p->z, &p->buff); 434 Closure *cl;
434 Closure *cl = luaF_newLclosure(L, 0, gt(L)); 435 luaC_checkGC(L);
436 p = cast(struct SParser *, ud);
437 tf = p->bin ? luaU_undump(L, p->z, &p->buff) : luaY_parser(L, p->z, &p->buff);
438 cl = luaF_newLclosure(L, 0, gt(L));
435 cl->l.p = tf; 439 cl->l.p = tf;
436 setclvalue(L->top, cl); 440 setclvalue(L->top, cl);
437 incr_top(L); 441 incr_top(L);
diff --git a/lgc.h b/lgc.h
index 78adf69a..8e3a3257 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 1.17 2002/11/25 12:38:47 roberto Exp roberto $ 2** $Id: lgc.h,v 1.18 2003/02/10 17:32:50 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -11,8 +11,8 @@
11#include "lobject.h" 11#include "lobject.h"
12 12
13 13
14#define luaC_checkGC(L) if (G(L)->nblocks >= G(L)->GCthreshold) \ 14#define luaC_checkGC(L) { lua_assert(!(L->ci->state & CI_CALLING)); \
15 luaC_collectgarbage(L) 15 if (G(L)->nblocks >= G(L)->GCthreshold) luaC_collectgarbage(L); }
16 16
17 17
18void luaC_separateudata (lua_State *L); 18void luaC_separateudata (lua_State *L);
diff --git a/lstate.c b/lstate.c
index c35da871..150eb14d 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 1.119 2003/02/10 17:32:50 roberto Exp roberto $ 2** $Id: lstate.c,v 1.120 2003/02/13 16:07:57 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*/
@@ -206,9 +206,14 @@ static void callallgcTM (lua_State *L, void *ud) {
206LUA_API void lua_close (lua_State *L) { 206LUA_API void lua_close (lua_State *L) {
207 lua_lock(L); 207 lua_lock(L);
208 L = G(L)->mainthread; /* only the main thread can be closed */ 208 L = G(L)->mainthread; /* only the main thread can be closed */
209 luaF_close(L, L->stack); /* close all upvalues for this thread */
209 luaC_separateudata(L); /* separate udata that have GC metamethods */ 210 luaC_separateudata(L); /* separate udata that have GC metamethods */
210 /* repeat until no more errors */ 211 L->errfunc = 0; /* no error function during GC metamethods */
211 while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0) /* skip */; 212 do { /* repeat until no more errors */
213 L->ci = L->base_ci;
214 L->base = L->top = L->ci->base;
215 L->nCcalls = 0;
216 } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
212 lua_assert(G(L)->tmudata == NULL); 217 lua_assert(G(L)->tmudata == NULL);
213 close_state(L); 218 close_state(L);
214} 219}
diff --git a/lvm.c b/lvm.c
index f999fae4..1a3054f8 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 1.277 2003/02/27 11:52:30 roberto Exp roberto $ 2** $Id: lvm.c,v 1.278 2003/02/27 12:33:07 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -393,15 +393,21 @@ static void Arith (lua_State *L, StkId ra,
393#define dojump(pc, i) ((pc) += (i)) 393#define dojump(pc, i) ((pc) += (i))
394 394
395 395
396unsigned int count = 0;
397
396StkId luaV_execute (lua_State *L) { 398StkId luaV_execute (lua_State *L) {
397 LClosure *cl; 399 LClosure *cl;
398 TObject *k; 400 TObject *k;
399 const Instruction *pc; 401 const Instruction *pc;
402unsigned int ii, ic, ir, io;
403ii = count;
400 callentry: /* entry point when calling new functions */ 404 callentry: /* entry point when calling new functions */
405ic = count;
401 L->ci->u.l.pc = &pc; 406 L->ci->u.l.pc = &pc;
402 if (L->hookmask & LUA_MASKCALL) 407 if (L->hookmask & LUA_MASKCALL)
403 luaD_callhook(L, LUA_HOOKCALL, -1); 408 luaD_callhook(L, LUA_HOOKCALL, -1);
404 retentry: /* entry point when returning to old functions */ 409 retentry: /* entry point when returning to old functions */
410ir = count;
405 lua_assert(L->ci->state == CI_SAVEDPC || 411 lua_assert(L->ci->state == CI_SAVEDPC ||
406 L->ci->state == (CI_SAVEDPC | CI_CALLING)); 412 L->ci->state == (CI_SAVEDPC | CI_CALLING));
407 L->ci->state = CI_HASFRAME; /* activate frame */ 413 L->ci->state = CI_HASFRAME; /* activate frame */
@@ -412,6 +418,7 @@ StkId luaV_execute (lua_State *L) {
412 for (;;) { 418 for (;;) {
413 const Instruction i = *pc++; 419 const Instruction i = *pc++;
414 StkId base, ra; 420 StkId base, ra;
421count++;
415 if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && 422 if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
416 (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { 423 (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
417 traceexec(L); 424 traceexec(L);
@@ -658,20 +665,24 @@ StkId luaV_execute (lua_State *L) {
658 break; 665 break;
659 } 666 }
660 case OP_RETURN: { 667 case OP_RETURN: {
661 CallInfo *ci = L->ci - 1; 668 CallInfo *ci = L->ci - 1; /* previous function frame */
662 int b = GETARG_B(i); 669 int b = GETARG_B(i);
670io = count;
663 if (b != 0) L->top = ra+b-1; 671 if (b != 0) L->top = ra+b-1;
664 lua_assert(L->ci->state & CI_HASFRAME); 672 lua_assert(L->ci->state & CI_HASFRAME);
665 if (L->openupval) luaF_close(L, base); 673 if (L->openupval) luaF_close(L, base);
666 L->ci->state = CI_SAVEDPC; /* deactivate current function */ 674 L->ci->state = CI_SAVEDPC; /* deactivate current function */
667 L->ci->u.l.savedpc = pc; 675 L->ci->u.l.savedpc = pc;
668 /* previous function was running `here'? */ 676 /* previous function was running `here'? */
669 if (!(ci->state & CI_CALLING)) 677 if (!(ci->state & CI_CALLING)) {
678 lua_assert((ci->state & CI_C) || ci->u.l.pc != &pc);
670 return ra; /* no: return */ 679 return ra; /* no: return */
671 else { /* yes: continue its execution (go through) */ 680 }
681 else { /* yes: continue its execution */
672 int nresults; 682 int nresults;
673 lua_assert(ttisfunction(ci->base - 1)); 683 lua_assert(ci->u.l.pc == &pc &&
674 lua_assert(ci->state & CI_SAVEDPC); 684 ttisfunction(ci->base - 1) &&
685 (ci->state & CI_SAVEDPC));
675 lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL); 686 lua_assert(GET_OPCODE(*(ci->u.l.savedpc - 1)) == OP_CALL);
676 nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1; 687 nresults = GETARG_C(*(ci->u.l.savedpc - 1)) - 1;
677 luaD_poscall(L, nresults, ra); 688 luaD_poscall(L, nresults, ra);