Avoid computing invalid addresses

luaV_execute should compute 'ra' only when the instruction uses it.
Computing an illegal address is undefined behavior even if the address
is never dereferenced.
This commit is contained in:
Roberto Ierusalimschy 2022-02-18 13:22:25 -03:00
parent 1f3c6f4534
commit 8426d9b4d4
1 changed files with 89 additions and 32 deletions

121
lvm.c
View File

@ -898,6 +898,7 @@ void luaV_finishOp (lua_State *L) {
** operation, 'fop' is the float operation. ** operation, 'fop' is the float operation.
*/ */
#define op_arithI(L,iop,fop) { \ #define op_arithI(L,iop,fop) { \
StkId ra = RA(i); \
TValue *v1 = vRB(i); \ TValue *v1 = vRB(i); \
int imm = GETARG_sC(i); \ int imm = GETARG_sC(i); \
if (ttisinteger(v1)) { \ if (ttisinteger(v1)) { \
@ -926,6 +927,7 @@ void luaV_finishOp (lua_State *L) {
** Arithmetic operations over floats and others with register operands. ** Arithmetic operations over floats and others with register operands.
*/ */
#define op_arithf(L,fop) { \ #define op_arithf(L,fop) { \
StkId ra = RA(i); \
TValue *v1 = vRB(i); \ TValue *v1 = vRB(i); \
TValue *v2 = vRC(i); \ TValue *v2 = vRC(i); \
op_arithf_aux(L, v1, v2, fop); } op_arithf_aux(L, v1, v2, fop); }
@ -935,6 +937,7 @@ void luaV_finishOp (lua_State *L) {
** Arithmetic operations with K operands for floats. ** Arithmetic operations with K operands for floats.
*/ */
#define op_arithfK(L,fop) { \ #define op_arithfK(L,fop) { \
StkId ra = RA(i); \
TValue *v1 = vRB(i); \ TValue *v1 = vRB(i); \
TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \ TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \
op_arithf_aux(L, v1, v2, fop); } op_arithf_aux(L, v1, v2, fop); }
@ -944,6 +947,7 @@ void luaV_finishOp (lua_State *L) {
** Arithmetic operations over integers and floats. ** Arithmetic operations over integers and floats.
*/ */
#define op_arith_aux(L,v1,v2,iop,fop) { \ #define op_arith_aux(L,v1,v2,iop,fop) { \
StkId ra = RA(i); \
if (ttisinteger(v1) && ttisinteger(v2)) { \ if (ttisinteger(v1) && ttisinteger(v2)) { \
lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \ lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \
pc++; setivalue(s2v(ra), iop(L, i1, i2)); \ pc++; setivalue(s2v(ra), iop(L, i1, i2)); \
@ -973,6 +977,7 @@ void luaV_finishOp (lua_State *L) {
** Bitwise operations with constant operand. ** Bitwise operations with constant operand.
*/ */
#define op_bitwiseK(L,op) { \ #define op_bitwiseK(L,op) { \
StkId ra = RA(i); \
TValue *v1 = vRB(i); \ TValue *v1 = vRB(i); \
TValue *v2 = KC(i); \ TValue *v2 = KC(i); \
lua_Integer i1; \ lua_Integer i1; \
@ -986,6 +991,7 @@ void luaV_finishOp (lua_State *L) {
** Bitwise operations with register operands. ** Bitwise operations with register operands.
*/ */
#define op_bitwise(L,op) { \ #define op_bitwise(L,op) { \
StkId ra = RA(i); \
TValue *v1 = vRB(i); \ TValue *v1 = vRB(i); \
TValue *v2 = vRC(i); \ TValue *v2 = vRC(i); \
lua_Integer i1; lua_Integer i2; \ lua_Integer i1; lua_Integer i2; \
@ -1000,18 +1006,19 @@ void luaV_finishOp (lua_State *L) {
** integers. ** integers.
*/ */
#define op_order(L,opi,opn,other) { \ #define op_order(L,opi,opn,other) { \
int cond; \ StkId ra = RA(i); \
TValue *rb = vRB(i); \ int cond; \
if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \ TValue *rb = vRB(i); \
lua_Integer ia = ivalue(s2v(ra)); \ if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \
lua_Integer ib = ivalue(rb); \ lua_Integer ia = ivalue(s2v(ra)); \
cond = opi(ia, ib); \ lua_Integer ib = ivalue(rb); \
} \ cond = opi(ia, ib); \
else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ } \
cond = opn(s2v(ra), rb); \ else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \
else \ cond = opn(s2v(ra), rb); \
Protect(cond = other(L, s2v(ra), rb)); \ else \
docondjump(); } Protect(cond = other(L, s2v(ra), rb)); \
docondjump(); }
/* /*
@ -1019,20 +1026,21 @@ void luaV_finishOp (lua_State *L) {
** always small enough to have an exact representation as a float.) ** always small enough to have an exact representation as a float.)
*/ */
#define op_orderI(L,opi,opf,inv,tm) { \ #define op_orderI(L,opi,opf,inv,tm) { \
int cond; \ StkId ra = RA(i); \
int im = GETARG_sB(i); \ int cond; \
if (ttisinteger(s2v(ra))) \ int im = GETARG_sB(i); \
cond = opi(ivalue(s2v(ra)), im); \ if (ttisinteger(s2v(ra))) \
else if (ttisfloat(s2v(ra))) { \ cond = opi(ivalue(s2v(ra)), im); \
lua_Number fa = fltvalue(s2v(ra)); \ else if (ttisfloat(s2v(ra))) { \
lua_Number fim = cast_num(im); \ lua_Number fa = fltvalue(s2v(ra)); \
cond = opf(fa, fim); \ lua_Number fim = cast_num(im); \
} \ cond = opf(fa, fim); \
else { \ } \
int isf = GETARG_C(i); \ else { \
Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ int isf = GETARG_C(i); \
} \ Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \
docondjump(); } } \
docondjump(); }
/* }================================================================== */ /* }================================================================== */
@ -1128,7 +1136,6 @@ void luaV_finishOp (lua_State *L) {
updatebase(ci); /* correct stack */ \ updatebase(ci); /* correct stack */ \
} \ } \
i = *(pc++); \ i = *(pc++); \
ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
} }
#define vmdispatch(o) switch(o) #define vmdispatch(o) switch(o)
@ -1164,7 +1171,6 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
/* main loop of interpreter */ /* main loop of interpreter */
for (;;) { for (;;) {
Instruction i; /* instruction being executed */ Instruction i; /* instruction being executed */
StkId ra; /* instruction's A register */
vmfetch(); vmfetch();
#if 0 #if 0
/* low-level line tracing for debugging Lua */ /* low-level line tracing for debugging Lua */
@ -1176,44 +1182,53 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
lua_assert(isIT(i) || (cast_void(L->top = base), 1)); lua_assert(isIT(i) || (cast_void(L->top = base), 1));
vmdispatch (GET_OPCODE(i)) { vmdispatch (GET_OPCODE(i)) {
vmcase(OP_MOVE) { vmcase(OP_MOVE) {
StkId ra = RA(i);
setobjs2s(L, ra, RB(i)); setobjs2s(L, ra, RB(i));
vmbreak; vmbreak;
} }
vmcase(OP_LOADI) { vmcase(OP_LOADI) {
StkId ra = RA(i);
lua_Integer b = GETARG_sBx(i); lua_Integer b = GETARG_sBx(i);
setivalue(s2v(ra), b); setivalue(s2v(ra), b);
vmbreak; vmbreak;
} }
vmcase(OP_LOADF) { vmcase(OP_LOADF) {
StkId ra = RA(i);
int b = GETARG_sBx(i); int b = GETARG_sBx(i);
setfltvalue(s2v(ra), cast_num(b)); setfltvalue(s2v(ra), cast_num(b));
vmbreak; vmbreak;
} }
vmcase(OP_LOADK) { vmcase(OP_LOADK) {
StkId ra = RA(i);
TValue *rb = k + GETARG_Bx(i); TValue *rb = k + GETARG_Bx(i);
setobj2s(L, ra, rb); setobj2s(L, ra, rb);
vmbreak; vmbreak;
} }
vmcase(OP_LOADKX) { vmcase(OP_LOADKX) {
StkId ra = RA(i);
TValue *rb; TValue *rb;
rb = k + GETARG_Ax(*pc); pc++; rb = k + GETARG_Ax(*pc); pc++;
setobj2s(L, ra, rb); setobj2s(L, ra, rb);
vmbreak; vmbreak;
} }
vmcase(OP_LOADFALSE) { vmcase(OP_LOADFALSE) {
StkId ra = RA(i);
setbfvalue(s2v(ra)); setbfvalue(s2v(ra));
vmbreak; vmbreak;
} }
vmcase(OP_LFALSESKIP) { vmcase(OP_LFALSESKIP) {
StkId ra = RA(i);
setbfvalue(s2v(ra)); setbfvalue(s2v(ra));
pc++; /* skip next instruction */ pc++; /* skip next instruction */
vmbreak; vmbreak;
} }
vmcase(OP_LOADTRUE) { vmcase(OP_LOADTRUE) {
StkId ra = RA(i);
setbtvalue(s2v(ra)); setbtvalue(s2v(ra));
vmbreak; vmbreak;
} }
vmcase(OP_LOADNIL) { vmcase(OP_LOADNIL) {
StkId ra = RA(i);
int b = GETARG_B(i); int b = GETARG_B(i);
do { do {
setnilvalue(s2v(ra++)); setnilvalue(s2v(ra++));
@ -1221,17 +1236,20 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_GETUPVAL) { vmcase(OP_GETUPVAL) {
StkId ra = RA(i);
int b = GETARG_B(i); int b = GETARG_B(i);
setobj2s(L, ra, cl->upvals[b]->v); setobj2s(L, ra, cl->upvals[b]->v);
vmbreak; vmbreak;
} }
vmcase(OP_SETUPVAL) { vmcase(OP_SETUPVAL) {
StkId ra = RA(i);
UpVal *uv = cl->upvals[GETARG_B(i)]; UpVal *uv = cl->upvals[GETARG_B(i)];
setobj(L, uv->v, s2v(ra)); setobj(L, uv->v, s2v(ra));
luaC_barrier(L, uv, s2v(ra)); luaC_barrier(L, uv, s2v(ra));
vmbreak; vmbreak;
} }
vmcase(OP_GETTABUP) { vmcase(OP_GETTABUP) {
StkId ra = RA(i);
const TValue *slot; const TValue *slot;
TValue *upval = cl->upvals[GETARG_B(i)]->v; TValue *upval = cl->upvals[GETARG_B(i)]->v;
TValue *rc = KC(i); TValue *rc = KC(i);
@ -1244,6 +1262,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_GETTABLE) { vmcase(OP_GETTABLE) {
StkId ra = RA(i);
const TValue *slot; const TValue *slot;
TValue *rb = vRB(i); TValue *rb = vRB(i);
TValue *rc = vRC(i); TValue *rc = vRC(i);
@ -1258,6 +1277,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_GETI) { vmcase(OP_GETI) {
StkId ra = RA(i);
const TValue *slot; const TValue *slot;
TValue *rb = vRB(i); TValue *rb = vRB(i);
int c = GETARG_C(i); int c = GETARG_C(i);
@ -1272,6 +1292,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_GETFIELD) { vmcase(OP_GETFIELD) {
StkId ra = RA(i);
const TValue *slot; const TValue *slot;
TValue *rb = vRB(i); TValue *rb = vRB(i);
TValue *rc = KC(i); TValue *rc = KC(i);
@ -1297,6 +1318,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_SETTABLE) { vmcase(OP_SETTABLE) {
StkId ra = RA(i);
const TValue *slot; const TValue *slot;
TValue *rb = vRB(i); /* key (table is in 'ra') */ TValue *rb = vRB(i); /* key (table is in 'ra') */
TValue *rc = RKC(i); /* value */ TValue *rc = RKC(i); /* value */
@ -1311,6 +1333,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_SETI) { vmcase(OP_SETI) {
StkId ra = RA(i);
const TValue *slot; const TValue *slot;
int c = GETARG_B(i); int c = GETARG_B(i);
TValue *rc = RKC(i); TValue *rc = RKC(i);
@ -1325,6 +1348,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_SETFIELD) { vmcase(OP_SETFIELD) {
StkId ra = RA(i);
const TValue *slot; const TValue *slot;
TValue *rb = KB(i); TValue *rb = KB(i);
TValue *rc = RKC(i); TValue *rc = RKC(i);
@ -1337,6 +1361,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_NEWTABLE) { vmcase(OP_NEWTABLE) {
StkId ra = RA(i);
int b = GETARG_B(i); /* log2(hash size) + 1 */ int b = GETARG_B(i); /* log2(hash size) + 1 */
int c = GETARG_C(i); /* array size */ int c = GETARG_C(i); /* array size */
Table *t; Table *t;
@ -1355,6 +1380,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_SELF) { vmcase(OP_SELF) {
StkId ra = RA(i);
const TValue *slot; const TValue *slot;
TValue *rb = vRB(i); TValue *rb = vRB(i);
TValue *rc = RKC(i); TValue *rc = RKC(i);
@ -1412,6 +1438,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_SHRI) { vmcase(OP_SHRI) {
StkId ra = RA(i);
TValue *rb = vRB(i); TValue *rb = vRB(i);
int ic = GETARG_sC(i); int ic = GETARG_sC(i);
lua_Integer ib; lua_Integer ib;
@ -1421,6 +1448,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_SHLI) { vmcase(OP_SHLI) {
StkId ra = RA(i);
TValue *rb = vRB(i); TValue *rb = vRB(i);
int ic = GETARG_sC(i); int ic = GETARG_sC(i);
lua_Integer ib; lua_Integer ib;
@ -1478,6 +1506,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_MMBIN) { vmcase(OP_MMBIN) {
StkId ra = RA(i);
Instruction pi = *(pc - 2); /* original arith. expression */ Instruction pi = *(pc - 2); /* original arith. expression */
TValue *rb = vRB(i); TValue *rb = vRB(i);
TMS tm = (TMS)GETARG_C(i); TMS tm = (TMS)GETARG_C(i);
@ -1487,6 +1516,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_MMBINI) { vmcase(OP_MMBINI) {
StkId ra = RA(i);
Instruction pi = *(pc - 2); /* original arith. expression */ Instruction pi = *(pc - 2); /* original arith. expression */
int imm = GETARG_sB(i); int imm = GETARG_sB(i);
TMS tm = (TMS)GETARG_C(i); TMS tm = (TMS)GETARG_C(i);
@ -1496,6 +1526,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_MMBINK) { vmcase(OP_MMBINK) {
StkId ra = RA(i);
Instruction pi = *(pc - 2); /* original arith. expression */ Instruction pi = *(pc - 2); /* original arith. expression */
TValue *imm = KB(i); TValue *imm = KB(i);
TMS tm = (TMS)GETARG_C(i); TMS tm = (TMS)GETARG_C(i);
@ -1505,6 +1536,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_UNM) { vmcase(OP_UNM) {
StkId ra = RA(i);
TValue *rb = vRB(i); TValue *rb = vRB(i);
lua_Number nb; lua_Number nb;
if (ttisinteger(rb)) { if (ttisinteger(rb)) {
@ -1519,6 +1551,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_BNOT) { vmcase(OP_BNOT) {
StkId ra = RA(i);
TValue *rb = vRB(i); TValue *rb = vRB(i);
lua_Integer ib; lua_Integer ib;
if (tointegerns(rb, &ib)) { if (tointegerns(rb, &ib)) {
@ -1529,6 +1562,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_NOT) { vmcase(OP_NOT) {
StkId ra = RA(i);
TValue *rb = vRB(i); TValue *rb = vRB(i);
if (l_isfalse(rb)) if (l_isfalse(rb))
setbtvalue(s2v(ra)); setbtvalue(s2v(ra));
@ -1537,10 +1571,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_LEN) { vmcase(OP_LEN) {
StkId ra = RA(i);
Protect(luaV_objlen(L, ra, vRB(i))); Protect(luaV_objlen(L, ra, vRB(i)));
vmbreak; vmbreak;
} }
vmcase(OP_CONCAT) { vmcase(OP_CONCAT) {
StkId ra = RA(i);
int n = GETARG_B(i); /* number of elements to concatenate */ int n = GETARG_B(i); /* number of elements to concatenate */
L->top = ra + n; /* mark the end of concat operands */ L->top = ra + n; /* mark the end of concat operands */
ProtectNT(luaV_concat(L, n)); ProtectNT(luaV_concat(L, n));
@ -1548,10 +1584,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_CLOSE) { vmcase(OP_CLOSE) {
StkId ra = RA(i);
Protect(luaF_close(L, ra, LUA_OK, 1)); Protect(luaF_close(L, ra, LUA_OK, 1));
vmbreak; vmbreak;
} }
vmcase(OP_TBC) { vmcase(OP_TBC) {
StkId ra = RA(i);
/* create new to-be-closed upvalue */ /* create new to-be-closed upvalue */
halfProtect(luaF_newtbcupval(L, ra)); halfProtect(luaF_newtbcupval(L, ra));
vmbreak; vmbreak;
@ -1561,6 +1599,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_EQ) { vmcase(OP_EQ) {
StkId ra = RA(i);
int cond; int cond;
TValue *rb = vRB(i); TValue *rb = vRB(i);
Protect(cond = luaV_equalobj(L, s2v(ra), rb)); Protect(cond = luaV_equalobj(L, s2v(ra), rb));
@ -1576,6 +1615,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_EQK) { vmcase(OP_EQK) {
StkId ra = RA(i);
TValue *rb = KB(i); TValue *rb = KB(i);
/* basic types do not use '__eq'; we can use raw equality */ /* basic types do not use '__eq'; we can use raw equality */
int cond = luaV_rawequalobj(s2v(ra), rb); int cond = luaV_rawequalobj(s2v(ra), rb);
@ -1583,6 +1623,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_EQI) { vmcase(OP_EQI) {
StkId ra = RA(i);
int cond; int cond;
int im = GETARG_sB(i); int im = GETARG_sB(i);
if (ttisinteger(s2v(ra))) if (ttisinteger(s2v(ra)))
@ -1611,11 +1652,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_TEST) { vmcase(OP_TEST) {
StkId ra = RA(i);
int cond = !l_isfalse(s2v(ra)); int cond = !l_isfalse(s2v(ra));
docondjump(); docondjump();
vmbreak; vmbreak;
} }
vmcase(OP_TESTSET) { vmcase(OP_TESTSET) {
StkId ra = RA(i);
TValue *rb = vRB(i); TValue *rb = vRB(i);
if (l_isfalse(rb) == GETARG_k(i)) if (l_isfalse(rb) == GETARG_k(i))
pc++; pc++;
@ -1626,6 +1669,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_CALL) { vmcase(OP_CALL) {
StkId ra = RA(i);
CallInfo *newci; CallInfo *newci;
int b = GETARG_B(i); int b = GETARG_B(i);
int nresults = GETARG_C(i) - 1; int nresults = GETARG_C(i) - 1;
@ -1642,6 +1686,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_TAILCALL) { vmcase(OP_TAILCALL) {
StkId ra = RA(i);
int b = GETARG_B(i); /* number of arguments + 1 (function) */ int b = GETARG_B(i); /* number of arguments + 1 (function) */
int n; /* number of results when calling a C function */ int n; /* number of results when calling a C function */
int nparams1 = GETARG_C(i); int nparams1 = GETARG_C(i);
@ -1667,6 +1712,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
} }
} }
vmcase(OP_RETURN) { vmcase(OP_RETURN) {
StkId ra = RA(i);
int n = GETARG_B(i) - 1; /* number of results */ int n = GETARG_B(i) - 1; /* number of results */
int nparams1 = GETARG_C(i); int nparams1 = GETARG_C(i);
if (n < 0) /* not fixed? */ if (n < 0) /* not fixed? */
@ -1689,6 +1735,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
} }
vmcase(OP_RETURN0) { vmcase(OP_RETURN0) {
if (l_unlikely(L->hookmask)) { if (l_unlikely(L->hookmask)) {
StkId ra = RA(i);
L->top = ra; L->top = ra;
savepc(ci); savepc(ci);
luaD_poscall(L, ci, 0); /* no hurry... */ luaD_poscall(L, ci, 0); /* no hurry... */
@ -1705,6 +1752,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
} }
vmcase(OP_RETURN1) { vmcase(OP_RETURN1) {
if (l_unlikely(L->hookmask)) { if (l_unlikely(L->hookmask)) {
StkId ra = RA(i);
L->top = ra + 1; L->top = ra + 1;
savepc(ci); savepc(ci);
luaD_poscall(L, ci, 1); /* no hurry... */ luaD_poscall(L, ci, 1); /* no hurry... */
@ -1716,6 +1764,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
if (nres == 0) if (nres == 0)
L->top = base - 1; /* asked for no results */ L->top = base - 1; /* asked for no results */
else { else {
StkId ra = RA(i);
setobjs2s(L, base - 1, ra); /* at least this result */ setobjs2s(L, base - 1, ra); /* at least this result */
L->top = base; L->top = base;
for (; l_unlikely(nres > 1); nres--) for (; l_unlikely(nres > 1); nres--)
@ -1731,6 +1780,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
} }
} }
vmcase(OP_FORLOOP) { vmcase(OP_FORLOOP) {
StkId ra = RA(i);
if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ if (ttisinteger(s2v(ra + 2))) { /* integer loop? */
lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1)));
if (count > 0) { /* still more iterations? */ if (count > 0) { /* still more iterations? */
@ -1749,12 +1799,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_FORPREP) { vmcase(OP_FORPREP) {
StkId ra = RA(i);
savestate(L, ci); /* in case of errors */ savestate(L, ci); /* in case of errors */
if (forprep(L, ra)) if (forprep(L, ra))
pc += GETARG_Bx(i) + 1; /* skip the loop */ pc += GETARG_Bx(i) + 1; /* skip the loop */
vmbreak; vmbreak;
} }
vmcase(OP_TFORPREP) { vmcase(OP_TFORPREP) {
StkId ra = RA(i);
/* create to-be-closed upvalue (if needed) */ /* create to-be-closed upvalue (if needed) */
halfProtect(luaF_newtbcupval(L, ra + 3)); halfProtect(luaF_newtbcupval(L, ra + 3));
pc += GETARG_Bx(i); pc += GETARG_Bx(i);
@ -1763,7 +1815,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
goto l_tforcall; goto l_tforcall;
} }
vmcase(OP_TFORCALL) { vmcase(OP_TFORCALL) {
l_tforcall: l_tforcall: {
StkId ra = RA(i);
/* 'ra' has the iterator function, 'ra + 1' has the state, /* 'ra' has the iterator function, 'ra + 1' has the state,
'ra + 2' has the control variable, and 'ra + 3' has the 'ra + 2' has the control variable, and 'ra + 3' has the
to-be-closed variable. The call will use the stack after to-be-closed variable. The call will use the stack after
@ -1777,16 +1830,18 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
i = *(pc++); /* go to next instruction */ i = *(pc++); /* go to next instruction */
lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i));
goto l_tforloop; goto l_tforloop;
} }}
vmcase(OP_TFORLOOP) { vmcase(OP_TFORLOOP) {
l_tforloop: l_tforloop: {
StkId ra = RA(i);
if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ if (!ttisnil(s2v(ra + 4))) { /* continue loop? */
setobjs2s(L, ra + 2, ra + 4); /* save control variable */ setobjs2s(L, ra + 2, ra + 4); /* save control variable */
pc -= GETARG_Bx(i); /* jump back */ pc -= GETARG_Bx(i); /* jump back */
} }
vmbreak; vmbreak;
} }}
vmcase(OP_SETLIST) { vmcase(OP_SETLIST) {
StkId ra = RA(i);
int n = GETARG_B(i); int n = GETARG_B(i);
unsigned int last = GETARG_C(i); unsigned int last = GETARG_C(i);
Table *h = hvalue(s2v(ra)); Table *h = hvalue(s2v(ra));
@ -1810,12 +1865,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmbreak; vmbreak;
} }
vmcase(OP_CLOSURE) { vmcase(OP_CLOSURE) {
StkId ra = RA(i);
Proto *p = cl->p->p[GETARG_Bx(i)]; Proto *p = cl->p->p[GETARG_Bx(i)];
halfProtect(pushclosure(L, p, cl->upvals, base, ra)); halfProtect(pushclosure(L, p, cl->upvals, base, ra));
checkGC(L, ra + 1); checkGC(L, ra + 1);
vmbreak; vmbreak;
} }
vmcase(OP_VARARG) { vmcase(OP_VARARG) {
StkId ra = RA(i);
int n = GETARG_C(i) - 1; /* required results */ int n = GETARG_C(i) - 1; /* required results */
Protect(luaT_getvarargs(L, ci, ra, n)); Protect(luaT_getvarargs(L, ci, ra, n));
vmbreak; vmbreak;