diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-02-13 04:37:03 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-02-13 04:37:03 +0100 |
| commit | ecb650316983697cca65b9b265692e4385a67d9c (patch) | |
| tree | dc518ed04ee8f7339609b579cdc543a56bf31da2 | |
| parent | 856e41142cad7b3ce2494ee8edd7d1c1d1e58a44 (diff) | |
| parent | 66c894e07f95a324a39bb4c281c8db4c8842689b (diff) | |
| download | rust-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.rs | 30 |
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( |
