Skip to content

Commit ee6a033

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 functions from_raw_parts, 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 34b4e66 + 8d71ca5 commit ee6a033

File tree

1 file changed

+42
-12
lines changed

1 file changed

+42
-12
lines changed

src/libcore/str/mod.rs

+42-12
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use marker::Sized;
2929
use mem;
3030
use ops::{Fn, FnMut, FnOnce};
3131
use option::Option::{self, None, Some};
32-
use raw::{Repr, Slice};
32+
use raw::Repr;
3333
use result::Result::{self, Ok, Err};
3434
use slice::{self, SliceExt};
3535

@@ -244,6 +244,41 @@ 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+
unsafe fn from_raw_parts<'a>(p: *const u8, len: usize) -> &'a str {
269+
from_utf8_unchecked(slice::from_raw_parts(p, len))
270+
}
271+
272+
/// Performs the same functionality as `from_raw_parts`, except that a mutable
273+
/// str is returned.
274+
///
275+
/// This function is unsafe for the same reasons as `from_raw_parts`, as well
276+
/// as not being able to provide a non-aliasing guarantee of the returned
277+
/// mutable str.
278+
unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
279+
mem::transmute::<&mut [u8], &mut str>(slice::from_raw_parts_mut(p, len))
280+
}
281+
247282
/// Converts a slice of bytes to a string slice without checking
248283
/// that the string contains valid UTF-8.
249284
///
@@ -1677,18 +1712,13 @@ impl StrExt for str {
16771712

16781713
#[inline]
16791714
unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
1680-
mem::transmute(Slice {
1681-
data: self.as_ptr().offset(begin as isize),
1682-
len: end - begin,
1683-
})
1715+
from_raw_parts(self.as_ptr().offset(begin as isize), end - begin)
16841716
}
16851717

16861718
#[inline]
16871719
unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
1688-
mem::transmute(Slice {
1689-
data: self.as_ptr().offset(begin as isize),
1690-
len: end - begin,
1691-
})
1720+
from_raw_parts_mut(self.as_ptr().offset(begin as isize) as *mut u8,
1721+
end - begin)
16921722
}
16931723

16941724
#[inline]
@@ -1843,10 +1873,10 @@ impl StrExt for str {
18431873
// is_char_boundary checks that the index is in [0, .len()]
18441874
if self.is_char_boundary(mid) {
18451875
let len = self.len();
1876+
let ptr = self.as_ptr() as *mut u8;
18461877
unsafe {
1847-
let self2: &mut str = mem::transmute_copy(&self);
1848-
(self.slice_mut_unchecked(0, mid),
1849-
self2.slice_mut_unchecked(mid, len))
1878+
(from_raw_parts_mut(ptr, mid),
1879+
from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
18501880
}
18511881
} else {
18521882
slice_error_fail(self, 0, mid)

0 commit comments

Comments
 (0)