commit 79354243e32b0e64f4dc93bb581ff1b3061e3861 (tree)
parent 8c32c09807ed5ae28afce3e9cf3145f350f8c4e3
Author: Euan Torano <euantorano@gmail.com>
Date: Mon, 5 Aug 2019 19:39:04 +0100
fix os.getrandom logic to fill the entire buffer
Diffstat:
| M | std/os.zig | | | 56 | ++++++++++++++++++++++++++++++++------------------------ |
1 file changed, 32 insertions(+), 24 deletions(-)
diff --git a/std/os.zig b/std/os.zig
@@ -103,33 +103,41 @@ pub fn getrandom(buf: []u8) GetRandomError!void {
if (windows.is_the_target) {
return windows.RtlGenRandom(buf);
}
- if (linux.is_the_target) {
- while (true) {
- const err = if (std.c.versionCheck(builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok) blk: {
- break :blk errno(std.c.getrandom(buf.ptr, buf.len, 0));
+ if (linux.is_the_target or freebsd.is_the_target) {
+ var buf_slice: []u8 = buf[0..];
+ var total_read: usize = 0;
+ const use_c = (!linux.is_the_target) or std.c.versionCheck(builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok;
+
+ while (total_read < buf.len) {
+ var err: u16 = 0;
+
+ const num_read: usize = if (use_c) blk: {
+ const res: c_int = std.c.getrandom(buf_slice.ptr, buf_slice.len, 0);
+
+ if (res == -1) {
+ err = @intCast(u16, std.c._errno().*);
+ break :blk 0;
+ } else {
+ break :blk @intCast(usize, res);
+ }
} else blk: {
- break :blk linux.getErrno(linux.getrandom(buf.ptr, buf.len, 0));
+ const res: usize = linux.getrandom(buf_slice.ptr, buf_slice.len, 0);
+
+ err = @intCast(u16, linux.getErrno(res));
+ break :blk res;
};
- switch (err) {
- 0 => return,
- EINVAL => unreachable,
- EFAULT => unreachable,
- EINTR => continue,
- ENOSYS => return getRandomBytesDevURandom(buf),
- else => return unexpectedErrno(err),
- }
- }
- }
- if (freebsd.is_the_target) {
- while (true) {
- const err = std.c.getErrno(std.c.getrandom(buf.ptr, buf.len, 0));
- switch (err) {
- 0 => return,
- EINVAL => unreachable,
- EFAULT => unreachable,
- EINTR => continue,
- else => return unexpectedErrno(err),
+ if (err != 0) {
+ switch (err) {
+ EINVAL => unreachable,
+ EFAULT => unreachable,
+ EINTR => continue,
+ ENOSYS => return getRandomBytesDevURandom(buf),
+ else => return unexpectedErrno(err),
+ }
+ } else {
+ total_read += num_read;
+ buf_slice = buf_slice[num_read..];
}
}
}