| Index: nss/lib/freebl/unix_rand.c
|
| ===================================================================
|
| --- nss/lib/freebl/unix_rand.c (revision 239365)
|
| +++ nss/lib/freebl/unix_rand.c (working copy)
|
| @@ -970,7 +970,8 @@
|
| size_t RNG_FileUpdate(const char *fileName, size_t limit)
|
| {
|
| FILE * file;
|
| - size_t bytes;
|
| + int fd;
|
| + int bytes;
|
| size_t fileBytes = 0;
|
| struct stat stat_buf;
|
| unsigned char buffer[BUFSIZ];
|
| @@ -983,12 +984,22 @@
|
| return fileBytes;
|
| RNG_RandomUpdate(&stat_buf, sizeof(stat_buf));
|
|
|
| - file = fopen((char *)fileName, "r");
|
| + file = fopen(fileName, "r");
|
| if (file != NULL) {
|
| + /* Read from the underlying file descriptor directly to bypass stdio
|
| + * buffering and avoid reading more bytes than we need from
|
| + * /dev/urandom. NOTE: we can't use fread with unbuffered I/O because
|
| + * fread may return EOF in unbuffered I/O mode on Android.
|
| + *
|
| + * Moreover, we read into a buffer of size BUFSIZ, so buffered I/O
|
| + * has no performance advantage. */
|
| + fd = fileno(file);
|
| + /* 'file' was just opened, so this should not fail. */
|
| + PORT_Assert(fd != -1);
|
| while (limit > fileBytes) {
|
| bytes = PR_MIN(sizeof buffer, limit - fileBytes);
|
| - bytes = fread(buffer, 1, bytes, file);
|
| - if (bytes == 0)
|
| + bytes = read(fd, buffer, bytes);
|
| + if (bytes <= 0)
|
| break;
|
| RNG_RandomUpdate(buffer, bytes);
|
| fileBytes += bytes;
|
| @@ -1020,7 +1031,7 @@
|
| FILE * file;
|
| unsigned char buffer[BUFSIZ];
|
|
|
| - file = fopen((char *)fileName, "rb");
|
| + file = fopen(fileName, "rb");
|
| if (file != NULL) {
|
| while (fread(buffer, 1, sizeof(buffer), file) > 0)
|
| ;
|
| @@ -1142,7 +1153,8 @@
|
| size_t RNG_SystemRNG(void *dest, size_t maxLen)
|
| {
|
| FILE *file;
|
| - size_t bytes;
|
| + int fd;
|
| + int bytes;
|
| size_t fileBytes = 0;
|
| unsigned char *buffer = dest;
|
|
|
| @@ -1153,10 +1165,18 @@
|
| fflush(stderr);
|
| abort();
|
| }
|
| + /* Read from the underlying file descriptor directly to bypass stdio
|
| + * buffering and avoid reading more bytes than we need from /dev/urandom.
|
| + * NOTE: we can't use fread with unbuffered I/O because fread may return
|
| + * EOF in unbuffered I/O mode on Android.
|
| + */
|
| + fd = fileno(file);
|
| + /* 'file' was just opened, so this should not fail. */
|
| + PORT_Assert(fd != -1);
|
| while (maxLen > fileBytes) {
|
| bytes = maxLen - fileBytes;
|
| - bytes = fread(buffer, 1, bytes, file);
|
| - if (bytes == 0)
|
| + bytes = read(fd, buffer, bytes);
|
| + if (bytes <= 0)
|
| break;
|
| fileBytes += bytes;
|
| buffer += bytes;
|
|
|