aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-25 12:50:20 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-25 12:50:20 -0300
commit41c800b352149e037bdebd5f20d2f25ed2a0e2a5 (patch)
tree740a459fd69d687dfe200fc91762208079e0c25b /lvm.c
parent0a9aca56caa925c42aaa683b43560357ab736ea4 (diff)
downloadlua-41c800b352149e037bdebd5f20d2f25ed2a0e2a5.tar.gz
lua-41c800b352149e037bdebd5f20d2f25ed2a0e2a5.tar.bz2
lua-41c800b352149e037bdebd5f20d2f25ed2a0e2a5.zip
Closing methods should not interfere with returning values
A closing method cannot be called in its own stack slot, as there may be returning values in the stack after that slot, and the call would corrupt those values. Instead, the closing method must be copied to the top of the stack to be called. Moreover, even when a function returns no value, its return istruction still has to have its position (which will set the stack top) after the local variables, otherwise a closing method might corrupt another not-yet-called closing method.
Diffstat (limited to 'lvm.c')
-rw-r--r--lvm.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/lvm.c b/lvm.c
index 0d82756b..2a1ee175 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1452,7 +1452,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1452 vmbreak; 1452 vmbreak;
1453 } 1453 }
1454 vmcase(OP_CLOSE) { 1454 vmcase(OP_CLOSE) {
1455 luaF_close(L, ra, LUA_OK); 1455 L->top = ra + 1; /* everything is free after this slot */
1456 ProtectNT(luaF_close(L, ra, LUA_OK));
1456 vmbreak; 1457 vmbreak;
1457 } 1458 }
1458 vmcase(OP_TBC) { 1459 vmcase(OP_TBC) {
@@ -1619,13 +1620,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1619 n = cast_int(L->top - ra); /* get what is available */ 1620 n = cast_int(L->top - ra); /* get what is available */
1620 else 1621 else
1621 L->top = ra + n; /* set call for 'luaD_poscall' */ 1622 L->top = ra + n; /* set call for 'luaD_poscall' */
1623 savepc(ci);
1622 if (TESTARG_k(i)) { 1624 if (TESTARG_k(i)) {
1623 int nparams1 = GETARG_C(i); 1625 int nparams1 = GETARG_C(i);
1624 if (nparams1) /* vararg function? */ 1626 if (nparams1) /* vararg function? */
1625 ci->func -= ci->u.l.nextraargs + nparams1; 1627 ci->func -= ci->u.l.nextraargs + nparams1;
1626 luaF_close(L, base, LUA_OK); /* there may be open upvalues */ 1628 luaF_close(L, base, LUA_OK); /* there may be open upvalues */
1627 } 1629 }
1628 halfProtect(luaD_poscall(L, ci, n)); 1630 luaD_poscall(L, ci, n);
1629 return; 1631 return;
1630 } 1632 }
1631 vmcase(OP_RETURN0) { 1633 vmcase(OP_RETURN0) {