~ 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