Avoid out-of-range PC for stack overflow error from snapshot restore.
Reported by Sergey Kaplun. #1359
This commit is contained in:
@@ -255,6 +255,11 @@ static LJ_AINLINE int bc_isret(BCOp op)
|
|||||||
return (op == BC_RETM || op == BC_RET || op == BC_RET0 || op == BC_RET1);
|
return (op == BC_RETM || op == BC_RET || op == BC_RET0 || op == BC_RET1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LJ_AINLINE int bc_isret_or_tail(BCOp op)
|
||||||
|
{
|
||||||
|
return (op == BC_CALLMT || op == BC_CALLT || bc_isret(op));
|
||||||
|
}
|
||||||
|
|
||||||
LJ_DATA const uint16_t lj_bc_mode[];
|
LJ_DATA const uint16_t lj_bc_mode[];
|
||||||
LJ_DATA const uint16_t lj_bc_ofs[];
|
LJ_DATA const uint16_t lj_bc_ofs[];
|
||||||
|
|
||||||
|
|||||||
@@ -1529,23 +1529,11 @@ static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check if bytecode op returns. */
|
|
||||||
static int bcopisret(BCOp op)
|
|
||||||
{
|
|
||||||
switch (op) {
|
|
||||||
case BC_CALLMT: case BC_CALLT:
|
|
||||||
case BC_RETM: case BC_RET: case BC_RET0: case BC_RET1:
|
|
||||||
return 1;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fixup return instruction for prototype. */
|
/* Fixup return instruction for prototype. */
|
||||||
static void fs_fixup_ret(FuncState *fs)
|
static void fs_fixup_ret(FuncState *fs)
|
||||||
{
|
{
|
||||||
BCPos lastpc = fs->pc;
|
BCPos lastpc = fs->pc;
|
||||||
if (lastpc <= fs->lasttarget || !bcopisret(bc_op(fs->bcbase[lastpc-1].ins))) {
|
if (lastpc <= fs->lasttarget || !bc_isret_or_tail(bc_op(fs->bcbase[lastpc-1].ins))) {
|
||||||
if ((fs->bl->flags & FSCOPE_UPVAL))
|
if ((fs->bl->flags & FSCOPE_UPVAL))
|
||||||
bcemit_AJ(fs, BC_UCLO, 0, 0);
|
bcemit_AJ(fs, BC_UCLO, 0, 0);
|
||||||
bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */
|
bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */
|
||||||
|
|||||||
@@ -872,8 +872,10 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
|
|||||||
const BCIns *pc = snap_pc(map[nent]);
|
const BCIns *pc = snap_pc(map[nent]);
|
||||||
lua_State *L = J->L;
|
lua_State *L = J->L;
|
||||||
|
|
||||||
/* Set interpreter PC to the next PC to get correct error messages. */
|
/* Set interpreter PC to the next PC to get correct error messages.
|
||||||
setcframe_pc(L->cframe, pc+1);
|
** But not for returns or tail calls, since pc+1 may be out-of-range.
|
||||||
|
*/
|
||||||
|
setcframe_pc(L->cframe, bc_isret_or_tail(bc_op(*pc)) ? pc : pc+1);
|
||||||
setcframe_pc(cframe_raw(cframe_prev(L->cframe)), pc);
|
setcframe_pc(cframe_raw(cframe_prev(L->cframe)), pc);
|
||||||
|
|
||||||
/* Make sure the stack is big enough for the slots from the snapshot. */
|
/* Make sure the stack is big enough for the slots from the snapshot. */
|
||||||
|
|||||||
Reference in New Issue
Block a user