summaryrefslogtreecommitdiffstats
path: root/src/evalfunc.c
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 /src/evalfunc.c
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
Diffstat (limited to 'src/evalfunc.c')
-rw-r--r--src/evalfunc.c39
1 files changed, 37 insertions, 2 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);