From 681297187ec45268e872b26753c441586c12bdd8 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 16 Apr 2021 15:41:44 -0300 Subject: Bug: yielding in '__close' mess up number of returns Yielding in a __close metamethod called when returning vararg results changes the top and so messes up the number of returned values. --- lvm.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'lvm.c') diff --git a/lvm.c b/lvm.c index 16e01d68..e4b1903e 100644 --- a/lvm.c +++ b/lvm.c @@ -847,10 +847,19 @@ void luaV_finishOp (lua_State *L) { luaV_concat(L, total); /* concat them (may yield again) */ break; } - case OP_CLOSE: case OP_RETURN: { /* yielded closing variables */ + case OP_CLOSE: { /* yielded closing variables */ ci->u.l.savedpc--; /* repeat instruction to close other vars. */ break; } + case OP_RETURN: { /* yielded closing variables */ + StkId ra = base + GETARG_A(inst); + /* adjust top to signal correct number of returns, in case the + return is "up to top" ('isIT') */ + L->top = ra + ci->u2.nres; + /* repeat instruction to close other vars. and complete the return */ + ci->u.l.savedpc--; + break; + } default: { /* only these other opcodes can yield */ lua_assert(op == OP_TFORCALL || op == OP_CALL || @@ -1672,6 +1681,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { n = cast_int(L->top - ra); /* get what is available */ savepc(ci); if (TESTARG_k(i)) { /* may there be open upvalues? */ + ci->u2.nres = n; /* save number of returns */ if (L->top < ci->top) L->top = ci->top; luaF_close(L, base, CLOSEKTOP, 1); -- cgit v1.2.3-55-g6feb