aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lauxlib.c50
-rw-r--r--lauxlib.h2
-rw-r--r--lmathlib.c24
-rw-r--r--lstate.c35
-rw-r--r--ltablib.c29
-rw-r--r--ltests.c4
-rw-r--r--ltests.h3
-rw-r--r--lua.h3
-rw-r--r--manual/manual.of23
9 files changed, 87 insertions, 86 deletions
diff --git a/lauxlib.c b/lauxlib.c
index 4ca6c654..64b325d3 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1091,8 +1091,56 @@ static void warnfon (void *ud, const char *message, int tocont) {
1091} 1091}
1092 1092
1093 1093
1094
1095/*
1096** A function to compute an unsigned int with some level of
1097** randomness. Rely on Address Space Layout Randomization (if present),
1098** current time, and clock.
1099*/
1100#if !defined(luai_makeseed)
1101
1102#include <time.h>
1103
1104
1105/*
1106** Size of 'e' measured in number of 'unsigned int's. (In the weird
1107** case that the division truncates, we just lose some part of the
1108** value, no big deal.)
1109*/
1110#define sof(e) (sizeof(e) / sizeof(unsigned int))
1111
1112
1113#define addbuff(b,v) \
1114 (memcpy(b, &(v), sof(v) * sizeof(unsigned int)), b += sof(v))
1115
1116
1117static unsigned int luai_makeseed (void) {
1118 unsigned int buff[sof(void*) + sof(clock_t) + sof(time_t)];
1119 unsigned int res;
1120 unsigned int *b = buff;
1121 clock_t c = clock();
1122 time_t t = time(NULL);
1123 void *h = buff;
1124 addbuff(b, h); /* local variable's address */
1125 addbuff(b, c); /* clock */
1126 addbuff(b, t); /* time */
1127 res = buff[0];
1128 for (b = buff + 1; b < buff + sof(buff); b++)
1129 res += *b;
1130 return res;
1131}
1132
1133#endif
1134
1135
1136LUALIB_API unsigned int luaL_makeseed (lua_State *L) {
1137 (void)L; /* unused */
1138 return luai_makeseed();
1139}
1140
1141
1094LUALIB_API lua_State *luaL_newstate (void) { 1142LUALIB_API lua_State *luaL_newstate (void) {
1095 lua_State *L = lua_newstate(l_alloc, NULL); 1143 lua_State *L = lua_newstate(l_alloc, NULL, luai_makeseed());
1096 if (l_likely(L)) { 1144 if (l_likely(L)) {
1097 lua_atpanic(L, &panic); 1145 lua_atpanic(L, &panic);
1098 lua_setwarnf(L, warnfoff, L); /* default is warnings off */ 1146 lua_setwarnf(L, warnfoff, L); /* default is warnings off */
diff --git a/lauxlib.h b/lauxlib.h
index 5b977e2a..0ee9a572 100644
--- a/lauxlib.h
+++ b/lauxlib.h
@@ -100,6 +100,8 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
100 100
101LUALIB_API lua_State *(luaL_newstate) (void); 101LUALIB_API lua_State *(luaL_newstate) (void);
102 102
103LUALIB_API unsigned int luaL_makeseed (lua_State *L);
104
103LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); 105LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
104 106
105LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s, 107LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s,
diff --git a/lmathlib.c b/lmathlib.c
index d0b1e1e5..f13cae4a 100644
--- a/lmathlib.c
+++ b/lmathlib.c
@@ -603,28 +603,18 @@ static void setseed (lua_State *L, Rand64 *state,
603} 603}
604 604
605 605
606/*
607** Set a "random" seed. To get some randomness, use the current time
608** and the address of 'L' (in case the machine does address space layout
609** randomization).
610*/
611static void randseed (lua_State *L, RanState *state) {
612 lua_Unsigned seed1 = (lua_Unsigned)time(NULL);
613 lua_Unsigned seed2 = (lua_Unsigned)(size_t)L;
614 setseed(L, state->s, seed1, seed2);
615}
616
617
618static int math_randomseed (lua_State *L) { 606static int math_randomseed (lua_State *L) {
619 RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); 607 RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1));
608 lua_Unsigned n1, n2;
620 if (lua_isnone(L, 1)) { 609 if (lua_isnone(L, 1)) {
621 randseed(L, state); 610 n1 = luaL_makeseed(L);
611 n2 = I2UInt(state->s[0]);
622 } 612 }
623 else { 613 else {
624 lua_Integer n1 = luaL_checkinteger(L, 1); 614 n1 = luaL_checkinteger(L, 1);
625 lua_Integer n2 = luaL_optinteger(L, 2, 0); 615 n2 = luaL_optinteger(L, 2, 0);
626 setseed(L, state->s, n1, n2);
627 } 616 }
617 setseed(L, state->s, n1, n2);
628 return 2; /* return seeds */ 618 return 2; /* return seeds */
629} 619}
630 620
@@ -641,7 +631,7 @@ static const luaL_Reg randfuncs[] = {
641*/ 631*/
642static void setrandfunc (lua_State *L) { 632static void setrandfunc (lua_State *L) {
643 RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0); 633 RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0);
644 randseed(L, state); /* initialize with a "random" seed */ 634 setseed(L, state->s, luaL_makeseed(L), 0); /* initialize with random seed */
645 lua_pop(L, 2); /* remove pushed seeds */ 635 lua_pop(L, 2); /* remove pushed seeds */
646 luaL_setfuncs(L, randfuncs, 1); 636 luaL_setfuncs(L, randfuncs, 1);
647} 637}
diff --git a/lstate.c b/lstate.c
index bee3bf66..1ce6b9a1 100644
--- a/lstate.c
+++ b/lstate.c
@@ -52,37 +52,6 @@ typedef struct LG {
52 52
53 53
54/* 54/*
55** A macro to create a "random" seed when a state is created;
56** the seed is used to randomize string hashes.
57*/
58#if !defined(luai_makeseed)
59
60#include <time.h>
61
62/*
63** Compute an initial seed with some level of randomness.
64** Rely on Address Space Layout Randomization (if present) and
65** current time.
66*/
67#define addbuff(b,p,e) \
68 { size_t t = cast_sizet(e); \
69 memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
70
71static unsigned int luai_makeseed (lua_State *L) {
72 char buff[3 * sizeof(size_t)];
73 unsigned int h = cast_uint(time(NULL));
74 int p = 0;
75 addbuff(buff, p, L); /* heap variable */
76 addbuff(buff, p, &h); /* local variable */
77 addbuff(buff, p, &lua_newstate); /* public function */
78 lua_assert(p == sizeof(buff));
79 return luaS_hash(buff, p, h);
80}
81
82#endif
83
84
85/*
86** set GCdebt to a new value keeping the value (totalobjs + GCdebt) 55** set GCdebt to a new value keeping the value (totalobjs + GCdebt)
87** invariant (and avoiding underflows in 'totalobjs') 56** invariant (and avoiding underflows in 'totalobjs')
88*/ 57*/
@@ -350,7 +319,7 @@ LUA_API int lua_resetthread (lua_State *L, lua_State *from) {
350} 319}
351 320
352 321
353LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { 322LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned int seed) {
354 int i; 323 int i;
355 lua_State *L; 324 lua_State *L;
356 global_State *g; 325 global_State *g;
@@ -370,7 +339,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
370 g->warnf = NULL; 339 g->warnf = NULL;
371 g->ud_warn = NULL; 340 g->ud_warn = NULL;
372 g->mainthread = L; 341 g->mainthread = L;
373 g->seed = luai_makeseed(L); 342 g->seed = seed;
374 g->gcstp = GCSTPGC; /* no GC while building state */ 343 g->gcstp = GCSTPGC; /* no GC while building state */
375 g->strt.size = g->strt.nuse = 0; 344 g->strt.size = g->strt.nuse = 0;
376 g->strt.hash = NULL; 345 g->strt.hash = NULL;
diff --git a/ltablib.c b/ltablib.c
index e6bc4d04..82584459 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -230,31 +230,8 @@ typedef unsigned int IdxT;
230** of a partition. (If you don't want/need this "randomness", ~0 is a 230** of a partition. (If you don't want/need this "randomness", ~0 is a
231** good choice.) 231** good choice.)
232*/ 232*/
233#if !defined(l_randomizePivot) /* { */ 233#if !defined(l_randomizePivot)
234 234#define l_randomizePivot(L) luaL_makeseed(L)
235#include <time.h>
236
237/* size of 'e' measured in number of 'unsigned int's */
238#define sof(e) (sizeof(e) / sizeof(unsigned int))
239
240/*
241** Use 'time' and 'clock' as sources of "randomness". Because we don't
242** know the types 'clock_t' and 'time_t', we cannot cast them to
243** anything without risking overflows. A safe way to use their values
244** is to copy them to an array of a known type and use the array values.
245*/
246static unsigned int l_randomizePivot (void) {
247 clock_t c = clock();
248 time_t t = time(NULL);
249 unsigned int buff[sof(c) + sof(t)];
250 unsigned int i, rnd = 0;
251 memcpy(buff, &c, sof(c) * sizeof(unsigned int));
252 memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int));
253 for (i = 0; i < sof(buff); i++)
254 rnd += buff[i];
255 return rnd;
256}
257
258#endif /* } */ 235#endif /* } */
259 236
260 237
@@ -391,7 +368,7 @@ static void auxsort (lua_State *L, IdxT lo, IdxT up,
391 up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ 368 up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */
392 } 369 }
393 if ((up - lo) / 128 > n) /* partition too imbalanced? */ 370 if ((up - lo) / 128 > n) /* partition too imbalanced? */
394 rnd = l_randomizePivot(); /* try a new randomization */ 371 rnd = l_randomizePivot(L); /* try a new randomization */
395 } /* tail call auxsort(L, lo, up, rnd) */ 372 } /* tail call auxsort(L, lo, up, rnd) */
396} 373}
397 374
diff --git a/ltests.c b/ltests.c
index e2e0d983..456e83e1 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1159,7 +1159,7 @@ static int num2int (lua_State *L) {
1159static int newstate (lua_State *L) { 1159static int newstate (lua_State *L) {
1160 void *ud; 1160 void *ud;
1161 lua_Alloc f = lua_getallocf(L, &ud); 1161 lua_Alloc f = lua_getallocf(L, &ud);
1162 lua_State *L1 = lua_newstate(f, ud); 1162 lua_State *L1 = lua_newstate(f, ud, 0);
1163 if (L1) { 1163 if (L1) {
1164 lua_atpanic(L1, tpanic); 1164 lua_atpanic(L1, tpanic);
1165 lua_pushlightuserdata(L, L1); 1165 lua_pushlightuserdata(L, L1);
@@ -1252,7 +1252,7 @@ static int checkpanic (lua_State *L) {
1252 lua_Alloc f = lua_getallocf(L, &ud); 1252 lua_Alloc f = lua_getallocf(L, &ud);
1253 b.paniccode = luaL_optstring(L, 2, ""); 1253 b.paniccode = luaL_optstring(L, 2, "");
1254 b.L = L; 1254 b.L = L;
1255 L1 = lua_newstate(f, ud); /* create new state */ 1255 L1 = lua_newstate(f, ud, 0); /* create new state */
1256 if (L1 == NULL) { /* error? */ 1256 if (L1 == NULL) { /* error? */
1257 lua_pushnil(L); 1257 lua_pushnil(L);
1258 return 1; 1258 return 1;
diff --git a/ltests.h b/ltests.h
index 45d5beba..da773d6e 100644
--- a/ltests.h
+++ b/ltests.h
@@ -102,7 +102,8 @@ LUA_API void *debug_realloc (void *ud, void *block,
102 size_t osize, size_t nsize); 102 size_t osize, size_t nsize);
103 103
104#if defined(lua_c) 104#if defined(lua_c)
105#define luaL_newstate() lua_newstate(debug_realloc, &l_memcontrol) 105#define luaL_newstate() \
106 lua_newstate(debug_realloc, &l_memcontrol, luaL_makeseed(NULL))
106#define luai_openlibs(L) \ 107#define luai_openlibs(L) \
107 { luaL_openlibs(L); \ 108 { luaL_openlibs(L); \
108 luaL_requiref(L, "T", luaB_opentests, 1); \ 109 luaL_requiref(L, "T", luaB_opentests, 1); \
diff --git a/lua.h b/lua.h
index cb32ec22..e950dfb4 100644
--- a/lua.h
+++ b/lua.h
@@ -160,7 +160,8 @@ extern const char lua_ident[];
160/* 160/*
161** state manipulation 161** state manipulation
162*/ 162*/
163LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); 163LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud,
164 unsigned int seed);
164LUA_API void (lua_close) (lua_State *L); 165LUA_API void (lua_close) (lua_State *L);
165LUA_API lua_State *(lua_newthread) (lua_State *L); 166LUA_API lua_State *(lua_newthread) (lua_State *L);
166LUA_API int (lua_resetthread) (lua_State *L, lua_State *from); 167LUA_API int (lua_resetthread) (lua_State *L, lua_State *from);
diff --git a/manual/manual.of b/manual/manual.of
index 73d25951..fdae76f2 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -20,7 +20,7 @@ making it ideal for configuration, scripting,
20and rapid prototyping. 20and rapid prototyping.
21 21
22Lua is implemented as a library, written in @emphx{clean C}, 22Lua is implemented as a library, written in @emphx{clean C},
23the common subset of @N{Standard C} and C++. 23the common subset of C and C++.
24The Lua distribution includes a host program called @id{lua}, 24The Lua distribution includes a host program called @id{lua},
25which uses the Lua library to offer a complete, 25which uses the Lua library to offer a complete,
26standalone Lua interpreter, 26standalone Lua interpreter,
@@ -2957,7 +2957,7 @@ static void *l_alloc (void *ud, void *ptr, size_t osize,
2957 return realloc(ptr, nsize); 2957 return realloc(ptr, nsize);
2958} 2958}
2959} 2959}
2960Note that @N{Standard C} ensures 2960Note that @N{ISO C} ensures
2961that @T{free(NULL)} has no effect and that 2961that @T{free(NULL)} has no effect and that
2962@T{realloc(NULL,size)} is equivalent to @T{malloc(size)}. 2962@T{realloc(NULL,size)} is equivalent to @T{malloc(size)}.
2963 2963
@@ -3644,7 +3644,8 @@ Other upvalues are initialized with @nil.
3644 3644
3645} 3645}
3646 3646
3647@APIEntry{lua_State *lua_newstate (lua_Alloc f, void *ud);| 3647@APIEntry{lua_State *lua_newstate (lua_Alloc f, void *ud,
3648 unsigned int seed);|
3648@apii{0,0,-} 3649@apii{0,0,-}
3649 3650
3650Creates a new independent state and returns its main thread. 3651Creates a new independent state and returns its main thread.
@@ -3655,6 +3656,8 @@ Lua will do all memory allocation for this state
3655through this function @seeF{lua_Alloc}. 3656through this function @seeF{lua_Alloc}.
3656The second argument, @id{ud}, is an opaque pointer that Lua 3657The second argument, @id{ud}, is an opaque pointer that Lua
3657passes to the allocator in every call. 3658passes to the allocator in every call.
3659The third argument, @id{seed}, is a seed for the hashing of
3660strings when they are used as table keys.
3658 3661
3659} 3662}
3660 3663
@@ -5721,6 +5724,16 @@ it does not run it.
5721 5724
5722} 5725}
5723 5726
5727@APIEntry{unsigned int luaL_makeseed (lua_State *L);|
5728@apii{0,0,-}
5729
5730Returns a value with a weak attempt for randomness.
5731(It produces that value based on the current date and time,
5732the current processor time, and the address of an internal variable,
5733in case the machine has Address Space Layout Randomization.)
5734
5735}
5736
5724 5737
5725@APIEntry{void luaL_newlib (lua_State *L, const luaL_Reg l[]);| 5738@APIEntry{void luaL_newlib (lua_State *L, const luaL_Reg l[]);|
5726@apii{0,1,m} 5739@apii{0,1,m}
@@ -6892,7 +6905,7 @@ including if necessary a path and an extension.
6892@id{funcname} must be the exact name exported by the @N{C library} 6905@id{funcname} must be the exact name exported by the @N{C library}
6893(which may depend on the @N{C compiler} and linker used). 6906(which may depend on the @N{C compiler} and linker used).
6894 6907
6895This function is not supported by @N{Standard C}. 6908This function is not supported by @N{ISO C}.
6896As such, it is only available on some platforms 6909As such, it is only available on some platforms
6897(Windows, Linux, Mac OS X, Solaris, BSD, 6910(Windows, Linux, Mac OS X, Solaris, BSD,
6898plus other Unix systems that support the @id{dlfcn} standard). 6911plus other Unix systems that support the @id{dlfcn} standard).
@@ -8093,7 +8106,7 @@ different sequences of results each time the program runs.
8093 8106
8094When called with at least one argument, 8107When called with at least one argument,
8095the integer parameters @id{x} and @id{y} are 8108the integer parameters @id{x} and @id{y} are
8096joined into a 128-bit @emphx{seed} that 8109joined into a @emphx{seed} that
8097is used to reinitialize the pseudo-random generator; 8110is used to reinitialize the pseudo-random generator;
8098equal seeds produce equal sequences of numbers. 8111equal seeds produce equal sequences of numbers.
8099The default for @id{y} is zero. 8112The default for @id{y} is zero.