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 ############################################################################## 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/jit/bcsave.lua b/src/jit/bcsave.lua index 0d79a70e..48378819 100644 --- a/src/jit/bcsave.lua +++ b/src/jit/bcsave.lua @@ -511,7 +511,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) diff --git a/src/lib_ffi.c b/src/lib_ffi.c index fb7f86f3..ddeb10c5 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c @@ -305,7 +305,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); 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_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"); diff --git a/src/lj_crecord.c b/src/lj_crecord.c index 55d0b3ef..79159454 100644 --- a/src/lj_crecord.c +++ b/src/lj_crecord.c @@ -1498,7 +1498,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; @@ -1548,6 +1549,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)) { @@ -1566,12 +1569,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; @@ -1583,7 +1586,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)))) && 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") diff --git a/src/lj_parse.c b/src/lj_parse.c index 67d33ca8..d89ffe44 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -2384,11 +2384,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); } @@ -2562,11 +2566,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; @@ -2615,7 +2617,7 @@ static void parse_for_iter(LexState *ls, GCstr *indexname) assign_adjust(ls, 3, expr_list(ls, &e), &e); /* The iterator needs another 3 [4] slots (func [pc] | state ctl). */ bcreg_bump(fs, 3+ls->fr2); - 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); 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<