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
This commit is contained in:
Jeffrey Altman
2015-04-11 01:25:55 -04:00
parent 0de18bdb5f
commit 4cf66ae8e4
2 changed files with 44 additions and 3 deletions

View File

@@ -33,6 +33,10 @@
#include "roken.h" #include "roken.h"
#ifdef HAVE_WIN32_RAND_S
static int hasRand_s = 1;
#endif
void ROKEN_LIB_FUNCTION void ROKEN_LIB_FUNCTION
rk_random_init(void) rk_random_init(void)
{ {
@@ -43,6 +47,32 @@ rk_random_init(void)
#elif defined(HAVE_RANDOM) #elif defined(HAVE_RANDOM)
srandom(time(NULL)); srandom(time(NULL));
#else #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)); srand (time(NULL));
#endif #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

View File

@@ -32,6 +32,12 @@
* SUCH DAMAGE. * 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 <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
@@ -1187,11 +1193,16 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL memset_s(void *s, size_t smax,
#endif #endif
#if defined(HAVE_ARC4RANDOM) #if defined(HAVE_ARC4RANDOM)
#define rk_random() arc4random() # define rk_random() arc4random()
#elif defined(HAVE_RANDOM) #elif defined(HAVE_RANDOM)
#define rk_random() random() # define rk_random() random()
#else #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 #endif
#ifndef HAVE_TDELETE #ifndef HAVE_TDELETE