Small bug with stack reallocation

OP_RETURN must update trap before updating stack. (Bug detected with
-DHARDSTACKTESTS). Also, in 'luaF_close', do not create a variable
with 'uplevel(uv)', as the stack may change and invalidate this
value. (This is not a bug, but could become one if 'upl' was used
again.)
This commit is contained in:
Roberto Ierusalimschy 2019-07-18 11:26:03 -03:00
parent 4eefef07ab
commit 024a6071ca
2 changed files with 9 additions and 7 deletions

View File

@ -202,13 +202,12 @@ void luaF_unlinkupval (UpVal *uv) {
int luaF_close (lua_State *L, StkId level, int status) { int luaF_close (lua_State *L, StkId level, int status) {
UpVal *uv; UpVal *uv;
while ((uv = L->openupval) != NULL && uplevel(uv) >= level) { while ((uv = L->openupval) != NULL && uplevel(uv) >= level) {
StkId upl = uplevel(uv);
TValue *slot = &uv->u.value; /* new position for value */ TValue *slot = &uv->u.value; /* new position for value */
lua_assert(upl < L->top); lua_assert(uplevel(uv) < L->top);
if (uv->tt == LUA_TUPVALTBC && status != NOCLOSINGMETH) { if (uv->tt == LUA_TUPVALTBC && status != NOCLOSINGMETH) {
/* must run closing method */ /* must run closing method, which may change the stack */
ptrdiff_t levelrel = savestack(L, level); ptrdiff_t levelrel = savestack(L, level);
status = callclosemth(L, upl, status); /* may change the stack */ status = callclosemth(L, uplevel(uv), status);
level = restorestack(L, levelrel); level = restorestack(L, levelrel);
} }
luaF_unlinkupval(uv); luaF_unlinkupval(uv);

9
lvm.c
View File

@ -1574,8 +1574,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
savepc(ci); /* some calls here can raise errors */ savepc(ci); /* some calls here can raise errors */
if (TESTARG_k(i)) { if (TESTARG_k(i)) {
/* close upvalues from current call; the compiler ensures /* close upvalues from current call; the compiler ensures
that there are no to-be-closed variables here */ that there are no to-be-closed variables here, so this
call cannot change the stack */
luaF_close(L, base, NOCLOSINGMETH); luaF_close(L, base, NOCLOSINGMETH);
lua_assert(base == ci->func + 1);
} }
if (!ttisfunction(s2v(ra))) { /* not a function? */ if (!ttisfunction(s2v(ra))) { /* not a function? */
luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
@ -1602,10 +1604,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
if (n < 0) /* not fixed? */ if (n < 0) /* not fixed? */
n = cast_int(L->top - ra); /* get what is available */ n = cast_int(L->top - ra); /* get what is available */
savepc(ci); savepc(ci);
if (TESTARG_k(i)) { if (TESTARG_k(i)) { /* may there be open upvalues? */
if (L->top < ci->top) if (L->top < ci->top)
L->top = ci->top; L->top = ci->top;
luaF_close(L, base, LUA_OK); /* there may be open upvalues */ luaF_close(L, base, LUA_OK);
updatetrap(ci);
updatestack(ci); updatestack(ci);
} }
if (nparams1) /* vararg function? */ if (nparams1) /* vararg function? */