Commit 56a8f2b018

Andrew Kelley <superjoe30@gmail.com>
2018-11-24 20:36:16
fix @intCast not catching negative numbers to unsigned
1 parent b953e32
Changed files (3)
src/codegen.cpp
@@ -1645,7 +1645,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
         zig_unreachable();
     }
 
-    if (actual_bits >= wanted_bits && actual_type->id == ZigTypeIdInt &&
+    if (actual_type->id == ZigTypeIdInt &&
         !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&
         want_runtime_safety)
     {
std/os/linux/index.zig
@@ -703,7 +703,7 @@ pub fn dup2(old: i32, new: i32) usize {
 }
 
 pub fn dup3(old: i32, new: i32, flags: u32) usize {
-    return syscall3(SYS_dup3, @intCast(usize, old), @intCast(usize, new), flags);
+    return syscall3(SYS_dup3, @bitCast(usize, isize(old)), @bitCast(usize, isize(new)), flags);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -747,7 +747,7 @@ pub fn getcwd(buf: [*]u8, size: usize) usize {
 }
 
 pub fn getdents64(fd: i32, dirp: [*]u8, count: usize) usize {
-    return syscall3(SYS_getdents64, @intCast(usize, fd), @ptrToInt(dirp), count);
+    return syscall3(SYS_getdents64, @bitCast(usize, isize(fd)), @ptrToInt(dirp), count);
 }
 
 pub fn inotify_init1(flags: u32) usize {
@@ -755,16 +755,16 @@ pub fn inotify_init1(flags: u32) usize {
 }
 
 pub fn inotify_add_watch(fd: i32, pathname: [*]const u8, mask: u32) usize {
-    return syscall3(SYS_inotify_add_watch, @intCast(usize, fd), @ptrToInt(pathname), mask);
+    return syscall3(SYS_inotify_add_watch, @bitCast(usize, isize(fd)), @ptrToInt(pathname), mask);
 }
 
 pub fn inotify_rm_watch(fd: i32, wd: i32) usize {
-    return syscall2(SYS_inotify_rm_watch, @intCast(usize, fd), @intCast(usize, wd));
+    return syscall2(SYS_inotify_rm_watch, @bitCast(usize, isize(fd)), @bitCast(usize, isize(wd)));
 }
 
 pub fn isatty(fd: i32) bool {
     var wsz: winsize = undefined;
-    return syscall3(SYS_ioctl, @intCast(usize, fd), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
+    return syscall3(SYS_ioctl, @bitCast(usize, isize(fd)), TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -774,7 +774,7 @@ pub fn readlink(noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usiz
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn readlinkat(dirfd: i32, noalias path: [*]const u8, noalias buf_ptr: [*]u8, buf_len: usize) usize {
-    return syscall4(SYS_readlinkat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
+    return syscall4(SYS_readlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(buf_ptr), buf_len);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -784,7 +784,7 @@ pub fn mkdir(path: [*]const u8, mode: u32) usize {
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn mkdirat(dirfd: i32, path: [*]const u8, mode: u32) usize {
-    return syscall3(SYS_mkdirat, @intCast(usize, dirfd), @ptrToInt(path), mode);
+    return syscall3(SYS_mkdirat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -803,7 +803,7 @@ pub fn umount2(special: [*]const u8, flags: u32) usize {
 }
 
 pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
-    return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @intCast(usize, fd), @bitCast(usize, offset));
+    return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
 }
 
 pub fn munmap(address: usize, length: usize) usize {
@@ -811,23 +811,23 @@ pub fn munmap(address: usize, length: usize) usize {
 }
 
 pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
-    return syscall3(SYS_read, @intCast(usize, fd), @ptrToInt(buf), count);
+    return syscall3(SYS_read, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
 }
 
 pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize {
-    return syscall4(SYS_preadv, @intCast(usize, fd), @ptrToInt(iov), count, offset);
+    return syscall4(SYS_preadv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
 }
 
 pub fn readv(fd: i32, iov: [*]const iovec, count: usize) usize {
-    return syscall3(SYS_readv, @intCast(usize, fd), @ptrToInt(iov), count);
+    return syscall3(SYS_readv, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
 }
 
 pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize {
-    return syscall3(SYS_writev, @intCast(usize, fd), @ptrToInt(iov), count);
+    return syscall3(SYS_writev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count);
 }
 
 pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize {
-    return syscall4(SYS_pwritev, @intCast(usize, fd), @ptrToInt(iov), count, offset);
+    return syscall4(SYS_pwritev, @bitCast(usize, isize(fd)), @ptrToInt(iov), count, offset);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -842,12 +842,12 @@ pub fn symlink(existing: [*]const u8, new: [*]const u8) usize {
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn symlinkat(existing: [*]const u8, newfd: i32, newpath: [*]const u8) usize {
-    return syscall3(SYS_symlinkat, @ptrToInt(existing), @intCast(usize, newfd), @ptrToInt(newpath));
+    return syscall3(SYS_symlinkat, @ptrToInt(existing), @bitCast(usize, isize(newfd)), @ptrToInt(newpath));
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: usize) usize {
-    return syscall4(SYS_pread, @intCast(usize, fd), @ptrToInt(buf), count, offset);
+    return syscall4(SYS_pread, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -856,7 +856,7 @@ pub fn access(path: [*]const u8, mode: u32) usize {
 }
 
 pub fn faccessat(dirfd: i32, path: [*]const u8, mode: u32) usize {
-    return syscall3(SYS_faccessat, @intCast(usize, dirfd), @ptrToInt(path), mode);
+    return syscall3(SYS_faccessat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), mode);
 }
 
 pub fn pipe(fd: *[2]i32) usize {
@@ -868,11 +868,11 @@ pub fn pipe2(fd: *[2]i32, flags: u32) usize {
 }
 
 pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
-    return syscall3(SYS_write, @intCast(usize, fd), @ptrToInt(buf), count);
+    return syscall3(SYS_write, @bitCast(usize, isize(fd)), @ptrToInt(buf), count);
 }
 
 pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
-    return syscall4(SYS_pwrite, @intCast(usize, fd), @ptrToInt(buf), count, offset);
+    return syscall4(SYS_pwrite, @bitCast(usize, isize(fd)), @ptrToInt(buf), count, offset);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -882,7 +882,7 @@ pub fn rename(old: [*]const u8, new: [*]const u8) usize {
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn renameat2(oldfd: i32, oldpath: [*]const u8, newfd: i32, newpath: [*]const u8, flags: u32) usize {
-    return syscall5(SYS_renameat2, @intCast(usize, oldfd), @ptrToInt(oldpath), @intCast(usize, newfd), @ptrToInt(newpath), flags);
+    return syscall5(SYS_renameat2, @bitCast(usize, isize(oldfd)), @ptrToInt(oldpath), @bitCast(usize, isize(newfd)), @ptrToInt(newpath), flags);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -897,7 +897,8 @@ pub fn create(path: [*]const u8, perm: usize) usize {
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn openat(dirfd: i32, path: [*]const u8, flags: u32, mode: usize) usize {
-    return syscall4(SYS_openat, @intCast(usize, dirfd), @ptrToInt(path), flags, mode);
+    // dirfd could be negative, for example AT_FDCWD is -100
+    return syscall4(SYS_openat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags, mode);
 }
 
 /// See also `clone` (from the arch-specific include)
@@ -911,11 +912,11 @@ pub fn clone2(flags: u32, child_stack_ptr: usize) usize {
 }
 
 pub fn close(fd: i32) usize {
-    return syscall1(SYS_close, @intCast(usize, fd));
+    return syscall1(SYS_close, @bitCast(usize, isize(fd)));
 }
 
 pub fn lseek(fd: i32, offset: isize, ref_pos: usize) usize {
-    return syscall3(SYS_lseek, @intCast(usize, fd), @bitCast(usize, offset), ref_pos);
+    return syscall3(SYS_lseek, @bitCast(usize, isize(fd)), @bitCast(usize, offset), ref_pos);
 }
 
 pub fn exit(status: i32) noreturn {
@@ -933,7 +934,7 @@ pub fn getrandom(buf: [*]u8, count: usize, flags: u32) usize {
 }
 
 pub fn kill(pid: i32, sig: i32) usize {
-    return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @intCast(usize, sig));
+    return syscall2(SYS_kill, @bitCast(usize, isize(pid)), @bitCast(usize, isize(sig)));
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -943,7 +944,7 @@ pub fn unlink(path: [*]const u8) usize {
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn unlinkat(dirfd: i32, path: [*]const u8, flags: u32) usize {
-    return syscall3(SYS_unlinkat, @intCast(usize, dirfd), @ptrToInt(path), flags);
+    return syscall3(SYS_unlinkat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), flags);
 }
 
 pub fn waitpid(pid: i32, status: *i32, options: i32) usize {
@@ -1120,8 +1121,8 @@ pub const empty_sigset = []usize{0} ** sigset_t.len;
 pub fn raise(sig: i32) usize {
     var set: sigset_t = undefined;
     blockAppSignals(&set);
-    const tid = @intCast(i32, syscall0(SYS_gettid));
-    const ret = syscall2(SYS_tkill, @intCast(usize, tid), @intCast(usize, sig));
+    const tid = syscall0(SYS_gettid);
+    const ret = syscall2(SYS_tkill, tid, @bitCast(usize, isize(sig)));
     restoreSignals(&set);
     return ret;
 }
@@ -1189,11 +1190,11 @@ pub const iovec_const = extern struct {
 };
 
 pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
-    return syscall3(SYS_getsockname, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len));
+    return syscall3(SYS_getsockname, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
 }
 
 pub fn getpeername(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
-    return syscall3(SYS_getpeername, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len));
+    return syscall3(SYS_getpeername, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len));
 }
 
 pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
@@ -1201,47 +1202,47 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) usize {
 }
 
 pub fn setsockopt(fd: i32, level: u32, optname: u32, optval: [*]const u8, optlen: socklen_t) usize {
-    return syscall5(SYS_setsockopt, @intCast(usize, fd), level, optname, @ptrToInt(optval), @intCast(usize, optlen));
+    return syscall5(SYS_setsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @intCast(usize, optlen));
 }
 
 pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noalias optlen: *socklen_t) usize {
-    return syscall5(SYS_getsockopt, @intCast(usize, fd), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
+    return syscall5(SYS_getsockopt, @bitCast(usize, isize(fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen));
 }
 
 pub fn sendmsg(fd: i32, msg: *const msghdr, flags: u32) usize {
-    return syscall3(SYS_sendmsg, @intCast(usize, fd), @ptrToInt(msg), flags);
+    return syscall3(SYS_sendmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
 }
 
 pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize {
-    return syscall3(SYS_connect, @intCast(usize, fd), @ptrToInt(addr), len);
+    return syscall3(SYS_connect, @bitCast(usize, isize(fd)), @ptrToInt(addr), len);
 }
 
 pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize {
-    return syscall3(SYS_recvmsg, @intCast(usize, fd), @ptrToInt(msg), flags);
+    return syscall3(SYS_recvmsg, @bitCast(usize, isize(fd)), @ptrToInt(msg), flags);
 }
 
 pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize {
-    return syscall6(SYS_recvfrom, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
+    return syscall6(SYS_recvfrom, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @ptrToInt(alen));
 }
 
 pub fn shutdown(fd: i32, how: i32) usize {
-    return syscall2(SYS_shutdown, @intCast(usize, fd), @intCast(usize, how));
+    return syscall2(SYS_shutdown, @bitCast(usize, isize(fd)), @bitCast(usize, isize(how)));
 }
 
 pub fn bind(fd: i32, addr: *const sockaddr, len: socklen_t) usize {
-    return syscall3(SYS_bind, @intCast(usize, fd), @ptrToInt(addr), @intCast(usize, len));
+    return syscall3(SYS_bind, @bitCast(usize, isize(fd)), @ptrToInt(addr), @intCast(usize, len));
 }
 
 pub fn listen(fd: i32, backlog: u32) usize {
-    return syscall2(SYS_listen, @intCast(usize, fd), backlog);
+    return syscall2(SYS_listen, @bitCast(usize, isize(fd)), backlog);
 }
 
 pub fn sendto(fd: i32, buf: [*]const u8, len: usize, flags: u32, addr: ?*const sockaddr, alen: socklen_t) usize {
-    return syscall6(SYS_sendto, @intCast(usize, fd), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
+    return syscall6(SYS_sendto, @bitCast(usize, isize(fd)), @ptrToInt(buf), len, flags, @ptrToInt(addr), @intCast(usize, alen));
 }
 
 pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usize {
-    return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(*fd[0]));
+    return syscall4(SYS_socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0]));
 }
 
 pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
@@ -1249,11 +1250,11 @@ pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
 }
 
 pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize {
-    return syscall4(SYS_accept4, @intCast(usize, fd), @ptrToInt(addr), @ptrToInt(len), flags);
+    return syscall4(SYS_accept4, @bitCast(usize, isize(fd)), @ptrToInt(addr), @ptrToInt(len), flags);
 }
 
 pub fn fstat(fd: i32, stat_buf: *Stat) usize {
-    return syscall2(SYS_fstat, @intCast(usize, fd), @ptrToInt(stat_buf));
+    return syscall2(SYS_fstat, @bitCast(usize, isize(fd)), @ptrToInt(stat_buf));
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -1268,7 +1269,7 @@ pub fn lstat(pathname: [*]const u8, statbuf: *Stat) usize {
 
 // TODO https://github.com/ziglang/zig/issues/265
 pub fn fstatat(dirfd: i32, path: [*]const u8, stat_buf: *Stat, flags: u32) usize {
-    return syscall4(SYS_fstatat, @intCast(usize, dirfd), @ptrToInt(path), @ptrToInt(stat_buf), flags);
+    return syscall4(SYS_fstatat, @bitCast(usize, isize(dirfd)), @ptrToInt(path), @ptrToInt(stat_buf), flags);
 }
 
 // TODO https://github.com/ziglang/zig/issues/265
@@ -1355,7 +1356,7 @@ pub fn epoll_create1(flags: usize) usize {
 }
 
 pub fn epoll_ctl(epoll_fd: i32, op: u32, fd: i32, ev: *epoll_event) usize {
-    return syscall4(SYS_epoll_ctl, @intCast(usize, epoll_fd), @intCast(usize, op), @intCast(usize, fd), @ptrToInt(ev));
+    return syscall4(SYS_epoll_ctl, @bitCast(usize, isize(epoll_fd)), @intCast(usize, op), @bitCast(usize, isize(fd)), @ptrToInt(ev));
 }
 
 pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32) usize {
@@ -1363,7 +1364,15 @@ pub fn epoll_wait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout
 }
 
 pub fn epoll_pwait(epoll_fd: i32, events: [*]epoll_event, maxevents: u32, timeout: i32, sigmask: ?*sigset_t) usize {
-    return syscall6(SYS_epoll_pwait, @intCast(usize, epoll_fd), @ptrToInt(events), @intCast(usize, maxevents), @intCast(usize, timeout), @ptrToInt(sigmask), @sizeOf(sigset_t));
+    return syscall6(
+        SYS_epoll_pwait,
+        @bitCast(usize, isize(epoll_fd)),
+        @ptrToInt(events),
+        @intCast(usize, maxevents),
+        @bitCast(usize, isize(timeout)),
+        @ptrToInt(sigmask),
+        @sizeOf(sigset_t),
+    );
 }
 
 pub fn eventfd(count: u32, flags: u32) usize {
@@ -1371,7 +1380,7 @@ pub fn eventfd(count: u32, flags: u32) usize {
 }
 
 pub fn timerfd_create(clockid: i32, flags: u32) usize {
-    return syscall2(SYS_timerfd_create, @intCast(usize, clockid), flags);
+    return syscall2(SYS_timerfd_create, @bitCast(usize, isize(clockid)), flags);
 }
 
 pub const itimerspec = extern struct {
@@ -1380,11 +1389,11 @@ pub const itimerspec = extern struct {
 };
 
 pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize {
-    return syscall2(SYS_timerfd_gettime, @intCast(usize, fd), @ptrToInt(curr_value));
+    return syscall2(SYS_timerfd_gettime, @bitCast(usize, isize(fd)), @ptrToInt(curr_value));
 }
 
 pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize {
-    return syscall4(SYS_timerfd_settime, @intCast(usize, fd), flags, @ptrToInt(new_value), @ptrToInt(old_value));
+    return syscall4(SYS_timerfd_settime, @bitCast(usize, isize(fd)), flags, @ptrToInt(new_value), @ptrToInt(old_value));
 }
 
 pub const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
test/runtime_safety.zig
@@ -275,6 +275,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         \\}
     );
 
+    cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer - widening",
+        \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
+        \\    @import("std").os.exit(126);
+        \\}
+        \\pub fn main() void {
+        \\    var value: c_short = -1;
+        \\    var casted = @intCast(u32, value);
+        \\}
+    );
+
     cases.addRuntimeSafety("unwrap error",
         \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
         \\    if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {