Skip to content

Remove mem::transmute used in Box<str> conversions #44890

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Oct 4, 2017
4 changes: 1 addition & 3 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,9 +528,7 @@ impl<'a> From<&'a str> for Box<str> {
#[stable(feature = "boxed_str_conv", since = "1.19.0")]
impl From<Box<str>> for Box<[u8]> {
fn from(s: Box<str>) -> Self {
unsafe {
mem::transmute(s)
}
unsafe { Box::from_raw(Box::into_raw(s) as *mut [u8]) }
}
}

Expand Down
8 changes: 3 additions & 5 deletions src/liballoc/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2047,10 +2047,8 @@ impl str {
/// ```
#[stable(feature = "box_str", since = "1.4.0")]
pub fn into_string(self: Box<str>) -> String {
unsafe {
let slice = mem::transmute::<Box<str>, Box<[u8]>>(self);
String::from_utf8_unchecked(slice.into_vec())
}
let slice = Box::<[u8]>::from(self);
unsafe { String::from_utf8_unchecked(slice.into_vec()) }
}

/// Create a [`String`] by repeating a string `n` times.
Expand Down Expand Up @@ -2087,5 +2085,5 @@ impl str {
/// ```
#[stable(feature = "str_box_extras", since = "1.20.0")]
pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
mem::transmute(v)
Box::from_raw(Box::into_raw(v) as *mut str)
}
17 changes: 9 additions & 8 deletions src/libstd/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,8 @@ impl CString {
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
let len = libc::strlen(ptr) + 1; // Including the NUL byte
let slice = slice::from_raw_parts(ptr, len as usize);
CString { inner: mem::transmute(slice) }
let slice = slice::from_raw_parts_mut(ptr, len as usize);
CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
}

/// Transfers ownership of the string to a C caller.
Expand Down Expand Up @@ -480,7 +480,7 @@ impl CString {
/// ```
#[stable(feature = "into_boxed_c_str", since = "1.20.0")]
pub fn into_boxed_c_str(self) -> Box<CStr> {
unsafe { mem::transmute(self.into_inner()) }
unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) }
}

// Bypass "move out of struct which implements [`Drop`] trait" restriction.
Expand Down Expand Up @@ -569,7 +569,7 @@ impl Borrow<CStr> for CString {
impl<'a> From<&'a CStr> for Box<CStr> {
fn from(s: &'a CStr) -> Box<CStr> {
let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul());
unsafe { mem::transmute(boxed) }
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
}
}

Expand All @@ -593,7 +593,7 @@ impl From<CString> for Box<CStr> {
impl Default for Box<CStr> {
fn default() -> Box<CStr> {
let boxed: Box<[u8]> = Box::from([0]);
unsafe { mem::transmute(boxed) }
unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) }
}
}

Expand Down Expand Up @@ -817,7 +817,7 @@ impl CStr {
#[inline]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
mem::transmute(bytes)
&*(bytes as *const [u8] as *const CStr)
}

/// Returns the inner pointer to this C string.
Expand Down Expand Up @@ -913,7 +913,7 @@ impl CStr {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes_with_nul(&self) -> &[u8] {
unsafe { mem::transmute(&self.inner) }
unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
}

/// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
Expand Down Expand Up @@ -1005,7 +1005,8 @@ impl CStr {
/// ```
#[stable(feature = "into_boxed_c_str", since = "1.20.0")]
pub fn into_c_string(self: Box<CStr>) -> CString {
unsafe { mem::transmute(self) }
let raw = Box::into_raw(self) as *mut [u8];
CString { inner: unsafe { Box::from_raw(raw) } }
}
}

Expand Down
18 changes: 10 additions & 8 deletions src/libstd/ffi/os_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

use borrow::{Borrow, Cow};
use fmt;
use mem;
use ops;
use cmp;
use hash::{Hash, Hasher};
Expand Down Expand Up @@ -260,7 +259,8 @@ impl OsString {
/// ```
#[stable(feature = "into_boxed_os_str", since = "1.20.0")]
pub fn into_boxed_os_str(self) -> Box<OsStr> {
unsafe { mem::transmute(self.inner.into_box()) }
let rw = Box::into_raw(self.inner.into_box()) as *mut OsStr;
unsafe { Box::from_raw(rw) }
}
}

Expand Down Expand Up @@ -394,7 +394,7 @@ impl OsStr {
}

fn from_inner(inner: &Slice) -> &OsStr {
unsafe { mem::transmute(inner) }
unsafe { &*(inner as *const Slice as *const OsStr) }
}

/// Yields a [`&str`] slice if the `OsStr` is valid Unicode.
Expand Down Expand Up @@ -511,23 +511,24 @@ impl OsStr {
/// [`OsString`]: struct.OsString.html
#[stable(feature = "into_boxed_os_str", since = "1.20.0")]
pub fn into_os_string(self: Box<OsStr>) -> OsString {
let inner: Box<Slice> = unsafe { mem::transmute(self) };
OsString { inner: Buf::from_box(inner) }
let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
OsString { inner: Buf::from_box(boxed) }
}

/// Gets the underlying byte representation.
///
/// Note: it is *crucial* that this API is private, to avoid
/// revealing the internal, platform-specific encodings.
fn bytes(&self) -> &[u8] {
unsafe { mem::transmute(&self.inner) }
unsafe { &*(&self.inner as *const _ as *const [u8]) }
}
}

#[stable(feature = "box_from_os_str", since = "1.17.0")]
impl<'a> From<&'a OsStr> for Box<OsStr> {
fn from(s: &'a OsStr) -> Box<OsStr> {
unsafe { mem::transmute(s.inner.into_box()) }
let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
unsafe { Box::from_raw(rw) }
}
}

Expand All @@ -548,7 +549,8 @@ impl From<OsString> for Box<OsStr> {
#[stable(feature = "box_default_extra", since = "1.17.0")]
impl Default for Box<OsStr> {
fn default() -> Box<OsStr> {
unsafe { mem::transmute(Slice::empty_box()) }
let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
unsafe { Box::from_raw(rw) }
}
}

Expand Down
16 changes: 9 additions & 7 deletions src/libstd/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ use fs;
use hash::{Hash, Hasher};
use io;
use iter::{self, FusedIterator};
use mem;
use ops::{self, Deref};

use ffi::{OsStr, OsString};
Expand Down Expand Up @@ -317,10 +316,10 @@ fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I>

// See note at the top of this module to understand why these are used:
fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
unsafe { mem::transmute(s) }
unsafe { &*(s as *const OsStr as *const [u8]) }
}
unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
mem::transmute(s)
&*(s as *const [u8] as *const OsStr)
}

// Detect scheme on Redox
Expand Down Expand Up @@ -1334,15 +1333,17 @@ impl PathBuf {
/// [`Path`]: struct.Path.html
#[stable(feature = "into_boxed_path", since = "1.20.0")]
pub fn into_boxed_path(self) -> Box<Path> {
unsafe { mem::transmute(self.inner.into_boxed_os_str()) }
let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;
unsafe { Box::from_raw(rw) }
}
}

#[stable(feature = "box_from_path", since = "1.17.0")]
impl<'a> From<&'a Path> for Box<Path> {
fn from(path: &'a Path) -> Box<Path> {
let boxed: Box<OsStr> = path.inner.into();
unsafe { mem::transmute(boxed) }
let rw = Box::into_raw(boxed) as *mut Path;
unsafe { Box::from_raw(rw) }
}
}

Expand Down Expand Up @@ -1589,7 +1590,7 @@ impl Path {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
unsafe { mem::transmute(s.as_ref()) }
unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
}

/// Yields the underlying [`OsStr`] slice.
Expand Down Expand Up @@ -2312,7 +2313,8 @@ impl Path {
/// [`PathBuf`]: struct.PathBuf.html
#[stable(feature = "into_boxed_path", since = "1.20.0")]
pub fn into_path_buf(self: Box<Path>) -> PathBuf {
let inner: Box<OsStr> = unsafe { mem::transmute(self) };
let rw = Box::into_raw(self) as *mut OsStr;
let inner = unsafe { Box::from_raw(rw) };
PathBuf { inner: OsString::from(inner) }
}
}
Expand Down