]> granicus.if.org Git - vim/commitdiff
patch 9.0.1015: without /dev/urandom srand() seed is too predictable v9.0.1015
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Mon, 5 Dec 2022 21:55:55 +0000 (21:55 +0000)
committerBram Moolenaar <Bram@vim.org>
Mon, 5 Dec 2022 21:55:55 +0000 (21:55 +0000)
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
src/testdir/test_random.vim
src/version.c

index 0b2ba00b6e14521195565f6555592a28250b55ec..428c4cb2b2c1fe267b901da603e46837a8e2646e 100644 (file)
@@ -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))))
index afb3044e7f2fa258e352ddd3356ce3e6b64af4e1..fdfaea2575992f9abd5cd5a37873bbfbf1bb695b 100644 (file)
@@ -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
index 9e4411eb69172a44f5f48d48edf2e4997d216219..a19d947653fb63995784aea942ff43ce61da2adc 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1015,
 /**/
     1014,
 /**/