From 6bc8f164b09b9994e6a2d4c4ca60d7d36c09d3fe Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 1 Nov 2017 12:32:13 -0700 Subject: std: Remove `rand` crate and module This commit removes the `rand` crate from the standard library facade as well as the `__rand` module in the standard library. Neither of these were used in any meaningful way in the standard library itself. The only need for randomness in libstd is to initialize the thread-local keys of a `HashMap`, and that unconditionally used `OsRng` defined in the standard library anyway. The cruft of the `rand` crate and the extra `rand` support in the standard library makes libstd slightly more difficult to port to new platforms, namely WebAssembly which doesn't have any randomness at all (without interfacing with JS). The purpose of this commit is to clarify and streamline randomness in libstd, focusing on how it's only required in one location, hashmap seeds. Note that the `rand` crate out of tree has almost always been a drop-in replacement for the `rand` crate in-tree, so any usage (accidental or purposeful) of the crate in-tree should switch to the `rand` crate on crates.io. This then also has the further benefit of avoiding duplication (mostly) between the two crates! --- src/libstd/Cargo.toml | 4 +- src/libstd/collections/hash/map.rs | 6 +- src/libstd/lib.rs | 16 +- src/libstd/rand/mod.rs | 286 ------------------------------------ src/libstd/rt.rs | 1 - src/libstd/sync/rwlock.rs | 4 +- src/libstd/sys/redox/mod.rs | 2 + src/libstd/sys/redox/rand.rs | 48 +----- src/libstd/sys/unix/mod.rs | 2 + src/libstd/sys/unix/rand.rs | 289 ++++++++++--------------------------- src/libstd/sys/windows/mod.rs | 2 + src/libstd/sys/windows/pipe.rs | 18 ++- src/libstd/sys/windows/rand.rs | 46 ++---- 13 files changed, 114 insertions(+), 610 deletions(-) delete mode 100644 src/libstd/rand/mod.rs (limited to 'src/libstd') diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index d239b79d4ba..3430ecabcbe 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -20,12 +20,14 @@ panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } core = { path = "../libcore" } libc = { path = "../rustc/libc_shim" } -rand = { path = "../librand" } compiler_builtins = { path = "../rustc/compiler_builtins_shim" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } std_unicode = { path = "../libstd_unicode" } unwind = { path = "../libunwind" } +[dev-dependencies] +rand = "0.3" + [target.x86_64-apple-darwin.dependencies] rustc_asan = { path = "../librustc_asan" } rustc_tsan = { path = "../librustc_tsan" } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index d96a4f40d3f..1771e924414 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -20,8 +20,8 @@ use hash::{Hash, Hasher, BuildHasher, SipHasher13}; use iter::{FromIterator, FusedIterator}; use mem::{self, replace}; use ops::{Deref, Index, InPlace, Place, Placer}; -use rand::{self, Rng}; use ptr; +use sys; use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash}; use super::table::BucketState::{Empty, Full}; @@ -2461,9 +2461,7 @@ impl RandomState { // increment one of the seeds on every RandomState creation, giving // every corresponding HashMap a different iteration order. thread_local!(static KEYS: Cell<(u64, u64)> = { - let r = rand::OsRng::new(); - let mut r = r.expect("failed to create an OS RNG"); - Cell::new((r.gen(), r.gen())) + Cell::new(sys::hashmap_random_keys()) }); KEYS.with(|keys| { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 429153dc58b..37cc7a49b52 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -356,6 +356,7 @@ use prelude::v1::*; // Access to Bencher, etc. #[cfg(test)] extern crate test; +#[cfg(test)] extern crate rand; // We want to reexport a few macros from core but libcore has already been // imported by the compiler (via our #[no_std] attribute) In this case we just @@ -364,9 +365,6 @@ use prelude::v1::*; debug_assert_ne, unreachable, unimplemented, write, writeln, try)] extern crate core as __core; -#[doc(masked)] -#[allow(deprecated)] -extern crate rand as core_rand; #[macro_use] #[macro_reexport(vec, format)] extern crate alloc; @@ -504,24 +502,12 @@ mod sys; // Private support modules mod panicking; -mod rand; mod memchr; // The runtime entry point and a few unstable public functions used by the // compiler pub mod rt; -// Some external utilities of the standard library rely on randomness (aka -// rustc_back::TempDir and tests) and need a way to get at the OS rng we've got -// here. This module is not at all intended for stabilization as-is, however, -// but it may be stabilized long-term. As a result we're exposing a hidden, -// unstable module so we can get our build working. -#[doc(hidden)] -#[unstable(feature = "rand", issue = "27703")] -pub mod __rand { - pub use rand::{thread_rng, ThreadRng, Rng}; -} - // Include a number of private modules that exist solely to provide // the rustdoc documentation for primitive types. Using `include!` // because rustdoc only looks for these modules at the crate level. diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs deleted file mode 100644 index 8da070e7a49..00000000000 --- a/src/libstd/rand/mod.rs +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Utilities for random number generation -//! -//! The key functions are `random()` and `Rng::gen()`. These are polymorphic -//! and so can be used to generate any type that implements `Rand`. Type inference -//! means that often a simple call to `rand::random()` or `rng.gen()` will -//! suffice, but sometimes an annotation is required, e.g. `rand::random::()`. -//! -//! See the `distributions` submodule for sampling random numbers from -//! distributions like normal and exponential. -//! -//! # Thread-local RNG -//! -//! There is built-in support for a RNG associated with each thread stored -//! in thread-local storage. This RNG can be accessed via `thread_rng`, or -//! used implicitly via `random`. This RNG is normally randomly seeded -//! from an operating-system source of randomness, e.g. `/dev/urandom` on -//! Unix systems, and will automatically reseed itself from this source -//! after generating 32 KiB of random data. -//! -//! # Cryptographic security -//! -//! An application that requires an entropy source for cryptographic purposes -//! must use `OsRng`, which reads randomness from the source that the operating -//! system provides (e.g. `/dev/urandom` on Unixes or `CryptGenRandom()` on Windows). -//! The other random number generators provided by this module are not suitable -//! for such purposes. -//! -//! *Note*: many Unix systems provide `/dev/random` as well as `/dev/urandom`. -//! This module uses `/dev/urandom` for the following reasons: -//! -//! - On Linux, `/dev/random` may block if entropy pool is empty; `/dev/urandom` will not block. -//! This does not mean that `/dev/random` provides better output than -//! `/dev/urandom`; the kernel internally runs a cryptographically secure pseudorandom -//! number generator (CSPRNG) based on entropy pool for random number generation, -//! so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases. -//! However, this means that `/dev/urandom` can yield somewhat predictable randomness -//! if the entropy pool is very small, such as immediately after first booting. -//! Linux 3.17 added the `getrandom(2)` system call which solves the issue: it blocks if entropy -//! pool is not initialized yet, but it does not block once initialized. -//! `getrandom(2)` was based on `getentropy(2)`, an existing system call in OpenBSD. -//! `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not. -//! If an application does not have `getrandom` and likely to be run soon after first booting, -//! or on a system with very few entropy sources, one should consider using `/dev/random` via -//! `ReaderRng`. -//! - On some systems (e.g. FreeBSD, OpenBSD and macOS) there is no difference -//! between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random` -//! and `/dev/urandom` may block once if the CSPRNG has not seeded yet.) - -#![unstable(feature = "rand", issue = "27703")] - -use cell::RefCell; -use fmt; -use io; -use mem; -use rc::Rc; -use sys; - -#[cfg(target_pointer_width = "32")] -use core_rand::IsaacRng as IsaacWordRng; -#[cfg(target_pointer_width = "64")] -use core_rand::Isaac64Rng as IsaacWordRng; - -pub use core_rand::{Rand, Rng, SeedableRng}; -pub use core_rand::{XorShiftRng, IsaacRng, Isaac64Rng}; -pub use core_rand::reseeding; - -pub mod reader; - -/// The standard RNG. This is designed to be efficient on the current -/// platform. -#[derive(Copy, Clone)] -pub struct StdRng { - rng: IsaacWordRng, -} - -impl StdRng { - /// Create a randomly seeded instance of `StdRng`. - /// - /// This is a very expensive operation as it has to read - /// randomness from the operating system and use this in an - /// expensive seeding operation. If one is only generating a small - /// number of random numbers, or doesn't need the utmost speed for - /// generating each number, `thread_rng` and/or `random` may be more - /// appropriate. - /// - /// Reading the randomness from the OS may fail, and any error is - /// propagated via the `io::Result` return value. - pub fn new() -> io::Result { - OsRng::new().map(|mut r| StdRng { rng: r.gen() }) - } -} - -impl Rng for StdRng { - #[inline] - fn next_u32(&mut self) -> u32 { - self.rng.next_u32() - } - - #[inline] - fn next_u64(&mut self) -> u64 { - self.rng.next_u64() - } -} - -impl<'a> SeedableRng<&'a [usize]> for StdRng { - fn reseed(&mut self, seed: &'a [usize]) { - // the internal RNG can just be seeded from the above - // randomness. - self.rng.reseed(unsafe {mem::transmute(seed)}) - } - - fn from_seed(seed: &'a [usize]) -> StdRng { - StdRng { rng: SeedableRng::from_seed(unsafe {mem::transmute(seed)}) } - } -} - -/// Controls how the thread-local RNG is reseeded. -struct ThreadRngReseeder; - -impl reseeding::Reseeder for ThreadRngReseeder { - fn reseed(&mut self, rng: &mut StdRng) { - *rng = match StdRng::new() { - Ok(r) => r, - Err(e) => panic!("could not reseed thread_rng: {}", e) - } - } -} -const THREAD_RNG_RESEED_THRESHOLD: usize = 32_768; -type ThreadRngInner = reseeding::ReseedingRng; - -/// The thread-local RNG. -#[derive(Clone)] -pub struct ThreadRng { - rng: Rc>, -} - -impl fmt::Debug for ThreadRng { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("ThreadRng { .. }") - } -} - -/// Retrieve the lazily-initialized thread-local random number -/// generator, seeded by the system. Intended to be used in method -/// chaining style, e.g. `thread_rng().gen::()`. -/// -/// The RNG provided will reseed itself from the operating system -/// after generating a certain amount of randomness. -/// -/// The internal RNG used is platform and architecture dependent, even -/// if the operating system random number generator is rigged to give -/// the same sequence always. If absolute consistency is required, -/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`. -pub fn thread_rng() -> ThreadRng { - // used to make space in TLS for a random number generator - thread_local!(static THREAD_RNG_KEY: Rc> = { - let r = match StdRng::new() { - Ok(r) => r, - Err(e) => panic!("could not initialize thread_rng: {}", e) - }; - let rng = reseeding::ReseedingRng::new(r, - THREAD_RNG_RESEED_THRESHOLD, - ThreadRngReseeder); - Rc::new(RefCell::new(rng)) - }); - - ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) } -} - -impl Rng for ThreadRng { - fn next_u32(&mut self) -> u32 { - self.rng.borrow_mut().next_u32() - } - - fn next_u64(&mut self) -> u64 { - self.rng.borrow_mut().next_u64() - } - - #[inline] - fn fill_bytes(&mut self, bytes: &mut [u8]) { - self.rng.borrow_mut().fill_bytes(bytes) - } -} - -/// A random number generator that retrieves randomness straight from -/// the operating system. Platform sources: -/// -/// - Unix-like systems (Linux, Android, macOS): read directly from -/// `/dev/urandom`, or from `getrandom(2)` system call if available. -/// - Windows: calls `CryptGenRandom`, using the default cryptographic -/// service provider with the `PROV_RSA_FULL` type. -/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed. -/// - OpenBSD: uses the `getentropy(2)` system call. -/// -/// This does not block. -pub struct OsRng(sys::rand::OsRng); - -impl OsRng { - /// Create a new `OsRng`. - pub fn new() -> io::Result { - sys::rand::OsRng::new().map(OsRng) - } -} - -impl Rng for OsRng { - #[inline] - fn next_u32(&mut self) -> u32 { - self.0.next_u32() - } - - #[inline] - fn next_u64(&mut self) -> u64 { - self.0.next_u64() - } - - #[inline] - fn fill_bytes(&mut self, bytes: &mut [u8]) { - self.0.fill_bytes(bytes) - } -} - - -#[cfg(test)] -mod tests { - use sync::mpsc::channel; - use rand::Rng; - use super::OsRng; - use thread; - - #[test] - fn test_os_rng() { - let mut r = OsRng::new().unwrap(); - - r.next_u32(); - r.next_u64(); - - let mut v = [0; 1000]; - r.fill_bytes(&mut v); - } - - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - fn test_os_rng_tasks() { - - let mut txs = vec![]; - for _ in 0..20 { - let (tx, rx) = channel(); - txs.push(tx); - - thread::spawn(move|| { - // wait until all the threads are ready to go. - rx.recv().unwrap(); - - // deschedule to attempt to interleave things as much - // as possible (XXX: is this a good test?) - let mut r = OsRng::new().unwrap(); - thread::yield_now(); - let mut v = [0; 1000]; - - for _ in 0..100 { - r.next_u32(); - thread::yield_now(); - r.next_u64(); - thread::yield_now(); - r.fill_bytes(&mut v); - thread::yield_now(); - } - }); - } - - // start all the threads - for tx in &txs { - tx.send(()).unwrap(); - } - } -} diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index 06fd838ea06..40b24cedcdc 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -23,7 +23,6 @@ #![doc(hidden)] - // Reexport some of our utilities which are expected by other crates. pub use panicking::{begin_panic, begin_panic_fmt, update_panic_count}; diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index d59a0b65a69..6216d78528d 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -554,8 +554,6 @@ impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> { #[cfg(all(test, not(target_os = "emscripten")))] mod tests { - #![allow(deprecated)] // rand - use rand::{self, Rng}; use sync::mpsc::channel; use thread; @@ -576,7 +574,7 @@ mod tests { #[test] fn frob() { - const N: usize = 10; + const N: u32 = 10; const M: usize = 1000; let r = Arc::new(RwLock::new(())); diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index 7c728ebb1af..7137a506743 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -12,6 +12,8 @@ use io::{self, ErrorKind}; +pub use self::rand::hashmap_random_keys; + pub mod args; #[cfg(feature = "backtrace")] pub mod backtrace; diff --git a/src/libstd/sys/redox/rand.rs b/src/libstd/sys/redox/rand.rs index eb28eca38bc..3b378f53429 100644 --- a/src/libstd/sys/redox/rand.rs +++ b/src/libstd/sys/redox/rand.rs @@ -8,50 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use io; -use rand::Rng; - -// FIXME: Use rand: -pub struct OsRng { - state: [u64; 2] -} - -impl OsRng { - /// Create a new `OsRng`. - pub fn new() -> io::Result { - Ok(OsRng { - state: [0xBADF00D1, 0xDEADBEEF] - }) - } -} - -impl Rng for OsRng { - fn next_u32(&mut self) -> u32 { - self.next_u64() as u32 - } - fn next_u64(&mut self) -> u64 { - // Store the first and second part. - let mut x = self.state[0]; - let y = self.state[1]; - - // Put the second part into the first slot. - self.state[0] = y; - // Twist the first slot. - x ^= x << 23; - // Update the second slot. - self.state[1] = x ^ y ^ (x >> 17) ^ (y >> 26); - - // Generate the final integer. - self.state[1].wrapping_add(y) - - } - fn fill_bytes(&mut self, buf: &mut [u8]) { - for chunk in buf.chunks_mut(8) { - let mut rand: u64 = self.next_u64(); - for b in chunk.iter_mut() { - *b = rand as u8; - rand = rand >> 8; - } - } - } +pub fn hashmap_random_keys() -> (u64, u64) { + (0, 0) } diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index c2772e2e2cc..4669b2a636c 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -29,6 +29,8 @@ use libc; #[cfg(all(not(dox), target_os = "fuchsia"))] pub use os::fuchsia as platform; #[cfg(all(not(dox), target_os = "l4re"))] pub use os::linux as platform; +pub use self::rand::hashmap_random_keys; + #[macro_use] pub mod weak; diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index e2d40742c71..bbffe0f0ffe 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -8,20 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::imp::OsRng; - use mem; - -fn next_u32(fill_buf: &mut FnMut(&mut [u8])) -> u32 { - let mut buf: [u8; 4] = [0; 4]; - fill_buf(&mut buf); - unsafe { mem::transmute::<[u8; 4], u32>(buf) } -} - -fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 { - let mut buf: [u8; 8] = [0; 8]; - fill_buf(&mut buf); - unsafe { mem::transmute::<[u8; 8], u64>(buf) } +use slice; + +pub fn hashmap_random_keys() -> (u64, u64) { + let mut v = (0, 0); + unsafe { + let view = slice::from_raw_parts_mut(&mut v as *mut _ as *mut u8, + mem::size_of_val(&v)); + imp::fill_bytes(view); + } + return v } #[cfg(all(unix, @@ -30,14 +27,9 @@ fn next_u64(fill_buf: &mut FnMut(&mut [u8])) -> u64 { not(target_os = "freebsd"), not(target_os = "fuchsia")))] mod imp { - use self::OsRngInner::*; - use super::{next_u32, next_u64}; - use fs::File; - use io; + use io::Read; use libc; - use rand::Rng; - use rand::reader::ReaderRng; use sys::os::errno; #[cfg(all(target_os = "linux", @@ -81,7 +73,7 @@ mod imp { target_arch = "s390x"))))] fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 } - fn getrandom_fill_bytes(v: &mut [u8]) { + fn getrandom_fill_bytes(v: &mut [u8]) -> bool { let mut read = 0; while read < v.len() { let result = getrandom(&mut v[read..]); @@ -90,18 +82,7 @@ mod imp { if err == libc::EINTR { continue; } else if err == libc::EAGAIN { - // if getrandom() returns EAGAIN it would have blocked - // because the non-blocking pool (urandom) has not - // initialized in the kernel yet due to a lack of entropy - // the fallback we do here is to avoid blocking applications - // which could depend on this call without ever knowing - // they do and don't have a work around. The PRNG of - // /dev/urandom will still be used but not over a completely - // full entropy pool - let reader = File::open("/dev/urandom").expect("Unable to open /dev/urandom"); - let mut reader_rng = ReaderRng::new(reader); - reader_rng.fill_bytes(&mut v[read..]); - read += v.len(); + return false } else { panic!("unexpected getrandom error: {}", err); } @@ -109,6 +90,8 @@ mod imp { read += result as usize; } } + + return true } #[cfg(all(target_os = "linux", @@ -120,6 +103,7 @@ mod imp { target_arch = "powerpc64", target_arch = "s390x")))] fn is_getrandom_available() -> bool { + use io; use sync::atomic::{AtomicBool, Ordering}; use sync::Once; @@ -151,89 +135,37 @@ mod imp { target_arch = "s390x"))))] fn is_getrandom_available() -> bool { false } - pub struct OsRng { - inner: OsRngInner, - } - - enum OsRngInner { - OsGetrandomRng, - OsReaderRng(ReaderRng), - } - - impl OsRng { - /// Create a new `OsRng`. - pub fn new() -> io::Result { - if is_getrandom_available() { - return Ok(OsRng { inner: OsGetrandomRng }); - } - - let reader = File::open("/dev/urandom")?; - let reader_rng = ReaderRng::new(reader); - - Ok(OsRng { inner: OsReaderRng(reader_rng) }) + pub fn fill_bytes(v: &mut [u8]) { + // getrandom_fill_bytes here can fail if getrandom() returns EAGAIN, + // meaning it would have blocked because the non-blocking pool (urandom) + // has not initialized in the kernel yet due to a lack of entropy the + // fallback we do here is to avoid blocking applications which could + // depend on this call without ever knowing they do and don't have a + // work around. The PRNG of /dev/urandom will still be used but not + // over a completely full entropy pool + if is_getrandom_available() && getrandom_fill_bytes(v) { + return } - } - impl Rng for OsRng { - fn next_u32(&mut self) -> u32 { - match self.inner { - OsGetrandomRng => next_u32(&mut getrandom_fill_bytes), - OsReaderRng(ref mut rng) => rng.next_u32(), - } - } - fn next_u64(&mut self) -> u64 { - match self.inner { - OsGetrandomRng => next_u64(&mut getrandom_fill_bytes), - OsReaderRng(ref mut rng) => rng.next_u64(), - } - } - fn fill_bytes(&mut self, v: &mut [u8]) { - match self.inner { - OsGetrandomRng => getrandom_fill_bytes(v), - OsReaderRng(ref mut rng) => rng.fill_bytes(v) - } - } + let mut file = File::open("/dev/urandom") + .expect("failed to open /dev/urandom"); + file.read_exact(v).expect("failed to read /dev/urandom"); } } #[cfg(target_os = "openbsd")] mod imp { - use super::{next_u32, next_u64}; - - use io; use libc; use sys::os::errno; - use rand::Rng; - - pub struct OsRng { - // dummy field to ensure that this struct cannot be constructed outside - // of this module - _dummy: (), - } - - impl OsRng { - /// Create a new `OsRng`. - pub fn new() -> io::Result { - Ok(OsRng { _dummy: () }) - } - } - impl Rng for OsRng { - fn next_u32(&mut self) -> u32 { - next_u32(&mut |v| self.fill_bytes(v)) - } - fn next_u64(&mut self) -> u64 { - next_u64(&mut |v| self.fill_bytes(v)) - } - fn fill_bytes(&mut self, v: &mut [u8]) { - // getentropy(2) permits a maximum buffer size of 256 bytes - for s in v.chunks_mut(256) { - let ret = unsafe { - libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len()) - }; - if ret == -1 { - panic!("unexpected getentropy error: {}", errno()); - } + pub fn fill_bytes(v: &mut [u8]) { + // getentropy(2) permits a maximum buffer size of 256 bytes + for s in v.chunks_mut(256) { + let ret = unsafe { + libc::getentropy(s.as_mut_ptr() as *mut libc::c_void, s.len()) + }; + if ret == -1 { + panic!("unexpected getentropy error: {}", errno()); } } } @@ -241,18 +173,9 @@ mod imp { #[cfg(target_os = "ios")] mod imp { - use super::{next_u32, next_u64}; - use io; - use ptr; - use rand::Rng; use libc::{c_int, size_t}; - - pub struct OsRng { - // dummy field to ensure that this struct cannot be constructed outside - // of this module - _dummy: (), - } + use ptr; enum SecRandom {} @@ -261,79 +184,41 @@ mod imp { extern { fn SecRandomCopyBytes(rnd: *const SecRandom, - count: size_t, bytes: *mut u8) -> c_int; + count: size_t, + bytes: *mut u8) -> c_int; } - impl OsRng { - /// Create a new `OsRng`. - pub fn new() -> io::Result { - Ok(OsRng { _dummy: () }) - } - } - - impl Rng for OsRng { - fn next_u32(&mut self) -> u32 { - next_u32(&mut |v| self.fill_bytes(v)) - } - fn next_u64(&mut self) -> u64 { - next_u64(&mut |v| self.fill_bytes(v)) - } - fn fill_bytes(&mut self, v: &mut [u8]) { - let ret = unsafe { - SecRandomCopyBytes(kSecRandomDefault, v.len(), - v.as_mut_ptr()) - }; - if ret == -1 { - panic!("couldn't generate random bytes: {}", - io::Error::last_os_error()); - } + pub fn fill_bytes(v: &mut [u8]) { + let ret = unsafe { + SecRandomCopyBytes(kSecRandomDefault, + v.len(), + v.as_mut_ptr()) + }; + if ret == -1 { + panic!("couldn't generate random bytes: {}", + io::Error::last_os_error()); } } } #[cfg(target_os = "freebsd")] mod imp { - use super::{next_u32, next_u64}; - - use io; use libc; - use rand::Rng; use ptr; - pub struct OsRng { - // dummy field to ensure that this struct cannot be constructed outside - // of this module - _dummy: (), - } - - impl OsRng { - /// Create a new `OsRng`. - pub fn new() -> io::Result { - Ok(OsRng { _dummy: () }) - } - } - - impl Rng for OsRng { - fn next_u32(&mut self) -> u32 { - next_u32(&mut |v| self.fill_bytes(v)) - } - fn next_u64(&mut self) -> u64 { - next_u64(&mut |v| self.fill_bytes(v)) - } - fn fill_bytes(&mut self, v: &mut [u8]) { - let mib = [libc::CTL_KERN, libc::KERN_ARND]; - // kern.arandom permits a maximum buffer size of 256 bytes - for s in v.chunks_mut(256) { - let mut s_len = s.len(); - let ret = unsafe { - libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint, - s.as_mut_ptr() as *mut _, &mut s_len, - ptr::null(), 0) - }; - if ret == -1 || s_len != s.len() { - panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})", - ret, s.len(), s_len); - } + pub fn fill_bytes(v: &mut [u8]) { + let mib = [libc::CTL_KERN, libc::KERN_ARND]; + // kern.arandom permits a maximum buffer size of 256 bytes + for s in v.chunks_mut(256) { + let mut s_len = s.len(); + let ret = unsafe { + libc::sysctl(mib.as_ptr(), mib.len() as libc::c_uint, + s.as_mut_ptr() as *mut _, &mut s_len, + ptr::null(), 0) + }; + if ret == -1 || s_len != s.len() { + panic!("kern.arandom sysctl failed! (returned {}, s.len() {}, oldlenp {})", + ret, s.len(), s_len); } } } @@ -341,11 +226,6 @@ mod imp { #[cfg(target_os = "fuchsia")] mod imp { - use super::{next_u32, next_u64}; - - use io; - use rand::Rng; - #[link(name = "zircon")] extern { fn zx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32; @@ -363,39 +243,18 @@ mod imp { } } - pub struct OsRng { - // dummy field to ensure that this struct cannot be constructed outside - // of this module - _dummy: (), - } - - impl OsRng { - /// Create a new `OsRng`. - pub fn new() -> io::Result { - Ok(OsRng { _dummy: () }) - } - } - - impl Rng for OsRng { - fn next_u32(&mut self) -> u32 { - next_u32(&mut |v| self.fill_bytes(v)) - } - fn next_u64(&mut self) -> u64 { - next_u64(&mut |v| self.fill_bytes(v)) - } - fn fill_bytes(&mut self, v: &mut [u8]) { - let mut buf = v; - while !buf.is_empty() { - let ret = getrandom(buf); - match ret { - Err(err) => { - panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})", - err, buf.len()) - } - Ok(actual) => { - let move_buf = buf; - buf = &mut move_buf[(actual as usize)..]; - } + pub fn fill_bytes(v: &mut [u8]) { + let mut buf = v; + while !buf.is_empty() { + let ret = getrandom(buf); + match ret { + Err(err) => { + panic!("kernel zx_cprng_draw call failed! (returned {}, buf.len() {})", + err, buf.len()) + } + Ok(actual) => { + let move_buf = buf; + buf = &mut move_buf[(actual as usize)..]; } } } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index e7a9a121b25..ab8e155331e 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -17,6 +17,8 @@ use os::windows::ffi::{OsStrExt, OsStringExt}; use path::PathBuf; use time::Duration; +pub use self::rand::hashmap_random_keys; + #[macro_use] pub mod compat; pub mod args; diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index 452d720ce59..f3b1185c6ea 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -15,11 +15,13 @@ use io; use mem; use path::Path; use ptr; -use rand::{self, Rng}; use slice; +use sync::atomic::Ordering::SeqCst; +use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; use sys::c; use sys::fs::{File, OpenOptions}; use sys::handle::Handle; +use sys::hashmap_random_keys; //////////////////////////////////////////////////////////////////////////////// // Anonymous pipes @@ -71,10 +73,9 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result { let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS; loop { tries += 1; - let key: u64 = rand::thread_rng().gen(); name = format!(r"\\.\pipe\__rust_anonymous_pipe1__.{}.{}", c::GetCurrentProcessId(), - key); + random_number()); let wide_name = OsStr::new(&name) .encode_wide() .chain(Some(0)) @@ -156,6 +157,17 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result { } } +fn random_number() -> usize { + static N: AtomicUsize = ATOMIC_USIZE_INIT; + loop { + if N.load(SeqCst) != 0 { + return N.fetch_add(1, SeqCst) + } + + N.store(hashmap_random_keys().0 as usize, SeqCst); + } +} + impl AnonPipe { pub fn handle(&self) -> &Handle { &self.inner } pub fn into_handle(self) -> Handle { self.inner } diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs index f66b0a3bdc3..262323656aa 100644 --- a/src/libstd/sys/windows/rand.rs +++ b/src/libstd/sys/windows/rand.rs @@ -8,45 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use io; use mem; -use rand::Rng; use sys::c; -pub struct OsRng; - -impl OsRng { - /// Create a new `OsRng`. - pub fn new() -> io::Result { - Ok(OsRng) - } -} - -impl Rng for OsRng { - fn next_u32(&mut self) -> u32 { - let mut v = [0; 4]; - self.fill_bytes(&mut v); - unsafe { mem::transmute(v) } - } - - fn next_u64(&mut self) -> u64 { - let mut v = [0; 8]; - self.fill_bytes(&mut v); - unsafe { mem::transmute(v) } - } - - fn fill_bytes(&mut self, v: &mut [u8]) { - // RtlGenRandom takes an ULONG (u32) for the length so we need to - // split up the buffer. - for slice in v.chunks_mut(::max_value() as usize) { - let ret = unsafe { - c::RtlGenRandom(slice.as_mut_ptr(), slice.len() as c::ULONG) - }; - if ret == 0 { - panic!("couldn't generate random bytes: {}", - io::Error::last_os_error()); - } - } +pub fn hashmap_random_keys() -> (u64, u64) { + let mut v = (0, 0); + let ret = unsafe { + c::RtlGenRandom(&mut v as *mut _ as *mut u8, + mem::size_of_val(&v) as c::ULONG) + }; + if ret == 0 { + panic!("couldn't generate random bytes: {}", + io::Error::last_os_error()); } + return v } -- cgit 1.4.1-3-g733a5 From 1ccb50eaa670f86b69e7a64484a8c97e13169183 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 1 Nov 2017 12:50:13 -0700 Subject: std: Change how EBADF is handled in `sys` This commit removes the reexport of `EBADF_ERR` as a constant from libstd's portability facade, instead opting for a platform-specific function that specifically queries an `io::Error`. Not all platforms may have a constant for this, so it makes the intent a little more clear that a code need not be supplied, just an answer to a query. --- src/libstd/io/stdio.rs | 4 +--- src/libstd/sys/redox/stdio.rs | 5 ++++- src/libstd/sys/unix/stdio.rs | 5 ++++- src/libstd/sys/windows/stdio.rs | 5 ++++- 4 files changed, 13 insertions(+), 6 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index fb489bf487b..831688bb73d 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -121,10 +121,8 @@ impl io::Read for Maybe { } fn handle_ebadf(r: io::Result, default: T) -> io::Result { - use sys::stdio::EBADF_ERR; - match r { - Err(ref e) if e.raw_os_error() == Some(EBADF_ERR) => Ok(default), + Err(ref e) if stdio::is_ebadf(e) => Ok(default), r => r } } diff --git a/src/libstd/sys/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs index c839531cc26..3abb094ac34 100644 --- a/src/libstd/sys/redox/stdio.rs +++ b/src/libstd/sys/redox/stdio.rs @@ -70,5 +70,8 @@ impl io::Write for Stderr { } } -pub const EBADF_ERR: i32 = ::sys::syscall::EBADF; +pub fn is_ebadf(err: &io::Error) -> bool { + err.raw_os_error() == Some(::sys::syscall::EBADF as i32) +} + pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs index 7a8fe25d98e..e9b3d4affc7 100644 --- a/src/libstd/sys/unix/stdio.rs +++ b/src/libstd/sys/unix/stdio.rs @@ -70,5 +70,8 @@ impl io::Write for Stderr { } } -pub const EBADF_ERR: i32 = ::libc::EBADF as i32; +pub fn is_ebadf(err: &io::Error) -> bool { + err.raw_os_error() == Some(libc::EBADF as i32) +} + pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE; diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index b5e5b5760f2..b43df20bddd 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -218,7 +218,10 @@ fn readconsole_input_control(wakeup_mask: c::ULONG) -> c::CONSOLE_READCONSOLE_CO const CTRL_Z: u8 = 0x1A; const CTRL_Z_MASK: c::ULONG = 0x4000000; //1 << 0x1A -pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32; +pub fn is_ebadf(err: &io::Error) -> bool { + err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32) +} + // The default buffer capacity is 64k, but apparently windows // doesn't like 64k reads on stdin. See #13304 for details, but the // idea is that on windows we use a slightly smaller buffer that's -- cgit 1.4.1-3-g733a5 From 348930eb4e75ee9ce42e783fe9942c8eb5165bc1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 1 Nov 2017 12:59:40 -0700 Subject: std: Move the `cmath` module into the `sys` module This commit moves the `f32::cmath` and `f64::cmath` modules into the `sys` module. Note that these are not publicly exported modules, simply implementation details. These modules are already platform-specific with shims on MSVC and this is mostly just a reflection of that reality. This should also help cut down on `#[cfg]` traffic if platforms are brought on which don't directly support these functions. --- src/libstd/f32.rs | 88 +--------------------------------- src/libstd/f64.rs | 49 +------------------ src/libstd/sys/redox/cmath.rs | 43 +++++++++++++++++ src/libstd/sys/redox/mod.rs | 1 + src/libstd/sys/unix/cmath.rs | 43 +++++++++++++++++ src/libstd/sys/unix/mod.rs | 1 + src/libstd/sys/windows/cmath.rs | 103 ++++++++++++++++++++++++++++++++++++++++ src/libstd/sys/windows/mod.rs | 1 + 8 files changed, 196 insertions(+), 133 deletions(-) create mode 100644 src/libstd/sys/redox/cmath.rs create mode 100644 src/libstd/sys/unix/cmath.rs create mode 100644 src/libstd/sys/windows/cmath.rs (limited to 'src/libstd') diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 0135cd0a588..7ec6124dfa4 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -23,6 +23,8 @@ use core::num; use intrinsics; #[cfg(not(test))] use num::FpCategory; +#[cfg(not(test))] +use sys::cmath; #[stable(feature = "rust1", since = "1.0.0")] @@ -36,92 +38,6 @@ pub use core::f32::{MIN, MIN_POSITIVE, MAX}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::f32::consts; -#[allow(dead_code)] -mod cmath { - use libc::{c_float, c_int}; - - extern { - pub fn cbrtf(n: c_float) -> c_float; - pub fn erff(n: c_float) -> c_float; - pub fn erfcf(n: c_float) -> c_float; - pub fn expm1f(n: c_float) -> c_float; - pub fn fdimf(a: c_float, b: c_float) -> c_float; - pub fn fmodf(a: c_float, b: c_float) -> c_float; - pub fn ilogbf(n: c_float) -> c_int; - pub fn logbf(n: c_float) -> c_float; - pub fn log1pf(n: c_float) -> c_float; - pub fn modff(n: c_float, iptr: &mut c_float) -> c_float; - pub fn nextafterf(x: c_float, y: c_float) -> c_float; - pub fn tgammaf(n: c_float) -> c_float; - - #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgammaf_r")] - pub fn lgammaf_r(n: c_float, sign: &mut c_int) -> c_float; - #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypotf")] - pub fn hypotf(x: c_float, y: c_float) -> c_float; - } - - // See the comments in the `floor` function for why MSVC is special - // here. - #[cfg(not(target_env = "msvc"))] - extern { - pub fn acosf(n: c_float) -> c_float; - pub fn asinf(n: c_float) -> c_float; - pub fn atan2f(a: c_float, b: c_float) -> c_float; - pub fn atanf(n: c_float) -> c_float; - pub fn coshf(n: c_float) -> c_float; - pub fn sinhf(n: c_float) -> c_float; - pub fn tanf(n: c_float) -> c_float; - pub fn tanhf(n: c_float) -> c_float; - } - - #[cfg(target_env = "msvc")] - pub use self::shims::*; - #[cfg(target_env = "msvc")] - mod shims { - use libc::c_float; - - #[inline] - pub unsafe fn acosf(n: c_float) -> c_float { - f64::acos(n as f64) as c_float - } - - #[inline] - pub unsafe fn asinf(n: c_float) -> c_float { - f64::asin(n as f64) as c_float - } - - #[inline] - pub unsafe fn atan2f(n: c_float, b: c_float) -> c_float { - f64::atan2(n as f64, b as f64) as c_float - } - - #[inline] - pub unsafe fn atanf(n: c_float) -> c_float { - f64::atan(n as f64) as c_float - } - - #[inline] - pub unsafe fn coshf(n: c_float) -> c_float { - f64::cosh(n as f64) as c_float - } - - #[inline] - pub unsafe fn sinhf(n: c_float) -> c_float { - f64::sinh(n as f64) as c_float - } - - #[inline] - pub unsafe fn tanf(n: c_float) -> c_float { - f64::tan(n as f64) as c_float - } - - #[inline] - pub unsafe fn tanhf(n: c_float) -> c_float { - f64::tanh(n as f64) as c_float - } - } -} - #[cfg(not(test))] #[lang = "f32"] impl f32 { diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index d73d7cd2c7b..e0f0acc6ac4 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -23,6 +23,8 @@ use core::num; use intrinsics; #[cfg(not(test))] use num::FpCategory; +#[cfg(not(test))] +use sys::cmath; #[stable(feature = "rust1", since = "1.0.0")] pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON}; @@ -35,53 +37,6 @@ pub use core::f64::{MIN, MIN_POSITIVE, MAX}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::f64::consts; -#[allow(dead_code)] -mod cmath { - use libc::{c_double, c_int}; - - #[link_name = "m"] - extern { - pub fn acos(n: c_double) -> c_double; - pub fn asin(n: c_double) -> c_double; - pub fn atan(n: c_double) -> c_double; - pub fn atan2(a: c_double, b: c_double) -> c_double; - pub fn cbrt(n: c_double) -> c_double; - pub fn cosh(n: c_double) -> c_double; - pub fn erf(n: c_double) -> c_double; - pub fn erfc(n: c_double) -> c_double; - pub fn expm1(n: c_double) -> c_double; - pub fn fdim(a: c_double, b: c_double) -> c_double; - pub fn fmod(a: c_double, b: c_double) -> c_double; - pub fn frexp(n: c_double, value: &mut c_int) -> c_double; - pub fn ilogb(n: c_double) -> c_int; - pub fn ldexp(x: c_double, n: c_int) -> c_double; - pub fn logb(n: c_double) -> c_double; - pub fn log1p(n: c_double) -> c_double; - pub fn nextafter(x: c_double, y: c_double) -> c_double; - pub fn modf(n: c_double, iptr: &mut c_double) -> c_double; - pub fn sinh(n: c_double) -> c_double; - pub fn tan(n: c_double) -> c_double; - pub fn tanh(n: c_double) -> c_double; - pub fn tgamma(n: c_double) -> c_double; - - // These are commonly only available for doubles - - pub fn j0(n: c_double) -> c_double; - pub fn j1(n: c_double) -> c_double; - pub fn jn(i: c_int, n: c_double) -> c_double; - - pub fn y0(n: c_double) -> c_double; - pub fn y1(n: c_double) -> c_double; - pub fn yn(i: c_int, n: c_double) -> c_double; - - #[cfg_attr(all(windows, target_env = "msvc"), link_name = "__lgamma_r")] - pub fn lgamma_r(n: c_double, sign: &mut c_int) -> c_double; - - #[cfg_attr(all(windows, target_env = "msvc"), link_name = "_hypot")] - pub fn hypot(x: c_double, y: c_double) -> c_double; - } -} - #[cfg(not(test))] #[lang = "f64"] impl f64 { diff --git a/src/libstd/sys/redox/cmath.rs b/src/libstd/sys/redox/cmath.rs new file mode 100644 index 00000000000..2bc96651b0c --- /dev/null +++ b/src/libstd/sys/redox/cmath.rs @@ -0,0 +1,43 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(not(test))] + +use libc::{c_float, c_double}; + +#[link_name = "m"] +extern { + pub fn acos(n: c_double) -> c_double; + pub fn acosf(n: c_float) -> c_float; + pub fn asin(n: c_double) -> c_double; + pub fn asinf(n: c_float) -> c_float; + pub fn atan(n: c_double) -> c_double; + pub fn atan2(a: c_double, b: c_double) -> c_double; + pub fn atan2f(a: c_float, b: c_float) -> c_float; + pub fn atanf(n: c_float) -> c_float; + pub fn cbrt(n: c_double) -> c_double; + pub fn cbrtf(n: c_float) -> c_float; + pub fn cosh(n: c_double) -> c_double; + pub fn coshf(n: c_float) -> c_float; + pub fn expm1(n: c_double) -> c_double; + pub fn expm1f(n: c_float) -> c_float; + pub fn fdim(a: c_double, b: c_double) -> c_double; + pub fn fdimf(a: c_float, b: c_float) -> c_float; + pub fn hypot(x: c_double, y: c_double) -> c_double; + pub fn hypotf(x: c_float, y: c_float) -> c_float; + pub fn log1p(n: c_double) -> c_double; + pub fn log1pf(n: c_float) -> c_float; + pub fn sinh(n: c_double) -> c_double; + pub fn sinhf(n: c_float) -> c_float; + pub fn tan(n: c_double) -> c_double; + pub fn tanf(n: c_float) -> c_float; + pub fn tanh(n: c_double) -> c_double; + pub fn tanhf(n: c_float) -> c_float; +} diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index 7137a506743..ca5f6637514 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -17,6 +17,7 @@ pub use self::rand::hashmap_random_keys; pub mod args; #[cfg(feature = "backtrace")] pub mod backtrace; +pub mod cmath; pub mod condvar; pub mod env; pub mod ext; diff --git a/src/libstd/sys/unix/cmath.rs b/src/libstd/sys/unix/cmath.rs new file mode 100644 index 00000000000..2bc96651b0c --- /dev/null +++ b/src/libstd/sys/unix/cmath.rs @@ -0,0 +1,43 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(not(test))] + +use libc::{c_float, c_double}; + +#[link_name = "m"] +extern { + pub fn acos(n: c_double) -> c_double; + pub fn acosf(n: c_float) -> c_float; + pub fn asin(n: c_double) -> c_double; + pub fn asinf(n: c_float) -> c_float; + pub fn atan(n: c_double) -> c_double; + pub fn atan2(a: c_double, b: c_double) -> c_double; + pub fn atan2f(a: c_float, b: c_float) -> c_float; + pub fn atanf(n: c_float) -> c_float; + pub fn cbrt(n: c_double) -> c_double; + pub fn cbrtf(n: c_float) -> c_float; + pub fn cosh(n: c_double) -> c_double; + pub fn coshf(n: c_float) -> c_float; + pub fn expm1(n: c_double) -> c_double; + pub fn expm1f(n: c_float) -> c_float; + pub fn fdim(a: c_double, b: c_double) -> c_double; + pub fn fdimf(a: c_float, b: c_float) -> c_float; + pub fn hypot(x: c_double, y: c_double) -> c_double; + pub fn hypotf(x: c_float, y: c_float) -> c_float; + pub fn log1p(n: c_double) -> c_double; + pub fn log1pf(n: c_float) -> c_float; + pub fn sinh(n: c_double) -> c_double; + pub fn sinhf(n: c_float) -> c_float; + pub fn tan(n: c_double) -> c_double; + pub fn tanf(n: c_float) -> c_float; + pub fn tanh(n: c_double) -> c_double; + pub fn tanhf(n: c_float) -> c_float; +} diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 4669b2a636c..47be7ab0394 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -38,6 +38,7 @@ pub mod args; pub mod android; #[cfg(feature = "backtrace")] pub mod backtrace; +pub mod cmath; pub mod condvar; pub mod env; pub mod ext; diff --git a/src/libstd/sys/windows/cmath.rs b/src/libstd/sys/windows/cmath.rs new file mode 100644 index 00000000000..b665a2c9ba4 --- /dev/null +++ b/src/libstd/sys/windows/cmath.rs @@ -0,0 +1,103 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg(not(test))] + +use libc::{c_float, c_double}; + +#[link_name = "m"] +extern { + pub fn acos(n: c_double) -> c_double; + pub fn asin(n: c_double) -> c_double; + pub fn atan(n: c_double) -> c_double; + pub fn atan2(a: c_double, b: c_double) -> c_double; + pub fn cbrt(n: c_double) -> c_double; + pub fn cbrtf(n: c_float) -> c_float; + pub fn cosh(n: c_double) -> c_double; + pub fn expm1(n: c_double) -> c_double; + pub fn expm1f(n: c_float) -> c_float; + pub fn fdim(a: c_double, b: c_double) -> c_double; + pub fn fdimf(a: c_float, b: c_float) -> c_float; + #[cfg_attr(target_env = "msvc", link_name = "_hypot")] + pub fn hypot(x: c_double, y: c_double) -> c_double; + #[cfg_attr(target_env = "msvc", link_name = "_hypotf")] + pub fn hypotf(x: c_float, y: c_float) -> c_float; + pub fn log1p(n: c_double) -> c_double; + pub fn log1pf(n: c_float) -> c_float; + pub fn sinh(n: c_double) -> c_double; + pub fn tan(n: c_double) -> c_double; + pub fn tanh(n: c_double) -> c_double; +} + +pub use self::shims::*; + +#[cfg(not(target_env = "msvc"))] +mod shims { + use libc::c_float; + + extern { + pub fn acosf(n: c_float) -> c_float; + pub fn asinf(n: c_float) -> c_float; + pub fn atan2f(a: c_float, b: c_float) -> c_float; + pub fn atanf(n: c_float) -> c_float; + pub fn coshf(n: c_float) -> c_float; + pub fn sinhf(n: c_float) -> c_float; + pub fn tanf(n: c_float) -> c_float; + pub fn tanhf(n: c_float) -> c_float; + } +} + +// On MSVC these functions aren't defined, so we just define shims which promote +// everything fo f64, perform the calculation, and then demote back to f32. +// While not precisely correct should be "correct enough" for now. +#[cfg(target_env = "msvc")] +mod shims { + use libc::c_float; + + #[inline] + pub unsafe fn acosf(n: c_float) -> c_float { + f64::acos(n as f64) as c_float + } + + #[inline] + pub unsafe fn asinf(n: c_float) -> c_float { + f64::asin(n as f64) as c_float + } + + #[inline] + pub unsafe fn atan2f(n: c_float, b: c_float) -> c_float { + f64::atan2(n as f64, b as f64) as c_float + } + + #[inline] + pub unsafe fn atanf(n: c_float) -> c_float { + f64::atan(n as f64) as c_float + } + + #[inline] + pub unsafe fn coshf(n: c_float) -> c_float { + f64::cosh(n as f64) as c_float + } + + #[inline] + pub unsafe fn sinhf(n: c_float) -> c_float { + f64::sinh(n as f64) as c_float + } + + #[inline] + pub unsafe fn tanf(n: c_float) -> c_float { + f64::tan(n as f64) as c_float + } + + #[inline] + pub unsafe fn tanhf(n: c_float) -> c_float { + f64::tanh(n as f64) as c_float + } +} diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index ab8e155331e..180b55a66e3 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -25,6 +25,7 @@ pub mod args; #[cfg(feature = "backtrace")] pub mod backtrace; pub mod c; +pub mod cmath; pub mod condvar; #[cfg(feature = "backtrace")] pub mod dynamic_lib; -- cgit 1.4.1-3-g733a5 From 5c3fe111d4a6e72f0461320f5166bcd6aaf2f37f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 1 Nov 2017 13:04:03 -0700 Subject: std: Avoid use of `libc` in portable modules This commit removes usage of the `libc` crate in "portable" modules like those at the top level and `sys_common`. Instead common types like `*mut u8` or `u32` are used instead of `*mut c_void` or `c_int` as well as switching to platform-specific functions like `sys::strlen` instead of `libc::strlen`. --- src/libstd/ffi/c_str.rs | 6 +++--- src/libstd/sys/redox/backtrace/tracing.rs | 4 ++-- src/libstd/sys/redox/mod.rs | 1 + src/libstd/sys/unix/backtrace/printing/dladdr.rs | 5 ++--- src/libstd/sys/unix/backtrace/printing/mod.rs | 2 +- src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs | 4 ++-- src/libstd/sys/unix/backtrace/tracing/gcc_s.rs | 4 ++-- src/libstd/sys/unix/mod.rs | 1 + src/libstd/sys/unix/thread.rs | 2 +- src/libstd/sys/windows/backtrace/mod.rs | 4 ++-- src/libstd/sys/windows/backtrace/printing/msvc.rs | 6 +++--- src/libstd/sys/windows/mod.rs | 1 + src/libstd/sys/windows/thread.rs | 2 +- src/libstd/sys_common/backtrace.rs | 11 ++++++----- src/libstd/sys_common/gnu/libbacktrace.rs | 8 ++++---- src/libstd/sys_common/thread.rs | 3 +-- 16 files changed, 33 insertions(+), 31 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index b5460391942..1aa47f066b6 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -14,7 +14,6 @@ use cmp::Ordering; use error::Error; use fmt::{self, Write}; use io; -use libc; use mem; use memchr; use ops; @@ -22,6 +21,7 @@ use os::raw::c_char; use ptr; use slice; use str::{self, Utf8Error}; +use sys; /// A type representing an owned, C-compatible, nul-terminated string with no nul bytes in the /// middle. @@ -404,7 +404,7 @@ impl CString { /// ``` #[stable(feature = "cstr_memory", since = "1.4.0")] pub unsafe fn from_raw(ptr: *mut c_char) -> CString { - let len = libc::strlen(ptr) + 1; // Including the NUL byte + let len = sys::strlen(ptr) + 1; // Including the NUL byte let slice = slice::from_raw_parts_mut(ptr, len as usize); CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) } } @@ -861,7 +861,7 @@ impl CStr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { - let len = libc::strlen(ptr); + let len = sys::strlen(ptr); let ptr = ptr as *const u8; CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) } diff --git a/src/libstd/sys/redox/backtrace/tracing.rs b/src/libstd/sys/redox/backtrace/tracing.rs index cfeabaddda9..0a174b3c3f5 100644 --- a/src/libstd/sys/redox/backtrace/tracing.rs +++ b/src/libstd/sys/redox/backtrace/tracing.rs @@ -96,8 +96,8 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context, if cx.idx < cx.frames.len() { cx.frames[cx.idx] = Frame { - symbol_addr: symaddr, - exact_position: ip, + symbol_addr: symaddr as *mut u8, + exact_position: ip as *mut u8, }; cx.idx += 1; } diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs index ca5f6637514..4352b72c307 100644 --- a/src/libstd/sys/redox/mod.rs +++ b/src/libstd/sys/redox/mod.rs @@ -12,6 +12,7 @@ use io::{self, ErrorKind}; +pub use libc::strlen; pub use self::rand::hashmap_random_keys; pub mod args; diff --git a/src/libstd/sys/unix/backtrace/printing/dladdr.rs b/src/libstd/sys/unix/backtrace/printing/dladdr.rs index 21f0b3724c1..bc56fd6594e 100644 --- a/src/libstd/sys/unix/backtrace/printing/dladdr.rs +++ b/src/libstd/sys/unix/backtrace/printing/dladdr.rs @@ -22,7 +22,7 @@ pub fn resolve_symname(frame: Frame, { unsafe { let mut info: Dl_info = intrinsics::init(); - let symname = if dladdr(frame.exact_position, &mut info) == 0 || + let symname = if dladdr(frame.exact_position as *mut _, &mut info) == 0 || info.dli_sname.is_null() { None } else { @@ -41,6 +41,5 @@ struct Dl_info { } extern { - fn dladdr(addr: *const libc::c_void, - info: *mut Dl_info) -> libc::c_int; + fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int; } diff --git a/src/libstd/sys/unix/backtrace/printing/mod.rs b/src/libstd/sys/unix/backtrace/printing/mod.rs index 8bd2d9eccd8..caa60712b1d 100644 --- a/src/libstd/sys/unix/backtrace/printing/mod.rs +++ b/src/libstd/sys/unix/backtrace/printing/mod.rs @@ -20,7 +20,7 @@ pub use self::dladdr::resolve_symname; #[cfg(target_os = "emscripten")] pub fn foreach_symbol_fileline(_: Frame, _: F, _: &BacktraceContext) -> io::Result where - F: FnMut(&[u8], ::libc::c_int) -> io::Result<()> + F: FnMut(&[u8], u32) -> io::Result<()> { Ok(false) } diff --git a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs index ecd32aa9462..400d39cd4bd 100644 --- a/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs +++ b/src/libstd/sys/unix/backtrace/tracing/backtrace_fn.rs @@ -36,8 +36,8 @@ pub fn unwind_backtrace(frames: &mut [Frame]) } as usize; for (from, to) in raw_frames.iter().zip(frames.iter_mut()).take(nb_frames) { *to = Frame { - exact_position: *from, - symbol_addr: *from, + exact_position: *from as *mut u8, + symbol_addr: *from as *mut u8, }; } Ok((nb_frames as usize, BacktraceContext)) diff --git a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs index e3ffbe88acd..000c08d2e0d 100644 --- a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs +++ b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs @@ -96,8 +96,8 @@ extern fn trace_fn(ctx: *mut uw::_Unwind_Context, if cx.idx < cx.frames.len() { cx.frames[cx.idx] = Frame { - symbol_addr: symaddr, - exact_position: ip, + symbol_addr: symaddr as *mut u8, + exact_position: ip as *mut u8, }; cx.idx += 1; } diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 47be7ab0394..9bdea945ea4 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -30,6 +30,7 @@ use libc; #[cfg(all(not(dox), target_os = "l4re"))] pub use os::linux as platform; pub use self::rand::hashmap_random_keys; +pub use libc::strlen; #[macro_use] pub mod weak; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index cc889454ce9..9da33f5adac 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -87,7 +87,7 @@ impl Thread { }; extern fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void { - unsafe { start_thread(main); } + unsafe { start_thread(main as *mut u8); } ptr::null_mut() } } diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 26b4cb90e0a..176891fff23 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -95,8 +95,8 @@ pub fn unwind_backtrace(frames: &mut [Frame]) frame.AddrReturn.Offset == 0 { break } frames[i] = Frame { - symbol_addr: (addr - 1) as *const c_void, - exact_position: (addr - 1) as *const c_void, + symbol_addr: (addr - 1) as *const u8, + exact_position: (addr - 1) as *const u8, }; i += 1; } diff --git a/src/libstd/sys/windows/backtrace/printing/msvc.rs b/src/libstd/sys/windows/backtrace/printing/msvc.rs index 3107d784324..5a49b77af8e 100644 --- a/src/libstd/sys/windows/backtrace/printing/msvc.rs +++ b/src/libstd/sys/windows/backtrace/printing/msvc.rs @@ -10,7 +10,7 @@ use ffi::CStr; use io; -use libc::{c_ulong, c_int, c_char}; +use libc::{c_ulong, c_char}; use mem; use sys::c; use sys::backtrace::BacktraceContext; @@ -59,7 +59,7 @@ pub fn foreach_symbol_fileline(frame: Frame, mut f: F, context: &BacktraceContext) -> io::Result - where F: FnMut(&[u8], c_int) -> io::Result<()> + where F: FnMut(&[u8], u32) -> io::Result<()> { let SymGetLineFromAddr64 = sym!(&context.dbghelp, "SymGetLineFromAddr64", @@ -76,7 +76,7 @@ pub fn foreach_symbol_fileline(frame: Frame, &mut line); if ret == c::TRUE { let name = CStr::from_ptr(line.Filename).to_bytes(); - f(name, line.LineNumber as c_int)?; + f(name, line.LineNumber as u32)?; } Ok(false) } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 180b55a66e3..0d12ecf8fe3 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -17,6 +17,7 @@ use os::windows::ffi::{OsStrExt, OsStringExt}; use path::PathBuf; use time::Duration; +pub use libc::strlen; pub use self::rand::hashmap_random_keys; #[macro_use] pub mod compat; diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index c47baaa2434..74786d09285 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -52,7 +52,7 @@ impl Thread { }; extern "system" fn thread_start(main: *mut c_void) -> c::DWORD { - unsafe { start_thread(main); } + unsafe { start_thread(main as *mut u8); } 0 } } diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 8f78c2e6f59..9f0214f5f05 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -14,7 +14,6 @@ use env; use io::prelude::*; use io; -use libc; use str; use sync::atomic::{self, Ordering}; use path::{self, Path}; @@ -39,9 +38,9 @@ pub const HEX_WIDTH: usize = 10; #[derive(Debug, Copy, Clone)] pub struct Frame { /// Exact address of the call that failed. - pub exact_position: *const libc::c_void, + pub exact_position: *const u8, /// Address of the enclosing function. - pub symbol_addr: *const libc::c_void, + pub symbol_addr: *const u8, } /// Max number of frames to print. @@ -201,8 +200,10 @@ fn output(w: &mut Write, idx: usize, frame: Frame, /// /// See also `output`. #[allow(dead_code)] -fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int, - format: PrintFormat) -> io::Result<()> { +fn output_fileline(w: &mut Write, + file: &[u8], + line: u32, + format: PrintFormat) -> io::Result<()> { // prior line: " ##: {:2$} - func" w.write_all(b"")?; match format { diff --git a/src/libstd/sys_common/gnu/libbacktrace.rs b/src/libstd/sys_common/gnu/libbacktrace.rs index 016c840d154..75c6bd5d2a2 100644 --- a/src/libstd/sys_common/gnu/libbacktrace.rs +++ b/src/libstd/sys_common/gnu/libbacktrace.rs @@ -20,13 +20,13 @@ use sys_common::backtrace::Frame; pub fn foreach_symbol_fileline(frame: Frame, mut f: F, _: &BacktraceContext) -> io::Result -where F: FnMut(&[u8], libc::c_int) -> io::Result<()> +where F: FnMut(&[u8], u32) -> io::Result<()> { // pcinfo may return an arbitrary number of file:line pairs, // in the order of stack trace (i.e. inlined calls first). // in order to avoid allocation, we stack-allocate a fixed size of entries. const FILELINE_SIZE: usize = 32; - let mut fileline_buf = [(ptr::null(), -1); FILELINE_SIZE]; + let mut fileline_buf = [(ptr::null(), !0); FILELINE_SIZE]; let ret; let fileline_count = { let state = unsafe { init_state() }; @@ -136,7 +136,7 @@ extern { // helper callbacks //////////////////////////////////////////////////////////////////////// -type FileLine = (*const libc::c_char, libc::c_int); +type FileLine = (*const libc::c_char, u32); extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char, _errnum: libc::c_int) { @@ -162,7 +162,7 @@ extern fn pcinfo_cb(data: *mut libc::c_void, // if the buffer is not full, add file:line to the buffer // and adjust the buffer for next possible calls to pcinfo_cb. if !buffer.is_empty() { - buffer[0] = (filename, lineno); + buffer[0] = (filename, lineno as u32); unsafe { ptr::write(slot, &mut buffer[1..]); } } } diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index 87fb34a9dec..c19424f2952 100644 --- a/src/libstd/sys_common/thread.rs +++ b/src/libstd/sys_common/thread.rs @@ -10,12 +10,11 @@ use env; use alloc::boxed::FnBox; -use libc; use sync::atomic::{self, Ordering}; use sys::stack_overflow; use sys::thread as imp; -pub unsafe fn start_thread(main: *mut libc::c_void) { +pub unsafe fn start_thread(main: *mut u8) { // Next, set up our stack overflow handler which may get triggered if we run // out of stack. let _handler = stack_overflow::Handler::new(); -- cgit 1.4.1-3-g733a5