patch 9.1.0518: initialize the random buffer can be improved

Commit: 
https://github.com/vim/vim/commit/9987fe8ca05e5d367fc54eb94a5a583138d2e1f8
Author: LemonBoy <thatle...@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 <thatle...@gmail.com>
    Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/src/evalfunc.c b/src/evalfunc.c
index 4fffa50d3..d18d50a28 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -9267,69 +9267,47 @@ f_test_srand_seed(typval_T *argvars, typval_T *rettv 
UNUSED)
     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
+    if (mch_get_random(buf.contents.bytes, sizeof(buf.contents.bytes)) == OK)
     {
-       // Reading /dev/urandom doesn't work, fall back to:
-       // - randombytes_random()
-       // - reltime() or time()
-       // - XOR with process ID
+       *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
+    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();
+       *x = vim_time();
 #endif
-           *x ^= mch_get_pid();
-       }
+       *x ^= mch_get_pid();
     }
 }
 
diff --git a/src/os_mswin.c b/src/os_mswin.c
index 9d0e1a08a..df760fd5e 100644
--- 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,
diff --git a/src/os_unix.c b/src/os_unix.c
index d15514268..b7da55205 100644
--- 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);
diff --git a/src/proto/os_mswin.pro b/src/proto/os_mswin.pro
index 383dcbad1..cde9ceaee 100644
--- 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);
diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro
index 6e13de6ca..d9dc8d9d5 100644
--- a/src/proto/os_unix.pro
+++ b/src/proto/os_unix.pro
@@ -76,6 +76,7 @@ int mch_rename(const char *src, const char *dest);
 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);
diff --git a/src/version.c b/src/version.c
index c33303ab4..2391e5ba9 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    518,
 /**/
     517,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/E1sPKf5-0027lX-Fx%40256bit.org.

Raspunde prin e-mail lui