about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorJeremy Soller <jackpot51@gmail.com>2016-11-10 20:37:34 -0700
committerJeremy Soller <jackpot51@gmail.com>2016-11-10 20:37:34 -0700
commit0bb9a959074bb7f027cf05a240a0044116fa0ab0 (patch)
tree69fca65cd12f30f97f8bcfd403b39577f2ce3c57 /src/libstd
parent25e1a4a0084a56807d7a1e4ca676e078c085b3aa (diff)
parent1473007618e6ab85a994f86348acdaf125b7914f (diff)
downloadrust-0bb9a959074bb7f027cf05a240a0044116fa0ab0.tar.gz
rust-0bb9a959074bb7f027cf05a240a0044116fa0ab0.zip
Merge branch 'master' into redox
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/collections/hash/map.rs26
-rw-r--r--src/libstd/ffi/c_str.rs2
-rw-r--r--src/libstd/io/error.rs78
-rw-r--r--src/libstd/io/mod.rs27
-rw-r--r--src/libstd/io/stdio.rs3
-rw-r--r--src/libstd/lib.rs2
-rw-r--r--src/libstd/net/udp.rs3
-rw-r--r--src/libstd/path.rs14
-rw-r--r--src/libstd/sys/mod.rs2
-rw-r--r--src/libstd/sys/unix/rand.rs28
-rw-r--r--src/libstd/sys_common/mod.rs2
11 files changed, 120 insertions, 67 deletions
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index fb8a0c3c265..ece51d6d826 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -11,6 +11,7 @@
 use self::Entry::*;
 use self::VacantEntryState::*;
 
+use cell::Cell;
 use borrow::Borrow;
 use cmp::max;
 use fmt::{self, Debug};
@@ -2049,24 +2050,21 @@ impl RandomState {
         // many hash maps are created on a thread. To solve this performance
         // trap we cache the first set of randomly generated keys per-thread.
         //
-        // In doing this, however, we lose the property that all hash maps have
-        // nondeterministic iteration order as all of those created on the same
-        // thread would have the same hash keys. This property has been nice in
-        // the past as it allows for maximal flexibility in the implementation
-        // of `HashMap` itself.
-        //
-        // The constraint here (if there even is one) is just that maps created
-        // on the same thread have the same iteration order, and that *may* be
-        // relied upon even though it is not a documented guarantee at all of
-        // the `HashMap` type. In any case we've decided that this is reasonable
-        // for now, so caching keys thread-locally seems fine.
-        thread_local!(static KEYS: (u64, u64) = {
+        // Later in #36481 it was discovered that exposing a deterministic
+        // iteration order allows a form of DOS attack. To counter that we
+        // 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");
-            (r.gen(), r.gen())
+            Cell::new((r.gen(), r.gen()))
         });
 
-        KEYS.with(|&(k0, k1)| RandomState { k0: k0, k1: k1 })
+        KEYS.with(|keys| {
+            let (k0, k1) = keys.get();
+            keys.set((k0.wrapping_add(1), k1));
+            RandomState { k0: k0, k1: k1 }
+        })
     }
 }
 
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 3ad5b5627d3..d1b8fcd7440 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -686,7 +686,7 @@ impl ToOwned for CStr {
     type Owned = CString;
 
     fn to_owned(&self) -> CString {
-        unsafe { CString::from_vec_unchecked(self.to_bytes().to_vec()) }
+        CString { inner: self.to_bytes_with_nul().to_vec().into_boxed_slice() }
     }
 }
 
diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs
index ddf0030858e..795c89c0007 100644
--- a/src/libstd/io/error.rs
+++ b/src/libstd/io/error.rs
@@ -12,6 +12,7 @@ use error;
 use fmt;
 use result;
 use sys;
+use convert::From;
 
 /// A specialized [`Result`](../result/enum.Result.html) type for I/O
 /// operations.
@@ -62,6 +63,7 @@ pub struct Error {
 
 enum Repr {
     Os(i32),
+    Simple(ErrorKind),
     Custom(Box<Custom>),
 }
 
@@ -124,23 +126,28 @@ pub enum ErrorKind {
     InvalidInput,
     /// Data not valid for the operation were encountered.
     ///
-    /// Unlike `InvalidInput`, this typically means that the operation
+    /// Unlike [`InvalidInput`], this typically means that the operation
     /// parameters were valid, however the error was caused by malformed
     /// input data.
     ///
     /// For example, a function that reads a file into a string will error with
     /// `InvalidData` if the file's contents are not valid UTF-8.
+    ///
+    /// [`InvalidInput`]: #variant.InvalidInput
     #[stable(feature = "io_invalid_data", since = "1.2.0")]
     InvalidData,
     /// The I/O operation's timeout expired, causing it to be canceled.
     #[stable(feature = "rust1", since = "1.0.0")]
     TimedOut,
     /// An error returned when an operation could not be completed because a
-    /// call to `write` returned `Ok(0)`.
+    /// call to [`write()`] returned [`Ok(0)`].
     ///
     /// This typically means that an operation could only succeed if it wrote a
     /// particular number of bytes but only a smaller number of bytes could be
     /// written.
+    ///
+    /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write
+    /// [`Ok(0)`]: ../../std/io/type.Result.html
     #[stable(feature = "rust1", since = "1.0.0")]
     WriteZero,
     /// This operation was interrupted.
@@ -171,6 +178,43 @@ pub enum ErrorKind {
     __Nonexhaustive,
 }
 
+impl ErrorKind {
+    fn as_str(&self) -> &'static str {
+        match *self {
+            ErrorKind::NotFound => "entity not found",
+            ErrorKind::PermissionDenied => "permission denied",
+            ErrorKind::ConnectionRefused => "connection refused",
+            ErrorKind::ConnectionReset => "connection reset",
+            ErrorKind::ConnectionAborted => "connection aborted",
+            ErrorKind::NotConnected => "not connected",
+            ErrorKind::AddrInUse => "address in use",
+            ErrorKind::AddrNotAvailable => "address not available",
+            ErrorKind::BrokenPipe => "broken pipe",
+            ErrorKind::AlreadyExists => "entity already exists",
+            ErrorKind::WouldBlock => "operation would block",
+            ErrorKind::InvalidInput => "invalid input parameter",
+            ErrorKind::InvalidData => "invalid data",
+            ErrorKind::TimedOut => "timed out",
+            ErrorKind::WriteZero => "write zero",
+            ErrorKind::Interrupted => "operation interrupted",
+            ErrorKind::Other => "other os error",
+            ErrorKind::UnexpectedEof => "unexpected end of file",
+            ErrorKind::__Nonexhaustive => unreachable!()
+        }
+    }
+}
+
+/// Intended for use for errors not exposed to the user, where allocating onto
+/// the heap (for normal construction via Error::new) is too costly.
+#[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
+impl From<ErrorKind> for Error {
+    fn from(kind: ErrorKind) -> Error {
+        Error {
+            repr: Repr::Simple(kind)
+        }
+    }
+}
+
 impl Error {
     /// Creates a new I/O error from a known kind of error as well as an
     /// arbitrary error payload.
@@ -285,6 +329,7 @@ impl Error {
         match self.repr {
             Repr::Os(i) => Some(i),
             Repr::Custom(..) => None,
+            Repr::Simple(..) => None,
         }
     }
 
@@ -317,6 +362,7 @@ impl Error {
     pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
         match self.repr {
             Repr::Os(..) => None,
+            Repr::Simple(..) => None,
             Repr::Custom(ref c) => Some(&*c.error),
         }
     }
@@ -387,6 +433,7 @@ impl Error {
     pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
         match self.repr {
             Repr::Os(..) => None,
+            Repr::Simple(..) => None,
             Repr::Custom(ref mut c) => Some(&mut *c.error),
         }
     }
@@ -420,6 +467,7 @@ impl Error {
     pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
         match self.repr {
             Repr::Os(..) => None,
+            Repr::Simple(..) => None,
             Repr::Custom(c) => Some(c.error)
         }
     }
@@ -447,6 +495,7 @@ impl Error {
         match self.repr {
             Repr::Os(code) => sys::decode_error_kind(code),
             Repr::Custom(ref c) => c.kind,
+            Repr::Simple(kind) => kind,
         }
     }
 }
@@ -458,6 +507,7 @@ impl fmt::Debug for Repr {
                 fmt.debug_struct("Os").field("code", code)
                    .field("message", &sys::os::error_string(*code)).finish(),
             Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
+            Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
         }
     }
 }
@@ -471,6 +521,7 @@ impl fmt::Display for Error {
                 write!(fmt, "{} (os error {})", detail, code)
             }
             Repr::Custom(ref c) => c.error.fmt(fmt),
+            Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
         }
     }
 }
@@ -479,27 +530,7 @@ impl fmt::Display for Error {
 impl error::Error for Error {
     fn description(&self) -> &str {
         match self.repr {
-            Repr::Os(..) => match self.kind() {
-                ErrorKind::NotFound => "entity not found",
-                ErrorKind::PermissionDenied => "permission denied",
-                ErrorKind::ConnectionRefused => "connection refused",
-                ErrorKind::ConnectionReset => "connection reset",
-                ErrorKind::ConnectionAborted => "connection aborted",
-                ErrorKind::NotConnected => "not connected",
-                ErrorKind::AddrInUse => "address in use",
-                ErrorKind::AddrNotAvailable => "address not available",
-                ErrorKind::BrokenPipe => "broken pipe",
-                ErrorKind::AlreadyExists => "entity already exists",
-                ErrorKind::WouldBlock => "operation would block",
-                ErrorKind::InvalidInput => "invalid input parameter",
-                ErrorKind::InvalidData => "invalid data",
-                ErrorKind::TimedOut => "timed out",
-                ErrorKind::WriteZero => "write zero",
-                ErrorKind::Interrupted => "operation interrupted",
-                ErrorKind::Other => "other os error",
-                ErrorKind::UnexpectedEof => "unexpected end of file",
-                ErrorKind::__Nonexhaustive => unreachable!()
-            },
+            Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(),
             Repr::Custom(ref c) => c.error.description(),
         }
     }
@@ -507,6 +538,7 @@ impl error::Error for Error {
     fn cause(&self) -> Option<&error::Error> {
         match self.repr {
             Repr::Os(..) => None,
+            Repr::Simple(..) => None,
             Repr::Custom(ref c) => c.error.cause(),
         }
     }
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 193f396c0d4..ad9ae5638b6 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -21,7 +21,7 @@
 //! of other types, and you can implement them for your types too. As such,
 //! you'll see a few different types of I/O throughout the documentation in
 //! this module: [`File`]s, [`TcpStream`]s, and sometimes even [`Vec<T>`]s. For
-//! example, `Read` adds a `read()` method, which we can use on `File`s:
+//! example, [`Read`] adds a [`read()`] method, which we can use on `File`s:
 //!
 //! ```
 //! use std::io;
@@ -251,6 +251,7 @@
 //! [`Lines`]: struct.Lines.html
 //! [`io::Result`]: type.Result.html
 //! [`try!`]: ../macro.try.html
+//! [`read()`]: trait.Read.html#tymethod.read
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -814,19 +815,23 @@ pub trait Read {
 ///
 /// Implementors of the `Write` trait are sometimes called 'writers'.
 ///
-/// Writers are defined by two required methods, `write()` and `flush()`:
+/// Writers are defined by two required methods, [`write()`] and [`flush()`]:
 ///
-/// * The `write()` method will attempt to write some data into the object,
+/// * The [`write()`] method will attempt to write some data into the object,
 ///   returning how many bytes were successfully written.
 ///
-/// * The `flush()` method is useful for adaptors and explicit buffers
+/// * The [`flush()`] method is useful for adaptors and explicit buffers
 ///   themselves for ensuring that all buffered data has been pushed out to the
 ///   'true sink'.
 ///
 /// Writers are intended to be composable with one another. Many implementors
-/// throughout `std::io` take and provide types which implement the `Write`
+/// throughout [`std::io`] take and provide types which implement the `Write`
 /// trait.
 ///
+/// [`write()`]: #tymethod.write
+/// [`flush()`]: #tymethod.flush
+/// [`std::io`]: index.html
+///
 /// # Examples
 ///
 /// ```
@@ -1475,10 +1480,10 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
 
 /// Reader adaptor which limits the bytes read from an underlying reader.
 ///
-/// This struct is generally created by calling [`take()`][take] on a reader.
-/// Please see the documentation of `take()` for more details.
+/// This struct is generally created by calling [`take()`] on a reader.
+/// Please see the documentation of [`take()`] for more details.
 ///
-/// [take]: trait.Read.html#method.take
+/// [`take()`]: trait.Read.html#method.take
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Take<T> {
     inner: T,
@@ -1491,8 +1496,10 @@ impl<T> Take<T> {
     ///
     /// # Note
     ///
-    /// This instance may reach EOF after reading fewer bytes than indicated by
-    /// this method if the underlying `Read` instance reaches EOF.
+    /// This instance may reach `EOF` after reading fewer bytes than indicated by
+    /// this method if the underlying [`Read`] instance reaches EOF.
+    ///
+    /// [`Read`]: ../../std/io/trait.Read.html
     ///
     /// # Examples
     ///
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 27bc5f0890c..f6ee0be47fa 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -324,10 +324,11 @@ impl<'a> BufRead for StdinLock<'a> {
 ///
 /// Each handle shares a global buffer of data to be written to the standard
 /// output stream. Access is also synchronized via a lock and explicit control
-/// over locking is available via the `lock` method.
+/// over locking is available via the [`lock()`] method.
 ///
 /// Created by the [`io::stdout`] method.
 ///
+/// [`lock()`]: #method.lock
 /// [`io::stdout`]: fn.stdout.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stdout {
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 8d973fc1ade..12dbbe3c469 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -249,7 +249,7 @@
 #![feature(const_fn)]
 #![feature(core_float)]
 #![feature(core_intrinsics)]
-#![feature(dotdot_in_tuple_patterns)]
+#![cfg_attr(stage0, feature(dotdot_in_tuple_patterns))]
 #![feature(dropck_parametricity)]
 #![feature(float_extras)]
 #![feature(float_from_str_radix)]
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index c03ac496adb..559250adac5 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -67,6 +67,9 @@ impl UdpSocket {
     ///
     /// Address type can be any implementor of `ToSocketAddrs` trait. See its
     /// documentation for concrete examples.
+    /// This will return an error when the IP version of the local socket
+    /// does not match that returned from `ToSocketAddrs`
+    /// See https://github.com/rust-lang/rust/issues/34202 for more details.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A)
                                      -> io::Result<usize> {
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 9b7f9980cc0..bb6883236e8 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1173,6 +1173,13 @@ impl From<OsString> for PathBuf {
     }
 }
 
+#[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
+impl From<PathBuf> for OsString {
+    fn from(path_buf : PathBuf) -> OsString {
+        path_buf.inner
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for PathBuf {
     fn from(s: String) -> PathBuf {
@@ -1283,13 +1290,6 @@ impl AsRef<OsStr> for PathBuf {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Into<OsString> for PathBuf {
-    fn into(self) -> OsString {
-        self.inner
-    }
-}
-
 /// A slice of a path (akin to [`str`]).
 ///
 /// This type supports a number of operations for inspecting a path, including
diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs
index a237d8a067e..e4b0d980c92 100644
--- a/src/libstd/sys/mod.rs
+++ b/src/libstd/sys/mod.rs
@@ -23,7 +23,7 @@
 //! integration code in `std::sys_common`. See that module's
 //! documentation for details.
 //!
-//! In the future it would be desirable for the indepedent
+//! In the future it would be desirable for the independent
 //! implementations of this module to be extracted to their own crates
 //! that `std` can link to, thus enabling their implementation
 //! out-of-tree via crate replacement. Though due to the complex
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index 3aebb8c18ec..9b1cf6ffd0e 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -350,11 +350,19 @@ mod imp {
 
     #[link(name = "magenta")]
     extern {
-        fn mx_cprng_draw(buffer: *mut u8, len: usize) -> isize;
+        fn mx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32;
     }
 
-    fn getrandom(buf: &mut [u8]) -> isize {
-        unsafe { mx_cprng_draw(buf.as_mut_ptr(), buf.len()) }
+    fn getrandom(buf: &mut [u8]) -> Result<usize, i32> {
+        unsafe {
+            let mut actual = 0;
+            let status = mx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual);
+            if status == 0 {
+                Ok(actual)
+            } else {
+                Err(status)
+            }
+        }
     }
 
     pub struct OsRng {
@@ -381,12 +389,16 @@ mod imp {
             let mut buf = v;
             while !buf.is_empty() {
                 let ret = getrandom(buf);
-                if ret < 0 {
-                    panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})",
-                        ret, buf.len());
+                match ret {
+                    Err(err) => {
+                        panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})",
+                            err, buf.len())
+                    }
+                    Ok(actual) => {
+                        let move_buf = buf;
+                        buf = &mut move_buf[(actual as usize)..];
+                    }
                 }
-                let move_buf = buf;
-                buf = &mut move_buf[(ret as usize)..];
             }
         }
     }
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 5f5ea09c78d..5c07e36508c 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -10,7 +10,7 @@
 
 //! Platform-independent platform abstraction
 //!
-//! This is the platform-independent portion of the standard libraries
+//! This is the platform-independent portion of the standard library's
 //! platform abstraction layer, whereas `std::sys` is the
 //! platform-specific portion.
 //!