aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Dewar <seandewar@users.noreply.github.com>2022-01-09 23:53:55 +0000
committerSean Dewar <seandewar@users.noreply.github.com>2022-02-05 14:00:35 +0000
commitf6a0d5498b5f0d62e10f7ba891bc6ea5e20dad69 (patch)
tree0ac5ea1ed298c284653bc800bd1d630bd36912f1
parent22f0725aac300ed9b249f995df7889f6c203d1e0 (diff)
downloadrneovim-f6a0d5498b5f0d62e10f7ba891bc6ea5e20dad69.tar.gz
rneovim-f6a0d5498b5f0d62e10f7ba891bc6ea5e20dad69.tar.bz2
rneovim-f6a0d5498b5f0d62e10f7ba891bc6ea5e20dad69.zip
vim-patch:8.1.2343: using time() for srand() is not very random
Problem: Using time() for srand() is not very random. Solution: use /dev/urandom if available https://github.com/vim/vim/commit/07e4a197953d12902fb97beb48830a5323a52280 Use os_open and os_close. time_settime is N/A, so some parts of the test are disabled. There's maybe a very, very, very, very small chance the /dev/urandom test fails, but it shouldn't matter. :P
-rw-r--r--src/nvim/eval/funcs.c32
-rw-r--r--src/nvim/testdir/test_random.vim16
2 files changed, 42 insertions, 6 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 96d8c93db3..6a0803704d 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -10528,16 +10528,44 @@ static void f_stdpath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "srand()" function
static void f_srand(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
+ static int dev_urandom_state = -1; // FAIL or OK once tried
+
tv_list_alloc_ret(rettv, 4);
if (argvars[0].v_type == VAR_UNKNOWN) {
- tv_list_append_number(rettv->vval.v_list, (varnumber_T)time(NULL));
+ if (dev_urandom_state != FAIL) {
+ const int fd = os_open("/dev/urandom", O_RDONLY, 0);
+ 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;
+ tv_list_append_number(rettv->vval.v_list, (varnumber_T)buf.cont.number);
+ }
+ os_close(fd);
+ }
+ }
+ if (dev_urandom_state != OK) {
+ // Reading /dev/urandom doesn't work, fall back to time().
+ tv_list_append_number(rettv->vval.v_list, (varnumber_T)time(NULL));
+ }
} else {
bool error = false;
const uint32_t x = tv_get_number_chk(&argvars[0], &error);
if (error) {
return;
}
- tv_list_append_number(rettv->vval.v_list, x);
+ tv_list_append_number(rettv->vval.v_list, (varnumber_T)x);
}
tv_list_append_number(rettv->vval.v_list, 362436069);
tv_list_append_number(rettv->vval.v_list, 521288629);
diff --git a/src/nvim/testdir/test_random.vim b/src/nvim/testdir/test_random.vim
index bde034a96c..46091836d4 100644
--- a/src/nvim/testdir/test_random.vim
+++ b/src/nvim/testdir/test_random.vim
@@ -11,10 +11,16 @@ func Test_Rand()
" Nvim does not support test_settime
" call test_settime(12341234)
- " let s = srand()
- " call assert_equal(s, srand())
- " call test_settime(12341235)
- " call assert_notequal(s, srand())
+ let 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()
@@ -26,6 +32,8 @@ 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
" vim: shiftwidth=2 sts=2 expandtab