mirror of
https://github.com/ziglang/zig.git
synced 2024-12-13 14:47:09 +00:00
fix test failure, organize code, add new compile error
This commit is contained in:
parent
ec59f76526
commit
44d8d654a0
@ -439,11 +439,10 @@ set(ZIG_STD_FILES
|
||||
"os/darwin_errno.zig"
|
||||
"os/get_user_id.zig"
|
||||
"os/index.zig"
|
||||
"os/linux.zig"
|
||||
"os/linux_errno.zig"
|
||||
"os/linux_random.zig"
|
||||
"os/linux_i386.zig"
|
||||
"os/linux_x86_64.zig"
|
||||
"os/linux/index.zig"
|
||||
"os/linux/errno.zig"
|
||||
"os/linux/i386.zig"
|
||||
"os/linux/x86_64.zig"
|
||||
"os/path.zig"
|
||||
"os/windows/error.zig"
|
||||
"os/windows/index.zig"
|
||||
|
18
src/ir.cpp
18
src/ir.cpp
@ -6193,6 +6193,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
|
||||
if (other_type->id == TypeTableEntryIdFloat) {
|
||||
return true;
|
||||
} else if (other_type->id == TypeTableEntryIdInt && const_val_is_int) {
|
||||
if (!other_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
|
||||
ir_add_error(ira, instruction,
|
||||
buf_sprintf("cannot cast negative value %s to unsigned integer type '%s'",
|
||||
buf_ptr(val_buf),
|
||||
buf_ptr(&other_type->name)));
|
||||
return false;
|
||||
}
|
||||
if (bigint_fits_in_bits(&const_val->data.x_bigint, other_type->data.integral.bit_count,
|
||||
other_type->data.integral.is_signed))
|
||||
{
|
||||
@ -6205,6 +6214,15 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
|
||||
if (const_val_fits_in_num_lit(const_val, child_type)) {
|
||||
return true;
|
||||
} else if (child_type->id == TypeTableEntryIdInt && const_val_is_int) {
|
||||
if (!child_type->data.integral.is_signed && const_val->data.x_bigint.is_negative) {
|
||||
Buf *val_buf = buf_alloc();
|
||||
bigint_append_buf(val_buf, &const_val->data.x_bigint, 10);
|
||||
ir_add_error(ira, instruction,
|
||||
buf_sprintf("cannot cast negative value %s to unsigned integer type '%s'",
|
||||
buf_ptr(val_buf),
|
||||
buf_ptr(&child_type->name)));
|
||||
return false;
|
||||
}
|
||||
if (bigint_fits_in_bits(&const_val->data.x_bigint,
|
||||
child_type->data.integral.bit_count,
|
||||
child_type->data.integral.is_signed))
|
||||
|
@ -1,4 +1,4 @@
|
||||
pub use @import("../os/linux_errno.zig");
|
||||
pub use @import("../os/linux/errno.zig");
|
||||
|
||||
pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize, flags: c_uint) c_int;
|
||||
extern "c" fn __errno_location() &c_int;
|
||||
|
@ -2,7 +2,7 @@ const std = @import("index.zig");
|
||||
const builtin = @import("builtin");
|
||||
const Os = builtin.Os;
|
||||
const system = switch(builtin.os) {
|
||||
Os.linux => @import("os/linux.zig"),
|
||||
Os.linux => @import("os/linux/index.zig"),
|
||||
Os.macosx, Os.ios => @import("os/darwin.zig"),
|
||||
Os.windows => @import("os/windows/index.zig"),
|
||||
else => @compileError("Unsupported OS"),
|
||||
|
@ -6,7 +6,7 @@ const os = this;
|
||||
|
||||
pub const windows = @import("windows/index.zig");
|
||||
pub const darwin = @import("darwin.zig");
|
||||
pub const linux = @import("linux.zig");
|
||||
pub const linux = @import("linux/index.zig");
|
||||
pub const zen = @import("zen.zig");
|
||||
pub const posix = switch(builtin.os) {
|
||||
Os.linux => linux,
|
||||
@ -78,13 +78,28 @@ error WouldBlock;
|
||||
pub fn getRandomBytes(buf: []u8) %void {
|
||||
switch (builtin.os) {
|
||||
Os.linux => while (true) {
|
||||
const err = posix.getErrno(posix.getRandomBytes(buf));
|
||||
if (err > 0) return unexpectedErrorPosix(err);
|
||||
// TODO check libc version and potentially call c.getrandom.
|
||||
// See #397
|
||||
const err = posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0));
|
||||
if (err > 0) {
|
||||
switch (err) {
|
||||
posix.EINVAL => unreachable,
|
||||
posix.EFAULT => unreachable,
|
||||
posix.EINTR => continue,
|
||||
posix.ENOSYS => {
|
||||
const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC, 0);
|
||||
defer close(fd);
|
||||
|
||||
try posixRead(fd, buf);
|
||||
return;
|
||||
},
|
||||
else => return unexpectedErrorPosix(err),
|
||||
}
|
||||
}
|
||||
return;
|
||||
},
|
||||
Os.macosx, Os.ios => {
|
||||
const fd = try posixOpen("/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC,
|
||||
0, null);
|
||||
const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC, 0);
|
||||
defer close(fd);
|
||||
|
||||
try posixRead(fd, buf);
|
||||
@ -253,8 +268,12 @@ pub fn posixOpen(file_path: []const u8, flags: u32, perm: usize, allocator: ?&Al
|
||||
mem.copy(u8, path0, file_path);
|
||||
path0[file_path.len] = 0;
|
||||
|
||||
return posixOpenC(path0.ptr, flags, perm);
|
||||
}
|
||||
|
||||
pub fn posixOpenC(file_path: &const u8, flags: u32, perm: usize) %i32 {
|
||||
while (true) {
|
||||
const result = posix.open(path0.ptr, flags, perm);
|
||||
const result = posix.open(file_path, flags, perm);
|
||||
const err = posix.getErrno(result);
|
||||
if (err > 0) {
|
||||
return switch (err) {
|
||||
@ -1486,10 +1505,10 @@ test "std.os" {
|
||||
_ = @import("darwin_errno.zig");
|
||||
_ = @import("darwin.zig");
|
||||
_ = @import("get_user_id.zig");
|
||||
_ = @import("linux_errno.zig");
|
||||
_ = @import("linux/errno.zig");
|
||||
//_ = @import("linux_i386.zig");
|
||||
_ = @import("linux_x86_64.zig");
|
||||
_ = @import("linux.zig");
|
||||
_ = @import("linux/x86_64.zig");
|
||||
_ = @import("linux/index.zig");
|
||||
_ = @import("path.zig");
|
||||
_ = @import("windows/index.zig");
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
const linux = @import("linux.zig");
|
||||
const std = @import("../../index.zig");
|
||||
const linux = std.os.linux;
|
||||
const socklen_t = linux.socklen_t;
|
||||
const iovec = linux.iovec;
|
||||
|
@ -1,13 +1,12 @@
|
||||
const std = @import("../index.zig");
|
||||
const std = @import("../../index.zig");
|
||||
const assert = std.debug.assert;
|
||||
const builtin = @import("builtin");
|
||||
const arch = switch (builtin.arch) {
|
||||
builtin.Arch.x86_64 => @import("linux_x86_64.zig"),
|
||||
builtin.Arch.i386 => @import("linux_i386.zig"),
|
||||
builtin.Arch.x86_64 => @import("x86_64.zig"),
|
||||
builtin.Arch.i386 => @import("i386.zig"),
|
||||
else => @compileError("unsupported arch"),
|
||||
};
|
||||
pub use @import("linux_errno.zig");
|
||||
pub use @import("linux_random.zig");
|
||||
pub use @import("errno.zig");
|
||||
|
||||
pub const PATH_MAX = 4096;
|
||||
|
||||
@ -788,10 +787,10 @@ pub fn timerfd_settime(fd: i32, flags: u32, new_value: &const itimerspec, old_va
|
||||
return arch.syscall4(arch.SYS_timerfd_settime, usize(fd), usize(flags), @ptrToInt(new_value), @ptrToInt(old_value));
|
||||
}
|
||||
|
||||
test "import linux_test" {
|
||||
test "import linux test" {
|
||||
// TODO lazy analysis should prevent this test from being compiled on windows, but
|
||||
// it is still compiled on windows
|
||||
if (builtin.os == builtin.Os.linux) {
|
||||
_ = @import("linux_test.zig");
|
||||
_ = @import("test.zig");
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
const std = @import("std");
|
||||
const std = @import("../../index.zig");
|
||||
const linux = std.os.linux;
|
||||
const assert = std.debug.assert;
|
||||
|
@ -1,4 +1,5 @@
|
||||
const linux = @import("linux.zig");
|
||||
const std = @import("../../index.zig");
|
||||
const linux = std.os.linux;
|
||||
const socklen_t = linux.socklen_t;
|
||||
const iovec = linux.iovec;
|
||||
|
@ -1,246 +0,0 @@
|
||||
const std = @import("../index.zig");
|
||||
const builtin = @import("builtin");
|
||||
const assert = std.debug.assert;
|
||||
const linux = std.os.linux;
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
const os = std.os;
|
||||
|
||||
use @import("linux_errno.zig");
|
||||
|
||||
const arch = switch (builtin.arch) {
|
||||
builtin.Arch.x86_64 => @import("linux_x86_64.zig"),
|
||||
builtin.Arch.i386 => @import("linux_i386.zig"),
|
||||
else => @compileError("unsupported arch"),
|
||||
};
|
||||
|
||||
const Method = enum {
|
||||
Syscall,
|
||||
Sysctl,
|
||||
Urandom,
|
||||
};
|
||||
|
||||
const Callback = fn(&i32, []u8) usize;
|
||||
|
||||
const Context = struct {
|
||||
syscall: Callback,
|
||||
sysctl: Callback,
|
||||
urandom: Callback,
|
||||
};
|
||||
|
||||
pub fn getRandomBytes(buf: []u8) usize {
|
||||
const ctx = Context {
|
||||
.syscall = syscall,
|
||||
.sysctl = sysctl,
|
||||
.urandom = urandom,
|
||||
};
|
||||
return withContext(ctx, buf);
|
||||
}
|
||||
|
||||
fn withContext(comptime ctx: Context, buf: []u8) usize {
|
||||
if (buf.len == 0) return 0;
|
||||
|
||||
var fd: i32 = -1;
|
||||
defer if (fd != -1) {
|
||||
const _ = linux.close(fd); // Ignore errors, can't do anything sensible.
|
||||
};
|
||||
|
||||
// TODO(bnoordhuis) Remember the method across invocations so we don't make
|
||||
// unnecessary system calls that are going to fail with ENOSYS anyway.
|
||||
var method = Method.Syscall;
|
||||
var i: usize = 0;
|
||||
while (i < buf.len) {
|
||||
const rc = switch (method) {
|
||||
Method.Syscall => ctx.syscall(&fd, buf[i..]),
|
||||
Method.Sysctl => ctx.sysctl(&fd, buf[i..]),
|
||||
Method.Urandom => ctx.urandom(&fd, buf[i..]),
|
||||
};
|
||||
if (rc == 0) return usize(-EIO); // Can't really happen.
|
||||
if (!isErr(rc)) {
|
||||
i += rc;
|
||||
continue;
|
||||
}
|
||||
if (rc == usize(-EINTR)) continue;
|
||||
if (rc == usize(-ENOSYS) and method == Method.Syscall) {
|
||||
method = Method.Urandom;
|
||||
continue;
|
||||
}
|
||||
if (method == Method.Urandom) {
|
||||
method = Method.Sysctl;
|
||||
continue;
|
||||
}
|
||||
return rc; // Unexpected error.
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
fn syscall(_: &i32, buf: []u8) usize {
|
||||
return arch.syscall3(arch.SYS_getrandom, @ptrToInt(&buf[0]), buf.len, 0);
|
||||
}
|
||||
|
||||
// Note: reads only 14 bytes at a time.
|
||||
fn sysctl(_: &i32, buf: []u8) usize {
|
||||
const __sysctl_args = extern struct {
|
||||
name: &c_int,
|
||||
nlen: c_int,
|
||||
oldval: &u8,
|
||||
oldlenp: &usize,
|
||||
newval: ?&u8,
|
||||
newlen: usize,
|
||||
unused: [4]usize,
|
||||
};
|
||||
|
||||
var name = [3]c_int { 1, 40, 6 }; // { CTL_KERN, KERN_RANDOM, RANDOM_UUID }
|
||||
var uuid: [16]u8 = undefined;
|
||||
|
||||
const expected: usize = @sizeOf(@typeOf(uuid));
|
||||
var len = expected;
|
||||
|
||||
var args = __sysctl_args {
|
||||
.name = &name[0],
|
||||
.nlen = c_int(name.len),
|
||||
.oldval = &uuid[0],
|
||||
.oldlenp = &len,
|
||||
.newval = null,
|
||||
.newlen = 0,
|
||||
.unused = []usize {0} ** 4,
|
||||
};
|
||||
|
||||
const rc = arch.syscall1(arch.SYS__sysctl, @ptrToInt(&args));
|
||||
if (rc != 0) return rc;
|
||||
if (len != expected) return 0; // Can't happen.
|
||||
|
||||
// uuid[] is now a type 4 UUID; bytes 6 and 8 (counting from zero)
|
||||
// contain 4 and 5 bits of entropy, respectively. For ease of use,
|
||||
// we skip those and only use 14 of the 16 bytes.
|
||||
uuid[6] = uuid[14];
|
||||
uuid[8] = uuid[15];
|
||||
|
||||
const n = math.min(buf.len, usize(14));
|
||||
@memcpy(&buf[0], &uuid[0], n);
|
||||
return n;
|
||||
}
|
||||
|
||||
fn urandom(fd: &i32, buf: []u8) usize {
|
||||
if (*fd == -1) {
|
||||
const flags = linux.O_CLOEXEC|linux.O_RDONLY;
|
||||
const rc = linux.open(c"/dev/urandom", flags, 0);
|
||||
if (isErr(rc)) return rc;
|
||||
*fd = i32(rc);
|
||||
}
|
||||
// read() doesn't like reads > INT_MAX.
|
||||
const n = math.min(buf.len, usize(0x7FFFFFFF));
|
||||
return linux.read(*fd, &buf[0], n);
|
||||
}
|
||||
|
||||
fn isErr(rc: usize) bool {
|
||||
return rc > usize(-4096);
|
||||
}
|
||||
|
||||
test "os.linux.getRandomBytes" {
|
||||
try check(42, getRandomBytesTrampoline);
|
||||
}
|
||||
|
||||
test "os.linux.getRandomBytes syscall" {
|
||||
try check(42, syscall);
|
||||
}
|
||||
|
||||
test "os.linux.getRandomBytes sysctl" {
|
||||
try check(14, sysctl);
|
||||
}
|
||||
|
||||
test "os.linux.getRandomBytes /dev/urandom" {
|
||||
try check(42, urandom);
|
||||
}
|
||||
|
||||
test "os.linux.getRandomBytes state machine" {
|
||||
const ctx = Context {
|
||||
.syscall = fortytwo,
|
||||
.urandom = fail,
|
||||
.sysctl = fail,
|
||||
};
|
||||
var buf = []u8 {0};
|
||||
assert(1 == withContext(ctx, buf[0..]));
|
||||
assert(42 == buf[0]);
|
||||
}
|
||||
|
||||
test "os.linux.getRandomBytes no-syscall state machine" {
|
||||
const ctx = Context {
|
||||
.syscall = enosys,
|
||||
.urandom = fortytwo,
|
||||
.sysctl = fail,
|
||||
};
|
||||
var buf = []u8 {0};
|
||||
assert(1 == withContext(ctx, buf[0..]));
|
||||
assert(42 == buf[0]);
|
||||
}
|
||||
|
||||
test "os.linux.getRandomBytes no-urandom state machine" {
|
||||
const ctx = Context {
|
||||
.syscall = enosys,
|
||||
.urandom = einval,
|
||||
.sysctl = fortytwo,
|
||||
};
|
||||
var buf = []u8 {0};
|
||||
assert(1 == withContext(ctx, buf[0..]));
|
||||
assert(42 == buf[0]);
|
||||
}
|
||||
|
||||
test "os.linux.getRandomBytes no-sysctl state machine" {
|
||||
const ctx = Context {
|
||||
.syscall = enosys,
|
||||
.urandom = einval,
|
||||
.sysctl = einval,
|
||||
};
|
||||
var buf = []u8 {0};
|
||||
assert(usize(-EINVAL) == withContext(ctx, buf[0..]));
|
||||
assert(0 == buf[0]);
|
||||
}
|
||||
|
||||
fn einval(_: &i32, buf: []u8) usize {
|
||||
return usize(-EINVAL);
|
||||
}
|
||||
|
||||
fn enosys(_: &i32, buf: []u8) usize {
|
||||
return usize(-ENOSYS);
|
||||
}
|
||||
|
||||
fn fail(_: &i32, buf: []u8) usize {
|
||||
os.abort();
|
||||
}
|
||||
|
||||
fn fortytwo(_: &i32, buf: []u8) usize {
|
||||
assert(buf.len == 1);
|
||||
buf[0] = 42;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fn check(comptime N: usize, cb: Callback) %void {
|
||||
if (builtin.os == builtin.Os.linux) {
|
||||
var fd: i32 = -1;
|
||||
defer if (fd != -1) {
|
||||
const _ = linux.close(fd); // Ignore errors, can't do anything sensible.
|
||||
};
|
||||
|
||||
var bufs = [3][N]u8 {
|
||||
[]u8 {0} ** N,
|
||||
[]u8 {0} ** N,
|
||||
[]u8 {0} ** N,
|
||||
};
|
||||
|
||||
for (bufs) |*buf| {
|
||||
const err = cb(&fd, (*buf)[0..]);
|
||||
assert(err == N);
|
||||
}
|
||||
|
||||
for (bufs) |*a|
|
||||
for (bufs) |*b|
|
||||
if (a != b)
|
||||
assert(!mem.eql(u8, *a, *b));
|
||||
}
|
||||
}
|
||||
|
||||
fn getRandomBytesTrampoline(_: &i32, buf: []u8) usize {
|
||||
return getRandomBytes(buf);
|
||||
}
|
@ -1,6 +1,12 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: &tests.CompileErrorContext) void {
|
||||
cases.add("cast negative integer literal to usize",
|
||||
\\export fn entry() void {
|
||||
\\ const x = usize(-10);
|
||||
\\}
|
||||
, ".tmp_source.zig:2:21: error: cannot cast negative value -10 to unsigned integer type 'usize'");
|
||||
|
||||
cases.add("use invalid number literal as array index",
|
||||
\\var v = 25;
|
||||
\\export fn entry() void {
|
||||
|
Loading…
Reference in New Issue
Block a user