about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZachary S <zasample18+github@gmail.com>2022-09-02 00:47:15 -0500
committerZachary S <zasample18+github@gmail.com>2022-11-18 12:50:41 -0600
commit8c38cb77090af4c876f1c021b86d6c184c80cc4f (patch)
treebc736f910510b03caa99b3e1b59efc3eb9875c45
parent96650fc7143dbacdbb3711e2d60f06401e727cea (diff)
downloadrust-8c38cb77090af4c876f1c021b86d6c184c80cc4f.tar.gz
rust-8c38cb77090af4c876f1c021b86d6c184c80cc4f.zip
Add examples to show when `{Arc,Rc}::get_mut_unchecked` is disallowed.
-rw-r--r--library/alloc/src/rc.rs32
-rw-r--r--library/alloc/src/sync.rs32
2 files changed, 64 insertions, 0 deletions
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 1e9ed3889e8..8ac1b5b488a 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1110,6 +1110,38 @@ impl<T: ?Sized> Rc<T> {
     /// }
     /// assert_eq!(*x, "foo");
     /// ```
+    /// Other `Rc` pointers to the same allocation must be to the same type.
+    /// ```ignore
+    /// #![feature(get_mut_unchecked)]
+    ///
+    /// use std::rc::Rc;
+    ///
+    /// let x: Rc<str> = Rc::from("Hello, world!");
+    /// let mut y: Rc<[u8]> = x.clone().into();
+    /// unsafe {
+    ///     // this is Undefined Behavior, because x's inner type is str, not [u8]
+    ///     Rc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8
+    /// }
+    /// println!("{}", &*x); // Invliad UTF-8 in a str
+    /// ```
+    /// Other `Rc` pointers to the same allocation must be to the exact same type, including lifetimes.
+    /// ```ignore
+    /// #![feature(get_mut_unchecked)]
+    ///
+    /// use std::rc::Rc;
+    ///
+    /// let x: Rc<&str> = Rc::new("Hello, world!");
+    /// {
+    ///     let s = String::from("Oh, no!");
+    ///     let mut y: Rc<&str> = x.clone().into();
+    ///     unsafe {
+    ///         // this is Undefined Behavior, because x's inner type
+    ///         // is &'long str, not &'short str
+    ///         *Rc::get_mut_unchecked(&mut y) = &s;
+    ///     }
+    /// }
+    /// println!("{}", &*x); // Use-after-free
+    /// ```
     #[inline]
     #[unstable(feature = "get_mut_unchecked", issue = "63292")]
     pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 2bb5030c51e..e4d7bfdaeed 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1649,6 +1649,38 @@ impl<T: ?Sized> Arc<T> {
     /// }
     /// assert_eq!(*x, "foo");
     /// ```
+    /// Other `Arc` pointers to the same allocation must be to the same type.
+    /// ```ignore
+    /// #![feature(get_mut_unchecked)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let x: Arc<str> = Arc::from("Hello, world!");
+    /// let mut y: Arc<[u8]> = x.clone().into();
+    /// unsafe {
+    ///     // this is Undefined Behavior, because x's inner type is str, not [u8]
+    ///     Arc::get_mut_unchecked(&mut y).fill(0xff); // 0xff is invalid in UTF-8
+    /// }
+    /// println!("{}", &*x); // Invliad UTF-8 in a str
+    /// ```
+    /// Other `Arc` pointers to the same allocation must be to the exact same type, including lifetimes.
+    /// ```ignore
+    /// #![feature(get_mut_unchecked)]
+    ///
+    /// use std::sync::Arc;
+    ///
+    /// let x: Arc<&str> = Arc::new("Hello, world!");
+    /// {
+    ///     let s = String::from("Oh, no!");
+    ///     let mut y: Arc<&str> = x.clone().into();
+    ///     unsafe {
+    ///         // this is Undefined Behavior, because x's inner type
+    ///         // is &'long str, not &'short str
+    ///         *Arc::get_mut_unchecked(&mut y) = &s;
+    ///     }
+    /// }
+    /// println!("{}", &*x); // Use-after-free
+    /// ```
     #[inline]
     #[unstable(feature = "get_mut_unchecked", issue = "63292")]
     pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T {