mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-12-10 18:43:42 +01:00
grand: Port /dev/urandom code from fread() to read()
Error handling in `fread()` is too complex, and the code explicitly disables the buffering feature of `FILE`, so there’s little point in using it. Instead, use `open()`/`read()` directly. This avoids any buffering issues, and gives us use of `errno` to check errors. `ferror()` doesn’t give us any more information than “there was an error”. This fixes an issue flagged by scan-build: that a failure in the first `fread()` loop iteration would leave the `FILE` in an undefined state (in particular, an undefined seek position) which would mess up the next iteration. Since `ferror()` couldn’t actually tell us what the error was (was it `EINTR`?) and `errno` is not guaranteed to be set by `fread()`, the whole approach was doomed. Signed-off-by: Philip Withnall <pwithnall@gnome.org>
This commit is contained in:
25
glib/grand.c
25
glib/grand.c
@@ -55,6 +55,7 @@
|
||||
#include "gtimer.h"
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
@@ -176,30 +177,24 @@ g_rand_new (void)
|
||||
|
||||
if (dev_urandom_exists)
|
||||
{
|
||||
FILE* dev_urandom;
|
||||
int dev_urandom;
|
||||
|
||||
do
|
||||
{
|
||||
dev_urandom = g_fopen ("/dev/urandom", "rbe");
|
||||
}
|
||||
while G_UNLIKELY (dev_urandom == NULL && errno == EINTR);
|
||||
dev_urandom = g_open ("/dev/urandom", O_RDONLY | O_CLOEXEC);
|
||||
while G_UNLIKELY (dev_urandom < 0 && errno == EINTR);
|
||||
|
||||
if (dev_urandom)
|
||||
if (dev_urandom >= 0)
|
||||
{
|
||||
size_t r;
|
||||
ssize_t r;
|
||||
|
||||
setvbuf (dev_urandom, NULL, _IONBF, 0);
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
r = fread (seed, sizeof (seed), 1, dev_urandom);
|
||||
}
|
||||
while G_UNLIKELY (r != 1 && errno == EINTR);
|
||||
r = read (dev_urandom, seed, sizeof (seed));
|
||||
while G_UNLIKELY (r < 0 && errno == EINTR);
|
||||
|
||||
if (r != 1)
|
||||
if (r != sizeof (seed))
|
||||
dev_urandom_exists = FALSE;
|
||||
|
||||
fclose (dev_urandom);
|
||||
close (dev_urandom);
|
||||
}
|
||||
else
|
||||
dev_urandom_exists = FALSE;
|
||||
|
||||
Reference in New Issue
Block a user