diff options
author | Ron Yorston <rmy@pobox.com> | 2023-01-11 08:13:53 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-01-11 08:13:53 +0000 |
commit | 67fb94dea61e74da032a8f0c51fbf216ec47dadb (patch) | |
tree | f832391ba28642e38fe848cd8e7684fdb3e85148 | |
parent | 6a61981e0480b8a469d9d4b84ea27a9ec1d2b8d9 (diff) | |
download | busybox-w32-67fb94dea61e74da032a8f0c51fbf216ec47dadb.tar.gz busybox-w32-67fb94dea61e74da032a8f0c51fbf216ec47dadb.tar.bz2 busybox-w32-67fb94dea61e74da032a8f0c51fbf216ec47dadb.zip |
awk: further improvements to randomness
POSIX requires that the awk srand() function uses the time of day
to seed the PRNG. The obvious implementation used in BusyBox does
exactly that, passing time(NULL) to srand(3).
When processes are started within a few seconds of one another their
seeds are very similar. Given the realtively poor quality of rand(3)
in some C runtimes this results in random number sequences that are
somewhat correlated.
Improve matters by using an integer hash on the seed, as recommended
here:
https://nullprogram.com/blog/2019/04/30/#the-wrong-places
Costs 48 bytes.
(GitHub issue #279)
-rw-r--r-- | editors/awk.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/editors/awk.c b/editors/awk.c index 342b93df9..cf9269c6f 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -2870,6 +2870,17 @@ static rstream *next_input_file(void) | |||
2870 | #undef files_happen | 2870 | #undef files_happen |
2871 | } | 2871 | } |
2872 | 2872 | ||
2873 | #if ENABLE_PLATFORM_MINGW32 | ||
2874 | static unsigned triple32(unsigned x) | ||
2875 | { | ||
2876 | x ^= x >> 17; x *= 0xed5ad4bb; | ||
2877 | x ^= x >> 11; x *= 0xac4c1b51; | ||
2878 | x ^= x >> 15; x *= 0x31848bab; | ||
2879 | x ^= x >> 14; | ||
2880 | return x; | ||
2881 | } | ||
2882 | #endif | ||
2883 | |||
2873 | /* | 2884 | /* |
2874 | * Evaluate node - the heart of the program. Supplied with subtree | 2885 | * Evaluate node - the heart of the program. Supplied with subtree |
2875 | * and "res" variable to assign the result to if we evaluate an expression. | 2886 | * and "res" variable to assign the result to if we evaluate an expression. |
@@ -3329,7 +3340,11 @@ static var *evaluate(node *op, var *res) | |||
3329 | case F_sr: | 3340 | case F_sr: |
3330 | R_d = (double)seed; | 3341 | R_d = (double)seed; |
3331 | seed = op1 ? (unsigned)L_d : (unsigned)time(NULL); | 3342 | seed = op1 ? (unsigned)L_d : (unsigned)time(NULL); |
3343 | #if ENABLE_PLATFORM_MINGW32 | ||
3344 | srand(seed == 1 ? 1 : triple32(seed)); | ||
3345 | #else | ||
3332 | srand(seed); | 3346 | srand(seed); |
3347 | #endif | ||
3333 | break; | 3348 | break; |
3334 | 3349 | ||
3335 | case F_ti: /*systime*/ | 3350 | case F_ti: /*systime*/ |