Skip to content

Commit 46dcffd

Browse files
committed
Auto merge of #31052 - bluss:split-at-mut-str, r=alexcrichton
Use raw pointers to avoid aliasing in str::split_at_mut Introduce private function from_raw_parts_mut for str to factor out the logic. We want to use raw pointers here instead of duplicating a &mut str, to be on safer ground w.r.t rust aliasing rules. This has already been fixed for slices in PR #27358, issue #27357
2 parents 9ae76b3 + ba9a3bc commit 46dcffd

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

src/libcore/str/mod.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,34 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
244244
Ok(unsafe { from_utf8_unchecked(v) })
245245
}
246246

247+
/// Forms a str from a pointer and a length.
248+
///
249+
/// The `len` argument is the number of bytes in the string.
250+
///
251+
/// # Safety
252+
///
253+
/// This function is unsafe as there is no guarantee that the given pointer is
254+
/// valid for `len` bytes, nor whether the lifetime inferred is a suitable
255+
/// lifetime for the returned str.
256+
///
257+
/// The data must be valid UTF-8
258+
///
259+
/// `p` must be non-null, even for zero-length str.
260+
///
261+
/// # Caveat
262+
///
263+
/// The lifetime for the returned str is inferred from its usage. To
264+
/// prevent accidental misuse, it's suggested to tie the lifetime to whichever
265+
/// source lifetime is safe in the context, such as by providing a helper
266+
/// function taking the lifetime of a host value for the str, or by explicit
267+
/// annotation.
268+
/// Performs the same functionality as `from_raw_parts`, except that a mutable
269+
/// str is returned.
270+
///
271+
unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
272+
mem::transmute::<&mut [u8], &mut str>(slice::from_raw_parts_mut(p, len))
273+
}
274+
247275
/// Converts a slice of bytes to a string slice without checking
248276
/// that the string contains valid UTF-8.
249277
///
@@ -1843,10 +1871,10 @@ impl StrExt for str {
18431871
// is_char_boundary checks that the index is in [0, .len()]
18441872
if self.is_char_boundary(mid) {
18451873
let len = self.len();
1874+
let ptr = self.as_ptr() as *mut u8;
18461875
unsafe {
1847-
let self2: &mut str = mem::transmute_copy(&self);
1848-
(self.slice_mut_unchecked(0, mid),
1849-
self2.slice_mut_unchecked(mid, len))
1876+
(from_raw_parts_mut(ptr, mid),
1877+
from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
18501878
}
18511879
} else {
18521880
slice_error_fail(self, 0, mid)

0 commit comments

Comments
 (0)