summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-11-26 12:23:30 +0100
committerBram Moolenaar <Bram@vim.org>2019-11-26 12:23:30 +0100
commit07e4a197953d12902fb97beb48830a5323a52280 (patch)
tree2606081e24020a6d9985531651099b0fc2aa3381
parent06b0b4bc27077013e9b4b48fd1d9b33e543ccf99 (diff)
patch 8.1.2343: using time() for srand() is not very randomv8.1.2343
Problem: Using time() for srand() is not very random. Solution: use /dev/urandom if available
-rw-r--r--src/evalfunc.c39
-rw-r--r--src/testdir/test_random.vim14
-rw-r--r--src/version.c2
3 files changed, 50 insertions, 5 deletions
diff --git a/src/evalfunc.c b/src/evalfunc.c
index a3e5b3e380..c6e4679e54 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -7095,10 +7095,45 @@ f_sqrt(typval_T *argvars, typval_T *rettv)
static void
f_srand(typval_T *argvars, typval_T *rettv)
{
+ static int dev_urandom_state = -1; // FAIL or OK once tried
+
if (rettv_list_alloc(rettv) == FAIL)
return;
if (argvars[0].v_type == VAR_UNKNOWN)
- list_append_number(rettv->vval.v_list, (varnumber_T)vim_time());
+ {
+ if (dev_urandom_state != FAIL)
+ {
+ int fd = open("/dev/urandom", O_RDONLY);
+ struct {
+ union {
+ UINT32_T number;
+ char bytes[sizeof(UINT32_T)];
+ } cont;
+ } buf;
+
+ // Attempt reading /dev/urandom.
+ if (fd == -1)
+ dev_urandom_state = FAIL;
+ else
+ {
+ buf.cont.number = 0;
+ if (read(fd, buf.cont.bytes, sizeof(UINT32_T))
+ != sizeof(UINT32_T))
+ dev_urandom_state = FAIL;
+ else
+ {
+ dev_urandom_state = OK;
+ list_append_number(rettv->vval.v_list,
+ (varnumber_T)buf.cont.number);
+ }
+ close(fd);
+ }
+
+ }
+ if (dev_urandom_state != OK)
+ // Reading /dev/urandom doesn't work, fall back to time().
+ list_append_number(rettv->vval.v_list, (varnumber_T)vim_time());
+ }
else
{
int error = FALSE;
@@ -7107,7 +7142,7 @@ f_srand(typval_T *argvars, typval_T *rettv)
if (error)
return;
- list_append_number(rettv->vval.v_list, x);
+ list_append_number(rettv->vval.v_list, (varnumber_T)x);
}
list_append_number(rettv->vval.v_list, 362436069);
list_append_number(rettv->vval.v_list, 521288629);
diff --git a/src/testdir/test_random.vim b/src/testdir/test_random.vim
index 381475a43f..9fe71a98c4 100644
--- a/src/testdir/test_random.vim
+++ b/src/testdir/test_random.vim
@@ -11,9 +11,15 @@ func Test_Rand()
call test_settime(12341234)
let s = srand()
- call assert_equal(s, srand())
- call test_settime(12341235)
- call assert_notequal(s, srand())
+ if filereadable('/dev/urandom')
+ " using /dev/urandom
+ call assert_notequal(s, srand())
+ else
+ " using time()
+ call assert_equal(s, srand())
+ call test_settime(12341235)
+ call assert_notequal(s, srand())
+ endif
call srand()
let v = rand()
@@ -25,4 +31,6 @@ func Test_Rand()
call assert_fails('echo rand([1, [2], 3, 4])', 'E475:')
call assert_fails('echo rand([1, 2, [3], 4])', 'E475:')
call assert_fails('echo rand([1, 2, 3, [4]])', 'E475:')
+
+ call test_settime(0)
endfunc
diff --git a/src/version.c b/src/version.c
index f88d0e9adc..9b8a02fac1 100644
--- a/src/version.c
+++ b/src/version.c
@@ -738,6 +738,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2343,
+/**/
2342,
/**/
2341,