diff options
Diffstat (limited to '')
-rw-r--r-- | src/Makefile | 4 | ||||
-rw-r--r-- | src/Makefile.dep | 50 | ||||
-rw-r--r-- | src/lib_aux.c | 8 | ||||
-rw-r--r-- | src/lib_math.c | 53 | ||||
-rw-r--r-- | src/lj_alloc.c | 83 | ||||
-rw-r--r-- | src/lj_alloc.h | 3 | ||||
-rw-r--r-- | src/lj_arch.h | 15 | ||||
-rw-r--r-- | src/lj_def.h | 5 | ||||
-rw-r--r-- | src/lj_ffrecord.c | 2 | ||||
-rw-r--r-- | src/lj_ir.c | 2 | ||||
-rw-r--r-- | src/lj_ircall.h | 2 | ||||
-rw-r--r-- | src/lj_jit.h | 13 | ||||
-rw-r--r-- | src/lj_lib.h | 5 | ||||
-rw-r--r-- | src/lj_mcode.c | 41 | ||||
-rw-r--r-- | src/lj_obj.h | 1 | ||||
-rw-r--r-- | src/lj_prng.c | 225 | ||||
-rw-r--r-- | src/lj_prng.h | 24 | ||||
-rw-r--r-- | src/lj_record.c | 3 | ||||
-rw-r--r-- | src/lj_state.c | 38 | ||||
-rw-r--r-- | src/lj_state.h | 2 | ||||
-rw-r--r-- | src/lj_trace.c | 3 | ||||
-rw-r--r-- | src/ljamalg.c | 1 |
22 files changed, 410 insertions, 173 deletions
diff --git a/src/Makefile b/src/Makefile index 667fff56..6a9de5db 100644 --- a/src/Makefile +++ b/src/Makefile | |||
@@ -485,8 +485,8 @@ LJLIB_C= $(LJLIB_O:.o=.c) | |||
485 | 485 | ||
486 | LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \ | 486 | LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \ |
487 | lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ | 487 | lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ |
488 | lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \ | 488 | lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \ |
489 | lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \ | 489 | lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \ |
490 | lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \ | 490 | lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \ |
491 | lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ | 491 | lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ |
492 | lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ | 492 | lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ |
diff --git a/src/Makefile.dep b/src/Makefile.dep index 03dba96b..3f26599e 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
@@ -1,6 +1,6 @@ | |||
1 | lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ | 1 | lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ |
2 | lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \ | 2 | lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \ |
3 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h lj_alloc.h | 3 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h |
4 | lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | 4 | lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ |
5 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \ | 5 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \ |
6 | lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \ | 6 | lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \ |
@@ -28,7 +28,7 @@ lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | |||
28 | lj_target.h lj_target_*.h lj_trace.h lj_dispatch.h lj_traceerr.h \ | 28 | lj_target.h lj_target_*.h lj_trace.h lj_dispatch.h lj_traceerr.h \ |
29 | lj_vm.h lj_vmevent.h lj_lib.h luajit.h lj_libdef.h | 29 | lj_vm.h lj_vmevent.h lj_lib.h luajit.h lj_libdef.h |
30 | lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | 30 | lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ |
31 | lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_libdef.h | 31 | lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_prng.h lj_libdef.h |
32 | lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 32 | lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
33 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_lib.h \ | 33 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_lib.h \ |
34 | lj_libdef.h | 34 | lj_libdef.h |
@@ -41,7 +41,8 @@ lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | |||
41 | lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | 41 | lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ |
42 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \ | 42 | lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \ |
43 | lj_tab.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h | 43 | lj_tab.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h |
44 | lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h | 44 | lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h \ |
45 | lj_prng.h | ||
45 | lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 46 | lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
46 | lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \ | 47 | lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \ |
47 | lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \ | 48 | lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \ |
@@ -126,7 +127,7 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
126 | lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 127 | lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
127 | lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ | 128 | lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ |
128 | lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \ | 129 | lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \ |
129 | lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h | 130 | lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_prng.h |
130 | lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 131 | lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
131 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \ | 132 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \ |
132 | lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \ | 133 | lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \ |
@@ -140,7 +141,7 @@ lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ | |||
140 | lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h | 141 | lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h |
141 | lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 142 | lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
142 | lj_gc.h lj_err.h lj_errmsg.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h \ | 143 | lj_gc.h lj_err.h lj_errmsg.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h \ |
143 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_vm.h | 144 | lj_dispatch.h lj_bc.h lj_traceerr.h lj_prng.h lj_vm.h |
144 | lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 145 | lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
145 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_meta.h lj_frame.h \ | 146 | lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_meta.h lj_frame.h \ |
146 | lj_bc.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h | 147 | lj_bc.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h |
@@ -172,11 +173,12 @@ lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
172 | lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 173 | lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
173 | lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \ | 174 | lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \ |
174 | lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h | 175 | lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h |
176 | lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h | ||
175 | lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 177 | lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
176 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ | 178 | lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ |
177 | lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \ | 179 | lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \ |
178 | lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \ | 180 | lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \ |
179 | lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h | 181 | lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h |
180 | lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 182 | lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
181 | lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ | 183 | lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ |
182 | lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ | 184 | lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ |
@@ -184,7 +186,8 @@ lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | |||
184 | lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 186 | lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
185 | lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_func.h \ | 187 | lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_func.h \ |
186 | lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_trace.h lj_jit.h \ | 188 | lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_trace.h lj_jit.h \ |
187 | lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_alloc.h luajit.h | 189 | lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \ |
190 | lj_alloc.h luajit.h | ||
188 | lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | 191 | lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ |
189 | lj_err.h lj_errmsg.h lj_str.h lj_char.h | 192 | lj_err.h lj_errmsg.h lj_str.h lj_char.h |
190 | lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 193 | lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
@@ -199,7 +202,7 @@ lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
199 | lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_frame.h lj_bc.h \ | 202 | lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_frame.h lj_bc.h \ |
200 | lj_state.h lj_ir.h lj_jit.h lj_iropt.h lj_mcode.h lj_trace.h \ | 203 | lj_state.h lj_ir.h lj_jit.h lj_iropt.h lj_mcode.h lj_trace.h \ |
201 | lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \ | 204 | lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \ |
202 | lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h | 205 | lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h |
203 | lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 206 | lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
204 | lj_gc.h lj_udata.h | 207 | lj_gc.h lj_udata.h |
205 | lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 208 | lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
@@ -214,21 +217,22 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \ | |||
214 | lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \ | 217 | lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \ |
215 | lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \ | 218 | lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \ |
216 | lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \ | 219 | lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \ |
217 | lj_state.c lj_lex.h lj_alloc.h luajit.h lj_dispatch.c lj_ccallback.h \ | 220 | lj_prng.c lj_prng.h lj_state.c lj_lex.h lj_alloc.h luajit.h \ |
218 | lj_profile.h lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_strscan.c \ | 221 | lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \ |
219 | lj_strfmt.c lj_strfmt_num.c lj_api.c lj_profile.c lj_lex.c lualib.h \ | 222 | lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_api.c \ |
220 | lj_parse.h lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c \ | 223 | lj_profile.c lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c \ |
221 | lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h \ | 224 | lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h \ |
222 | lj_ccallback.c lj_target.h lj_target_*.h lj_mcode.h lj_carith.c \ | 225 | lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \ |
223 | lj_carith.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c \ | 226 | lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \ |
224 | lj_ircall.h lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h \ | 227 | lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \ |
225 | lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c \ | 228 | lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ |
226 | lj_opt_sink.c lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h \ | 229 | lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \ |
227 | lj_crecord.c lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h \ | 230 | lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ |
228 | lj_emit_*.h lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c \ | 231 | lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \ |
229 | lib_aux.c lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c \ | 232 | lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \ |
230 | lib_io.c lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c \ | 233 | lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \ |
231 | lib_ffi.c lib_init.c | 234 | lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \ |
235 | lib_init.c | ||
232 | luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h | 236 | luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h |
233 | host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ | 237 | host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ |
234 | lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ | 238 | lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ |
diff --git a/src/lib_aux.c b/src/lib_aux.c index 8f10e23c..35866f8d 100644 --- a/src/lib_aux.c +++ b/src/lib_aux.c | |||
@@ -345,17 +345,13 @@ LUALIB_API lua_State *luaL_newstate(void) | |||
345 | 345 | ||
346 | #else | 346 | #else |
347 | 347 | ||
348 | #include "lj_alloc.h" | ||
349 | |||
350 | LUALIB_API lua_State *luaL_newstate(void) | 348 | LUALIB_API lua_State *luaL_newstate(void) |
351 | { | 349 | { |
352 | lua_State *L; | 350 | lua_State *L; |
353 | void *ud = lj_alloc_create(); | ||
354 | if (ud == NULL) return NULL; | ||
355 | #if LJ_64 && !LJ_GC64 | 351 | #if LJ_64 && !LJ_GC64 |
356 | L = lj_state_newstate(lj_alloc_f, ud); | 352 | L = lj_state_newstate(LJ_ALLOCF_INTERNAL, NULL); |
357 | #else | 353 | #else |
358 | L = lua_newstate(lj_alloc_f, ud); | 354 | L = lua_newstate(LJ_ALLOCF_INTERNAL, NULL); |
359 | #endif | 355 | #endif |
360 | if (L) G(L)->panic = panic; | 356 | if (L) G(L)->panic = panic; |
361 | return L; | 357 | return L; |
diff --git a/src/lib_math.c b/src/lib_math.c index 4cc2ba6e..95b7d460 100644 --- a/src/lib_math.c +++ b/src/lib_math.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "lj_obj.h" | 15 | #include "lj_obj.h" |
16 | #include "lj_lib.h" | 16 | #include "lj_lib.h" |
17 | #include "lj_vm.h" | 17 | #include "lj_vm.h" |
18 | #include "lj_prng.h" | ||
18 | 19 | ||
19 | /* ------------------------------------------------------------------------ */ | 20 | /* ------------------------------------------------------------------------ */ |
20 | 21 | ||
@@ -105,34 +106,11 @@ LJLIB_PUSH(1e310) LJLIB_SET(huge) | |||
105 | ** Full-period ME-CF generator with L=64, J=4, k=223, N1=49. | 106 | ** Full-period ME-CF generator with L=64, J=4, k=223, N1=49. |
106 | */ | 107 | */ |
107 | 108 | ||
108 | /* PRNG state. */ | ||
109 | struct RandomState { | ||
110 | uint64_t gen[4]; /* State of the 4 LFSR generators. */ | ||
111 | int valid; /* State is valid. */ | ||
112 | }; | ||
113 | |||
114 | /* Union needed for bit-pattern conversion between uint64_t and double. */ | 109 | /* Union needed for bit-pattern conversion between uint64_t and double. */ |
115 | typedef union { uint64_t u64; double d; } U64double; | 110 | typedef union { uint64_t u64; double d; } U64double; |
116 | 111 | ||
117 | /* Update generator i and compute a running xor of all states. */ | 112 | /* PRNG seeding function. */ |
118 | #define TW223_GEN(i, k, q, s) \ | 113 | static void random_seed(PRNGState *rs, double d) |
119 | z = rs->gen[i]; \ | ||
120 | z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \ | ||
121 | r ^= z; rs->gen[i] = z; | ||
122 | |||
123 | /* PRNG step function. Returns a double in the range 1.0 <= d < 2.0. */ | ||
124 | LJ_NOINLINE uint64_t LJ_FASTCALL lj_math_random_step(RandomState *rs) | ||
125 | { | ||
126 | uint64_t z, r = 0; | ||
127 | TW223_GEN(0, 63, 31, 18) | ||
128 | TW223_GEN(1, 58, 19, 28) | ||
129 | TW223_GEN(2, 55, 24, 7) | ||
130 | TW223_GEN(3, 47, 21, 8) | ||
131 | return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000); | ||
132 | } | ||
133 | |||
134 | /* PRNG initialization function. */ | ||
135 | static void random_init(RandomState *rs, double d) | ||
136 | { | 114 | { |
137 | uint32_t r = 0x11090601; /* 64-k[i] as four 8 bit constants. */ | 115 | uint32_t r = 0x11090601; /* 64-k[i] as four 8 bit constants. */ |
138 | int i; | 116 | int i; |
@@ -141,24 +119,22 @@ static void random_init(RandomState *rs, double d) | |||
141 | uint32_t m = 1u << (r&255); | 119 | uint32_t m = 1u << (r&255); |
142 | r >>= 8; | 120 | r >>= 8; |
143 | u.d = d = d * 3.14159265358979323846 + 2.7182818284590452354; | 121 | u.d = d = d * 3.14159265358979323846 + 2.7182818284590452354; |
144 | if (u.u64 < m) u.u64 += m; /* Ensure k[i] MSB of gen[i] are non-zero. */ | 122 | if (u.u64 < m) u.u64 += m; /* Ensure k[i] MSB of u[i] are non-zero. */ |
145 | rs->gen[i] = u.u64; | 123 | rs->u[i] = u.u64; |
146 | } | 124 | } |
147 | rs->valid = 1; | ||
148 | for (i = 0; i < 10; i++) | 125 | for (i = 0; i < 10; i++) |
149 | lj_math_random_step(rs); | 126 | (void)lj_prng_u64(rs); |
150 | } | 127 | } |
151 | 128 | ||
152 | /* PRNG extract function. */ | 129 | /* PRNG extract function. */ |
153 | LJLIB_PUSH(top-2) /* Upvalue holds userdata with RandomState. */ | 130 | LJLIB_PUSH(top-2) /* Upvalue holds userdata with PRNGState. */ |
154 | LJLIB_CF(math_random) LJLIB_REC(.) | 131 | LJLIB_CF(math_random) LJLIB_REC(.) |
155 | { | 132 | { |
156 | int n = (int)(L->top - L->base); | 133 | int n = (int)(L->top - L->base); |
157 | RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); | 134 | PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); |
158 | U64double u; | 135 | U64double u; |
159 | double d; | 136 | double d; |
160 | if (LJ_UNLIKELY(!rs->valid)) random_init(rs, 0.0); | 137 | u.u64 = lj_prng_u64d(rs); |
161 | u.u64 = lj_math_random_step(rs); | ||
162 | d = u.d - 1.0; | 138 | d = u.d - 1.0; |
163 | if (n > 0) { | 139 | if (n > 0) { |
164 | #if LJ_DUALNUM | 140 | #if LJ_DUALNUM |
@@ -203,11 +179,11 @@ LJLIB_CF(math_random) LJLIB_REC(.) | |||
203 | } | 179 | } |
204 | 180 | ||
205 | /* PRNG seed function. */ | 181 | /* PRNG seed function. */ |
206 | LJLIB_PUSH(top-2) /* Upvalue holds userdata with RandomState. */ | 182 | LJLIB_PUSH(top-2) /* Upvalue holds userdata with PRNGState. */ |
207 | LJLIB_CF(math_randomseed) | 183 | LJLIB_CF(math_randomseed) |
208 | { | 184 | { |
209 | RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); | 185 | PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); |
210 | random_init(rs, lj_lib_checknum(L, 1)); | 186 | random_seed(rs, lj_lib_checknum(L, 1)); |
211 | return 0; | 187 | return 0; |
212 | } | 188 | } |
213 | 189 | ||
@@ -217,9 +193,8 @@ LJLIB_CF(math_randomseed) | |||
217 | 193 | ||
218 | LUALIB_API int luaopen_math(lua_State *L) | 194 | LUALIB_API int luaopen_math(lua_State *L) |
219 | { | 195 | { |
220 | RandomState *rs; | 196 | PRNGState *rs = (PRNGState *)lua_newuserdata(L, sizeof(PRNGState)); |
221 | rs = (RandomState *)lua_newuserdata(L, sizeof(RandomState)); | 197 | lj_prng_seed_fixed(rs); |
222 | rs->valid = 0; /* Use lazy initialization to save some time on startup. */ | ||
223 | LJ_LIB_REG(L, LUA_MATHLIBNAME, math); | 198 | LJ_LIB_REG(L, LUA_MATHLIBNAME, math); |
224 | return 1; | 199 | return 1; |
225 | } | 200 | } |
diff --git a/src/lj_alloc.c b/src/lj_alloc.c index 70ca1e3b..bf2ae847 100644 --- a/src/lj_alloc.c +++ b/src/lj_alloc.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "lj_def.h" | 31 | #include "lj_def.h" |
32 | #include "lj_arch.h" | 32 | #include "lj_arch.h" |
33 | #include "lj_alloc.h" | 33 | #include "lj_alloc.h" |
34 | #include "lj_prng.h" | ||
34 | 35 | ||
35 | #ifndef LUAJIT_USE_SYSMALLOC | 36 | #ifndef LUAJIT_USE_SYSMALLOC |
36 | 37 | ||
@@ -140,7 +141,7 @@ static void init_mmap(void) | |||
140 | #define INIT_MMAP() init_mmap() | 141 | #define INIT_MMAP() init_mmap() |
141 | 142 | ||
142 | /* Win64 32 bit MMAP via NtAllocateVirtualMemory. */ | 143 | /* Win64 32 bit MMAP via NtAllocateVirtualMemory. */ |
143 | static void *CALL_MMAP(size_t size) | 144 | static void *mmap_plain(size_t size) |
144 | { | 145 | { |
145 | DWORD olderr = GetLastError(); | 146 | DWORD olderr = GetLastError(); |
146 | void *ptr = NULL; | 147 | void *ptr = NULL; |
@@ -164,7 +165,7 @@ static void *direct_mmap(size_t size) | |||
164 | #else | 165 | #else |
165 | 166 | ||
166 | /* Win32 MMAP via VirtualAlloc */ | 167 | /* Win32 MMAP via VirtualAlloc */ |
167 | static void *CALL_MMAP(size_t size) | 168 | static void *mmap_plain(size_t size) |
168 | { | 169 | { |
169 | DWORD olderr = GetLastError(); | 170 | DWORD olderr = GetLastError(); |
170 | void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); | 171 | void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); |
@@ -184,7 +185,8 @@ static void *direct_mmap(size_t size) | |||
184 | 185 | ||
185 | #endif | 186 | #endif |
186 | 187 | ||
187 | #define DIRECT_MMAP(size) direct_mmap(size) | 188 | #define CALL_MMAP(prng, size) mmap_plain(size) |
189 | #define DIRECT_MMAP(prng, size) direct_mmap(size) | ||
188 | 190 | ||
189 | /* This function supports releasing coalesed segments */ | 191 | /* This function supports releasing coalesed segments */ |
190 | static int CALL_MUNMAP(void *ptr, size_t size) | 192 | static int CALL_MUNMAP(void *ptr, size_t size) |
@@ -228,30 +230,10 @@ static int CALL_MUNMAP(void *ptr, size_t size) | |||
228 | 230 | ||
229 | #define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000) | 231 | #define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000) |
230 | 232 | ||
231 | /* No point in a giant ifdef mess. Just try to open /dev/urandom. | 233 | static void *mmap_probe(PRNGState *rs, size_t size) |
232 | ** It doesn't really matter if this fails, since we get some ASLR bits from | ||
233 | ** every unsuitable allocation, too. And we prefer linear allocation, anyway. | ||
234 | */ | ||
235 | #include <fcntl.h> | ||
236 | #include <unistd.h> | ||
237 | |||
238 | static uintptr_t mmap_probe_seed(void) | ||
239 | { | ||
240 | uintptr_t val; | ||
241 | int fd = open("/dev/urandom", O_RDONLY); | ||
242 | if (fd != -1) { | ||
243 | int ok = ((size_t)read(fd, &val, sizeof(val)) == sizeof(val)); | ||
244 | (void)close(fd); | ||
245 | if (ok) return val; | ||
246 | } | ||
247 | return 1; /* Punt. */ | ||
248 | } | ||
249 | |||
250 | static void *mmap_probe(size_t size) | ||
251 | { | 234 | { |
252 | /* Hint for next allocation. Doesn't need to be thread-safe. */ | 235 | /* Hint for next allocation. Doesn't need to be thread-safe. */ |
253 | static uintptr_t hint_addr = 0; | 236 | static uintptr_t hint_addr = 0; |
254 | static uintptr_t hint_prng = 0; | ||
255 | int olderr = errno; | 237 | int olderr = errno; |
256 | int retry; | 238 | int retry; |
257 | for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) { | 239 | for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) { |
@@ -283,15 +265,8 @@ static void *mmap_probe(size_t size) | |||
283 | } | 265 | } |
284 | } | 266 | } |
285 | /* Finally, try pseudo-random probing. */ | 267 | /* Finally, try pseudo-random probing. */ |
286 | if (LJ_UNLIKELY(hint_prng == 0)) { | 268 | do { |
287 | hint_prng = mmap_probe_seed(); | 269 | hint_addr = lj_prng_u64(rs) & (((uintptr_t)1<<LJ_ALLOC_MBITS)-LJ_PAGESIZE); |
288 | } | ||
289 | /* The unsuitable address we got has some ASLR PRNG bits. */ | ||
290 | hint_addr ^= addr & ~((uintptr_t)(LJ_PAGESIZE-1)); | ||
291 | do { /* The PRNG itself is very weak, but see above. */ | ||
292 | hint_prng = hint_prng * 1103515245 + 12345; | ||
293 | hint_addr ^= hint_prng * (uintptr_t)LJ_PAGESIZE; | ||
294 | hint_addr &= (((uintptr_t)1 << LJ_ALLOC_MBITS)-1); | ||
295 | } while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER); | 270 | } while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER); |
296 | } | 271 | } |
297 | errno = olderr; | 272 | errno = olderr; |
@@ -308,12 +283,16 @@ static void *mmap_probe(size_t size) | |||
308 | #define LJ_ALLOC_MMAP32_START ((uintptr_t)0) | 283 | #define LJ_ALLOC_MMAP32_START ((uintptr_t)0) |
309 | #endif | 284 | #endif |
310 | 285 | ||
286 | #if LJ_ALLOC_MMAP_PROBE | ||
287 | static void *mmap_map32(PRNGState *rs, size_t size) | ||
288 | #else | ||
311 | static void *mmap_map32(size_t size) | 289 | static void *mmap_map32(size_t size) |
290 | #endif | ||
312 | { | 291 | { |
313 | #if LJ_ALLOC_MMAP_PROBE | 292 | #if LJ_ALLOC_MMAP_PROBE |
314 | static int fallback = 0; | 293 | static int fallback = 0; |
315 | if (fallback) | 294 | if (fallback) |
316 | return mmap_probe(size); | 295 | return mmap_probe(rs, size); |
317 | #endif | 296 | #endif |
318 | { | 297 | { |
319 | int olderr = errno; | 298 | int olderr = errno; |
@@ -323,7 +302,7 @@ static void *mmap_map32(size_t size) | |||
323 | #if LJ_ALLOC_MMAP_PROBE | 302 | #if LJ_ALLOC_MMAP_PROBE |
324 | if (ptr == MFAIL) { | 303 | if (ptr == MFAIL) { |
325 | fallback = 1; | 304 | fallback = 1; |
326 | return mmap_probe(size); | 305 | return mmap_probe(rs, size); |
327 | } | 306 | } |
328 | #endif | 307 | #endif |
329 | return ptr; | 308 | return ptr; |
@@ -333,17 +312,22 @@ static void *mmap_map32(size_t size) | |||
333 | #endif | 312 | #endif |
334 | 313 | ||
335 | #if LJ_ALLOC_MMAP32 | 314 | #if LJ_ALLOC_MMAP32 |
336 | #define CALL_MMAP(size) mmap_map32(size) | 315 | #if LJ_ALLOC_MMAP_PROBE |
316 | #define CALL_MMAP(prng, size) mmap_map32(prng, size) | ||
317 | #else | ||
318 | #define CALL_MMAP(prng, size) mmap_map32(size) | ||
319 | #endif | ||
337 | #elif LJ_ALLOC_MMAP_PROBE | 320 | #elif LJ_ALLOC_MMAP_PROBE |
338 | #define CALL_MMAP(size) mmap_probe(size) | 321 | #define CALL_MMAP(prng, size) mmap_probe(prng, size) |
339 | #else | 322 | #else |
340 | static void *CALL_MMAP(size_t size) | 323 | static void *mmap_plain(size_t size) |
341 | { | 324 | { |
342 | int olderr = errno; | 325 | int olderr = errno; |
343 | void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0); | 326 | void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0); |
344 | errno = olderr; | 327 | errno = olderr; |
345 | return ptr; | 328 | return ptr; |
346 | } | 329 | } |
330 | #define CALL_MMAP(prng, size) mmap_plain(size) | ||
347 | #endif | 331 | #endif |
348 | 332 | ||
349 | #if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4 | 333 | #if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4 |
@@ -396,7 +380,7 @@ static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags) | |||
396 | #endif | 380 | #endif |
397 | 381 | ||
398 | #ifndef DIRECT_MMAP | 382 | #ifndef DIRECT_MMAP |
399 | #define DIRECT_MMAP(s) CALL_MMAP(s) | 383 | #define DIRECT_MMAP(prng, s) CALL_MMAP(prng, s) |
400 | #endif | 384 | #endif |
401 | 385 | ||
402 | #ifndef CALL_MREMAP | 386 | #ifndef CALL_MREMAP |
@@ -555,6 +539,7 @@ struct malloc_state { | |||
555 | mchunkptr smallbins[(NSMALLBINS+1)*2]; | 539 | mchunkptr smallbins[(NSMALLBINS+1)*2]; |
556 | tbinptr treebins[NTREEBINS]; | 540 | tbinptr treebins[NTREEBINS]; |
557 | msegment seg; | 541 | msegment seg; |
542 | PRNGState *prng; | ||
558 | }; | 543 | }; |
559 | 544 | ||
560 | typedef struct malloc_state *mstate; | 545 | typedef struct malloc_state *mstate; |
@@ -837,11 +822,11 @@ static int has_segment_link(mstate m, msegmentptr ss) | |||
837 | 822 | ||
838 | /* ----------------------- Direct-mmapping chunks ----------------------- */ | 823 | /* ----------------------- Direct-mmapping chunks ----------------------- */ |
839 | 824 | ||
840 | static void *direct_alloc(size_t nb) | 825 | static void *direct_alloc(mstate m, size_t nb) |
841 | { | 826 | { |
842 | size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); | 827 | size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); |
843 | if (LJ_LIKELY(mmsize > nb)) { /* Check for wrap around 0 */ | 828 | if (LJ_LIKELY(mmsize > nb)) { /* Check for wrap around 0 */ |
844 | char *mm = (char *)(DIRECT_MMAP(mmsize)); | 829 | char *mm = (char *)(DIRECT_MMAP(m->prng, mmsize)); |
845 | if (mm != CMFAIL) { | 830 | if (mm != CMFAIL) { |
846 | size_t offset = align_offset(chunk2mem(mm)); | 831 | size_t offset = align_offset(chunk2mem(mm)); |
847 | size_t psize = mmsize - offset - DIRECT_FOOT_PAD; | 832 | size_t psize = mmsize - offset - DIRECT_FOOT_PAD; |
@@ -853,6 +838,7 @@ static void *direct_alloc(size_t nb) | |||
853 | return chunk2mem(p); | 838 | return chunk2mem(p); |
854 | } | 839 | } |
855 | } | 840 | } |
841 | UNUSED(m); | ||
856 | return NULL; | 842 | return NULL; |
857 | } | 843 | } |
858 | 844 | ||
@@ -1001,7 +987,7 @@ static void *alloc_sys(mstate m, size_t nb) | |||
1001 | 987 | ||
1002 | /* Directly map large chunks */ | 988 | /* Directly map large chunks */ |
1003 | if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) { | 989 | if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) { |
1004 | void *mem = direct_alloc(nb); | 990 | void *mem = direct_alloc(m, nb); |
1005 | if (mem != 0) | 991 | if (mem != 0) |
1006 | return mem; | 992 | return mem; |
1007 | } | 993 | } |
@@ -1010,7 +996,7 @@ static void *alloc_sys(mstate m, size_t nb) | |||
1010 | size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE; | 996 | size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE; |
1011 | size_t rsize = granularity_align(req); | 997 | size_t rsize = granularity_align(req); |
1012 | if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */ | 998 | if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */ |
1013 | char *mp = (char *)(CALL_MMAP(rsize)); | 999 | char *mp = (char *)(CALL_MMAP(m->prng, rsize)); |
1014 | if (mp != CMFAIL) { | 1000 | if (mp != CMFAIL) { |
1015 | tbase = mp; | 1001 | tbase = mp; |
1016 | tsize = rsize; | 1002 | tsize = rsize; |
@@ -1237,12 +1223,13 @@ static void *tmalloc_small(mstate m, size_t nb) | |||
1237 | 1223 | ||
1238 | /* ----------------------------------------------------------------------- */ | 1224 | /* ----------------------------------------------------------------------- */ |
1239 | 1225 | ||
1240 | void *lj_alloc_create(void) | 1226 | void *lj_alloc_create(PRNGState *rs) |
1241 | { | 1227 | { |
1242 | size_t tsize = DEFAULT_GRANULARITY; | 1228 | size_t tsize = DEFAULT_GRANULARITY; |
1243 | char *tbase; | 1229 | char *tbase; |
1244 | INIT_MMAP(); | 1230 | INIT_MMAP(); |
1245 | tbase = (char *)(CALL_MMAP(tsize)); | 1231 | UNUSED(rs); |
1232 | tbase = (char *)(CALL_MMAP(rs, tsize)); | ||
1246 | if (tbase != CMFAIL) { | 1233 | if (tbase != CMFAIL) { |
1247 | size_t msize = pad_request(sizeof(struct malloc_state)); | 1234 | size_t msize = pad_request(sizeof(struct malloc_state)); |
1248 | mchunkptr mn; | 1235 | mchunkptr mn; |
@@ -1261,6 +1248,12 @@ void *lj_alloc_create(void) | |||
1261 | return NULL; | 1248 | return NULL; |
1262 | } | 1249 | } |
1263 | 1250 | ||
1251 | void lj_alloc_setprng(void *msp, PRNGState *rs) | ||
1252 | { | ||
1253 | mstate ms = (mstate)msp; | ||
1254 | ms->prng = rs; | ||
1255 | } | ||
1256 | |||
1264 | void lj_alloc_destroy(void *msp) | 1257 | void lj_alloc_destroy(void *msp) |
1265 | { | 1258 | { |
1266 | mstate ms = (mstate)msp; | 1259 | mstate ms = (mstate)msp; |
diff --git a/src/lj_alloc.h b/src/lj_alloc.h index f87a7cf3..669f50b7 100644 --- a/src/lj_alloc.h +++ b/src/lj_alloc.h | |||
@@ -9,7 +9,8 @@ | |||
9 | #include "lj_def.h" | 9 | #include "lj_def.h" |
10 | 10 | ||
11 | #ifndef LUAJIT_USE_SYSMALLOC | 11 | #ifndef LUAJIT_USE_SYSMALLOC |
12 | LJ_FUNC void *lj_alloc_create(void); | 12 | LJ_FUNC void *lj_alloc_create(PRNGState *rs); |
13 | LJ_FUNC void lj_alloc_setprng(void *msp, PRNGState *rs); | ||
13 | LJ_FUNC void lj_alloc_destroy(void *msp); | 14 | LJ_FUNC void lj_alloc_destroy(void *msp); |
14 | LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize); | 15 | LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize); |
15 | #endif | 16 | #endif |
diff --git a/src/lj_arch.h b/src/lj_arch.h index 3e3581c2..626f6c13 100644 --- a/src/lj_arch.h +++ b/src/lj_arch.h | |||
@@ -633,4 +633,19 @@ extern void *LJ_WIN_LOADLIBA(const char *path); | |||
633 | #define LJ_52 0 | 633 | #define LJ_52 0 |
634 | #endif | 634 | #endif |
635 | 635 | ||
636 | /* -- VM security --------------------------------------------------------- */ | ||
637 | |||
638 | /* Don't make any changes here. Instead build with: | ||
639 | ** make "XCFLAGS=-DLUAJIT_SECURITY_flag=value" | ||
640 | */ | ||
641 | |||
642 | /* Security defaults. */ | ||
643 | #ifndef LUAJIT_SECURITY_PRNG | ||
644 | #define LUAJIT_SECURITY_PRNG 1 | ||
645 | #endif | ||
646 | |||
647 | #ifndef LUAJIT_SECURITY_MCODE | ||
648 | #define LUAJIT_SECURITY_MCODE 1 | ||
649 | #endif | ||
650 | |||
636 | #endif | 651 | #endif |
diff --git a/src/lj_def.h b/src/lj_def.h index af0687c4..e458c89f 100644 --- a/src/lj_def.h +++ b/src/lj_def.h | |||
@@ -372,4 +372,9 @@ static LJ_AINLINE uint32_t lj_getu32(const void *v) | |||
372 | extern void LJ_ASSERT_NAME(__LINE__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1]) | 372 | extern void LJ_ASSERT_NAME(__LINE__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1]) |
373 | #endif | 373 | #endif |
374 | 374 | ||
375 | /* PRNG state. Need this here, details in lj_prng.h. */ | ||
376 | typedef struct PRNGState { | ||
377 | uint64_t u[4]; | ||
378 | } PRNGState; | ||
379 | |||
375 | #endif | 380 | #endif |
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index d34340ce..19da15a2 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
@@ -616,7 +616,7 @@ static void LJ_FASTCALL recff_math_random(jit_State *J, RecordFFData *rd) | |||
616 | GCudata *ud = udataV(&J->fn->c.upvalue[0]); | 616 | GCudata *ud = udataV(&J->fn->c.upvalue[0]); |
617 | TRef tr, one; | 617 | TRef tr, one; |
618 | lj_ir_kgc(J, obj2gco(ud), IRT_UDATA); /* Prevent collection. */ | 618 | lj_ir_kgc(J, obj2gco(ud), IRT_UDATA); /* Prevent collection. */ |
619 | tr = lj_ir_call(J, IRCALL_lj_math_random_step, lj_ir_kptr(J, uddata(ud))); | 619 | tr = lj_ir_call(J, IRCALL_lj_prng_u64d, lj_ir_kptr(J, uddata(ud))); |
620 | one = lj_ir_knum_one(J); | 620 | one = lj_ir_knum_one(J); |
621 | tr = emitir(IRTN(IR_SUB), tr, one); | 621 | tr = emitir(IRTN(IR_SUB), tr, one); |
622 | if (J->base[0]) { | 622 | if (J->base[0]) { |
diff --git a/src/lj_ir.c b/src/lj_ir.c index 600e432c..b5e94eb8 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include "lj_vm.h" | 31 | #include "lj_vm.h" |
32 | #include "lj_strscan.h" | 32 | #include "lj_strscan.h" |
33 | #include "lj_strfmt.h" | 33 | #include "lj_strfmt.h" |
34 | #include "lj_lib.h" | 34 | #include "lj_prng.h" |
35 | 35 | ||
36 | /* Some local macros to save typing. Undef'd at the end. */ | 36 | /* Some local macros to save typing. Undef'd at the end. */ |
37 | #define IR(ref) (&J->cur.ir[(ref)]) | 37 | #define IR(ref) (&J->cur.ir[(ref)]) |
diff --git a/src/lj_ircall.h b/src/lj_ircall.h index dbc8c0db..58cebc5d 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
@@ -172,7 +172,7 @@ typedef struct CCallInfo { | |||
172 | _(ANY, lj_gc_step_jit, 2, FS, NIL, CCI_L) \ | 172 | _(ANY, lj_gc_step_jit, 2, FS, NIL, CCI_L) \ |
173 | _(ANY, lj_gc_barrieruv, 2, FS, NIL, 0) \ | 173 | _(ANY, lj_gc_barrieruv, 2, FS, NIL, 0) \ |
174 | _(ANY, lj_mem_newgco, 2, FS, PGC, CCI_L) \ | 174 | _(ANY, lj_mem_newgco, 2, FS, PGC, CCI_L) \ |
175 | _(ANY, lj_math_random_step, 1, FS, NUM, CCI_CASTU64) \ | 175 | _(ANY, lj_prng_u64d, 1, FS, NUM, CCI_CASTU64) \ |
176 | _(ANY, lj_vm_modi, 2, FN, INT, 0) \ | 176 | _(ANY, lj_vm_modi, 2, FN, INT, 0) \ |
177 | _(ANY, log10, 1, N, NUM, XA_FP) \ | 177 | _(ANY, log10, 1, N, NUM, XA_FP) \ |
178 | _(ANY, exp, 1, N, NUM, XA_FP) \ | 178 | _(ANY, exp, 1, N, NUM, XA_FP) \ |
diff --git a/src/lj_jit.h b/src/lj_jit.h index fa754b64..b0d90fcd 100644 --- a/src/lj_jit.h +++ b/src/lj_jit.h | |||
@@ -438,9 +438,9 @@ typedef struct jit_State { | |||
438 | int32_t framedepth; /* Current frame depth. */ | 438 | int32_t framedepth; /* Current frame depth. */ |
439 | int32_t retdepth; /* Return frame depth (count of RETF). */ | 439 | int32_t retdepth; /* Return frame depth (count of RETF). */ |
440 | 440 | ||
441 | uint32_t k32[LJ_K32__MAX]; /* Common 4 byte constants used by backends. */ | ||
441 | TValue ksimd[LJ_KSIMD__MAX*2+1]; /* 16 byte aligned SIMD constants. */ | 442 | TValue ksimd[LJ_KSIMD__MAX*2+1]; /* 16 byte aligned SIMD constants. */ |
442 | TValue k64[LJ_K64__MAX]; /* Common 8 byte constants used by backends. */ | 443 | TValue k64[LJ_K64__MAX]; /* Common 8 byte constants. */ |
443 | uint32_t k32[LJ_K32__MAX]; /* Ditto for 4 byte constants. */ | ||
444 | 444 | ||
445 | IRIns *irbuf; /* Temp. IR instruction buffer. Biased with REF_BIAS. */ | 445 | IRIns *irbuf; /* Temp. IR instruction buffer. Biased with REF_BIAS. */ |
446 | IRRef irtoplim; /* Upper limit of instuction buffer (biased). */ | 446 | IRRef irtoplim; /* Upper limit of instuction buffer (biased). */ |
@@ -472,7 +472,6 @@ typedef struct jit_State { | |||
472 | 472 | ||
473 | HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */ | 473 | HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */ |
474 | uint32_t penaltyslot; /* Round-robin index into penalty slots. */ | 474 | uint32_t penaltyslot; /* Round-robin index into penalty slots. */ |
475 | uint32_t prngstate; /* PRNG state. */ | ||
476 | 475 | ||
477 | #ifdef LUAJIT_ENABLE_TABLE_BUMP | 476 | #ifdef LUAJIT_ENABLE_TABLE_BUMP |
478 | RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */ | 477 | RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */ |
@@ -516,12 +515,4 @@ jit_State; | |||
516 | #define lj_assertJ(c, ...) ((void)J) | 515 | #define lj_assertJ(c, ...) ((void)J) |
517 | #endif | 516 | #endif |
518 | 517 | ||
519 | /* Trivial PRNG e.g. used for penalty randomization. */ | ||
520 | static LJ_AINLINE uint32_t LJ_PRNG_BITS(jit_State *J, int bits) | ||
521 | { | ||
522 | /* Yes, this LCG is very weak, but that doesn't matter for our use case. */ | ||
523 | J->prngstate = J->prngstate * 1103515245 + 12345; | ||
524 | return J->prngstate >> (32-bits); | ||
525 | } | ||
526 | |||
527 | #endif | 518 | #endif |
diff --git a/src/lj_lib.h b/src/lj_lib.h index 83778b83..496bdb2a 100644 --- a/src/lj_lib.h +++ b/src/lj_lib.h | |||
@@ -107,9 +107,4 @@ LJ_FUNC int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id, | |||
107 | #define LIBINIT_FFID 0xfe | 107 | #define LIBINIT_FFID 0xfe |
108 | #define LIBINIT_END 0xff | 108 | #define LIBINIT_END 0xff |
109 | 109 | ||
110 | /* Exported library functions. */ | ||
111 | |||
112 | typedef struct RandomState RandomState; | ||
113 | LJ_FUNC uint64_t LJ_FASTCALL lj_math_random_step(RandomState *rs); | ||
114 | |||
115 | #endif | 110 | #endif |
diff --git a/src/lj_mcode.c b/src/lj_mcode.c index e64c5878..b2d12118 100644 --- a/src/lj_mcode.c +++ b/src/lj_mcode.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include "lj_mcode.h" | 14 | #include "lj_mcode.h" |
15 | #include "lj_trace.h" | 15 | #include "lj_trace.h" |
16 | #include "lj_dispatch.h" | 16 | #include "lj_dispatch.h" |
17 | #include "lj_prng.h" | ||
17 | #endif | 18 | #endif |
18 | #if LJ_HASJIT || LJ_HASFFI | 19 | #if LJ_HASJIT || LJ_HASFFI |
19 | #include "lj_vm.h" | 20 | #include "lj_vm.h" |
@@ -118,52 +119,34 @@ static int mcode_setprot(void *p, size_t sz, int prot) | |||
118 | return mprotect(p, sz, prot); | 119 | return mprotect(p, sz, prot); |
119 | } | 120 | } |
120 | 121 | ||
121 | #elif LJ_64 | ||
122 | |||
123 | #error "Missing OS support for explicit placement of executable memory" | ||
124 | |||
125 | #else | 122 | #else |
126 | 123 | ||
127 | /* Fallback allocator. This will fail if memory is not executable by default. */ | 124 | #error "Missing OS support for explicit placement of executable memory" |
128 | #define LUAJIT_UNPROTECT_MCODE | ||
129 | #define MCPROT_RW 0 | ||
130 | #define MCPROT_RX 0 | ||
131 | #define MCPROT_RWX 0 | ||
132 | |||
133 | static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, int prot) | ||
134 | { | ||
135 | UNUSED(hint); UNUSED(prot); | ||
136 | return lj_mem_new(J->L, sz); | ||
137 | } | ||
138 | |||
139 | static void mcode_free(jit_State *J, void *p, size_t sz) | ||
140 | { | ||
141 | lj_mem_free(J2G(J), p, sz); | ||
142 | } | ||
143 | 125 | ||
144 | #endif | 126 | #endif |
145 | 127 | ||
146 | /* -- MCode area protection ----------------------------------------------- */ | 128 | /* -- MCode area protection ----------------------------------------------- */ |
147 | 129 | ||
148 | /* Define this ONLY if page protection twiddling becomes a bottleneck. */ | 130 | #if LUAJIT_SECURITY_MCODE == 0 |
149 | #ifdef LUAJIT_UNPROTECT_MCODE | ||
150 | 131 | ||
151 | /* It's generally considered to be a potential security risk to have | 132 | /* Define this ONLY if page protection twiddling becomes a bottleneck. |
133 | ** | ||
134 | ** It's generally considered to be a potential security risk to have | ||
152 | ** pages with simultaneous write *and* execute access in a process. | 135 | ** pages with simultaneous write *and* execute access in a process. |
153 | ** | 136 | ** |
154 | ** Do not even think about using this mode for server processes or | 137 | ** Do not even think about using this mode for server processes or |
155 | ** apps handling untrusted external data (such as a browser). | 138 | ** apps handling untrusted external data. |
156 | ** | 139 | ** |
157 | ** The security risk is not in LuaJIT itself -- but if an adversary finds | 140 | ** The security risk is not in LuaJIT itself -- but if an adversary finds |
158 | ** any *other* flaw in your C application logic, then any RWX memory page | 141 | ** any *other* flaw in your C application logic, then any RWX memory pages |
159 | ** simplifies writing an exploit considerably. | 142 | ** simplify writing an exploit considerably. |
160 | */ | 143 | */ |
161 | #define MCPROT_GEN MCPROT_RWX | 144 | #define MCPROT_GEN MCPROT_RWX |
162 | #define MCPROT_RUN MCPROT_RWX | 145 | #define MCPROT_RUN MCPROT_RWX |
163 | 146 | ||
164 | static void mcode_protect(jit_State *J, int prot) | 147 | static void mcode_protect(jit_State *J, int prot) |
165 | { | 148 | { |
166 | UNUSED(J); UNUSED(prot); | 149 | UNUSED(J); UNUSED(prot); UNUSED(mcode_setprot); |
167 | } | 150 | } |
168 | 151 | ||
169 | #else | 152 | #else |
@@ -242,7 +225,7 @@ static void *mcode_alloc(jit_State *J, size_t sz) | |||
242 | } | 225 | } |
243 | /* Next try probing 64K-aligned pseudo-random addresses. */ | 226 | /* Next try probing 64K-aligned pseudo-random addresses. */ |
244 | do { | 227 | do { |
245 | hint = LJ_PRNG_BITS(J, LJ_TARGET_JUMPRANGE-16) << 16; | 228 | hint = lj_prng_u64(&J2G(J)->prng) & ((1u<<LJ_TARGET_JUMPRANGE)-0x10000); |
246 | } while (!(hint + sz < range+range)); | 229 | } while (!(hint + sz < range+range)); |
247 | hint = target + hint - range; | 230 | hint = target + hint - range; |
248 | } | 231 | } |
@@ -331,7 +314,7 @@ void lj_mcode_abort(jit_State *J) | |||
331 | /* Set/reset protection to allow patching of MCode areas. */ | 314 | /* Set/reset protection to allow patching of MCode areas. */ |
332 | MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) | 315 | MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) |
333 | { | 316 | { |
334 | #ifdef LUAJIT_UNPROTECT_MCODE | 317 | #if LUAJIT_SECURITY_MCODE == 0 |
335 | UNUSED(J); UNUSED(ptr); UNUSED(finish); | 318 | UNUSED(J); UNUSED(ptr); UNUSED(finish); |
336 | return NULL; | 319 | return NULL; |
337 | #else | 320 | #else |
diff --git a/src/lj_obj.h b/src/lj_obj.h index c0ae6892..6c974812 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h | |||
@@ -620,6 +620,7 @@ typedef struct global_State { | |||
620 | GCRef cur_L; /* Currently executing lua_State. */ | 620 | GCRef cur_L; /* Currently executing lua_State. */ |
621 | MRef jit_base; /* Current JIT code L->base or NULL. */ | 621 | MRef jit_base; /* Current JIT code L->base or NULL. */ |
622 | MRef ctype_state; /* Pointer to C type state. */ | 622 | MRef ctype_state; /* Pointer to C type state. */ |
623 | PRNGState prng; /* Global PRNG state. */ | ||
623 | GCRef gcroot[GCROOT_MAX]; /* GC roots. */ | 624 | GCRef gcroot[GCROOT_MAX]; /* GC roots. */ |
624 | } global_State; | 625 | } global_State; |
625 | 626 | ||
diff --git a/src/lj_prng.c b/src/lj_prng.c new file mode 100644 index 00000000..62a6bbb7 --- /dev/null +++ b/src/lj_prng.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | ** Pseudo-random number generation. | ||
3 | ** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h | ||
4 | */ | ||
5 | |||
6 | #define lj_prng_c | ||
7 | #define LUA_CORE | ||
8 | |||
9 | /* To get the syscall prototype. */ | ||
10 | #if defined(__linux__) && !defined(_GNU_SOURCE) | ||
11 | #define _GNU_SOURCE | ||
12 | #endif | ||
13 | |||
14 | #include "lj_def.h" | ||
15 | #include "lj_arch.h" | ||
16 | #include "lj_prng.h" | ||
17 | |||
18 | /* -- PRNG step function -------------------------------------------------- */ | ||
19 | |||
20 | /* This implements a Tausworthe PRNG with period 2^223. Based on: | ||
21 | ** Tables of maximally-equidistributed combined LFSR generators, | ||
22 | ** Pierre L'Ecuyer, 1991, table 3, 1st entry. | ||
23 | ** Full-period ME-CF generator with L=64, J=4, k=223, N1=49. | ||
24 | ** | ||
25 | ** Important note: This PRNG is NOT suitable for cryptographic use! | ||
26 | ** | ||
27 | ** But it works fine for math.random(), which has an API that's not | ||
28 | ** suitable for cryptography, anyway. | ||
29 | ** | ||
30 | ** When used as a securely seeded global PRNG, it substantially raises | ||
31 | ** the difficulty for various attacks on the VM. | ||
32 | */ | ||
33 | |||
34 | /* Update generator i and compute a running xor of all states. */ | ||
35 | #define TW223_GEN(rs, z, r, i, k, q, s) \ | ||
36 | z = rs->u[i]; \ | ||
37 | z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \ | ||
38 | r ^= z; rs->u[i] = z; | ||
39 | |||
40 | #define TW223_STEP(rs, z, r) \ | ||
41 | TW223_GEN(rs, z, r, 0, 63, 31, 18) \ | ||
42 | TW223_GEN(rs, z, r, 1, 58, 19, 28) \ | ||
43 | TW223_GEN(rs, z, r, 2, 55, 24, 7) \ | ||
44 | TW223_GEN(rs, z, r, 3, 47, 21, 8) | ||
45 | |||
46 | /* PRNG step function with uint64_t result. */ | ||
47 | LJ_NOINLINE uint64_t LJ_FASTCALL lj_prng_u64(PRNGState *rs) | ||
48 | { | ||
49 | uint64_t z, r = 0; | ||
50 | TW223_STEP(rs, z, r) | ||
51 | return r; | ||
52 | } | ||
53 | |||
54 | /* PRNG step function with double in uint64_t result. */ | ||
55 | LJ_NOINLINE uint64_t LJ_FASTCALL lj_prng_u64d(PRNGState *rs) | ||
56 | { | ||
57 | uint64_t z, r = 0; | ||
58 | TW223_STEP(rs, z, r) | ||
59 | /* Returns a double bit pattern in the range 1.0 <= d < 2.0. */ | ||
60 | return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000); | ||
61 | } | ||
62 | |||
63 | /* Condition seed: ensure k[i] MSB of u[i] are non-zero. */ | ||
64 | static LJ_AINLINE void lj_prng_condition(PRNGState *rs) | ||
65 | { | ||
66 | if (rs->u[0] < (1u << 1)) rs->u[0] += (1u << 1); | ||
67 | if (rs->u[1] < (1u << 6)) rs->u[1] += (1u << 6); | ||
68 | if (rs->u[2] < (1u << 9)) rs->u[2] += (1u << 9); | ||
69 | if (rs->u[3] < (1u << 17)) rs->u[3] += (1u << 17); | ||
70 | } | ||
71 | |||
72 | /* -- PRNG seeding from OS ------------------------------------------------ */ | ||
73 | |||
74 | #if LUAJIT_SECURITY_PRNG == 0 | ||
75 | |||
76 | /* Nothing to define. */ | ||
77 | |||
78 | #elif LJ_TARGET_XBOX360 | ||
79 | |||
80 | extern int XNetRandom(void *buf, unsigned int len); | ||
81 | |||
82 | #elif LJ_TARGET_PS3 | ||
83 | |||
84 | extern int sys_get_random_number(void *buf, uint64_t len); | ||
85 | |||
86 | #elif LJ_TARGET_PS4 || LJ_TARGET_PSVITA | ||
87 | |||
88 | extern int sceRandomGetRandomNumber(void *buf, size_t len); | ||
89 | |||
90 | #elif LJ_TARGET_WINDOWS || LJ_TARGET_XBOXONE | ||
91 | |||
92 | #define WIN32_LEAN_AND_MEAN | ||
93 | #include <windows.h> | ||
94 | |||
95 | #if LJ_TARGET_UWP || LJ_TARGET_XBOXONE | ||
96 | /* Must use BCryptGenRandom. */ | ||
97 | #include <bcrypt.h> | ||
98 | #pragma comment(lib, "bcrypt.lib") | ||
99 | #else | ||
100 | /* If you wonder about this mess, then search online for RtlGenRandom. */ | ||
101 | typedef BOOLEAN (WINAPI *PRGR)(void *buf, ULONG len); | ||
102 | static PRGR libfunc_rgr; | ||
103 | #endif | ||
104 | |||
105 | #elif LJ_TARGET_POSIX | ||
106 | |||
107 | #if LJ_TARGET_LINUX | ||
108 | /* Avoid a dependency on glibc 2.25+ and use the getrandom syscall instead. */ | ||
109 | #include <sys/syscall.h> | ||
110 | #elif LJ_TARGET_OSX || LJ_TARGET_BSD || LJ_TARGET_SOLARIS || LJ_TARGET_CYGWIN | ||
111 | extern int getentropy(void *buf, size_t len); | ||
112 | #ifdef __ELF__ | ||
113 | __attribute__((weak)) | ||
114 | #endif | ||
115 | ; | ||
116 | #endif | ||
117 | |||
118 | /* For the /dev/urandom fallback. */ | ||
119 | #include <fcntl.h> | ||
120 | #include <unistd.h> | ||
121 | |||
122 | #endif | ||
123 | |||
124 | #if LUAJIT_SECURITY_PRNG == 0 | ||
125 | |||
126 | /* If you really don't care about security, then define | ||
127 | ** LUAJIT_SECURITY_PRNG=0. This yields a predictable seed | ||
128 | ** and provides NO SECURITY against various attacks on the VM. | ||
129 | ** | ||
130 | ** BTW: This is NOT the way to get predictable table iteration, | ||
131 | ** predictable trace generation, predictable bytecode generation, etc. | ||
132 | */ | ||
133 | int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs) | ||
134 | { | ||
135 | lj_prng_seed_fixed(rs); /* The fixed seed is already conditioned. */ | ||
136 | return 1; | ||
137 | } | ||
138 | |||
139 | #else | ||
140 | |||
141 | /* Securely seed PRNG from system entropy. Returns 0 on failure. */ | ||
142 | int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs) | ||
143 | { | ||
144 | #if LJ_TARGET_XBOX360 | ||
145 | |||
146 | if (XNetRandom(rs->u, (unsigned int)sizeof(rs->u)) == 0) | ||
147 | goto ok; | ||
148 | |||
149 | #elif LJ_TARGET_PS3 | ||
150 | |||
151 | if (sys_get_random_number(rs->u, sizeof(rs->u)) == 0) | ||
152 | goto ok; | ||
153 | |||
154 | #elif LJ_TARGET_PS4 || LJ_TARGET_PSVITA | ||
155 | |||
156 | if (sceRandomGetRandomNumber(rs->u, sizeof(rs->u) == 0) | ||
157 | goto ok; | ||
158 | |||
159 | #elif LJ_TARGET_UWP || LJ_TARGET_XBOXONE | ||
160 | |||
161 | if (BCryptGenRandom(NULL, (PUCHAR)(rs->u), (ULONG)sizeof(rs->u), | ||
162 | BCRYPT_USE_SYSTEM_PREFERRED_RNG) >= 0) | ||
163 | goto ok; | ||
164 | |||
165 | #elif LJ_TARGET_WINDOWS | ||
166 | |||
167 | /* Keep the library loaded in case multiple VMs are started. */ | ||
168 | if (!libfunc_rgr) { | ||
169 | HMODULE lib = LJ_WIN_LOADLIBA("advapi32.dll"); | ||
170 | if (!lib) return 0; | ||
171 | libfunc_rgr = (PRGR)GetProcAddress(lib, "SystemFunction036"); | ||
172 | if (!libfunc_rgr) return 0; | ||
173 | } | ||
174 | if (libfunc_rgr(rs->u, (ULONG)sizeof(rs->u))) | ||
175 | goto ok; | ||
176 | |||
177 | #elif LJ_TARGET_POSIX | ||
178 | |||
179 | #if LJ_TARGET_LINUX && defined(SYS_getrandom) | ||
180 | |||
181 | if (syscall(SYS_getrandom, rs->u, sizeof(rs->u), 0) == (long)sizeof(rs->u)) | ||
182 | goto ok; | ||
183 | |||
184 | #elif LJ_TARGET_OSX || LJ_TARGET_BSD || LJ_TARGET_SOLARIS || LJ_TARGET_CYGWIN | ||
185 | |||
186 | if ((!__ELF__ || getentropy) && getentropy(rs->u, sizeof(rs->u)) == 0) | ||
187 | goto ok; | ||
188 | |||
189 | #endif | ||
190 | |||
191 | /* Fallback to /dev/urandom. This may fail if the device is not | ||
192 | ** existent or accessible in a chroot or container, or if the process | ||
193 | ** or the OS ran out of file descriptors. | ||
194 | */ | ||
195 | { | ||
196 | int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC); | ||
197 | if (fd != -1) { | ||
198 | ssize_t n = read(fd, rs->u, sizeof(rs->u)); | ||
199 | (void)close(fd); | ||
200 | if (n == (ssize_t)sizeof(rs->u)) | ||
201 | goto ok; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | #else | ||
206 | |||
207 | /* Add an elif above for your OS with a secure PRNG seed. | ||
208 | ** Note that fiddling around with rand(), getpid(), time() or coercing | ||
209 | ** ASLR to yield a few bits of randomness is not helpful. | ||
210 | ** If you don't want any security, then don't pretend you have any | ||
211 | ** and simply define LUAJIT_SECURITY_PRNG=0 for the build. | ||
212 | */ | ||
213 | #error "Missing secure PRNG seed for this OS" | ||
214 | |||
215 | #endif | ||
216 | return 0; /* Fail. */ | ||
217 | |||
218 | ok: | ||
219 | lj_prng_condition(rs); | ||
220 | (void)lj_prng_u64(rs); | ||
221 | return 1; /* Success. */ | ||
222 | } | ||
223 | |||
224 | #endif | ||
225 | |||
diff --git a/src/lj_prng.h b/src/lj_prng.h new file mode 100644 index 00000000..40c34a71 --- /dev/null +++ b/src/lj_prng.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | ** Pseudo-random number generation. | ||
3 | ** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h | ||
4 | */ | ||
5 | |||
6 | #ifndef _LJ_PRNG_H | ||
7 | #define _LJ_PRNG_H | ||
8 | |||
9 | #include "lj_def.h" | ||
10 | |||
11 | LJ_FUNC int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs); | ||
12 | LJ_FUNC uint64_t LJ_FASTCALL lj_prng_u64(PRNGState *rs); | ||
13 | LJ_FUNC uint64_t LJ_FASTCALL lj_prng_u64d(PRNGState *rs); | ||
14 | |||
15 | /* This is just the precomputed result of lib_math.c:random_seed(rs, 0.0). */ | ||
16 | static LJ_AINLINE void lj_prng_seed_fixed(PRNGState *rs) | ||
17 | { | ||
18 | rs->u[0] = U64x(a0d27757,0a345b8c); | ||
19 | rs->u[1] = U64x(764a296c,5d4aa64f); | ||
20 | rs->u[2] = U64x(51220704,070adeaa); | ||
21 | rs->u[3] = U64x(2a2717b5,a7b7b927); | ||
22 | } | ||
23 | |||
24 | #endif | ||
diff --git a/src/lj_record.c b/src/lj_record.c index cfa48ecf..df428818 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "lj_snap.h" | 33 | #include "lj_snap.h" |
34 | #include "lj_dispatch.h" | 34 | #include "lj_dispatch.h" |
35 | #include "lj_vm.h" | 35 | #include "lj_vm.h" |
36 | #include "lj_prng.h" | ||
36 | 37 | ||
37 | /* Some local macros to save typing. Undef'd at the end. */ | 38 | /* Some local macros to save typing. Undef'd at the end. */ |
38 | #define IR(ref) (&J->cur.ir[(ref)]) | 39 | #define IR(ref) (&J->cur.ir[(ref)]) |
@@ -1696,7 +1697,7 @@ static void check_call_unroll(jit_State *J, TraceNo lnk) | |||
1696 | if (lnk) { /* Possible tail- or up-recursion. */ | 1697 | if (lnk) { /* Possible tail- or up-recursion. */ |
1697 | lj_trace_flush(J, lnk); /* Flush trace that only returns. */ | 1698 | lj_trace_flush(J, lnk); /* Flush trace that only returns. */ |
1698 | /* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */ | 1699 | /* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */ |
1699 | hotcount_set(J2GG(J), J->pc+1, LJ_PRNG_BITS(J, 4)); | 1700 | hotcount_set(J2GG(J), J->pc+1, lj_prng_u64(&J2G(J)->prng) & 15u); |
1700 | } | 1701 | } |
1701 | lj_trace_err(J, LJ_TRERR_CUNROLL); | 1702 | lj_trace_err(J, LJ_TRERR_CUNROLL); |
1702 | } | 1703 | } |
diff --git a/src/lj_state.c b/src/lj_state.c index 7081a474..a4d072be 100644 --- a/src/lj_state.c +++ b/src/lj_state.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "lj_trace.h" | 25 | #include "lj_trace.h" |
26 | #include "lj_dispatch.h" | 26 | #include "lj_dispatch.h" |
27 | #include "lj_vm.h" | 27 | #include "lj_vm.h" |
28 | #include "lj_prng.h" | ||
28 | #include "lj_lex.h" | 29 | #include "lj_lex.h" |
29 | #include "lj_alloc.h" | 30 | #include "lj_alloc.h" |
30 | #include "luajit.h" | 31 | #include "luajit.h" |
@@ -185,16 +186,33 @@ static void close_state(lua_State *L) | |||
185 | } | 186 | } |
186 | 187 | ||
187 | #if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC)) | 188 | #if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC)) |
188 | lua_State *lj_state_newstate(lua_Alloc f, void *ud) | 189 | lua_State *lj_state_newstate(lua_Alloc allocf, void *allocd) |
189 | #else | 190 | #else |
190 | LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) | 191 | LUA_API lua_State *lua_newstate(lua_Alloc allocf, void *allocd) |
191 | #endif | 192 | #endif |
192 | { | 193 | { |
193 | GG_State *GG = (GG_State *)f(ud, NULL, 0, sizeof(GG_State)); | 194 | PRNGState prng; |
194 | lua_State *L = &GG->L; | 195 | GG_State *GG; |
195 | global_State *g = &GG->g; | 196 | lua_State *L; |
197 | global_State *g; | ||
198 | /* We need the PRNG for the memory allocator, so initialize this first. */ | ||
199 | if (!lj_prng_seed_secure(&prng)) { | ||
200 | lj_assertX(0, "secure PRNG seeding failed"); | ||
201 | /* Can only return NULL here, so this errors with "not enough memory". */ | ||
202 | return NULL; | ||
203 | } | ||
204 | #ifndef LUAJIT_USE_SYSMALLOC | ||
205 | if (allocf == LJ_ALLOCF_INTERNAL) { | ||
206 | allocd = lj_alloc_create(&prng); | ||
207 | if (!allocd) return NULL; | ||
208 | allocf = lj_alloc_f; | ||
209 | } | ||
210 | #endif | ||
211 | GG = (GG_State *)allocf(allocd, NULL, 0, sizeof(GG_State)); | ||
196 | if (GG == NULL || !checkptrGC(GG)) return NULL; | 212 | if (GG == NULL || !checkptrGC(GG)) return NULL; |
197 | memset(GG, 0, sizeof(GG_State)); | 213 | memset(GG, 0, sizeof(GG_State)); |
214 | L = &GG->L; | ||
215 | g = &GG->g; | ||
198 | L->gct = ~LJ_TTHREAD; | 216 | L->gct = ~LJ_TTHREAD; |
199 | L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED; /* Prevent free. */ | 217 | L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED; /* Prevent free. */ |
200 | L->dummy_ffid = FF_C; | 218 | L->dummy_ffid = FF_C; |
@@ -202,8 +220,14 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) | |||
202 | g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED; | 220 | g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED; |
203 | g->strempty.marked = LJ_GC_WHITE0; | 221 | g->strempty.marked = LJ_GC_WHITE0; |
204 | g->strempty.gct = ~LJ_TSTR; | 222 | g->strempty.gct = ~LJ_TSTR; |
205 | g->allocf = f; | 223 | g->allocf = allocf; |
206 | g->allocd = ud; | 224 | g->allocd = allocd; |
225 | g->prng = prng; | ||
226 | #ifndef LUAJIT_USE_SYSMALLOC | ||
227 | if (allocf == lj_alloc_f) { | ||
228 | lj_alloc_setprng(allocd, &g->prng); | ||
229 | } | ||
230 | #endif | ||
207 | setgcref(g->mainthref, obj2gco(L)); | 231 | setgcref(g->mainthref, obj2gco(L)); |
208 | setgcref(g->uvhead.prev, obj2gco(&g->uvhead)); | 232 | setgcref(g->uvhead.prev, obj2gco(&g->uvhead)); |
209 | setgcref(g->uvhead.next, obj2gco(&g->uvhead)); | 233 | setgcref(g->uvhead.next, obj2gco(&g->uvhead)); |
diff --git a/src/lj_state.h b/src/lj_state.h index 9a8c7d93..50fe9000 100644 --- a/src/lj_state.h +++ b/src/lj_state.h | |||
@@ -32,4 +32,6 @@ LJ_FUNC void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L); | |||
32 | LJ_FUNC lua_State *lj_state_newstate(lua_Alloc f, void *ud); | 32 | LJ_FUNC lua_State *lj_state_newstate(lua_Alloc f, void *ud); |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #define LJ_ALLOCF_INTERNAL ((lua_Alloc)(void *)(uintptr_t)(1237<<4)) | ||
36 | |||
35 | #endif | 37 | #endif |
diff --git a/src/lj_trace.c b/src/lj_trace.c index c4e728c6..77e9d05b 100644 --- a/src/lj_trace.c +++ b/src/lj_trace.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "lj_vm.h" | 30 | #include "lj_vm.h" |
31 | #include "lj_vmevent.h" | 31 | #include "lj_vmevent.h" |
32 | #include "lj_target.h" | 32 | #include "lj_target.h" |
33 | #include "lj_prng.h" | ||
33 | 34 | ||
34 | /* -- Error handling ------------------------------------------------------ */ | 35 | /* -- Error handling ------------------------------------------------------ */ |
35 | 36 | ||
@@ -384,7 +385,7 @@ static void penalty_pc(jit_State *J, GCproto *pt, BCIns *pc, TraceError e) | |||
384 | if (mref(J->penalty[i].pc, const BCIns) == pc) { /* Cache slot found? */ | 385 | if (mref(J->penalty[i].pc, const BCIns) == pc) { /* Cache slot found? */ |
385 | /* First try to bump its hotcount several times. */ | 386 | /* First try to bump its hotcount several times. */ |
386 | val = ((uint32_t)J->penalty[i].val << 1) + | 387 | val = ((uint32_t)J->penalty[i].val << 1) + |
387 | LJ_PRNG_BITS(J, PENALTY_RNDBITS); | 388 | (lj_prng_u64(&J2G(J)->prng) & ((1u<<PENALTY_RNDBITS)-1)); |
388 | if (val > PENALTY_MAX) { | 389 | if (val > PENALTY_MAX) { |
389 | blacklist_pc(pt, pc); /* Blacklist it, if that didn't help. */ | 390 | blacklist_pc(pt, pc); /* Blacklist it, if that didn't help. */ |
390 | return; | 391 | return; |
diff --git a/src/ljamalg.c b/src/ljamalg.c index 19980241..56585e6d 100644 --- a/src/ljamalg.c +++ b/src/ljamalg.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "lj_udata.c" | 31 | #include "lj_udata.c" |
32 | #include "lj_meta.c" | 32 | #include "lj_meta.c" |
33 | #include "lj_debug.c" | 33 | #include "lj_debug.c" |
34 | #include "lj_prng.c" | ||
34 | #include "lj_state.c" | 35 | #include "lj_state.c" |
35 | #include "lj_dispatch.c" | 36 | #include "lj_dispatch.c" |
36 | #include "lj_vmevent.c" | 37 | #include "lj_vmevent.c" |