From 6b55c8d44fcf6b44c55d20ef1002981f80ed13ff Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Mon, 3 May 2021 20:56:45 -0500 Subject: [PATCH] Fix(?) windows errnos --- Cargo.lock | 4 +- vm/Cargo.toml | 2 +- vm/src/stdlib/errno.rs | 144 ++++++++++++++++---------------------- vm/src/stdlib/os.rs | 19 ++++- vm/src/stdlib/resource.rs | 7 +- vm/src/stdlib/socket.rs | 32 +++------ 6 files changed, 92 insertions(+), 116 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f765ff0aa..9e0adb0b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1051,9 +1051,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.91" +version = "0.2.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" +checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e" [[package]] name = "libffi" diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 54a6ba270..c43a3cf7e 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -63,7 +63,7 @@ indexmap = "1.0.2" ahash = "0.7.2" crc = "^1.0.0" bitflags = "1.2.1" -libc = "0.2" +libc = "0.2.94" nix = "0.20.0" csv-core = "0.1" paste = "1.0.5" diff --git a/vm/src/stdlib/errno.rs b/vm/src/stdlib/errno.rs index 1febf7db5..8b464421e 100644 --- a/vm/src/stdlib/errno.rs +++ b/vm/src/stdlib/errno.rs @@ -15,60 +15,31 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { module } -#[rustfmt::skip] -#[allow(unused)] +#[cfg(any(unix, windows, target_os = "wasi"))] pub mod errors { pub use libc::*; #[cfg(windows)] pub use winapi::shared::winerror::*; - #[cfg(windows)] pub const EADDRINUSE: i32 = WSAEADDRINUSE as _; - #[cfg(windows)] pub const EADDRNOTAVAIL: i32 = WSAEADDRNOTAVAIL as _; - #[cfg(windows)] pub const EAFNOSUPPORT: i32 = WSAEAFNOSUPPORT as _; - #[cfg(windows)] pub const EALREADY: i32 = WSAEALREADY as _; - #[cfg(windows)] pub const ECANCELED: i32 = WSAECANCELLED as _; - #[cfg(windows)] pub const ECONNABORTED: i32 = WSAECONNABORTED as _; - #[cfg(windows)] pub const ECONNREFUSED: i32 = WSAECONNREFUSED as _; - #[cfg(windows)] pub const ECONNRESET: i32 = WSAECONNRESET as _; - #[cfg(windows)] pub const EDESTADDRREQ: i32 = WSAEDESTADDRREQ as _; - #[cfg(windows)] pub const EDISCON: i32 = WSAEDISCON as _; - #[cfg(windows)] pub const EDQUOT: i32 = WSAEDQUOT as _; - #[cfg(windows)] pub const EFAULT: i32 = WSAEFAULT as _; - #[cfg(windows)] pub const EHOSTDOWN: i32 = WSAEHOSTDOWN as _; - #[cfg(windows)] pub const EHOSTUNREACH: i32 = WSAEHOSTUNREACH as _; - #[cfg(windows)] pub const EINPROGRESS: i32 = WSAEINPROGRESS as _; - #[cfg(windows)] pub const EINVALIDPROCTABLE: i32 = WSAEINVALIDPROCTABLE as _; - #[cfg(windows)] pub const EINVALIDPROVIDER: i32 = WSAEINVALIDPROVIDER as _; - #[cfg(windows)] pub const EISCONN: i32 = WSAEISCONN as _; - #[cfg(windows)] pub const ELOOP: i32 = WSAELOOP as _; - #[cfg(windows)] pub const EMFILE: i32 = WSAEMFILE as _; - #[cfg(windows)] pub const EMSGSIZE: i32 = WSAEMSGSIZE as _; - #[cfg(windows)] pub const ENAMETOOLONG: i32 = WSAENAMETOOLONG as _; - #[cfg(windows)] pub const ENETDOWN: i32 = WSAENETDOWN as _; - #[cfg(windows)] pub const ENETRESET: i32 = WSAENETRESET as _; - #[cfg(windows)] pub const ENETUNREACH: i32 = WSAENETUNREACH as _; - #[cfg(windows)] pub const ENOBUFS: i32 = WSAENOBUFS as _; - #[cfg(windows)] pub const ENOMORE: i32 = WSAENOMORE as _; - #[cfg(windows)] pub const ENOPROTOOPT: i32 = WSAENOPROTOOPT as _; - #[cfg(windows)] pub const ENOTCONN: i32 = WSAENOTCONN as _; - #[cfg(windows)] pub const ENOTEMPTY: i32 = WSAENOTEMPTY as _; - #[cfg(windows)] pub const ENOTSOCK: i32 = WSAENOTSOCK as _; - #[cfg(windows)] pub const EOPNOTSUPP: i32 = WSAEOPNOTSUPP as _; - #[cfg(windows)] pub const EPFNOSUPPORT: i32 = WSAEPFNOSUPPORT as _; - #[cfg(windows)] pub const EPROCLIM: i32 = WSAEPROCLIM as _; - #[cfg(windows)] pub const EPROTONOSUPPORT: i32 = WSAEPROTONOSUPPORT as _; - #[cfg(windows)] pub const EPROTOTYPE: i32 = WSAEPROTOTYPE as _; - #[cfg(windows)] pub const EPROVIDERFAILEDINIT: i32 = WSAEPROVIDERFAILEDINIT as _; - #[cfg(windows)] pub const EREFUSED: i32 = WSAEREFUSED as _; - #[cfg(windows)] pub const EREMOTE: i32 = WSAEREMOTE as _; - #[cfg(windows)] pub const ESHUTDOWN: i32 = WSAESHUTDOWN as _; - #[cfg(windows)] pub const ESOCKTNOSUPPORT: i32 = WSAESOCKTNOSUPPORT as _; - #[cfg(windows)] pub const ESTALE: i32 = WSAESTALE as _; - #[cfg(windows)] pub const ETIMEDOUT: i32 = WSAETIMEDOUT as _; - #[cfg(windows)] pub const ETOOMANYREFS: i32 = WSAETOOMANYREFS as _; - #[cfg(windows)] pub const EUSERS: i32 = WSAEUSERS as _; - #[cfg(windows)] pub const EWOULDBLOCK: i32 = WSAEWOULDBLOCK as _; + #[cfg(windows)] + macro_rules! reexport_wsa { + ($($errname:ident),*$(,)?) => { + paste::paste! { + $(pub const $errname: i32 = [] as i32;)* + } + } + } + #[cfg(windows)] + reexport_wsa! { + EADDRINUSE, EADDRNOTAVAIL, EAFNOSUPPORT, EALREADY, ECONNABORTED, ECONNREFUSED, ECONNRESET, + EDESTADDRREQ, EDQUOT, EHOSTDOWN, EHOSTUNREACH, EINPROGRESS, EISCONN, ELOOP, EMSGSIZE, + ENETDOWN, ENETRESET, ENETUNREACH, ENOBUFS, ENOPROTOOPT, ENOTCONN, ENOTSOCK, EOPNOTSUPP, + EPFNOSUPPORT, EPROTONOSUPPORT, EPROTOTYPE, EREMOTE, ESHUTDOWN, ESOCKTNOSUPPORT, ESTALE, + ETIMEDOUT, ETOOMANYREFS, EUSERS, EWOULDBLOCK, + // TODO: EBADF should be here once winerrs are translated to errnos but it messes up some things atm + } } +#[cfg(any(unix, windows))] macro_rules! e { ($name:ident) => { (stringify!($name), errors::$name as _) @@ -93,6 +64,7 @@ const ERROR_CODES: &[(&str, i32)] = &[ ENODATA ), e!(cfg(not(windows)), ENOTBLK), + e!(EOPNOTSUPP), e!(ENOSYS), e!(EPIPE), e!(EINVAL), @@ -196,50 +168,54 @@ const ERROR_CODES: &[(&str, i32)] = &[ e!(EWOULDBLOCK), e!(cfg(not(windows)), EOWNERDEAD), e!(cfg(not(windows)), ENOTRECOVERABLE), - e!(cfg(windows), WSAEAFNOSUPPORT), e!(cfg(windows), WSAEHOSTDOWN), - e!(cfg(windows), WSAEPFNOSUPPORT), - e!(cfg(windows), WSAENOPROTOOPT), - e!(cfg(windows), WSAEISCONN), - e!(cfg(windows), WSAESHUTDOWN), - e!(cfg(windows), WSAEINVAL), - e!(cfg(windows), WSAEBADF), - e!(cfg(windows), WSAENAMETOOLONG), - e!(cfg(windows), WSAEPROCLIM), - e!(cfg(windows), WSAEMFILE), - e!(cfg(windows), WSAEINPROGRESS), - e!(cfg(windows), WSAETOOMANYREFS), - e!(cfg(windows), WSAESOCKTNOSUPPORT), - e!(cfg(windows), WSAECONNRESET), - e!(cfg(windows), WSAENOTSOCK), - e!(cfg(windows), WSAECONNABORTED), - e!(cfg(windows), WSAENOTCONN), - e!(cfg(windows), WSAEDQUOT), - e!(cfg(windows), WSAENETRESET), - e!(cfg(windows), WSAEADDRNOTAVAIL), - e!(cfg(windows), WSAEPROTONOSUPPORT), - e!(cfg(windows), WSAECONNREFUSED), - e!(cfg(windows), WSAEALREADY), - e!(cfg(windows), WSAEPROTOTYPE), - e!(cfg(windows), WSAEWOULDBLOCK), - e!(cfg(windows), WSAEMSGSIZE), - e!(cfg(windows), WSAELOOP), - e!(cfg(windows), WSAEREMOTE), - e!(cfg(windows), WSAENOBUFS), - e!(cfg(windows), WSAEUSERS), - e!(cfg(windows), WSAEHOSTUNREACH), e!(cfg(windows), WSAENETDOWN), - e!(cfg(windows), WSAETIMEDOUT), - e!(cfg(windows), WSAEDESTADDRREQ), - e!(cfg(windows), WSAENETUNREACH), + e!(cfg(windows), WSAENOTSOCK), + e!(cfg(windows), WSAEHOSTUNREACH), + e!(cfg(windows), WSAELOOP), + e!(cfg(windows), WSAEMFILE), e!(cfg(windows), WSAESTALE), - e!(cfg(windows), WSAEADDRINUSE), - e!(cfg(windows), WSAEOPNOTSUPP), + e!(cfg(windows), WSAVERNOTSUPPORTED), + e!(cfg(windows), WSAENETUNREACH), + e!(cfg(windows), WSAEPROCLIM), e!(cfg(windows), WSAEFAULT), + e!(cfg(windows), WSANOTINITIALISED), + e!(cfg(windows), WSAEUSERS), + e!(cfg(windows), WSAENOPROTOOPT), + e!(cfg(windows), WSAECONNABORTED), + e!(cfg(windows), WSAENAMETOOLONG), e!(cfg(windows), WSAENOTEMPTY), + e!(cfg(windows), WSAESHUTDOWN), + e!(cfg(windows), WSAEAFNOSUPPORT), + e!(cfg(windows), WSAETOOMANYREFS), e!(cfg(windows), WSAEACCES), + e!(cfg(windows), WSABASEERR), + e!(cfg(windows), WSAEMSGSIZE), + e!(cfg(windows), WSAEBADF), + e!(cfg(windows), WSAECONNRESET), + e!(cfg(windows), WSAETIMEDOUT), + e!(cfg(windows), WSAENOBUFS), e!(cfg(windows), WSAEDISCON), e!(cfg(windows), WSAEINTR), + e!(cfg(windows), WSAEPROTOTYPE), + e!(cfg(windows), WSAEADDRINUSE), + e!(cfg(windows), WSAEADDRNOTAVAIL), + e!(cfg(windows), WSAEALREADY), + e!(cfg(windows), WSAEPROTONOSUPPORT), + e!(cfg(windows), WSASYSNOTREADY), + e!(cfg(windows), WSAEWOULDBLOCK), + e!(cfg(windows), WSAEPFNOSUPPORT), + e!(cfg(windows), WSAEOPNOTSUPP), + e!(cfg(windows), WSAEISCONN), + e!(cfg(windows), WSAEDQUOT), + e!(cfg(windows), WSAENOTCONN), + e!(cfg(windows), WSAEREMOTE), + e!(cfg(windows), WSAEINVAL), + e!(cfg(windows), WSAEINPROGRESS), + e!(cfg(windows), WSAESOCKTNOSUPPORT), + e!(cfg(windows), WSAEDESTADDRREQ), + e!(cfg(windows), WSAECONNREFUSED), + e!(cfg(windows), WSAENETRESET), ]; #[cfg(not(any(unix, windows)))] diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 9589ca7a8..ae75a8d0c 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1759,7 +1759,7 @@ mod posix { #[pyattr] fn environ(vm: &VirtualMachine) -> PyDictRef { let environ = vm.ctx.new_dict(); - use std::os::unix::ffi::OsStringExt; + use ffi_ext::OsStringExt; for (key, value) in env::vars_os() { environ .set_item( @@ -3136,6 +3136,7 @@ mod minor { pub const SYMLINK_DIR_FD: bool = false; #[derive(FromArgs)] + #[allow(unused)] pub(super) struct SimlinkArgs { #[pyarg(any)] src: PyPathLike, @@ -3148,13 +3149,25 @@ mod minor { } #[pyfunction] - pub(super) fn symlink(args: SimkinkArgs, vm: &VirtualMachine) -> PyResult<()> { + pub(super) fn symlink(_args: SimlinkArgs, vm: &VirtualMachine) -> PyResult<()> { os_unimpl("os.symlink", vm) } #[pyattr] fn environ(vm: &VirtualMachine) -> PyDictRef { - vm.ctx.new_dict() + let environ = vm.ctx.new_dict(); + use ffi_ext::OsStringExt; + for (key, value) in env::vars_os() { + environ + .set_item( + vm.ctx.new_bytes(key.into_vec()), + vm.ctx.new_bytes(value.into_vec()), + vm, + ) + .unwrap(); + } + + environ } pub(super) fn support_funcs() -> Vec { diff --git a/vm/src/stdlib/resource.rs b/vm/src/stdlib/resource.rs index f04b342b9..0c52c45a0 100644 --- a/vm/src/stdlib/resource.rs +++ b/vm/src/stdlib/resource.rs @@ -9,11 +9,8 @@ mod resource { use std::{io, mem}; cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { - use libc::RLIMIT_NLIMITS as RLIM_NLIMITS; - } else if #[cfg(target_os = "android")] { - // TODO: this should be in libc soon - const RLIM_NLIMITS: i32 = 16; + if #[cfg(any(target_os = "linux", target_os = "android"))] { + use libc::RLIM_NLIMITS; } else { // in bsd-ish platforms, this constant isn't abi-stable across os versions, so we just // pick a high number so we don't get false positive ValueErrors and just bubble up the diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 83707dc82..0e6f94eb4 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -56,13 +56,6 @@ mod c { pub const AI_ADDRCONFIG: c_int = 0x0020; #[cfg(target_os = "redox")] pub const AI_NUMERICSERV: c_int = 0x0400; - // https://gitlab.redox-os.org/redox-os/relibc/-/blob/master/src/header/sys_socket/constants.rs - #[cfg(target_os = "redox")] - pub const SO_TYPE: c_int = 3; - #[cfg(target_os = "redox")] - pub const MSG_OOB: c_int = 1; - #[cfg(target_os = "redox")] - pub const MSG_WAITALL: c_int = 256; } #[cfg(windows)] mod c { @@ -1323,16 +1316,21 @@ fn get_addr(vm: &VirtualMachine, name: &str, af: i32) -> PyResult { } fn sock_from_raw(fileno: RawSocket, vm: &VirtualMachine) -> PyResult { - let invalid = if cfg!(windows) { - fileno == INVALID_SOCKET - } else { - fileno < 0 + let invalid = { + cfg_if::cfg_if! { + if #[cfg(windows)] { + fileno == INVALID_SOCKET + } else { + fileno < 0 + } + } }; if invalid { return Err(vm.new_value_error("negative file descriptor".to_owned())); } Ok(unsafe { sock_from_raw_unchecked(fileno) }) } +/// SAFETY: fileno must not be equal to INVALID_SOCKET unsafe fn sock_from_raw_unchecked(fileno: RawSocket) -> Socket { #[cfg(unix)] { @@ -1381,16 +1379,8 @@ const INVALID_SOCKET: RawSocket = { } }; fn invalid_sock() -> Socket { - #[cfg(unix)] - { - use std::os::unix::io::FromRawFd; - unsafe { Socket::from_raw_fd(INVALID_SOCKET) } - } - #[cfg(windows)] - { - use std::os::windows::io::FromRawSocket; - unsafe { Socket::from_raw_socket(INVALID_SOCKET) } - } + // TODO: socket2 might make Socket have a niche at -1, so this may be UB in the future + unsafe { sock_from_raw_unchecked(INVALID_SOCKET) } } fn convert_gai_error(vm: &VirtualMachine, err: dns_lookup::LookupError) -> PyBaseExceptionRef {