From 346dc37aee60f995e6c1548ce7f406d5500f8570 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 5 Feb 2019 20:07:45 +0100 Subject: [PATCH 1/4] fix str mutating through a ptr derived from &self --- src/libcore/str/mod.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 3cb39360380..b01cb688ee5 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1757,7 +1757,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { } #[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)) } @@ -1821,7 +1821,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { } #[inline] unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { - let ptr = slice.as_ptr(); + let ptr = slice.as_mut_ptr(); super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end)) } #[inline] @@ -1883,7 +1883,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { } #[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)) } @@ -2213,6 +2213,22 @@ pub const fn as_ptr(&self) -> *const u8 { 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 = "0")] + #[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 From 13bbba273c2a3d6a83c081ba3c2129f8d572c1b7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 6 Feb 2019 11:23:10 +0100 Subject: [PATCH 2/4] remove now-unneeded raw ptr casts --- src/libcore/str/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index b01cb688ee5..8c8f280f847 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1759,7 +1759,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { 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 { @@ -1822,7 +1822,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { #[inline] unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { let ptr = slice.as_mut_ptr(); - super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr as *mut u8, self.end)) + super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, self.end)) } #[inline] fn index(self, slice: &str) -> &Self::Output { @@ -1885,7 +1885,7 @@ unsafe fn get_unchecked(self, slice: &str) -> &Self::Output { unsafe fn get_unchecked_mut(self, slice: &mut str) -> &mut Self::Output { 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 { From a996f2c8dcfd08b545374a0b6c0cc0c0c349ad30 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 6 Feb 2019 12:55:50 +0100 Subject: [PATCH 3/4] add tracking issue --- src/libcore/str/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 8c8f280f847..f95cd0dab43 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2223,7 +2223,7 @@ pub const fn as_ptr(&self) -> *const u8 { /// modified in a way that it remains valid UTF-8. /// /// [`u8`]: primitive.u8.html - #[unstable(feature = "str_as_mut_ptr", issue = "0")] + #[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 From 66c894e07f95a324a39bb4c281c8db4c8842689b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 7 Feb 2019 17:55:25 +0100 Subject: [PATCH 4/4] also fix bad use of shared ref in split_at_mut --- src/libcore/str/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index f95cd0dab43..6793b16481e 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2516,7 +2516,7 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut 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(