From 5f1c956eb0239b15fc5ec5cebd4194dfb7b2a8ec Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Tue, 8 May 2012 20:38:00 +0000 Subject: [PATCH] [Support] Fix sys::GetRandomNumber() to always use a high quality seed. llvm-svn: 156414 --- llvm/lib/Support/Unix/Process.inc | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Support/Unix/Process.inc b/llvm/lib/Support/Unix/Process.inc index dd855b0d3ff8..4e1bd5db142c 100644 --- a/llvm/lib/Support/Unix/Process.inc +++ b/llvm/lib/Support/Unix/Process.inc @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "Unix.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/Support/TimeValue.h" #ifdef HAVE_SYS_TIME_H #include #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