~ chicken-core (chicken-5) c90c64998455d74d611056b4ecd10e3907dbaed9


commit c90c64998455d74d611056b4ecd10e3907dbaed9
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Fri Nov 3 19:44:44 2017 +0100
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Fri Nov 3 19:44:44 2017 +0100

    fix several bugs, possibly introducing new, allow arbitrary large buffer for ranodm-bytes, trying to please the ruthless committee

diff --git a/extras.scm b/extras.scm
index 1ffb35e3..e3ecad8c 100644
--- a/extras.scm
+++ b/extras.scm
@@ -673,18 +673,18 @@
     (lambda (#!optional buf size)
       (when size
         (##sys#check-fixnum size 'random-bytes)
-        (when (or (< size 0) 
-                  (> size 256))
-          (##sys#error 'random-bytes "size out of range" size)))
+        (when (< size 0) 
+          (##sys#error 'random-bytes "invalid size" size)))
       (let* ((dest (cond (buf
-                         (unless (##core#inline "C_byteblockp" buf)
+                         (when (or (##core#inline "C_immediatep" buf)
+                                   (not (##core#inline "C_byteblockp" buf)))
                            (##sys#error 'random-bytes
                                         "invalid buffer type" buf))
                          buf)
                         (else (make-string (or size nstate)))))
              (r (##core#inline "C_random_bytes" dest
                                (or size (##sys#size dest)))))
-        (when (eq? -1 r)
+        (unless r
           (##sys#error 'random-bytes "unable to read random bytes"))
         (unless (eq? buf dest)
           (##core#inline "C_string_to_bytevector" dest))
diff --git a/runtime.c b/runtime.c
index 0bbefb25..df42986f 100644
--- a/runtime.c
+++ b/runtime.c
@@ -12548,35 +12548,49 @@ C_word C_random_bytes(C_word buf, C_word size)
 {
   int count = C_unfix(size);
   int r = 0;
+  int off = 0;
 
 #ifdef __OpenBSD__
   arc4random_buf(C_data_pointer(buf), count);
 #elif defined(SYS_getrandom) && defined(__NR_getrandom)
-  do {
-    r = getrandom(C_data_pointer(buf), count, 0);
-  } while(r < 0 && (errno == EINTR));
+  while(count > 0) {
+    r = getrandom(C_data_pointer(buf) + off, count, GRND_NONBLOCK);
+
+    if(r == -1) {
+      if(errno != EINTR) return C_SCHEME_FALSE;
+      else r = 0;
+    }
+
+    count -= r;
+    off += r;
+  }
 #elif defined(_WIN32) && !defined(__CYGWIN__)
   if(!RtlGenRandom((PVOID)C_data_pointer(buf), (LONG)count)) 
-    r = -1;
+    return C_SCHEME_FALSE;
 #else 
-  static int fd = 0;
+  static int fd = -1;
 
-  if(fd == 0) {
+  if(fd == -1) {
     fd = open("/dev/urandom", O_RDONLY);
 
     if(fd == -1) {
-      fd = 0;
-      return C_fix(-1);
+      return C_SCHEME_FALSE;
     }
   }
 
-  do {
-     r = read(fd, C_data_pointer(buf), count);
-   } while(r == -1 && errno == EINTR);
+  while(count > 0) {
+    r = read(fd, C_data_pointer(buf) + off, count);
 
-  r = 0;
+    if(r == -1) {
+      if(errno != EINTR && errno != EAGAIN) return C_SCHEME_FALSE;
+      else r = 0;
+    }
+
+    count -= r;
+    off += r;
+   }
 #endif
-  return C_fix(r);
+  return C_SCHEME_TRUE;
 }
 
 
Trap