From 8c32c09807ed5ae28afce3e9cf3145f350f8c4e3 Mon Sep 17 00:00:00 2001 From: Euan Torano Date: Mon, 5 Aug 2019 19:18:19 +0100 Subject: [PATCH 1/3] Fix InStream.readNoEof --- std/io.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/io.zig b/std/io.zig index 3a8da3ed3e..dcf2ec5f61 100644 --- a/std/io.zig +++ b/std/io.zig @@ -146,7 +146,7 @@ pub fn InStream(comptime ReadError: type) type { /// Same as `readFull` but end of stream returns `error.EndOfStream`. pub fn readNoEof(self: *Self, buf: []u8) !void { - const amt_read = try self.read(buf); + const amt_read = try self.readFull(buf); if (amt_read < buf.len) return error.EndOfStream; } From 79354243e32b0e64f4dc93bb581ff1b3061e3861 Mon Sep 17 00:00:00 2001 From: Euan Torano Date: Mon, 5 Aug 2019 19:39:04 +0100 Subject: [PATCH 2/3] fix os.getrandom logic to fill the entire buffer --- std/os.zig | 60 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/std/os.zig b/std/os.zig index 0a826c26c2..58ee569f0c 100644 --- 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)); - } else blk: { - break :blk linux.getErrno(linux.getrandom(buf.ptr, buf.len, 0)); - }; - 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)); + 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; - switch (err) { - 0 => return, - EINVAL => unreachable, - EFAULT => unreachable, - EINTR => continue, - else => return unexpectedErrno(err), + 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: { + const res: usize = linux.getrandom(buf_slice.ptr, buf_slice.len, 0); + + err = @intCast(u16, linux.getErrno(res)); + break :blk res; + }; + + 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..]; } } } From 9bf283c0851b39d6c54d1f5dfb5c2c55cd0a1ab0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 20 Aug 2019 15:25:30 -0400 Subject: [PATCH 3/3] fixups * getrandom libc prototypes had the wrong return type * `total_read` local variable was unnecessary since the sub-slice buffer has a length * I was able to get rid of all the integer casts * the err == 0 check can be a switch case * add missing `return` statement --- std/c/freebsd.zig | 2 +- std/c/linux.zig | 2 +- std/os.zig | 57 ++++++++++++++++++++--------------------------- 3 files changed, 26 insertions(+), 35 deletions(-) diff --git a/std/c/freebsd.zig b/std/c/freebsd.zig index 3d5736d37b..71dd4705f8 100644 --- a/std/c/freebsd.zig +++ b/std/c/freebsd.zig @@ -6,4 +6,4 @@ pub const _errno = __error; pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize; pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; -pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int; +pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; diff --git a/std/c/linux.zig b/std/c/linux.zig index a69f3c18b2..b3b3cbdde7 100644 --- a/std/c/linux.zig +++ b/std/c/linux.zig @@ -7,7 +7,7 @@ pub const _errno = __errno_location; pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize)); -pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) c_int; +pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int; pub extern "c" fn eventfd(initval: c_uint, flags: c_uint) c_int; pub extern "c" fn epoll_ctl(epfd: fd_t, op: c_uint, fd: fd_t, event: ?*epoll_event) c_int; diff --git a/std/os.zig b/std/os.zig index 58ee569f0c..0291282a77 100644 --- a/std/os.zig +++ b/std/os.zig @@ -99,55 +99,46 @@ pub const GetRandomError = OpenError; /// When linking against libc, this calls the /// appropriate OS-specific library call. Otherwise it uses the zig standard /// library implementation. -pub fn getrandom(buf: []u8) GetRandomError!void { +pub fn getrandom(buffer: []u8) GetRandomError!void { if (windows.is_the_target) { - return windows.RtlGenRandom(buf); + return windows.RtlGenRandom(buffer); } 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; + var buf = buffer; + 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; + while (buf.len != 0) { + var err: u16 = undefined; - 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); - } + const num_read = if (use_c) blk: { + const rc = std.c.getrandom(buf.ptr, buf.len, 0); + err = std.c.getErrno(rc); + break :blk @bitCast(usize, rc); } else blk: { - const res: usize = linux.getrandom(buf_slice.ptr, buf_slice.len, 0); - - err = @intCast(u16, linux.getErrno(res)); - break :blk res; + const rc = linux.getrandom(buf.ptr, buf.len, 0); + err = linux.getErrno(rc); + break :blk rc; }; - 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..]; + switch (err) { + 0 => buf = buf[num_read..], + EINVAL => unreachable, + EFAULT => unreachable, + EINTR => continue, + ENOSYS => return getRandomBytesDevURandom(buf), + else => return unexpectedErrno(err), } } + return; } if (wasi.is_the_target) { - switch (wasi.random_get(buf.ptr, buf.len)) { + switch (wasi.random_get(buffer.ptr, buffer.len)) { 0 => return, else => |err| return unexpectedErrno(err), } } - return getRandomBytesDevURandom(buf); + return getRandomBytesDevURandom(buffer); } fn getRandomBytesDevURandom(buf: []u8) !void {