2
0
Эх сурвалжийг харах

New function 'luaL_makeseed'

This function unifies code from 'lua_newstate', 'math.randomseed',
and 'table.sort' that tries to create a value with a minimum level
of randomness.
Roberto Ierusalimschy 2 жил өмнө
parent
commit
5a04f1851e
9 өөрчлөгдсөн 87 нэмэгдсэн , 86 устгасан
  1. 49 1
      lauxlib.c
  2. 2 0
      lauxlib.h
  3. 7 17
      lmathlib.c
  4. 2 33
      lstate.c
  5. 3 26
      ltablib.c
  6. 2 2
      ltests.c
  7. 2 1
      ltests.h
  8. 2 1
      lua.h
  9. 18 5
      manual/manual.of

+ 49 - 1
lauxlib.c

@@ -1091,8 +1091,56 @@ static void warnfon (void *ud, const char *message, int tocont) {
 }
 
 
+
+/*
+** A function to compute an unsigned int with some level of
+** randomness. Rely on Address Space Layout Randomization (if present),
+** current time, and clock.
+*/
+#if !defined(luai_makeseed)
+
+#include <time.h>
+
+
+/*
+** Size of 'e' measured in number of 'unsigned int's. (In the weird
+** case that the division truncates, we just lose some part of the
+** value, no big deal.)
+*/
+#define sof(e)          (sizeof(e) / sizeof(unsigned int))
+
+
+#define addbuff(b,v) \
+	(memcpy(b, &(v), sof(v) * sizeof(unsigned int)), b += sof(v))
+
+
+static unsigned int luai_makeseed (void) {
+  unsigned int buff[sof(void*) + sof(clock_t) + sof(time_t)];
+  unsigned int res;
+  unsigned int *b = buff;
+  clock_t c = clock();
+  time_t t = time(NULL);
+  void *h = buff;
+  addbuff(b, h);  /* local variable's address */
+  addbuff(b, c);  /* clock */
+  addbuff(b, t);  /* time */
+  res = buff[0];
+  for (b = buff + 1; b < buff + sof(buff); b++)
+    res += *b;
+  return res;
+}
+
+#endif
+
+
+LUALIB_API unsigned int luaL_makeseed (lua_State *L) {
+  (void)L;  /* unused */
+  return luai_makeseed();
+}
+
+
 LUALIB_API lua_State *luaL_newstate (void) {
-  lua_State *L = lua_newstate(l_alloc, NULL);
+  lua_State *L = lua_newstate(l_alloc, NULL, luai_makeseed());
   if (l_likely(L)) {
     lua_atpanic(L, &panic);
     lua_setwarnf(L, warnfoff, L);  /* default is warnings off */

+ 2 - 0
lauxlib.h

@@ -100,6 +100,8 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
 
 LUALIB_API lua_State *(luaL_newstate) (void);
 
+LUALIB_API unsigned int luaL_makeseed (lua_State *L);
+
 LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
 
 LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s,

+ 7 - 17
lmathlib.c

@@ -603,28 +603,18 @@ static void setseed (lua_State *L, Rand64 *state,
 }
 
 
-/*
-** Set a "random" seed. To get some randomness, use the current time
-** and the address of 'L' (in case the machine does address space layout
-** randomization).
-*/
-static void randseed (lua_State *L, RanState *state) {
-  lua_Unsigned seed1 = (lua_Unsigned)time(NULL);
-  lua_Unsigned seed2 = (lua_Unsigned)(size_t)L;
-  setseed(L, state->s, seed1, seed2);
-}
-
-
 static int math_randomseed (lua_State *L) {
   RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1));
+  lua_Unsigned n1, n2;
   if (lua_isnone(L, 1)) {
-    randseed(L, state);
+    n1 = luaL_makeseed(L);
+    n2 = I2UInt(state->s[0]);
   }
   else {
-    lua_Integer n1 = luaL_checkinteger(L, 1);
-    lua_Integer n2 = luaL_optinteger(L, 2, 0);
-    setseed(L, state->s, n1, n2);
+    n1 = luaL_checkinteger(L, 1);
+    n2 = luaL_optinteger(L, 2, 0);
   }
+  setseed(L, state->s, n1, n2);
   return 2;  /* return seeds */
 }
 
@@ -641,7 +631,7 @@ static const luaL_Reg randfuncs[] = {
 */
 static void setrandfunc (lua_State *L) {
   RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0);
-  randseed(L, state);  /* initialize with a "random" seed */
+  setseed(L, state->s, luaL_makeseed(L), 0);  /* initialize with random seed */
   lua_pop(L, 2);  /* remove pushed seeds */
   luaL_setfuncs(L, randfuncs, 1);
 }

+ 2 - 33
lstate.c

@@ -51,37 +51,6 @@ typedef struct LG {
 #define fromstate(L)	(cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
 
 
-/*
-** A macro to create a "random" seed when a state is created;
-** the seed is used to randomize string hashes.
-*/
-#if !defined(luai_makeseed)
-
-#include <time.h>
-
-/*
-** Compute an initial seed with some level of randomness.
-** Rely on Address Space Layout Randomization (if present) and
-** current time.
-*/
-#define addbuff(b,p,e) \
-  { size_t t = cast_sizet(e); \
-    memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
-
-static unsigned int luai_makeseed (lua_State *L) {
-  char buff[3 * sizeof(size_t)];
-  unsigned int h = cast_uint(time(NULL));
-  int p = 0;
-  addbuff(buff, p, L);  /* heap variable */
-  addbuff(buff, p, &h);  /* local variable */
-  addbuff(buff, p, &lua_newstate);  /* public function */
-  lua_assert(p == sizeof(buff));
-  return luaS_hash(buff, p, h);
-}
-
-#endif
-
-
 /*
 ** set GCdebt to a new value keeping the value (totalobjs + GCdebt)
 ** invariant (and avoiding underflows in 'totalobjs')
@@ -350,7 +319,7 @@ LUA_API int lua_resetthread (lua_State *L, lua_State *from) {
 }
 
 
-LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
+LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned int seed) {
   int i;
   lua_State *L;
   global_State *g;
@@ -370,7 +339,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
   g->warnf = NULL;
   g->ud_warn = NULL;
   g->mainthread = L;
-  g->seed = luai_makeseed(L);
+  g->seed = seed;
   g->gcstp = GCSTPGC;  /* no GC while building state */
   g->strt.size = g->strt.nuse = 0;
   g->strt.hash = NULL;

+ 3 - 26
ltablib.c

@@ -230,31 +230,8 @@ typedef unsigned int IdxT;
 ** of a partition. (If you don't want/need this "randomness", ~0 is a
 ** good choice.)
 */
-#if !defined(l_randomizePivot)		/* { */
-
-#include <time.h>
-
-/* size of 'e' measured in number of 'unsigned int's */
-#define sof(e)		(sizeof(e) / sizeof(unsigned int))
-
-/*
-** Use 'time' and 'clock' as sources of "randomness". Because we don't
-** know the types 'clock_t' and 'time_t', we cannot cast them to
-** anything without risking overflows. A safe way to use their values
-** is to copy them to an array of a known type and use the array values.
-*/
-static unsigned int l_randomizePivot (void) {
-  clock_t c = clock();
-  time_t t = time(NULL);
-  unsigned int buff[sof(c) + sof(t)];
-  unsigned int i, rnd = 0;
-  memcpy(buff, &c, sof(c) * sizeof(unsigned int));
-  memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int));
-  for (i = 0; i < sof(buff); i++)
-    rnd += buff[i];
-  return rnd;
-}
-
+#if !defined(l_randomizePivot)
+#define l_randomizePivot(L)	luaL_makeseed(L)
 #endif					/* } */
 
 
@@ -391,7 +368,7 @@ static void auxsort (lua_State *L, IdxT lo, IdxT up,
       up = p - 1;  /* tail call for [lo .. p - 1]  (lower interval) */
     }
     if ((up - lo) / 128 > n) /* partition too imbalanced? */
-      rnd = l_randomizePivot();  /* try a new randomization */
+      rnd = l_randomizePivot(L);  /* try a new randomization */
   }  /* tail call auxsort(L, lo, up, rnd) */
 }
 

+ 2 - 2
ltests.c

@@ -1159,7 +1159,7 @@ static int num2int (lua_State *L) {
 static int newstate (lua_State *L) {
   void *ud;
   lua_Alloc f = lua_getallocf(L, &ud);
-  lua_State *L1 = lua_newstate(f, ud);
+  lua_State *L1 = lua_newstate(f, ud, 0);
   if (L1) {
     lua_atpanic(L1, tpanic);
     lua_pushlightuserdata(L, L1);
@@ -1252,7 +1252,7 @@ static int checkpanic (lua_State *L) {
   lua_Alloc f = lua_getallocf(L, &ud);
   b.paniccode = luaL_optstring(L, 2, "");
   b.L = L;
-  L1 = lua_newstate(f, ud);  /* create new state */
+  L1 = lua_newstate(f, ud, 0);  /* create new state */
   if (L1 == NULL) {  /* error? */
     lua_pushnil(L);
     return 1;

+ 2 - 1
ltests.h

@@ -102,7 +102,8 @@ LUA_API void *debug_realloc (void *ud, void *block,
                              size_t osize, size_t nsize);
 
 #if defined(lua_c)
-#define luaL_newstate()		lua_newstate(debug_realloc, &l_memcontrol)
+#define luaL_newstate()  \
+	lua_newstate(debug_realloc, &l_memcontrol, luaL_makeseed(NULL))
 #define luai_openlibs(L)  \
   {  luaL_openlibs(L); \
      luaL_requiref(L, "T", luaB_opentests, 1); \

+ 2 - 1
lua.h

@@ -160,7 +160,8 @@ extern const char lua_ident[];
 /*
 ** state manipulation
 */
-LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
+LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud,
+                                   unsigned int seed);
 LUA_API void       (lua_close) (lua_State *L);
 LUA_API lua_State *(lua_newthread) (lua_State *L);
 LUA_API int        (lua_resetthread) (lua_State *L, lua_State *from);

+ 18 - 5
manual/manual.of

@@ -20,7 +20,7 @@ making it ideal for configuration, scripting,
 and rapid prototyping.
 
 Lua is implemented as a library, written in @emphx{clean C},
-the common subset of @N{Standard C} and C++.
+the common subset of C and C++.
 The Lua distribution includes a host program called @id{lua},
 which uses the Lua library to offer a complete,
 standalone Lua interpreter,
@@ -2957,7 +2957,7 @@ static void *l_alloc (void *ud, void *ptr, size_t osize,
     return realloc(ptr, nsize);
 }
 }
-Note that @N{Standard C} ensures
+Note that @N{ISO C} ensures
 that @T{free(NULL)} has no effect and that
 @T{realloc(NULL,size)} is equivalent to @T{malloc(size)}.
 
@@ -3644,7 +3644,8 @@ Other upvalues are initialized with @nil.
 
 }
 
-@APIEntry{lua_State *lua_newstate (lua_Alloc f, void *ud);|
+@APIEntry{lua_State *lua_newstate (lua_Alloc f, void *ud,
+                                   unsigned int seed);|
 @apii{0,0,-}
 
 Creates a new independent state and returns its main thread.
@@ -3655,6 +3656,8 @@ Lua will do all memory allocation for this state
 through this function @seeF{lua_Alloc}.
 The second argument, @id{ud}, is an opaque pointer that Lua
 passes to the allocator in every call.
+The third argument, @id{seed}, is a seed for the hashing of
+strings when they are used as table keys.
 
 }
 
@@ -5721,6 +5724,16 @@ it does not run it.
 
 }
 
+@APIEntry{unsigned int luaL_makeseed (lua_State *L);|
+@apii{0,0,-}
+
+Returns a value with a weak attempt for randomness.
+(It produces that value based on the current date and time,
+the current processor time, and the address of an internal variable,
+in case the machine has Address Space Layout Randomization.)
+
+}
+
 
 @APIEntry{void luaL_newlib (lua_State *L, const luaL_Reg l[]);|
 @apii{0,1,m}
@@ -6892,7 +6905,7 @@ including if necessary a path and an extension.
 @id{funcname} must be the exact name exported by the @N{C library}
 (which may depend on the @N{C compiler} and linker used).
 
-This function is not supported by @N{Standard C}.
+This function is not supported by @N{ISO C}.
 As such, it is only available on some platforms
 (Windows, Linux, Mac OS X, Solaris, BSD,
 plus other Unix systems that support the @id{dlfcn} standard).
@@ -8093,7 +8106,7 @@ different sequences of results each time the program runs.
 
 When called with at least one argument,
 the integer parameters @id{x} and @id{y} are
-joined into a 128-bit @emphx{seed} that
+joined into a @emphx{seed} that
 is used to reinitialize the pseudo-random generator;
 equal seeds produce equal sequences of numbers.
 The default for @id{y} is zero.