[Support] Fix sys::GetRandomNumber() to always use a high quality seed.
authorDaniel Dunbar <daniel@zuster.org>
Tue, 8 May 2012 20:38:00 +0000 (20:38 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Tue, 8 May 2012 20:38:00 +0000 (20:38 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156414 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/Unix/Process.inc

index dd855b0d3ff87e1c8f1b15f9b66fc4b7785ad349..4e1bd5db142cdc6c2856ddec5d9e14896c971f05 100644 (file)
@@ -12,6 +12,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "Unix.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/TimeValue.h"
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
@@ -300,13 +302,21 @@ const char *Process::ResetColor() {
 
 #if !defined(HAVE_ARC4RANDOM)
 static unsigned GetRandomNumberSeed() {
-  unsigned seed = ::time(NULL); // FIXME: It might not provide unique seed.
-  FILE *RandomSource = ::fopen("/dev/urandom", "r");
-  if (RandomSource) {
-    ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
+  // Attempt to get the initial seed from /dev/urandom, if possible.
+  if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) {
+    unsigned seed;
+    int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource);
     ::fclose(RandomSource);
+
+    // Return the seed if the read was successful.
+    if (count == 1)
+      return seed;
   }
-  return seed;
+
+  // Otherwise, swizzle the current time and the process ID to form a reasonable
+  // seed.
+  TimeValue Now = llvm::TimeValue::now();
+  return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid());
 }
 #endif