From f0a9c004825ab686270ee57260652cce25e61049 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Mon, 5 Dec 2022 21:55:55 +0000 Subject: [PATCH] patch 9.0.1015: without /dev/urandom srand() seed is too predictable Problem: Without /dev/urandom srand() seed is too predictable. Solution: Use micro seconds and XOR with process ID. (Yasuhiro Matsumoto, closes #11656) --- src/evalfunc.c | 27 +++++++++++++++++++++++++-- src/testdir/test_random.vim | 19 +++++++++++++++++++ src/version.c | 2 ++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/evalfunc.c b/src/evalfunc.c index 0b2ba00b6..428c4cb2b 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -8159,9 +8159,32 @@ init_srand(UINT32_T *x) } } if (dev_urandom_state != OK) - // Reading /dev/urandom doesn't work, fall back to time(). #endif - *x = vim_time(); + { + // Reading /dev/urandom doesn't work, fall back to: + // - randombytes_random() + // - reltime() or time() + // - XOR with process ID +#if defined(FEAT_SODIUM) + if (sodium_init() >= 0) + *x = randombytes_random(); + else +#endif + { +#if defined(FEAT_RELTIME) + proftime_T res; + profile_start(&res); +# if defined(MSWIN) + *x = (UINT32_T)res.LowPart; +# else + *x = (UINT32_T)res.tv_usec; +# endif +#else + *x = vim_time(); +#endif + *x ^= mch_get_pid(); + } + } } #define ROTL(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) diff --git a/src/testdir/test_random.vim b/src/testdir/test_random.vim index afb3044e7..fdfaea257 100644 --- a/src/testdir/test_random.vim +++ b/src/testdir/test_random.vim @@ -1,5 +1,8 @@ " Tests for srand() and rand() +source check.vim +source shared.vim + func Test_Rand() let r = srand(123456789) call assert_equal([1573771921, 319883699, 2742014374, 1324369493], r) @@ -44,4 +47,20 @@ func Test_issue_5587() call rand() endfunc +func Test_srand() + CheckNotGui + + let cmd = GetVimCommand() .. ' -V -es -c "echo rand()" -c qa!' + let bad = 0 + for _ in range(10) + echo cmd + let result1 = system(cmd) + let result2 = system(cmd) + if result1 ==# result2 + let bad += 1 + endif + endfor + call assert_inrange(0, 4, bad) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c index 9e4411eb6..a19d94765 100644 --- a/src/version.c +++ b/src/version.c @@ -695,6 +695,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1015, /**/ 1014, /**/ -- 2.40.0