changeset 31363:0608de106485 v9.0.1015

patch 9.0.1015: without /dev/urandom srand() seed is too predictable Commit: https://github.com/vim/vim/commit/f0a9c004825ab686270ee57260652cce25e61049 Author: Yasuhiro Matsumoto <mattn.jp@gmail.com> Date: Mon Dec 5 21:55:55 2022 +0000 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)
author Bram Moolenaar <Bram@vim.org>
date Mon, 05 Dec 2022 23:00:05 +0100
parents 7fc63cd1c462
children ba81163e2223
files src/evalfunc.c src/testdir/test_random.vim src/version.c
diffstat 3 files changed, 47 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- 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();
+#endif
+    {
+	// 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))))
--- 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
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1015,
+/**/
     1014,
 /**/
     1013,