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.
This commit is contained in:
commit
ecb6503169
@ -1741,9 +1741,9 @@ 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))
|
||||
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len))
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
@ -1805,8 +1805,8 @@ 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();
|
||||
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 @@ 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))
|
||||
super::from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, len))
|
||||
}
|
||||
#[inline]
|
||||
fn index(self, slice: &str) -> &Self::Output {
|
||||
@ -2197,6 +2197,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 = "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 @@ 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(
|
||||
|
Loading…
Reference in New Issue
Block a user