Mercurial > vim
changeset 35513:6e98e7638914 v9.1.0518
patch 9.1.0518: initialize the random buffer can be improved
Commit: https://github.com/vim/vim/commit/9987fe8ca05e5d367fc54eb94a5a583138d2e1f8
Author: LemonBoy <thatlemon@gmail.com>
Date: Thu Jul 4 13:20:49 2024 +0200
patch 9.1.0518: initialize the random buffer can be improved
Problem: initialize the random buffer can be improved
Solution: refactor init_srand() function, move machine-specific parts to
os_mswin and os_unix, implement a fallback for Windows 10 and
later (LemonBoy)
closes: #15125
Signed-off-by: LemonBoy <thatlemon@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 04 Jul 2024 13:30:03 +0200 |
parents | 801bf95533b2 |
children | 399fa2081431 |
files | src/evalfunc.c src/os_mswin.c src/os_unix.c src/proto/os_mswin.pro src/proto/os_unix.pro src/version.c |
diffstat | 6 files changed, 95 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -9267,69 +9267,47 @@ f_test_srand_seed(typval_T *argvars, typ static void init_srand(UINT32_T *x) { -#ifndef MSWIN - static int dev_urandom_state = NOTDONE; // FAIL or OK once tried -#endif + struct { + union { + UINT32_T number; + char_u bytes[sizeof(UINT32_T)]; + } contents; + } buf; if (srand_seed_for_testing_is_used) { *x = srand_seed_for_testing; return; } -#ifndef MSWIN - if (dev_urandom_state != FAIL) - { - int fd = open("/dev/urandom", O_RDONLY); - struct { - union { - UINT32_T number; - char bytes[sizeof(UINT32_T)]; - } contents; - } buf; - - // Attempt reading /dev/urandom. - if (fd == -1) - dev_urandom_state = FAIL; - else - { - buf.contents.number = 0; - if (read(fd, buf.contents.bytes, sizeof(UINT32_T)) - != sizeof(UINT32_T)) - dev_urandom_state = FAIL; - else - { - dev_urandom_state = OK; - *x = buf.contents.number; - } - close(fd); - } - } - if (dev_urandom_state != OK) -#endif - { - // Reading /dev/urandom doesn't work, fall back to: - // - randombytes_random() - // - reltime() or time() - // - XOR with process ID + + if (mch_get_random(buf.contents.bytes, sizeof(buf.contents.bytes)) == OK) + { + *x = buf.contents.number; + return; + } + + // The system's random number generator doesn't work, fall back to: + // - randombytes_random() + // - reltime() or time() + // - XOR with process ID #if defined(FEAT_SODIUM) - if (crypt_sodium_init() >= 0) - *x = crypt_sodium_randombytes_random(); - else -#endif - { + if (crypt_sodium_init() >= 0) + *x = crypt_sodium_randombytes_random(); + else +#endif + { #if defined(FEAT_RELTIME) - proftime_T res; - profile_start(&res); + proftime_T res; + profile_start(&res); # if defined(MSWIN) - *x = (UINT32_T)res.LowPart; + *x = (UINT32_T)res.LowPart; # else - *x = (UINT32_T)res.tv_fsec; + *x = (UINT32_T)res.tv_fsec; # endif #else - *x = vim_time(); -#endif - *x ^= mch_get_pid(); - } + *x = vim_time(); +#endif + *x ^= mch_get_pid(); } }
--- a/src/os_mswin.c +++ b/src/os_mswin.c @@ -830,6 +830,40 @@ mch_icon_load(HANDLE *iconp) 0, mch_icon_load_cb, iconp); } +/* + * Fill the buffer 'buf' with 'len' random bytes. + * Returns FAIL if the OS PRNG is not available or something went wrong. + */ + int +mch_get_random(char_u *buf, int len) +{ + static int initialized = NOTDONE; + static HINSTANCE hInstLib; + static BOOL (WINAPI *pProcessPrng)(PUCHAR, ULONG); + + if (initialized == NOTDONE) + { + hInstLib = vimLoadLib("bcryptprimitives.dll"); + if (hInstLib != NULL) + pProcessPrng = (void *)GetProcAddress(hInstLib, "ProcessPrng"); + if (hInstLib == NULL || pProcessPrng == NULL) + { + FreeLibrary(hInstLib); + initialized = FAIL; + } + else + initialized = OK; + } + + if (initialized == FAIL) + return FAIL; + + // According to the documentation this call cannot fail. + pProcessPrng(buf, len); + + return OK; +} + int mch_libcall( char_u *libname,
--- a/src/os_unix.c +++ b/src/os_unix.c @@ -7722,6 +7722,34 @@ sig_sysmouse SIGDEFARG(sigarg) } #endif // FEAT_SYSMOUSE +/* + * Fill the buffer 'buf' with 'len' random bytes. + * Returns FAIL if the OS PRNG is not available or something went wrong. + */ + int +mch_get_random(char_u *buf, int len) +{ + static int dev_urandom_state = NOTDONE; + + if (dev_urandom_state == FAIL) + return FAIL; + + int fd = open("/dev/urandom", O_RDONLY); + + // Attempt reading /dev/urandom. + if (fd == -1) + dev_urandom_state = FAIL; + else if (read(fd, buf, len) == len) + dev_urandom_state = OK; + else + { + dev_urandom_state = FAIL; + close(fd); + } + + return dev_urandom_state; +} + #if defined(FEAT_LIBCALL) || defined(PROTO) typedef char_u * (*STRPROCSTR)(char_u *); typedef char_u * (*INTPROCSTR)(int);
--- a/src/proto/os_mswin.pro +++ b/src/proto/os_mswin.pro @@ -23,6 +23,7 @@ int mch_has_wildcard(char_u *p); int mch_chdir(char *path); int mch_icon_load(HANDLE *iconp); int mch_libcall(char_u *libname, char_u *funcname, char_u *argstring, int argint, char_u **string_result, int *number_result); +int mch_get_random(char_u *buf, int len); void DumpPutS(const char *psz); int mch_get_winpos(int *x, int *y); void mch_set_winpos(int x, int y);
--- a/src/proto/os_unix.pro +++ b/src/proto/os_unix.pro @@ -76,6 +76,7 @@ int mch_rename(const char *src, const ch int gpm_available(void); int gpm_enabled(void); int mch_libcall(char_u *libname, char_u *funcname, char_u *argstring, int argint, char_u **string_result, int *number_result); +int mch_get_random(char_u *buf, int len); void setup_term_clip(void); void start_xterm_trace(int button); void stop_xterm_trace(void);