~ 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