From fc9e28ea37e0110836d6958c39ffe78ea6cad0f3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 8 Jul 2019 14:26:40 -0400 Subject: [PATCH] std.os.getrandom does a libc version check closes #397 --- src/ir.cpp | 2 +- std/c.zig | 27 +++++++++++++++++++++++++++ std/os.zig | 10 +++++++--- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index f0ac2f8ea..94307627a 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11191,7 +11191,7 @@ static IrBasicBlock *ir_get_new_bb_runtime(IrAnalyze *ira, IrBasicBlock *old_bb, } static void ir_start_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrBasicBlock *const_predecessor_bb) { - assert(!old_bb->suspended); + ir_assert(!old_bb->suspended, old_bb->instruction_list.at(0)); ira->instruction_index = 0; ira->old_irb.current_basic_block = old_bb; ira->const_predecessor_bb = const_predecessor_bb; diff --git a/std/c.zig b/std/c.zig index 029b92e54..693f26008 100644 --- a/std/c.zig +++ b/std/c.zig @@ -21,6 +21,33 @@ pub fn getErrno(rc: var) u16 { } } +/// The return type is `type` to force comptime function call execution. +/// TODO: https://github.com/ziglang/zig/issues/425 +/// If not linking libc, returns struct{pub const ok = false;} +/// If linking musl libc, returns struct{pub const ok = true;} +/// If linking gnu libc (glibc), the `ok` value will be true if the target +/// version is greater than or equal to `glibc_version`. +/// If linking a libc other than these, returns `false`. +pub fn versionCheck(glibc_version: builtin.Version) type { + return struct { + pub const ok = blk: { + if (!builtin.link_libc) break :blk false; + switch (builtin.abi) { + .musl, .musleabi, .musleabihf => break :blk true, + .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => { + const ver = builtin.glibc_version orelse break :blk false; + if (ver.major < glibc_version.major) break :blk false; + if (ver.major > glibc_version.major) break :blk true; + if (ver.minor < glibc_version.minor) break :blk false; + if (ver.minor > glibc_version.minor) break :blk true; + break :blk ver.patch >= glibc_version.patch; + }, + else => break :blk false, + } + }; + }; +} + // TODO https://github.com/ziglang/zig/issues/265 on this whole file pub extern "c" fn fopen(filename: [*]const u8, modes: [*]const u8) ?*FILE; diff --git a/std/os.zig b/std/os.zig index e9e9c89b4..1971b51df 100644 --- a/std/os.zig +++ b/std/os.zig @@ -105,14 +105,18 @@ pub fn getrandom(buf: []u8) GetRandomError!void { } if (linux.is_the_target) { while (true) { - // Bypass libc because it's missing on even relatively new versions. - switch (linux.getErrno(linux.getrandom(buf.ptr, buf.len, 0))) { + 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 => |err| return unexpectedErrno(err), + else => return unexpectedErrno(err), } } }