summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-18 11:26:03 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-18 11:26:03 -0300
commit024a6071cac749504e0b26a915bda4f52c41a892 (patch)
tree564572b784d477d1ba460012031caf277bf89a74
parent4eefef07ab1c136f901d816822c79336fa89336d (diff)
downloadlua-024a6071cac749504e0b26a915bda4f52c41a892.tar.gz
lua-024a6071cac749504e0b26a915bda4f52c41a892.tar.bz2
lua-024a6071cac749504e0b26a915bda4f52c41a892.zip
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.)
-rw-r--r--lfunc.c7
-rw-r--r--lvm.c9
2 files changed, 9 insertions, 7 deletions
diff --git a/lfunc.c b/lfunc.c
index cd85cc1f..c07e9b35 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -202,13 +202,12 @@ void luaF_unlinkupval (UpVal *uv) {
202int luaF_close (lua_State *L, StkId level, int status) { 202int luaF_close (lua_State *L, StkId level, int status) {
203 UpVal *uv; 203 UpVal *uv;
204 while ((uv = L->openupval) != NULL && uplevel(uv) >= level) { 204 while ((uv = L->openupval) != NULL && uplevel(uv) >= level) {
205 StkId upl = uplevel(uv);
206 TValue *slot = &uv->u.value; /* new position for value */ 205 TValue *slot = &uv->u.value; /* new position for value */
207 lua_assert(upl < L->top); 206 lua_assert(uplevel(uv) < L->top);
208 if (uv->tt == LUA_TUPVALTBC && status != NOCLOSINGMETH) { 207 if (uv->tt == LUA_TUPVALTBC && status != NOCLOSINGMETH) {
209 /* must run closing method */ 208 /* must run closing method, which may change the stack */
210 ptrdiff_t levelrel = savestack(L, level); 209 ptrdiff_t levelrel = savestack(L, level);
211 status = callclosemth(L, upl, status); /* may change the stack */ 210 status = callclosemth(L, uplevel(uv), status);
212 level = restorestack(L, levelrel); 211 level = restorestack(L, levelrel);
213 } 212 }
214 luaF_unlinkupval(uv); 213 luaF_unlinkupval(uv);
diff --git a/lvm.c b/lvm.c
index 7e6f148d..c1b6749d 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1574,8 +1574,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1574 savepc(ci); /* some calls here can raise errors */ 1574 savepc(ci); /* some calls here can raise errors */
1575 if (TESTARG_k(i)) { 1575 if (TESTARG_k(i)) {
1576 /* close upvalues from current call; the compiler ensures 1576 /* close upvalues from current call; the compiler ensures
1577 that there are no to-be-closed variables here */ 1577 that there are no to-be-closed variables here, so this
1578 call cannot change the stack */
1578 luaF_close(L, base, NOCLOSINGMETH); 1579 luaF_close(L, base, NOCLOSINGMETH);
1580 lua_assert(base == ci->func + 1);
1579 } 1581 }
1580 if (!ttisfunction(s2v(ra))) { /* not a function? */ 1582 if (!ttisfunction(s2v(ra))) { /* not a function? */
1581 luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ 1583 luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
@@ -1602,10 +1604,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1602 if (n < 0) /* not fixed? */ 1604 if (n < 0) /* not fixed? */
1603 n = cast_int(L->top - ra); /* get what is available */ 1605 n = cast_int(L->top - ra); /* get what is available */
1604 savepc(ci); 1606 savepc(ci);
1605 if (TESTARG_k(i)) { 1607 if (TESTARG_k(i)) { /* may there be open upvalues? */
1606 if (L->top < ci->top) 1608 if (L->top < ci->top)
1607 L->top = ci->top; 1609 L->top = ci->top;
1608 luaF_close(L, base, LUA_OK); /* there may be open upvalues */ 1610 luaF_close(L, base, LUA_OK);
1611 updatetrap(ci);
1609 updatestack(ci); 1612 updatestack(ci);
1610 } 1613 }
1611 if (nparams1) /* vararg function? */ 1614 if (nparams1) /* vararg function? */