diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-05-22 14:48:19 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-05-22 14:48:19 -0300 |
| commit | d39bb51faaa0467ad6a0f5b4ee2ee8400d620727 (patch) | |
| tree | 64d49afe6eb909412693c5e1c7498571aaa947ff | |
| parent | 6142e663e4d3180d2afaea50bd0978a040f518a4 (diff) | |
| download | lua-d39bb51faaa0467ad6a0f5b4ee2ee8400d620727.tar.gz lua-d39bb51faaa0467ad6a0f5b4ee2ee8400d620727.tar.bz2 lua-d39bb51faaa0467ad6a0f5b4ee2ee8400d620727.zip | |
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)
| -rw-r--r-- | ldo.c | 18 | ||||
| -rw-r--r-- | ldo.h | 4 | ||||
| -rw-r--r-- | lvm.c | 5 |
3 files changed, 13 insertions, 14 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 2.136 2015/03/06 19:49:50 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.137 2015/03/30 16:05:23 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 | */ |
| @@ -337,7 +337,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 337 | n = (*f)(L); /* do the actual call */ | 337 | n = (*f)(L); /* do the actual call */ |
| 338 | lua_lock(L); | 338 | lua_lock(L); |
| 339 | api_checknelems(L, n); | 339 | api_checknelems(L, n); |
| 340 | luaD_poscall(L, L->top - n); | 340 | luaD_poscall(L, L->top - n, n); |
| 341 | return 1; | 341 | return 1; |
| 342 | } | 342 | } |
| 343 | case LUA_TLCL: { /* Lua function: prepare its call */ | 343 | case LUA_TLCL: { /* Lua function: prepare its call */ |
| @@ -379,7 +379,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | 381 | ||
| 382 | int luaD_poscall (lua_State *L, StkId firstResult) { | 382 | int luaD_poscall (lua_State *L, StkId firstResult, int nres) { |
| 383 | StkId res; | 383 | StkId res; |
| 384 | int wanted, i; | 384 | int wanted, i; |
| 385 | CallInfo *ci = L->ci; | 385 | CallInfo *ci = L->ci; |
| @@ -395,7 +395,7 @@ int luaD_poscall (lua_State *L, StkId firstResult) { | |||
| 395 | wanted = ci->nresults; | 395 | wanted = ci->nresults; |
| 396 | L->ci = ci->previous; /* back to caller */ | 396 | L->ci = ci->previous; /* back to caller */ |
| 397 | /* move results to correct place */ | 397 | /* move results to correct place */ |
| 398 | for (i = wanted; i != 0 && firstResult < L->top; i--) | 398 | for (i = wanted; i != 0 && nres-- > 0; i--) |
| 399 | setobjs2s(L, res++, firstResult++); | 399 | setobjs2s(L, res++, firstResult++); |
| 400 | while (i-- > 0) | 400 | while (i-- > 0) |
| 401 | setnilvalue(res++); | 401 | setnilvalue(res++); |
| @@ -449,7 +449,7 @@ static void finishCcall (lua_State *L, int status) { | |||
| 449 | lua_lock(L); | 449 | lua_lock(L); |
| 450 | api_checknelems(L, n); | 450 | api_checknelems(L, n); |
| 451 | /* finish 'luaD_precall' */ | 451 | /* finish 'luaD_precall' */ |
| 452 | luaD_poscall(L, L->top - n); | 452 | luaD_poscall(L, L->top - n, n); |
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | 455 | ||
| @@ -533,7 +533,8 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { | |||
| 533 | */ | 533 | */ |
| 534 | static void resume (lua_State *L, void *ud) { | 534 | static void resume (lua_State *L, void *ud) { |
| 535 | int nCcalls = L->nCcalls; | 535 | int nCcalls = L->nCcalls; |
| 536 | StkId firstArg = cast(StkId, ud); | 536 | int n = *(cast(int*, ud)); /* number of arguments */ |
| 537 | StkId firstArg = L->top - n; /* first argument */ | ||
| 537 | CallInfo *ci = L->ci; | 538 | CallInfo *ci = L->ci; |
| 538 | if (nCcalls >= LUAI_MAXCCALLS) | 539 | if (nCcalls >= LUAI_MAXCCALLS) |
| 539 | resume_error(L, "C stack overflow", firstArg); | 540 | resume_error(L, "C stack overflow", firstArg); |
| @@ -553,14 +554,13 @@ static void resume (lua_State *L, void *ud) { | |||
| 553 | luaV_execute(L); /* just continue running Lua code */ | 554 | luaV_execute(L); /* just continue running Lua code */ |
| 554 | else { /* 'common' yield */ | 555 | else { /* 'common' yield */ |
| 555 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ | 556 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ |
| 556 | int n; | ||
| 557 | lua_unlock(L); | 557 | lua_unlock(L); |
| 558 | n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ | 558 | n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ |
| 559 | lua_lock(L); | 559 | lua_lock(L); |
| 560 | api_checknelems(L, n); | 560 | api_checknelems(L, n); |
| 561 | firstArg = L->top - n; /* yield results come from continuation */ | 561 | firstArg = L->top - n; /* yield results come from continuation */ |
| 562 | } | 562 | } |
| 563 | luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ | 563 | luaD_poscall(L, firstArg, n); /* finish 'luaD_precall' */ |
| 564 | } | 564 | } |
| 565 | unroll(L, NULL); /* run continuation */ | 565 | unroll(L, NULL); /* run continuation */ |
| 566 | } | 566 | } |
| @@ -576,7 +576,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { | |||
| 576 | L->nCcalls = (from) ? from->nCcalls + 1 : 1; | 576 | L->nCcalls = (from) ? from->nCcalls + 1 : 1; |
| 577 | L->nny = 0; /* allow yields */ | 577 | L->nny = 0; /* allow yields */ |
| 578 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); | 578 | api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); |
| 579 | status = luaD_rawrunprotected(L, resume, L->top - nargs); | 579 | status = luaD_rawrunprotected(L, resume, &nargs); |
| 580 | if (status == -1) /* error calling 'lua_resume'? */ | 580 | if (status == -1) /* error calling 'lua_resume'? */ |
| 581 | status = LUA_ERRRUN; | 581 | status = LUA_ERRRUN; |
| 582 | else { /* continue running after recoverable errors */ | 582 | else { /* continue running after recoverable errors */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.h,v 2.20 2011/11/29 15:55:08 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 2.21 2014/10/25 11:50:46 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 | */ |
| @@ -34,7 +34,7 @@ LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, | |||
| 34 | int allowyield); | 34 | int allowyield); |
| 35 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, | 35 | LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, |
| 36 | ptrdiff_t oldtop, ptrdiff_t ef); | 36 | ptrdiff_t oldtop, ptrdiff_t ef); |
| 37 | LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); | 37 | LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult, int nres); |
| 38 | LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); | 38 | LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); |
| 39 | LUAI_FUNC void luaD_growstack (lua_State *L, int n); | 39 | LUAI_FUNC void luaD_growstack (lua_State *L, int n); |
| 40 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); | 40 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.241 2015/05/20 16:22:55 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.242 2015/05/20 18:19:11 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 | */ |
| @@ -1106,9 +1106,8 @@ void luaV_execute (lua_State *L) { | |||
| 1106 | } | 1106 | } |
| 1107 | vmcase(OP_RETURN) { | 1107 | vmcase(OP_RETURN) { |
| 1108 | int b = GETARG_B(i); | 1108 | int b = GETARG_B(i); |
| 1109 | if (b != 0) L->top = ra+b-1; | ||
| 1110 | if (cl->p->sizep > 0) luaF_close(L, base); | 1109 | if (cl->p->sizep > 0) luaF_close(L, base); |
| 1111 | b = luaD_poscall(L, ra); | 1110 | b = luaD_poscall(L, ra, (b != 0 ? b - 1 : L->top - ra)); |
| 1112 | if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ | 1111 | if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ |
| 1113 | return; /* external invocation: return */ | 1112 | return; /* external invocation: return */ |
| 1114 | else { /* invocation via reentry: continue execution */ | 1113 | else { /* invocation via reentry: continue execution */ |
