aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2023-01-11 08:13:53 +0000
committerRon Yorston <rmy@pobox.com>2023-01-11 08:13:53 +0000
commit67fb94dea61e74da032a8f0c51fbf216ec47dadb (patch)
treef832391ba28642e38fe848cd8e7684fdb3e85148
parent6a61981e0480b8a469d9d4b84ea27a9ec1d2b8d9 (diff)
downloadbusybox-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.c15
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
2874static 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*/