about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-02-13 04:37:03 +0100
committerGitHub <noreply@github.com>2019-02-13 04:37:03 +0100
commitecb650316983697cca65b9b265692e4385a67d9c (patch)
treedc518ed04ee8f7339609b579cdc543a56bf31da2
parent856e41142cad7b3ce2494ee8edd7d1c1d1e58a44 (diff)
parent66c894e07f95a324a39bb4c281c8db4c8842689b (diff)
downloadrust-ecb650316983697cca65b9b265692e4385a67d9c.tar.gz
rust-ecb650316983697cca65b9b265692e4385a67d9c.zip
Rollup merge of #58200 - RalfJung:str-as-mut-ptr, r=SimonSapin
fix str mutating through a ptr derived from &self

Found by Miri: In `get_unchecked_mut` (also used by the checked variants internally) uses `str::as_ptr` to create a mutable reference, but `as_ptr` takes `&self`.  This means the mutable references we return here got created from a shared reference, which violates the shared-references-are-read-only discipline!

For this by using a newly introduced `as_mut_ptr` instead.
-rw-r--r--src/libcore/str/mod.rs30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 363eae04f03..76a45e53684 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1741,9 +1741,9 @@ mod traits {
         }
         #[inline]
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
-            let ptr = slice.as_ptr().add(self.start);
+            let ptr = slice.as_mut_ptr().add(self.start);
             let len = self.end - self.start;
-            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
+            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len))
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
@@ -1805,8 +1805,8 @@ mod traits {
         }
         #[inline]
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
-            let ptr = slice.as_ptr();
-            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end))
+            let ptr = slice.as_mut_ptr();
+            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, self.end))
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
@@ -1867,9 +1867,9 @@ mod traits {
         }
         #[inline]
         unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output {
-            let ptr = slice.as_ptr().add(self.start);
+            let ptr = slice.as_mut_ptr().add(self.start);
             let len = slice.len() - self.start;
-            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, len))
+            super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len))
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
@@ -2197,6 +2197,22 @@ impl str {
         self as *const str as *const u8
     }
 
+    /// Converts a mutable string slice to a raw pointer.
+    ///
+    /// As string slices are a slice of bytes, the raw pointer points to a
+    /// [`u8`]. This pointer will be pointing to the first byte of the string
+    /// slice.
+    ///
+    /// It is your responsibility to make sure that the string slice only gets
+    /// modified in a way that it remains valid UTF-8.
+    ///
+    /// [`u8`]: primitive.u8.html
+    #[unstable(feature = "str_as_mut_ptr", issue = "58215")]
+    #[inline]
+    pub fn as_mut_ptr(&mut self) -> *mut u8 {
+        self as *mut str as *mut u8
+    }
+
     /// Returns a subslice of `str`.
     ///
     /// This is the non-panicking alternative to indexing the `str`. Returns
@@ -2484,7 +2500,7 @@ impl str {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
             let len = self.len();
-            let ptr = self.as_ptr() as *mut u8;
+            let ptr = self.as_mut_ptr();
             unsafe {
                 (from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
                  from_utf8_unchecked_mut(slice::from_raw_parts_mut(