diff --git a/ldo.c b/ldo.c index b7a76ef6..2762fefa 100644 --- a/ldo.c +++ b/ldo.c @@ -383,8 +383,10 @@ static void moveresults (lua_State *L, StkId res, int nres, int wanted) { wanted = nres; /* we want all results */ break; default: /* multiple results (or to-be-closed variables) */ - if (hastocloseCfunc(wanted)) { - luaF_close(L, res, LUA_OK); + if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ + ptrdiff_t savedres = savestack(L, res); + luaF_close(L, res, LUA_OK); /* may change the stack */ + res = restorestack(L, savedres); wanted = codeNresults(wanted); /* correct value */ if (wanted == LUA_MULTRET) wanted = nres; @@ -590,7 +592,8 @@ static int recover (lua_State *L, int status) { if (ci == NULL) return 0; /* no recovery point */ /* "finish" luaD_pcall */ oldtop = restorestack(L, ci->u2.funcidx); - luaF_close(L, oldtop, status); + luaF_close(L, oldtop, status); /* may change the stack */ + oldtop = restorestack(L, ci->u2.funcidx); luaD_seterrorobj(L, status, oldtop); L->ci = ci; L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ diff --git a/ljumptab.h b/ljumptab.h index 0af997d0..9fa72a73 100644 --- a/ljumptab.h +++ b/ljumptab.h @@ -16,7 +16,7 @@ #define vmbreak vmfetch(); vmdispatch(GET_OPCODE(i)); -static void *disptab[] = { +static void *disptab[NUM_OPCODES] = { #if 0 ** you can update the following list with this command: diff --git a/ltests.c b/ltests.c index c5c1040a..63d423e0 100644 --- a/ltests.c +++ b/ltests.c @@ -142,7 +142,7 @@ void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) { freeblock(mc, block); return NULL; } - if (mc->countlimit != ~0UL && size > 0) { /* count limit in use? */ + if (mc->countlimit != ~0UL && size != oldsize) { /* count limit in use? */ if (mc->countlimit == 0) return NULL; /* fake a memory allocation error */ mc->countlimit--; diff --git a/lvm.c b/lvm.c index 27ef68cf..a6dcc9ff 100644 --- a/lvm.c +++ b/lvm.c @@ -946,6 +946,9 @@ void luaV_finishOp (lua_State *L) { #define updatebase(ci) (base = ci->func + 1) +#define updatestack(ci) { if (trap) { updatebase(ci); ra = RA(i); } } + + /* ** Execute a jump instruction. The 'updatetrap' allows signals to stop ** tight loops. (Without it, the local copy of 'trap' could never change.) @@ -1557,24 +1560,21 @@ void luaV_execute (lua_State *L, CallInfo *ci) { L->top = ra + b; else /* previous instruction set top */ b = cast_int(L->top - ra); - savepc(ci); if (TESTARG_k(i)) { int nparams1 = GETARG_C(i); if (nparams1) /* vararg function? */ delta = ci->u.l.nextraargs + nparams1; - luaF_close(L, base, LUA_OK); /* close upvalues from current call */ + /* close upvalues from current call */ + ProtectNT(luaF_close(L, base, LUA_OK)); + updatestack(ci); } if (!ttisfunction(s2v(ra))) { /* not a function? */ luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ b++; /* there is now one extra argument */ } if (!ttisLclosure(s2v(ra))) { /* C function? */ - luaD_call(L, ra, LUA_MULTRET); /* call it */ - updatetrap(ci); - if (trap) { /* stack may have been relocated */ - updatebase(ci); - ra = RA(i); - } + ProtectNT(luaD_call(L, ra, LUA_MULTRET)); /* call it */ + updatestack(ci); /* stack may have been relocated */ ci->func -= delta; luaD_poscall(L, ci, cast_int(L->top - ra)); return; @@ -1739,10 +1739,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { memcpy(ra + 4, ra, 3 * sizeof(*ra)); L->top = ra + 4 + 3; Protect(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ - if (trap) { /* stack may have changed? */ - updatebase(ci); /* keep 'base' correct */ - ra = RA(i); /* keep 'ra' correct for next instruction */ - } + updatestack(ci); /* stack may have changed */ i = *(pc++); /* go to next instruction */ ra += 2; /* adjust for next instruction */ lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));