aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-24 11:59:15 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-24 11:59:15 -0200
commit7e63d3da0240325db4011f5d2f2e8abfb5d60288 (patch)
treef6f486aaa9c1279ccdc26a1cc8bc814e005a277b
parent84e32ad2ebd6bd160c1320456743a5b1d8f233e9 (diff)
downloadlua-7e63d3da0240325db4011f5d2f2e8abfb5d60288.tar.gz
lua-7e63d3da0240325db4011f5d2f2e8abfb5d60288.tar.bz2
lua-7e63d3da0240325db4011f5d2f2e8abfb5d60288.zip
Some bugs with stack reallocation by 'luaF_close'
(Long time without testing with '-DHARDSTACKTESTS'...) With the introduction of to-be-closed variables, calls to 'luaF_close' can move the stack, but some call sites where keeping pointers to the stack without correcting them.
-rw-r--r--ldo.c9
-rw-r--r--ljumptab.h2
-rw-r--r--ltests.c2
-rw-r--r--lvm.c21
4 files changed, 17 insertions, 17 deletions
diff --git a/ldo.c b/ldo.c
index b7a76ef6..2762fefa 100644
--- a/ldo.c
+++ b/ldo.c
@@ -383,8 +383,10 @@ static void moveresults (lua_State *L, StkId res, int nres, int wanted) {
383 wanted = nres; /* we want all results */ 383 wanted = nres; /* we want all results */
384 break; 384 break;
385 default: /* multiple results (or to-be-closed variables) */ 385 default: /* multiple results (or to-be-closed variables) */
386 if (hastocloseCfunc(wanted)) { 386 if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */
387 luaF_close(L, res, LUA_OK); 387 ptrdiff_t savedres = savestack(L, res);
388 luaF_close(L, res, LUA_OK); /* may change the stack */
389 res = restorestack(L, savedres);
388 wanted = codeNresults(wanted); /* correct value */ 390 wanted = codeNresults(wanted); /* correct value */
389 if (wanted == LUA_MULTRET) 391 if (wanted == LUA_MULTRET)
390 wanted = nres; 392 wanted = nres;
@@ -590,7 +592,8 @@ static int recover (lua_State *L, int status) {
590 if (ci == NULL) return 0; /* no recovery point */ 592 if (ci == NULL) return 0; /* no recovery point */
591 /* "finish" luaD_pcall */ 593 /* "finish" luaD_pcall */
592 oldtop = restorestack(L, ci->u2.funcidx); 594 oldtop = restorestack(L, ci->u2.funcidx);
593 luaF_close(L, oldtop, status); 595 luaF_close(L, oldtop, status); /* may change the stack */
596 oldtop = restorestack(L, ci->u2.funcidx);
594 luaD_seterrorobj(L, status, oldtop); 597 luaD_seterrorobj(L, status, oldtop);
595 L->ci = ci; 598 L->ci = ci;
596 L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ 599 L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
diff --git a/ljumptab.h b/ljumptab.h
index 0af997d0..9fa72a73 100644
--- a/ljumptab.h
+++ b/ljumptab.h
@@ -16,7 +16,7 @@
16#define vmbreak vmfetch(); vmdispatch(GET_OPCODE(i)); 16#define vmbreak vmfetch(); vmdispatch(GET_OPCODE(i));
17 17
18 18
19static void *disptab[] = { 19static void *disptab[NUM_OPCODES] = {
20 20
21#if 0 21#if 0
22** you can update the following list with this command: 22** you can update the following list with this command:
diff --git a/ltests.c b/ltests.c
index c5c1040a..63d423e0 100644
--- a/ltests.c
+++ b/ltests.c
@@ -142,7 +142,7 @@ void *debug_realloc (void *ud, void *b, size_t oldsize, size_t size) {
142 freeblock(mc, block); 142 freeblock(mc, block);
143 return NULL; 143 return NULL;
144 } 144 }
145 if (mc->countlimit != ~0UL && size > 0) { /* count limit in use? */ 145 if (mc->countlimit != ~0UL && size != oldsize) { /* count limit in use? */
146 if (mc->countlimit == 0) 146 if (mc->countlimit == 0)
147 return NULL; /* fake a memory allocation error */ 147 return NULL; /* fake a memory allocation error */
148 mc->countlimit--; 148 mc->countlimit--;
diff --git a/lvm.c b/lvm.c
index 27ef68cf..a6dcc9ff 100644
--- a/lvm.c
+++ b/lvm.c
@@ -946,6 +946,9 @@ void luaV_finishOp (lua_State *L) {
946#define updatebase(ci) (base = ci->func + 1) 946#define updatebase(ci) (base = ci->func + 1)
947 947
948 948
949#define updatestack(ci) { if (trap) { updatebase(ci); ra = RA(i); } }
950
951
949/* 952/*
950** Execute a jump instruction. The 'updatetrap' allows signals to stop 953** Execute a jump instruction. The 'updatetrap' allows signals to stop
951** tight loops. (Without it, the local copy of 'trap' could never change.) 954** tight loops. (Without it, the local copy of 'trap' could never change.)
@@ -1557,24 +1560,21 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1557 L->top = ra + b; 1560 L->top = ra + b;
1558 else /* previous instruction set top */ 1561 else /* previous instruction set top */
1559 b = cast_int(L->top - ra); 1562 b = cast_int(L->top - ra);
1560 savepc(ci);
1561 if (TESTARG_k(i)) { 1563 if (TESTARG_k(i)) {
1562 int nparams1 = GETARG_C(i); 1564 int nparams1 = GETARG_C(i);
1563 if (nparams1) /* vararg function? */ 1565 if (nparams1) /* vararg function? */
1564 delta = ci->u.l.nextraargs + nparams1; 1566 delta = ci->u.l.nextraargs + nparams1;
1565 luaF_close(L, base, LUA_OK); /* close upvalues from current call */ 1567 /* close upvalues from current call */
1568 ProtectNT(luaF_close(L, base, LUA_OK));
1569 updatestack(ci);
1566 } 1570 }
1567 if (!ttisfunction(s2v(ra))) { /* not a function? */ 1571 if (!ttisfunction(s2v(ra))) { /* not a function? */
1568 luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ 1572 luaD_tryfuncTM(L, ra); /* try '__call' metamethod */
1569 b++; /* there is now one extra argument */ 1573 b++; /* there is now one extra argument */
1570 } 1574 }
1571 if (!ttisLclosure(s2v(ra))) { /* C function? */ 1575 if (!ttisLclosure(s2v(ra))) { /* C function? */
1572 luaD_call(L, ra, LUA_MULTRET); /* call it */ 1576 ProtectNT(luaD_call(L, ra, LUA_MULTRET)); /* call it */
1573 updatetrap(ci); 1577 updatestack(ci); /* stack may have been relocated */
1574 if (trap) { /* stack may have been relocated */
1575 updatebase(ci);
1576 ra = RA(i);
1577 }
1578 ci->func -= delta; 1578 ci->func -= delta;
1579 luaD_poscall(L, ci, cast_int(L->top - ra)); 1579 luaD_poscall(L, ci, cast_int(L->top - ra));
1580 return; 1580 return;
@@ -1739,10 +1739,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1739 memcpy(ra + 4, ra, 3 * sizeof(*ra)); 1739 memcpy(ra + 4, ra, 3 * sizeof(*ra));
1740 L->top = ra + 4 + 3; 1740 L->top = ra + 4 + 3;
1741 Protect(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ 1741 Protect(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */
1742 if (trap) { /* stack may have changed? */ 1742 updatestack(ci); /* stack may have changed */
1743 updatebase(ci); /* keep 'base' correct */
1744 ra = RA(i); /* keep 'ra' correct for next instruction */
1745 }
1746 i = *(pc++); /* go to next instruction */ 1743 i = *(pc++); /* go to next instruction */
1747 ra += 2; /* adjust for next instruction */ 1744 ra += 2; /* adjust for next instruction */
1748 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); 1745 lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));