Bug 1206596: Make random_generateSeed visible, and let it generate wider seeds. r=fitzgen
authorJim Blandy <jimb@mozilla.com>
Wed, 16 Sep 2015 21:46:54 -0700
changeset 267007 2a4b512df31d589ff52000cd172be8eb8cf17851
parent 267006 08ad86045731a2668b20541ca7d388d5968a4371
child 267008 df0f9214b22402bd7badcd4d3547da1e3bf7ff5a
push id29504
push usercbook@mozilla.com
push dateFri, 09 Oct 2015 09:43:23 +0000
treeherdermozilla-central@d01dd42e654b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfitzgen
bugs1206596
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1206596: Make random_generateSeed visible, and let it generate wider seeds. r=fitzgen
js/src/jsmath.cpp
js/src/jsmath.h
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -729,25 +729,21 @@ js::math_pow_handle(JSContext* cx, Handl
 bool
 js::math_pow(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     return math_pow_handle(cx, args.get(0), args.get(1), args.rval());
 }
 
-static uint64_t
-random_generateSeed()
+void
+js::random_generateSeed(uint64_t* seedBuffer, size_t length)
 {
-    union {
-        uint8_t     u8[8];
-        uint32_t    u32[2];
-        uint64_t    u64;
-    } seed;
-    seed.u64 = 0;
+    if (length == 0)
+        return;
 
 #if defined(XP_WIN)
     /*
      * Temporary diagnostic for bug 1167248: Test whether the injected hooks
      * react differently to LoadLibraryW / LoadLibraryExW.
      */
     HMODULE oldWay = LoadLibraryW(L"ADVAPI32.DLL");
     HMODULE newWay = LoadLibraryExW(L"ADVAPI32.DLL",
@@ -755,55 +751,82 @@ random_generateSeed()
                                     LOAD_LIBRARY_SEARCH_SYSTEM32);
     /* Fallback for older versions of Windows */
     if (!newWay && GetLastError() == ERROR_INVALID_PARAMETER)
         newWay = LoadLibraryExW(L"ADVAPI32.DLL", nullptr, 0);
 
     if (oldWay && !newWay)
         MOZ_CRASH();
 
+    union {
+        uint32_t    u32[2];
+        uint64_t    u64;
+    } seed;
+    seed.u64 = 0;
+
     errno_t error = rand_s(&seed.u32[0]);
 
     if (oldWay)
         FreeLibrary(oldWay);
     if (newWay)
         FreeLibrary(newWay);
 
     MOZ_ASSERT(error == 0, "rand_s() error?!");
 
     error = rand_s(&seed.u32[1]);
     MOZ_ASSERT(error == 0, "rand_s() error?!");
+
+    seedBuffer[0] = seed.u64 ^= PRMJ_Now();
+    for (size_t i = 1; i < length; i++) {
+        error = rand_s(&seed.u32[0]);
+        MOZ_ASSERT(error == 0, "rand_s() error?!");
+
+        error = rand_s(&seed.u32[1]);
+        MOZ_ASSERT(error == 0, "rand_s() error?!");
+
+        seedBuffer[i] = seed.u64 ^ PRMJ_Now();
+    }
+
 #elif defined(HAVE_ARC4RANDOM)
-    seed.u32[0] = arc4random();
-    seed.u32[1] = arc4random();
+    union {
+        uint32_t    u32[2];
+        uint64_t    u64;
+    } seed;
+    seed.u64 = 0;
+
+    for (size_t i = 0; i < length; i++) {
+        seed.u32[0] = arc4random();
+        seed.u32[1] = arc4random();
+        seedBuffer[i] = seed.u64 ^ PRMJ_Now();
+    }
+
 #elif defined(XP_UNIX)
     int fd = open("/dev/urandom", O_RDONLY);
     MOZ_ASSERT(fd >= 0, "Can't open /dev/urandom?!");
     if (fd >= 0) {
-        ssize_t nread = read(fd, seed.u8, mozilla::ArrayLength(seed.u8));
-        MOZ_ASSERT(nread == 8, "Can't read /dev/urandom?!");
+        ssize_t size = length * sizeof(seedBuffer[0]);
+        ssize_t nread = read(fd, (char *) seedBuffer, size);
+        MOZ_ASSERT(nread == size, "Can't read /dev/urandom?!");
         mozilla::unused << nread;
         close(fd);
     }
 #else
 # error "Platform needs to implement random_generateSeed()"
 #endif
-
-    seed.u64 ^= PRMJ_Now();
-    return seed.u64;
 }
 
 /*
  * Math.random() support, lifted from java.util.Random.java.
  */
 void
 js::random_initState(uint64_t* rngState)
 {
     /* Our PRNG only uses 48 bits, so squeeze our entropy into those bits. */
-    uint64_t seed = random_generateSeed();
+    uint64_t seed;
+    random_generateSeed(&seed, 1);
     seed ^= (seed >> 16);
     *rngState = (seed ^ RNG_MULTIPLIER) & RNG_MASK;
 }
 
 uint64_t
 js::random_next(uint64_t* rngState, int bits)
 {
     MOZ_ASSERT((*rngState & 0xffff000000000000ULL) == 0, "Bad rngState");
--- a/js/src/jsmath.h
+++ b/js/src/jsmath.h
@@ -104,16 +104,23 @@ class MathCache
 
 /*
  * JS math functions.
  */
 
 extern JSObject*
 InitMathClass(JSContext* cx, HandleObject obj);
 
+/*
+ * Fill |seed[0]| through |seed[length-1]| with random bits, suitable for
+ * seeding a random number generator.
+ */
+extern void
+random_generateSeed(uint64_t* seed, size_t length);
+
 extern void
 random_initState(uint64_t* rngState);
 
 extern uint64_t
 random_next(uint64_t* rngState, int bits);
 
 static const double RNG_DSCALE = double(1LL << 53);
 static const int RNG_STATE_WIDTH = 48;