Browse Source

bug: interpreter cannot pop activation frame before calling return

hook (as it may want to access local variables active by the end
of the function)
pull/9/head
Roberto Ierusalimschy 10 years ago
parent
commit
d39bb51faa
  1. 18
      ldo.c
  2. 4
      ldo.h
  3. 5
      lvm.c

18
ldo.c

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.c,v 2.136 2015/03/06 19:49:50 roberto Exp roberto $ ** $Id: ldo.c,v 2.137 2015/03/30 16:05:23 roberto Exp roberto $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -337,7 +337,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
n = (*f)(L); /* do the actual call */ n = (*f)(L); /* do the actual call */
lua_lock(L); lua_lock(L);
api_checknelems(L, n); api_checknelems(L, n);
luaD_poscall(L, L->top - n); luaD_poscall(L, L->top - n, n);
return 1; return 1;
} }
case LUA_TLCL: { /* Lua function: prepare its call */ case LUA_TLCL: { /* Lua function: prepare its call */
@ -379,7 +379,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
} }
int luaD_poscall (lua_State *L, StkId firstResult) { int luaD_poscall (lua_State *L, StkId firstResult, int nres) {
StkId res; StkId res;
int wanted, i; int wanted, i;
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
@ -395,7 +395,7 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
wanted = ci->nresults; wanted = ci->nresults;
L->ci = ci->previous; /* back to caller */ L->ci = ci->previous; /* back to caller */
/* move results to correct place */ /* move results to correct place */
for (i = wanted; i != 0 && firstResult < L->top; i--) for (i = wanted; i != 0 && nres-- > 0; i--)
setobjs2s(L, res++, firstResult++); setobjs2s(L, res++, firstResult++);
while (i-- > 0) while (i-- > 0)
setnilvalue(res++); setnilvalue(res++);
@ -449,7 +449,7 @@ static void finishCcall (lua_State *L, int status) {
lua_lock(L); lua_lock(L);
api_checknelems(L, n); api_checknelems(L, n);
/* finish 'luaD_precall' */ /* finish 'luaD_precall' */
luaD_poscall(L, L->top - n); luaD_poscall(L, L->top - n, n);
} }
@ -533,7 +533,8 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
*/ */
static void resume (lua_State *L, void *ud) { static void resume (lua_State *L, void *ud) {
int nCcalls = L->nCcalls; int nCcalls = L->nCcalls;
StkId firstArg = cast(StkId, ud); int n = *(cast(int*, ud)); /* number of arguments */
StkId firstArg = L->top - n; /* first argument */
CallInfo *ci = L->ci; CallInfo *ci = L->ci;
if (nCcalls >= LUAI_MAXCCALLS) if (nCcalls >= LUAI_MAXCCALLS)
resume_error(L, "C stack overflow", firstArg); resume_error(L, "C stack overflow", firstArg);
@ -553,14 +554,13 @@ static void resume (lua_State *L, void *ud) {
luaV_execute(L); /* just continue running Lua code */ luaV_execute(L); /* just continue running Lua code */
else { /* 'common' yield */ else { /* 'common' yield */
if (ci->u.c.k != NULL) { /* does it have a continuation function? */ if (ci->u.c.k != NULL) { /* does it have a continuation function? */
int n;
lua_unlock(L); lua_unlock(L);
n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
lua_lock(L); lua_lock(L);
api_checknelems(L, n); api_checknelems(L, n);
firstArg = L->top - n; /* yield results come from continuation */ firstArg = L->top - n; /* yield results come from continuation */
} }
luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ luaD_poscall(L, firstArg, n); /* finish 'luaD_precall' */
} }
unroll(L, NULL); /* run continuation */ unroll(L, NULL); /* run continuation */
} }
@ -576,7 +576,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
L->nCcalls = (from) ? from->nCcalls + 1 : 1; L->nCcalls = (from) ? from->nCcalls + 1 : 1;
L->nny = 0; /* allow yields */ L->nny = 0; /* allow yields */
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
status = luaD_rawrunprotected(L, resume, L->top - nargs); status = luaD_rawrunprotected(L, resume, &nargs);
if (status == -1) /* error calling 'lua_resume'? */ if (status == -1) /* error calling 'lua_resume'? */
status = LUA_ERRRUN; status = LUA_ERRRUN;
else { /* continue running after recoverable errors */ else { /* continue running after recoverable errors */

4
ldo.h

@ -1,5 +1,5 @@
/* /*
** $Id: ldo.h,v 2.20 2011/11/29 15:55:08 roberto Exp roberto $ ** $Id: ldo.h,v 2.21 2014/10/25 11:50:46 roberto Exp roberto $
** Stack and Call structure of Lua ** Stack and Call structure of Lua
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -34,7 +34,7 @@ LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults,
int allowyield); int allowyield);
LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
ptrdiff_t oldtop, ptrdiff_t ef); ptrdiff_t oldtop, ptrdiff_t ef);
LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult, int nres);
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
LUAI_FUNC void luaD_growstack (lua_State *L, int n); LUAI_FUNC void luaD_growstack (lua_State *L, int n);
LUAI_FUNC void luaD_shrinkstack (lua_State *L); LUAI_FUNC void luaD_shrinkstack (lua_State *L);

5
lvm.c

@ -1,5 +1,5 @@
/* /*
** $Id: lvm.c,v 2.241 2015/05/20 16:22:55 roberto Exp roberto $ ** $Id: lvm.c,v 2.242 2015/05/20 18:19:11 roberto Exp roberto $
** Lua virtual machine ** Lua virtual machine
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -1106,9 +1106,8 @@ void luaV_execute (lua_State *L) {
} }
vmcase(OP_RETURN) { vmcase(OP_RETURN) {
int b = GETARG_B(i); int b = GETARG_B(i);
if (b != 0) L->top = ra+b-1;
if (cl->p->sizep > 0) luaF_close(L, base); if (cl->p->sizep > 0) luaF_close(L, base);
b = luaD_poscall(L, ra); b = luaD_poscall(L, ra, (b != 0 ? b - 1 : L->top - ra));
if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */
return; /* external invocation: return */ return; /* external invocation: return */
else { /* invocation via reentry: continue execution */ else { /* invocation via reentry: continue execution */

Loading…
Cancel
Save