From 811c5322c8ab6bdbb6784cd43aa57041a1cc9360 Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Wed, 3 Jul 2024 21:42:21 +0200
Subject: [PATCH 01/10] Handle partial snapshot restore due to stack overflow.
Reported by pwnhacker0x18. Fixed by Peter Cawley. #1196
---
src/lj_debug.c | 9 ++++++---
src/lj_trace.c | 4 +++-
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/lj_debug.c b/src/lj_debug.c
index bca1d7a5..abb7572c 100644
--- a/src/lj_debug.c
+++ b/src/lj_debug.c
@@ -102,9 +102,12 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe)
pos = proto_bcpos(pt, ins) - 1;
#if LJ_HASJIT
if (pos > pt->sizebc) { /* Undo the effects of lj_trace_exit for JLOOP. */
- GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins));
- lua_assert(bc_isret(bc_op(ins[-1])));
- pos = proto_bcpos(pt, mref(T->startpc, const BCIns));
+ if (bc_isret(bc_op(ins[-1]))) {
+ GCtrace *T = (GCtrace *)((char *)(ins-1) - offsetof(GCtrace, startins));
+ pos = proto_bcpos(pt, mref(T->startpc, const BCIns));
+ } else {
+ pos = NO_BCPOS; /* Punt in case of stack overflow. */
+ }
}
#endif
return pos;
diff --git a/src/lj_trace.c b/src/lj_trace.c
index d015f2ab..8385f3d1 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -788,8 +788,10 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr)
exd.J = J;
exd.exptr = exptr;
errcode = lj_vm_cpcall(L, NULL, &exd, trace_exit_cp);
- if (errcode)
+ if (errcode) {
+ setcframe_pc(cframe_raw(L->cframe), L); /* Point to any valid memory. */
return -errcode; /* Return negated error code. */
+ }
lj_vmevent_send(L, TEXIT,
lj_state_checkstack(L, 4+RID_NUM_GPR+RID_NUM_FPR+LUA_MINSTACK);
From 0f8b878e2f3ea280648fc04309c5527cf261bfc8 Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Wed, 3 Jul 2024 23:43:29 +0200
Subject: [PATCH 02/10] Fix typo.
Reported by Sergey Bronnikov. #1223
---
src/jit/bcsave.lua | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/jit/bcsave.lua b/src/jit/bcsave.lua
index 55fae993..030e6a16 100644
--- a/src/jit/bcsave.lua
+++ b/src/jit/bcsave.lua
@@ -553,7 +553,7 @@ typedef struct {
o.sym_entry.strx = 1
ffi.copy(o.space+1, symname)
- -- Write Macho-O object file.
+ -- Write Mach-O object file.
local fp = savefile(output, "wb")
fp:write(ffi.string(o, mach_size))
bcsave_tail(fp, output, s)
From f2a1cd43281361035149b6eedbd267b5e71d64d0 Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Wed, 3 Jul 2024 23:43:57 +0200
Subject: [PATCH 03/10] FFI: Fix __tostring metamethod access to enum cdata
value.
Thanks to Sergey Kaplun. #1232
---
src/lib_ffi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index cf9cf9f5..1422dea6 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -304,7 +304,7 @@ LJLIB_CF(ffi_meta___tostring)
p = *(void **)p;
} else if (ctype_isenum(ct->info)) {
msg = "cdata<%s>: %d";
- p = (void *)(uintptr_t)*(uint32_t **)p;
+ p = (void *)(uintptr_t)*(uint32_t *)p;
} else {
if (ctype_isptr(ct->info)) {
p = cdata_getptr(p, ct->size);
From f602f0154b644211283cfeea92a570ca38f71947 Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Wed, 3 Jul 2024 23:45:16 +0200
Subject: [PATCH 04/10] Fix predict_next() in parser (for real now).
Reported by Sergey Kaplun. #1226 #1054
---
src/lj_parse.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/lj_parse.c b/src/lj_parse.c
index afdbcc3d..cb200663 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -2527,11 +2527,9 @@ static void parse_for_num(LexState *ls, GCstr *varname, BCLine line)
*/
static int predict_next(LexState *ls, FuncState *fs, BCPos pc)
{
- BCIns ins;
+ BCIns ins = fs->bcbase[pc].ins;
GCstr *name;
cTValue *o;
- if (pc >= fs->bclim) return 0;
- ins = fs->bcbase[pc].ins;
switch (bc_op(ins)) {
case BC_MOV:
if (bc_d(ins) >= fs->nactvar) return 0;
@@ -2579,7 +2577,7 @@ static void parse_for_iter(LexState *ls, GCstr *indexname)
line = ls->linenumber;
assign_adjust(ls, 3, expr_list(ls, &e), &e);
bcreg_bump(fs, 3); /* The iterator needs another 3 slots (func + 2 args). */
- isnext = (nvars <= 5 && predict_next(ls, fs, exprpc));
+ isnext = (nvars <= 5 && fs->pc > exprpc && predict_next(ls, fs, exprpc));
var_add(ls, 3); /* Hidden control variables. */
lex_check(ls, TK_do);
loop = bcemit_AJ(fs, isnext ? BC_ISNEXT : BC_JMP, base, NO_JMP);
From 7a608e4425ce0777f5c980dad9f4fdc1bcce0b8c Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Wed, 3 Jul 2024 23:46:47 +0200
Subject: [PATCH 05/10] FFI: Fix various issues in recff_cdata_arith.
Thanks to Sergey Kaplun. #1224
---
src/lj_crecord.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index 63a72aa4..1f6396f6 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -1367,7 +1367,8 @@ static TRef crec_arith_meta(jit_State *J, TRef *sp, CType **s, CTState *cts,
void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
{
- CTState *cts = ctype_ctsG(J2G(J));
+ CTState *cts = ctype_cts(J->L);
+ MMS mm = (MMS)rd->data;
TRef sp[2];
CType *s[2];
MSize i;
@@ -1417,6 +1418,8 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
}
}
} else if (tref_isnil(tr)) {
+ if (!(mm == MM_len || mm == MM_eq || mm == MM_lt || mm == MM_le))
+ lj_trace_err(J, LJ_TRERR_BADTYPE);
tr = lj_ir_kptr(J, NULL);
ct = ctype_get(cts, CTID_P_VOID);
} else if (tref_isinteger(tr)) {
@@ -1435,12 +1438,12 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
ct = ctype_child(cts, cct);
tr = lj_ir_kint(J, (int32_t)ofs);
} else { /* Interpreter will throw or return false. */
- ct = ctype_get(cts, CTID_P_VOID);
+ lj_trace_err(J, LJ_TRERR_BADTYPE);
}
} else if (ctype_isptr(ct->info)) {
tr = emitir(IRT(IR_ADD, IRT_PTR), tr, lj_ir_kintp(J, sizeof(GCstr)));
} else {
- ct = ctype_get(cts, CTID_P_VOID);
+ lj_trace_err(J, LJ_TRERR_BADTYPE);
}
} else if (!tref_isnum(tr)) {
tr = 0;
@@ -1452,7 +1455,6 @@ void LJ_FASTCALL recff_cdata_arith(jit_State *J, RecordFFData *rd)
}
{
TRef tr;
- MMS mm = (MMS)rd->data;
if ((mm == MM_len || mm == MM_concat ||
(!(tr = crec_arith_int64(J, sp, s, mm)) &&
!(tr = crec_arith_ptr(J, sp, s, mm)))) &&
From 747fc02eb97f0c12e08723df788fd20a2f449397 Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Wed, 3 Jul 2024 23:59:59 +0200
Subject: [PATCH 06/10] OSX: Fix installed luajit.pc.
Reported by leleliu008. #1221
---
Makefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/Makefile b/Makefile
index 3aed365d..6ae2c49d 100644
--- a/Makefile
+++ b/Makefile
@@ -114,6 +114,7 @@ ifeq (Darwin,$(TARGET_SYS))
INSTALL_SOSHORT1= $(INSTALL_DYLIBSHORT1)
INSTALL_SOSHORT2= $(INSTALL_DYLIBSHORT2)
LDCONFIG= :
+ SED_PC+= -e "s| -Wl,-E||"
endif
##############################################################################
From 444c8ff19a39248307a7037354d6d259cc0e5efc Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Thu, 4 Jul 2024 00:03:40 +0200
Subject: [PATCH 07/10] Clarify that lj_buf_shrink() does not keep any buffer
data.
https://www.freelists.org/post/luajit/lj-buf-shrink-may-truncate-the-data-and-sbw-point-over-the-end-of-the-buffer,1
Thanks to Junlong li.
---
src/lj_buf.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/lj_buf.c b/src/lj_buf.c
index ae2ccd82..702c5a40 100644
--- a/src/lj_buf.c
+++ b/src/lj_buf.c
@@ -92,10 +92,8 @@ void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb)
char *b = sb->b;
MSize osz = (MSize)(sb->e - b);
if (osz > 2*LJ_MIN_SBUF) {
- MSize n = (MSize)(sb->w - b);
b = lj_mem_realloc(L, b, osz, (osz >> 1));
- sb->b = b;
- sb->w = b + n;
+ sb->w = sb->b = b; /* Not supposed to keep data across shrinks. */
sb->e = b + (osz >> 1);
}
lj_assertG_(G(sbufL(sb)), !sbufisext(sb), "YAGNI shrink SBufExt");
From 510f88d468b8a6d6feb02890417a7261073bcd87 Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Thu, 4 Jul 2024 00:13:58 +0200
Subject: [PATCH 08/10] Add build flag LUAJIT_DISABLE_TAILCALL to disable
tailcall generation.
Only use this for debugging purposes. NEVER set it for regular builds
or distro builds! In Lua, tailcalls are a language guarantee.
Suggested by Steve Vermeulen. #1220
---
src/lj_parse.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/lj_parse.c b/src/lj_parse.c
index db3ce8e7..4fdd4c65 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -2339,11 +2339,15 @@ static void parse_return(LexState *ls)
BCReg nret = expr_list(ls, &e);
if (nret == 1) { /* Return one result. */
if (e.k == VCALL) { /* Check for tail call. */
+#ifdef LUAJIT_DISABLE_TAILCALL
+ goto notailcall;
+#else
BCIns *ip = bcptr(fs, &e);
/* It doesn't pay off to add BC_VARGT just for 'return ...'. */
if (bc_op(*ip) == BC_VARG) goto notailcall;
fs->pc--;
ins = BCINS_AD(bc_op(*ip)-BC_CALL+BC_CALLT, bc_a(*ip), bc_c(*ip));
+#endif
} else { /* Can return the result from any register. */
ins = BCINS_AD(BC_RET1, expr_toanyreg(fs, &e), 2);
}
From 7421a1b33c7ea46f12bba9700c15b5c90253fee0 Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Thu, 4 Jul 2024 00:48:49 +0200
Subject: [PATCH 09/10] Restore state when recording __concat metamethod throws
an error.
Thanks to Sergey Kaplun. #1234
---
src/lj_record.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/src/lj_record.c b/src/lj_record.c
index 48bbbb20..6666b3c6 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -1025,7 +1025,9 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
J->L->base = b + baseadj;
copyTV(J->L, b-(2<= 0xffffff00) {
+ lj_err_throw(J->L, -(int32_t)tr); /* Propagate errors. */
+ } else if (tr) { /* Store final result. */
BCReg dst = bc_a(*(frame_contpc(frame)-1));
J->base[dst] = tr;
if (dst >= J->maxslot) {
@@ -2075,12 +2077,27 @@ static TRef rec_tnew(jit_State *J, uint32_t ah)
/* -- Concatenation ------------------------------------------------------- */
+typedef struct RecCatDataCP {
+ jit_State *J;
+ RecordIndex *ix;
+} RecCatDataCP;
+
+static TValue *rec_mm_concat_cp(lua_State *L, lua_CFunction dummy, void *ud)
+{
+ RecCatDataCP *rcd = (RecCatDataCP *)ud;
+ UNUSED(L); UNUSED(dummy);
+ rec_mm_arith(rcd->J, rcd->ix, MM_concat); /* Call __concat metamethod. */
+ return NULL;
+}
+
static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
{
TRef *top = &J->base[topslot];
TValue savetv[5+LJ_FR2];
BCReg s;
RecordIndex ix;
+ RecCatDataCP rcd;
+ int errcode;
lj_assertJ(baseslot < topslot, "bad CAT arg");
for (s = baseslot; s <= topslot; s++)
(void)getslot(J, s); /* Ensure all arguments have a reference. */
@@ -2116,8 +2133,11 @@ static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
ix.tab = top[-1];
ix.key = top[0];
memcpy(savetv, &J->L->base[topslot-1], sizeof(savetv)); /* Save slots. */
- rec_mm_arith(J, &ix, MM_concat); /* Call __concat metamethod. */
+ rcd.J = J;
+ rcd.ix = &ix;
+ errcode = lj_vm_cpcall(J->L, NULL, &rcd, rec_mm_concat_cp);
memcpy(&J->L->base[topslot-1], savetv, sizeof(savetv)); /* Restore slots. */
+ if (errcode) return (TRef)(-errcode);
return 0; /* No result yet. */
}
@@ -2440,6 +2460,8 @@ void lj_record_ins(jit_State *J)
case BC_CAT:
rc = rec_cat(J, rb, rc);
+ if (rc >= 0xffffff00)
+ lj_err_throw(J->L, -(int32_t)rc); /* Propagate errors. */
break;
/* -- Constant and move ops --------------------------------------------- */
From 04dca7911ea255f37be799c18d74c305b921c1a6 Mon Sep 17 00:00:00 2001
From: Mike Pall
Date: Thu, 4 Jul 2024 01:26:29 +0200
Subject: [PATCH 10/10] Call math.randomseed() without arguments to seed from
system entropy.
Reminder: the math.random() PRNG is NOT SUITABLE FOR CRYPTOGRAPHIC USE.
---
doc/extensions.html | 6 +++++-
src/Makefile.dep | 3 ++-
src/lib_math.c | 6 +++++-
src/lj_errmsg.h | 1 +
4 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/doc/extensions.html b/doc/extensions.html
index c1c9a808..e9aaa096 100644
--- a/doc/extensions.html
+++ b/doc/extensions.html
@@ -265,7 +265,7 @@ and let the GC do its work.
LuaJIT uses a Tausworthe PRNG with period 2^223 to implement
math.random() and math.randomseed(). The quality of
the PRNG results is much superior compared to the standard Lua
-implementation, which uses the platform-specific ANSI rand().
+implementation, which uses the platform-specific ANSI rand().
The PRNG generates the same sequences from the same seeds on all
@@ -276,6 +276,10 @@ It's correctly scaled up and rounded for math.random(n [,m]) to
preserve uniformity.
+Call math.randomseed() without any arguments to seed it from
+system entropy.
+
+
Important: Neither this nor any other PRNG based on the simplistic
math.random() API is suitable for cryptographic use.
diff --git a/src/Makefile.dep b/src/Makefile.dep
index fda77c83..e9f83399 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -32,7 +32,8 @@ lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lj_target.h lj_target_*.h lj_trace.h lj_dispatch.h lj_traceerr.h \
lj_vm.h lj_vmevent.h lj_lib.h luajit.h lj_libdef.h
lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
- lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_prng.h lj_libdef.h
+ lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_vm.h lj_prng.h \
+ lj_libdef.h
lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_lib.h \
lj_libdef.h
diff --git a/src/lib_math.c b/src/lib_math.c
index 4539f804..08bb7673 100644
--- a/src/lib_math.c
+++ b/src/lib_math.c
@@ -13,6 +13,7 @@
#include "lualib.h"
#include "lj_obj.h"
+#include "lj_err.h"
#include "lj_lib.h"
#include "lj_vm.h"
#include "lj_prng.h"
@@ -183,7 +184,10 @@ LJLIB_PUSH(top-2) /* Upvalue holds userdata with PRNGState. */
LJLIB_CF(math_randomseed)
{
PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
- random_seed(rs, lj_lib_checknum(L, 1));
+ if (L->base != L->top)
+ random_seed(rs, lj_lib_checknum(L, 1));
+ else if (!lj_prng_seed_secure(rs))
+ lj_err_caller(L, LJ_ERR_PRNGSD);
return 0;
}
diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h
index 127c06da..109e909c 100644
--- a/src/lj_errmsg.h
+++ b/src/lj_errmsg.h
@@ -79,6 +79,7 @@ ERRDEF(SETFENV, LUA_QL("setfenv") " cannot change environment of given object")
ERRDEF(CORUN, "cannot resume running coroutine")
ERRDEF(CODEAD, "cannot resume dead coroutine")
ERRDEF(COSUSP, "cannot resume non-suspended coroutine")
+ERRDEF(PRNGSD, "PRNG seeding failed")
ERRDEF(TABINS, "wrong number of arguments to " LUA_QL("insert"))
ERRDEF(TABCAT, "invalid value (%s) at index %d in table for " LUA_QL("concat"))
ERRDEF(TABSORT, "invalid order function for sorting")