From bed54e035cabd9b25373db153304d46fd8de3be7 Mon Sep 17 00:00:00 2001 From: coolreader18 <33094578+coolreader18@users.noreply.github.com> Date: Thu, 7 Nov 2019 18:28:18 -0600 Subject: [PATCH] Add some constants to native modules --- Cargo.lock | 1 + bytecode/src/bytecode.rs | 7 +++++ vm/Cargo.toml | 1 + vm/src/obj/objcode.rs | 5 ++++ vm/src/stdlib/dis.rs | 19 ++++++++++++-- vm/src/stdlib/os.rs | 12 +++++++++ vm/src/stdlib/select.rs | 5 ++++ vm/src/stdlib/socket.rs | 57 +++++++++++++++++++++++++--------------- 8 files changed, 84 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63615acd2..e7b309465 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1295,6 +1295,7 @@ dependencies = [ "flamer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/bytecode/src/bytecode.rs b/bytecode/src/bytecode.rs index bd166ff8d..7f84163b7 100644 --- a/bytecode/src/bytecode.rs +++ b/bytecode/src/bytecode.rs @@ -65,6 +65,13 @@ impl Default for CodeFlags { } } +impl CodeFlags { + pub const NAME_MAPPING: &'static [(&'static str, CodeFlags)] = &[ + ("GENERATOR", CodeFlags::IS_GENERATOR), + ("COROUTINE", CodeFlags::IS_COROUTINE), + ]; +} + #[derive(Serialize, Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash)] pub struct Label(usize); diff --git a/vm/Cargo.toml b/vm/Cargo.toml index f5df633fa..89a7b8ce9 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -32,6 +32,7 @@ num-rational = "0.2.2" num-iter = "0.1.39" rand = "0.7" rand_distr = "0.2" +getrandom = "0.1" log = "0.4" rustpython-derive = {path = "../derive", version = "0.1.1"} rustpython-parser = {path = "../parser", optional = true, version = "0.1.1"} diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs index c15fe47f9..23a99fbfd 100644 --- a/vm/src/obj/objcode.rs +++ b/vm/src/obj/objcode.rs @@ -86,6 +86,10 @@ impl PyCodeRef { fn co_name(self, _vm: &VirtualMachine) -> String { self.code.obj_name.clone() } + + fn co_flags(self, _vm: &VirtualMachine) -> u8 { + self.code.flags.bits() + } } pub fn init(context: &PyContext) { @@ -99,5 +103,6 @@ pub fn init(context: &PyContext) { "co_firstlineno" => context.new_property(PyCodeRef::co_firstlineno), "co_kwonlyargcount" => context.new_property(PyCodeRef::co_kwonlyargcount), "co_name" => context.new_property(PyCodeRef::co_name), + "co_flags" => context.new_property(PyCodeRef::co_flags), }); } diff --git a/vm/src/stdlib/dis.rs b/vm/src/stdlib/dis.rs index 4c35f45e9..8302ef919 100644 --- a/vm/src/stdlib/dis.rs +++ b/vm/src/stdlib/dis.rs @@ -1,5 +1,6 @@ +use crate::bytecode::CodeFlags; use crate::obj::objcode::PyCodeRef; -use crate::pyobject::{PyObjectRef, PyResult, TryFromObject}; +use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult, TryFromObject}; use crate::vm::VirtualMachine; fn dis_dis(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { @@ -17,11 +18,25 @@ fn dis_disassemble(co: PyObjectRef, vm: &VirtualMachine) -> PyResult { Ok(vm.get_none()) } +fn dis_compiler_flag_names(vm: &VirtualMachine) -> PyObjectRef { + let dict = vm.ctx.new_dict(); + for (name, flag) in CodeFlags::NAME_MAPPING { + dict.set_item( + &vm.ctx.new_int(flag.bits()), + vm.ctx.new_str(name.to_string()), + vm, + ) + .unwrap(); + } + dict.into_object() +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; py_module!(vm, "dis", { "dis" => ctx.new_rustfunc(dis_dis), - "disassemble" => ctx.new_rustfunc(dis_disassemble) + "disassemble" => ctx.new_rustfunc(dis_disassemble), + "COMPILER_FLAG_NAMES" => dis_compiler_flag_names(vm), }) } diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index ec01180a4..9307b98e5 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1090,6 +1090,17 @@ pub fn os_ttyname(fd: i32, vm: &VirtualMachine) -> PyResult { } } +fn os_urandom(size: usize, vm: &VirtualMachine) -> PyResult> { + let mut buf = vec![0u8; size]; + match getrandom::getrandom(&mut buf) { + Ok(()) => Ok(buf), + Err(e) => match e.raw_os_error() { + Some(errno) => Err(convert_io_error(vm, io::Error::from_raw_os_error(errno))), + None => Err(vm.new_os_error("Getting random failed".to_string())), + }, + } +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; @@ -1214,6 +1225,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "getpid" => ctx.new_rustfunc(os_getpid), "cpu_count" => ctx.new_rustfunc(os_cpu_count), "_exit" => ctx.new_rustfunc(os_exit), + "urandom" => ctx.new_rustfunc(os_urandom), "O_RDONLY" => ctx.new_int(libc::O_RDONLY), "O_WRONLY" => ctx.new_int(libc::O_WRONLY), diff --git a/vm/src/stdlib/select.rs b/vm/src/stdlib/select.rs index c8e81442f..9da61b441 100644 --- a/vm/src/stdlib/select.rs +++ b/vm/src/stdlib/select.rs @@ -135,6 +135,11 @@ fn select_select( let (wlist, mut w) = seq2set(&wlist)?; let (xlist, mut x) = seq2set(&xlist)?; + if rlist.is_empty() && wlist.is_empty() && xlist.is_empty() { + let empty = vm.ctx.new_list(vec![]); + return Ok((empty.clone(), empty.clone(), empty)); + } + let nfds = [&mut r, &mut w, &mut x] .iter_mut() .filter_map(|set| set.highest()) diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 970a05afe..84d88c977 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -7,7 +7,7 @@ use byteorder::{BigEndian, ByteOrder}; use gethostname::gethostname; #[cfg(all(unix, not(target_os = "redox")))] use nix::unistd::sethostname; -use socket2::{Domain, Socket, Type as SocketType}; +use socket2::{Domain, Protocol, Socket, Type as SocketType}; use super::os::convert_io_error; #[cfg(unix)] @@ -27,7 +27,31 @@ type RawSocket = std::os::unix::io::RawFd; type RawSocket = std::os::windows::raw::SOCKET; #[cfg(unix)] -use libc as c; +mod c { + pub use libc::*; + // TODO: open a PR to add these constants to libc; then just use libc + #[cfg(target_os = "android")] + pub const AI_PASSIVE: c_int = 0x00000001; + #[cfg(target_os = "android")] + pub const AI_CANONNAME: c_int = 0x00000002; + #[cfg(target_os = "android")] + pub const AI_NUMERICHOST: c_int = 0x00000004; + #[cfg(target_os = "android")] + pub const AI_NUMERICSERV: c_int = 0x00000008; + #[cfg(target_os = "android")] + pub const AI_MASK: c_int = + AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_ADDRCONFIG; + #[cfg(target_os = "android")] + pub const AI_ALL: c_int = 0x00000100; + #[cfg(target_os = "android")] + pub const AI_V4MAPPED_CFG: c_int = 0x00000200; + #[cfg(target_os = "android")] + pub const AI_ADDRCONFIG: c_int = 0x00000400; + #[cfg(target_os = "android")] + pub const AI_V4MAPPED: c_int = 0x00000800; + #[cfg(target_os = "android")] + pub const AI_DEFAULT: c_int = AI_V4MAPPED_CFG | AI_ADDRCONFIG; +} #[cfg(windows)] mod c { pub use winapi::shared::ws2def::*; @@ -92,28 +116,17 @@ impl PySocket { unsafe { Socket::from_raw_socket(fileno) } } } else { - let domain = match family { - c::AF_INET => Domain::ipv4(), - c::AF_INET6 => Domain::ipv6(), - #[cfg(unix)] - c::AF_UNIX => Domain::unix(), - _ => { - return Err(vm.new_os_error(format!("Unknown address family value: {}", family))) - } - }; + let sock = Socket::new( + Domain::from(family), + SocketType::from(socket_kind), + Some(Protocol::from(proto)), + ) + .map_err(|err| convert_sock_error(vm, err))?; + self.family.set(family); - let socket_type = match socket_kind { - c::SOCK_STREAM => SocketType::stream(), - c::SOCK_DGRAM => SocketType::dgram(), - _ => { - return Err( - vm.new_os_error(format!("Unknown socket kind value: {}", socket_kind)) - ) - } - }; self.kind.set(socket_kind); self.proto.set(proto); - Socket::new(domain, socket_type, None).map_err(|err| convert_sock_error(vm, err))? + sock }; self.sock.replace(sock); Ok(()) @@ -435,6 +448,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "error" => ctx.exceptions.os_error.clone(), "timeout" => socket_timeout, "gaierror" => socket_gaierror, + "AF_UNSPEC" => ctx.new_int(0), "AF_INET" => ctx.new_int(c::AF_INET), "AF_INET6" => ctx.new_int(c::AF_INET6), "SOCK_STREAM" => ctx.new_int(c::SOCK_STREAM), @@ -446,6 +460,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "MSG_PEEK" => ctx.new_int(c::MSG_PEEK), "MSG_WAITALL" => ctx.new_int(c::MSG_WAITALL), "AI_ALL" => ctx.new_int(c::AI_ALL), + "AI_PASSIVE" => ctx.new_int(c::AI_PASSIVE), "socket" => PySocket::make_class(ctx), "inet_aton" => ctx.new_rustfunc(socket_inet_aton), "inet_ntoa" => ctx.new_rustfunc(socket_inet_ntoa),