about summary refs log tree commit diff
path: root/src/libcore/str
diff options
context:
space:
mode:
authorUlrik Sverdrup <bluss@users.noreply.github.com>2016-01-20 17:18:54 +0100
committerUlrik Sverdrup <bluss@users.noreply.github.com>2016-01-21 15:25:49 +0100
commitba9a3bc4533bccbb0db70bd975109916c3b8754f (patch)
tree88143310dfa20bb5b5e7d82926d8bf3180745ddb /src/libcore/str
parent9d21acaf9b41ea2529b15d5efd06266e924c0496 (diff)
downloadrust-ba9a3bc4533bccbb0db70bd975109916c3b8754f.tar.gz
rust-ba9a3bc4533bccbb0db70bd975109916c3b8754f.zip
core: 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.
Diffstat (limited to 'src/libcore/str')
-rw-r--r--src/libcore/str/mod.rs34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index dd111981f0e..3892455395f 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -244,6 +244,34 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     Ok(unsafe { from_utf8_unchecked(v) })
 }
 
+/// Forms a str from a pointer and a length.
+///
+/// The `len` argument is the number of bytes in the string.
+///
+/// # Safety
+///
+/// This function is unsafe as there is no guarantee that the given pointer is
+/// valid for `len` bytes, nor whether the lifetime inferred is a suitable
+/// lifetime for the returned str.
+///
+/// The data must be valid UTF-8
+///
+/// `p` must be non-null, even for zero-length str.
+///
+/// # Caveat
+///
+/// The lifetime for the returned str is inferred from its usage. To
+/// prevent accidental misuse, it's suggested to tie the lifetime to whichever
+/// source lifetime is safe in the context, such as by providing a helper
+/// function taking the lifetime of a host value for the str, or by explicit
+/// annotation.
+/// Performs the same functionality as `from_raw_parts`, except that a mutable
+/// str is returned.
+///
+unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
+    mem::transmute::<&mut [u8], &mut str>(slice::from_raw_parts_mut(p, len))
+}
+
 /// Converts a slice of bytes to a string slice without checking
 /// that the string contains valid UTF-8.
 ///
@@ -1843,10 +1871,10 @@ impl StrExt for 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;
             unsafe {
-                let self2: &mut str = mem::transmute_copy(&self);
-                (self.slice_mut_unchecked(0, mid),
-                 self2.slice_mut_unchecked(mid, len))
+                (from_raw_parts_mut(ptr, mid),
+                 from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
             }
         } else {
             slice_error_fail(self, 0, mid)