add a seeded random number generator so that sequences of random numbers can be easily reproduced (for https://github.com/mozilla/rust/issues/2379)
This commit is contained in:
committed by
Brian Anderson
parent
64130f1589
commit
c9f8ae02bc
@@ -32,46 +32,6 @@ align_to(T size, size_t alignment) {
|
||||
return x;
|
||||
}
|
||||
|
||||
// Initialization helper for ISAAC RNG
|
||||
|
||||
inline void
|
||||
isaac_init(rust_kernel *kernel, randctx *rctx)
|
||||
{
|
||||
memset(rctx, 0, sizeof(randctx));
|
||||
|
||||
char *rust_seed = kernel->env->rust_seed;
|
||||
if (rust_seed != NULL) {
|
||||
ub4 seed = (ub4) atoi(rust_seed);
|
||||
for (size_t i = 0; i < RANDSIZ; i ++) {
|
||||
memcpy(&rctx->randrsl[i], &seed, sizeof(ub4));
|
||||
seed = (seed + 0x7ed55d16) + (seed << 12);
|
||||
}
|
||||
} else {
|
||||
#ifdef __WIN32__
|
||||
HCRYPTPROV hProv;
|
||||
kernel->win32_require
|
||||
(_T("CryptAcquireContext"),
|
||||
CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
|
||||
kernel->win32_require
|
||||
(_T("CryptGenRandom"),
|
||||
CryptGenRandom(hProv, sizeof(rctx->randrsl),
|
||||
(BYTE*)(&rctx->randrsl)));
|
||||
kernel->win32_require
|
||||
(_T("CryptReleaseContext"),
|
||||
CryptReleaseContext(hProv, 0));
|
||||
#else
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
assert(fd > 0);
|
||||
assert(read(fd, (void*) &rctx->randrsl, sizeof(rctx->randrsl))
|
||||
== sizeof(rctx->randrsl));
|
||||
assert(close(fd) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
randinit(rctx, 1);
|
||||
}
|
||||
|
||||
// Interior vectors (rust-user-code level).
|
||||
|
||||
struct
|
||||
@@ -136,6 +96,53 @@ make_str_vec(rust_kernel* kernel, size_t nstrs, char **strs) {
|
||||
return v;
|
||||
}
|
||||
|
||||
// Initialization helpers for ISAAC RNG
|
||||
|
||||
inline void isaac_seed(uint8_t* dest)
|
||||
{
|
||||
size_t size = sizeof(ub4) * RANDSIZ;
|
||||
#ifdef __WIN32__
|
||||
HCRYPTPROV hProv;
|
||||
kernel->win32_require
|
||||
(_T("CryptAcquireContext"),
|
||||
CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT|CRYPT_SILENT));
|
||||
kernel->win32_require
|
||||
(_T("CryptGenRandom"), CryptGenRandom(hProv, size, (BYTE*) dest));
|
||||
kernel->win32_require
|
||||
(_T("CryptReleaseContext"), CryptReleaseContext(hProv, 0));
|
||||
#else
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
assert(fd > 0);
|
||||
assert(read(fd, dest, size) == (int) size);
|
||||
assert(close(fd) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
isaac_init(rust_kernel *kernel, randctx *rctx, rust_vec* user_seed)
|
||||
{
|
||||
memset(rctx, 0, sizeof(randctx));
|
||||
|
||||
char *env_seed = kernel->env->rust_seed;
|
||||
if (user_seed != NULL) {
|
||||
// ignore bytes after the required length
|
||||
size_t seed_len = user_seed->fill < sizeof(rctx->randrsl)
|
||||
? user_seed->fill : sizeof(rctx->randrsl);
|
||||
memcpy(&rctx->randrsl, user_seed->data, seed_len);
|
||||
} else if (env_seed != NULL) {
|
||||
ub4 seed = (ub4) atoi(env_seed);
|
||||
for (size_t i = 0; i < RANDSIZ; i ++) {
|
||||
memcpy(&rctx->randrsl[i], &seed, sizeof(ub4));
|
||||
seed = (seed + 0x7ed55d16) + (seed << 12);
|
||||
}
|
||||
} else {
|
||||
isaac_seed((uint8_t*) &rctx->randrsl);
|
||||
}
|
||||
|
||||
randinit(rctx, 1);
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: C++
|
||||
|
||||
Reference in New Issue
Block a user