lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 024a6071cac749504e0b26a915bda4f52c41a892
parent 4eefef07ab1c136f901d816822c79336fa89336d
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Thu, 18 Jul 2019 11:25:36 -0300

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.)

Diffstat:
Mlfunc.c | 7+++----
Mlvm.c | 9++++++---
2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/lfunc.c b/lfunc.c @@ -202,13 +202,12 @@ void luaF_unlinkupval (UpVal *uv) { int luaF_close (lua_State *L, StkId level, int status) { UpVal *uv; while ((uv = L->openupval) != NULL && uplevel(uv) >= level) { - StkId upl = uplevel(uv); 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) { - /* must run closing method */ + /* must run closing method, which may change the stack */ 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); } luaF_unlinkupval(uv); diff --git a/lvm.c b/lvm.c @@ -1574,8 +1574,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) { savepc(ci); /* some calls here can raise errors */ if (TESTARG_k(i)) { /* 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); + lua_assert(base == ci->func + 1); } if (!ttisfunction(s2v(ra))) { /* not a function? */ luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ @@ -1602,10 +1604,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) { if (n < 0) /* not fixed? */ n = cast_int(L->top - ra); /* get what is available */ savepc(ci); - if (TESTARG_k(i)) { + if (TESTARG_k(i)) { /* may there be open upvalues? */ if (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); } if (nparams1) /* vararg function? */