aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2025-05-28 21:02:31 +0200
committerMike Pall <mike>2025-05-28 21:02:31 +0200
commitcd4af8ad80bb6430ad2e547f7af236268c9be7d9 (patch)
tree60cb40dd5a5d3cbec90b3563c9c750923d3542d8 /src
parent9c8eb7cfe10ef5939d9b358a0bd805a610818ba5 (diff)
downloadluajit-cd4af8ad80bb6430ad2e547f7af236268c9be7d9.tar.gz
luajit-cd4af8ad80bb6430ad2e547f7af236268c9be7d9.tar.bz2
luajit-cd4af8ad80bb6430ad2e547f7af236268c9be7d9.zip
Avoid out-of-range PC for stack overflow error from snapshot restore.
Reported by Sergey Kaplun. #1359
Diffstat (limited to 'src')
-rw-r--r--src/lj_bc.h5
-rw-r--r--src/lj_parse.c14
-rw-r--r--src/lj_snap.c6
3 files changed, 10 insertions, 15 deletions
diff --git a/src/lj_bc.h b/src/lj_bc.h
index 3f0563e4..0c7249b3 100644
--- a/src/lj_bc.h
+++ b/src/lj_bc.h
@@ -255,6 +255,11 @@ static LJ_AINLINE int bc_isret(BCOp op)
255 return (op == BC_RETM || op == BC_RET || op == BC_RET0 || op == BC_RET1); 255 return (op == BC_RETM || op == BC_RET || op == BC_RET0 || op == BC_RET1);
256} 256}
257 257
258static LJ_AINLINE int bc_isret_or_tail(BCOp op)
259{
260 return (op == BC_CALLMT || op == BC_CALLT || bc_isret(op));
261}
262
258LJ_DATA const uint16_t lj_bc_mode[]; 263LJ_DATA const uint16_t lj_bc_mode[];
259LJ_DATA const uint16_t lj_bc_ofs[]; 264LJ_DATA const uint16_t lj_bc_ofs[];
260 265
diff --git a/src/lj_parse.c b/src/lj_parse.c
index ffd11b3b..3370296f 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -1529,23 +1529,11 @@ static void fs_fixup_var(LexState *ls, GCproto *pt, uint8_t *p, size_t ofsvar)
1529 1529
1530#endif 1530#endif
1531 1531
1532/* Check if bytecode op returns. */
1533static int bcopisret(BCOp op)
1534{
1535 switch (op) {
1536 case BC_CALLMT: case BC_CALLT:
1537 case BC_RETM: case BC_RET: case BC_RET0: case BC_RET1:
1538 return 1;
1539 default:
1540 return 0;
1541 }
1542}
1543
1544/* Fixup return instruction for prototype. */ 1532/* Fixup return instruction for prototype. */
1545static void fs_fixup_ret(FuncState *fs) 1533static void fs_fixup_ret(FuncState *fs)
1546{ 1534{
1547 BCPos lastpc = fs->pc; 1535 BCPos lastpc = fs->pc;
1548 if (lastpc <= fs->lasttarget || !bcopisret(bc_op(fs->bcbase[lastpc-1].ins))) { 1536 if (lastpc <= fs->lasttarget || !bc_isret_or_tail(bc_op(fs->bcbase[lastpc-1].ins))) {
1549 if ((fs->bl->flags & FSCOPE_UPVAL)) 1537 if ((fs->bl->flags & FSCOPE_UPVAL))
1550 bcemit_AJ(fs, BC_UCLO, 0, 0); 1538 bcemit_AJ(fs, BC_UCLO, 0, 0);
1551 bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */ 1539 bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */
diff --git a/src/lj_snap.c b/src/lj_snap.c
index 82ab6983..54260021 100644
--- a/src/lj_snap.c
+++ b/src/lj_snap.c
@@ -872,8 +872,10 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
872 const BCIns *pc = snap_pc(map[nent]); 872 const BCIns *pc = snap_pc(map[nent]);
873 lua_State *L = J->L; 873 lua_State *L = J->L;
874 874
875 /* Set interpreter PC to the next PC to get correct error messages. */ 875 /* Set interpreter PC to the next PC to get correct error messages.
876 setcframe_pc(L->cframe, pc+1); 876 ** But not for returns or tail calls, since pc+1 may be out-of-range.
877 */
878 setcframe_pc(L->cframe, bc_isret_or_tail(bc_op(*pc)) ? pc : pc+1);
877 setcframe_pc(cframe_raw(cframe_prev(L->cframe)), pc); 879 setcframe_pc(cframe_raw(cframe_prev(L->cframe)), pc);
878 880
879 /* Make sure the stack is big enough for the slots from the snapshot. */ 881 /* Make sure the stack is big enough for the slots from the snapshot. */