From 2ff14bd80b4f64ac43fa36e35cd2d5e2b653f8b3 Mon Sep 17 00:00:00 2001 From: Julien Fischer Date: Sat, 13 Feb 2021 15:06:23 +1100 Subject: [PATCH] Implement the system RNG on Windows. On Windows we implement the system RNG by calling the CRT's rand_s() function. library/random.system_rng.m: Implement the system RNG on Windows using rand_s(). runtime/mercury_std.h: On Windows define the macro _CRT_RAND_S before the initial inclusion of stdlib.h -- we must do this otherwise the declaration of rand_s() will not be visible. --- library/random.system_rng.m | 59 ++++++++++++++++++++++++++++++++++++- runtime/mercury_std.h | 9 +++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/library/random.system_rng.m b/library/random.system_rng.m index 96dea968e..a8d084372 100644 --- a/library/random.system_rng.m +++ b/library/random.system_rng.m @@ -119,6 +119,9 @@ #include #include + +// On Windows we need to ensure that _CRT_RAND_S is defined before stdlib.h +// is included but this must be done in runtime/mercury_std.h. #include // The following macros define if the system random number exists on this @@ -136,7 +139,7 @@ // PRNG, such as ChaCha20; it should _not_ be enabled on systems where // arc4random() still uses RC4. // -// ML_SYSRAND_IMPL_RAND_S (NYI) +// ML_SYSRAND_IMPL_RAND_S // the system RNG is implemented by calling the rand_s() function // (Windows only). // @@ -169,6 +172,8 @@ #else #define ML_SYSRAND_IMPL_URANDOM #endif +#elif defined(MR_WIN32) + #define ML_SYSRAND_IMPL_RAND_S #else #define ML_SYSRAND_IMPL_NONE #endif @@ -675,6 +680,58 @@ ML_random_generate_bytes(ML_SystemRandomHandle handle, return MR_TRUE; } +#elif defined(ML_SYSRAND_IMPL_RAND_S) + +ML_SystemRandomHandle +ML_random_open(MR_Bool *succeeded, MR_String *err_msg) +{ + *succeeded = MR_TRUE; + *err_msg = MR_make_string_const(\"\"); + return 0; +} + +MR_Bool +ML_random_close(ML_SystemRandomHandle handle, MR_String *err_msg) +{ + *err_msg = MR_make_string_const(\"\"); + return MR_TRUE; +} + +MR_Bool +ML_random_generate_bytes(ML_SystemRandomHandle handle, + unsigned char *buffer, size_t len, MR_String *err_msg) +{ + int err; + unsigned int n; + size_t num_to_read = len; + + while (num_to_read > 0) { + if (num_to_read < 4) { + err = rand_s(&n); + if (err != 0) { + goto rand_s_failure_handler; + } + MR_memcpy(buffer, (unsigned char *) &n, num_to_read); + break; + } else { + err = rand_s((unsigned int *) buffer); + if (err != 0) { + goto rand_s_failure_handler; + } + num_to_read -= 4; + buffer += 4; + } + } + + *err_msg = MR_make_string_const(\"\"); + return MR_TRUE; + +rand_s_failure_handler: + + *err_msg = MR_make_string_const(\"rand_s failed\"); + return MR_FALSE; +} + #else // ML_SYSRAND_IMPL_NONE ML_SystemRandomHandle diff --git a/runtime/mercury_std.h b/runtime/mercury_std.h index e34d0df36..5cdb77434 100644 --- a/runtime/mercury_std.h +++ b/runtime/mercury_std.h @@ -1,7 +1,7 @@ // vim: ts=4 sw=4 expandtab ft=c // Copyright (C) 1993-1995, 1997-2005, 2011-2012 The University of Melbourne. -// Copyright (C) 2014, 2016-2018 The Mercury team. +// Copyright (C) 2014, 2016-2019, 2021 The Mercury team. // This file is distributed under the terms specified in COPYING.LIB. // std.h - "standard" [sic] definitions for C: @@ -22,7 +22,14 @@ #error "Mercury requires a system that provides stdint.h" #endif +// On Windows we need to define _CRT_RAND_S *before* stdlib.h is included, +// otherwise the declaration for rand_s() will not be visible. +// +#if defined(MR_WIN32) && !defined(_CRT_RAND_S) + #define _CRT_RAND_S +#endif #include // for size_t + #include // for assert() #include // for EINTR #include // for isalnum(), etc.