From 4cf66ae8e4341b02d45ddba9cf860c79e731b3fb Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 11 Apr 2015 01:25:55 -0400 Subject: [PATCH] roken: use Win32 rand_s() for rk_random() when available On Windows if the compiler and C RTL is >= 1400 then the rand_s() function is available. rand_s() unlike rand() makes use of the RtlGenRandom() API to produce a random number between 0 and UINT_MAX. If rand_s() is not available or fails, fallback to rand(). One of the benefits of rand_s() is that no initialization is required so it will provide random output even if rk_random_init() is not called. Change-Id: I2768155de744bd49604fc8237728bb205d637f2a --- lib/roken/rand.c | 30 ++++++++++++++++++++++++++++++ lib/roken/roken.h.in | 17 ++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/lib/roken/rand.c b/lib/roken/rand.c index ef92c2052..cfae5107e 100644 --- a/lib/roken/rand.c +++ b/lib/roken/rand.c @@ -33,6 +33,10 @@ #include "roken.h" +#ifdef HAVE_WIN32_RAND_S +static int hasRand_s = 1; +#endif + void ROKEN_LIB_FUNCTION rk_random_init(void) { @@ -43,6 +47,32 @@ rk_random_init(void) #elif defined(HAVE_RANDOM) srandom(time(NULL)); #else +# ifdef HAVE_WIN32_RAND_S + OSVERSIONINFO osInfo; + + osInfo.dwOSVersionInfoSize = sizeof(osInfo); + hasRand_s = + (GetVersionEx(&osInfo) + && ((osInfo.dwMajorVersion > 5) || + (osInfo.dwMajorVersion == 5) && (osInfo.dwMinorVersion >= 1))); +# endif srand (time(NULL)); #endif } + +#ifdef HAVE_WIN32_RAND_S +unsigned int ROKEN_LIB_FUNCTION +rk_random(void) +{ + if (hasRand_s) { + unsigned int n; + int code; + + code = rand_s(&n); + if (code == 0) + return n; + } + + return rand(); +} +#endif diff --git a/lib/roken/roken.h.in b/lib/roken/roken.h.in index 14034dc12..910c79a46 100644 --- a/lib/roken/roken.h.in +++ b/lib/roken/roken.h.in @@ -32,6 +32,12 @@ * SUCH DAMAGE. */ +#if defined(_WIN32) && _MSC_VER >= 1400 +/* _CRT_RAND_S must be defined before including stdlib.h */ +# define _CRT_RAND_S +# define HAVE_WIN32_RAND_S 1 +#endif + #include #include #include @@ -1187,11 +1193,16 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL memset_s(void *s, size_t smax, #endif #if defined(HAVE_ARC4RANDOM) -#define rk_random() arc4random() +# define rk_random() arc4random() #elif defined(HAVE_RANDOM) -#define rk_random() random() +# define rk_random() random() #else -#define rk_random() rand() +# ifdef HAVE_WIN32_RAND_S +ROKEN_LIB_FUNCTION unsigned int ROKEN_LIB_CALL +rk_random(void); +# else +# define rk_random() rand() +# endif #endif #ifndef HAVE_TDELETE