From 3ac862816fc57fb6047986624d98f986cbfd40b9 Mon Sep 17 00:00:00 2001 From: Mikhail Zabaluev Date: Wed, 4 Feb 2015 01:00:38 +0200 Subject: [PATCH 1/2] Replace usage of slice::from_raw_buf with slice::from_raw_parts New functions, slice::from_raw_parts and slice::from_raw_parts_mut, are added to implement the lifetime convention as agreed in RFC PR #556. The functions slice::from_raw_buf and slice::from_raw_mut_buf are left deprecated for the time being. --- src/libcollections/slice.rs | 1 + src/libcore/slice.rs | 56 ++++++++++++++++++++++++++++++--- src/libflate/lib.rs | 2 +- src/librand/isaac.rs | 4 +-- src/librustc/metadata/loader.rs | 8 ++--- src/librustdoc/html/markdown.rs | 28 +++++++++-------- src/libstd/ffi/c_str.rs | 4 +-- src/libstd/os.rs | 2 +- src/libstd/sys/windows/os.rs | 4 +-- 9 files changed, 80 insertions(+), 29 deletions(-) diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 4b4ea3e4c3ca5..2f547c72d0543 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -113,6 +113,7 @@ pub use core::slice::{Iter, IterMut}; pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split}; pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; pub use core::slice::{bytes, mut_ref_slice, ref_slice}; +pub use core::slice::{from_raw_parts, from_raw_parts_mut}; pub use core::slice::{from_raw_buf, from_raw_mut_buf}; //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index a750e81bf596b..c622baa0cc22d 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1357,6 +1357,52 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { } } +/// Forms a slice from a pointer and a length. +/// +/// The `len` argument is the number of **elements**, not the number of bytes. +/// +/// This function is unsafe as there is no guarantee that the given pointer is +/// valid for `len` elements, nor whether the lifetime inferred is a suitable +/// lifetime for the returned slice. +/// +/// # Caveat +/// +/// The lifetime for the returned slice 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 slice, or by explicit +/// annotation. +/// +/// # Example +/// +/// ```rust +/// use std::slice; +/// +/// // manifest a slice out of thin air! +/// let ptr = 0x1234 as *const uint; +/// let amt = 10; +/// unsafe { +/// let slice = slice::from_raw_parts(ptr, amt); +/// } +/// ``` +#[inline] +#[unstable(feature = "core")] +pub unsafe fn from_raw_parts<'a, T>(p: *const T, len: uint) -> &'a [T] { + transmute(RawSlice { data: p, len: len }) +} + +/// Performs the same functionality as `from_raw_parts`, except that a mutable +/// slice is returned. +/// +/// This function is unsafe for the same reasons as `from_raw_parts`, as well +/// as not being able to provide a non-aliasing guarantee of the returned +/// mutable slice. +#[inline] +#[unstable(feature = "core")] +pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: uint) -> &'a mut [T] { + transmute(RawSlice { data: p, len: len }) +} + /// Forms a slice from a pointer and a length. /// /// The pointer given is actually a reference to the base of the slice. This @@ -1383,8 +1429,9 @@ pub fn mut_ref_slice<'a, A>(s: &'a mut A) -> &'a mut [A] { /// } /// ``` #[inline] -#[unstable(feature = "core", - reason = "should be renamed to from_raw_parts")] +#[unstable(feature = "core")] +#[deprecated(since = "1.0.0", + reason = "use from_raw_parts")] pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] { transmute(RawSlice { data: *p, len: len }) } @@ -1396,8 +1443,9 @@ pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: uint) -> &'a [T] { /// not being able to provide a non-aliasing guarantee of the returned mutable /// slice. #[inline] -#[unstable(feature = "core", - reason = "should be renamed to from_raw_parts_mut")] +#[unstable(feature = "core")] +#[deprecated(since = "1.0.0", + reason = "use from_raw_parts_mut")] pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] { transmute(RawSlice { data: *p, len: len }) } diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index a3bbba6d7b432..6c0c00002142a 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -45,7 +45,7 @@ pub struct Bytes { impl Deref for Bytes { type Target = [u8]; fn deref(&self) -> &[u8] { - unsafe { slice::from_raw_mut_buf(&self.ptr.0, self.len) } + unsafe { slice::from_raw_parts_mut(self.ptr.0, self.len) } } } diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index d399c244e83b8..67942a7e5b6eb 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -246,7 +246,7 @@ impl Rand for IsaacRng { unsafe { let ptr = ret.rsl.as_mut_ptr() as *mut u8; - let slice = slice::from_raw_mut_buf(&ptr, (RAND_SIZE * 4) as uint); + let slice = slice::from_raw_parts_mut(ptr, (RAND_SIZE * 4) as uint); other.fill_bytes(slice); } ret.cnt = 0; @@ -489,7 +489,7 @@ impl Rand for Isaac64Rng { unsafe { let ptr = ret.rsl.as_mut_ptr() as *mut u8; - let slice = slice::from_raw_mut_buf(&ptr, (RAND_SIZE_64 * 8) as uint); + let slice = slice::from_raw_parts_mut(ptr, (RAND_SIZE_64 * 8) as uint); other.fill_bytes(slice); } ret.cnt = 0; diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 2fb5a6b64a652..b7111d49d06ac 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -744,8 +744,8 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result Result Result return Ok(MetadataVec(inflated)), None => {} diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 7e08226019f98..8680604d3683d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -165,6 +165,13 @@ extern { } +// hoedown_buffer helpers +impl hoedown_buffer { + fn as_bytes(&self) -> &[u8] { + unsafe { slice::from_raw_parts(self.data, self.size as usize) } + } +} + /// Returns Some(code) if `s` is a line that should be stripped from /// documentation but used in example code. `code` is the portion of /// `s` that should be used in tests. (None for lines that should be @@ -194,15 +201,13 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { let opaque = opaque as *mut hoedown_html_renderer_state; let my_opaque: &MyOpaque = &*((*opaque).opaque as *const MyOpaque); - let text = slice::from_raw_buf(&(*orig_text).data, - (*orig_text).size as uint); + let text = (*orig_text).as_bytes(); let origtext = str::from_utf8(text).unwrap(); debug!("docblock: ==============\n{:?}\n=======", text); let rendered = if lang.is_null() { false } else { - let rlang = slice::from_raw_buf(&(*lang).data, - (*lang).size as uint); + let rlang = (*lang).as_bytes(); let rlang = str::from_utf8(rlang).unwrap(); if !LangString::parse(rlang).rust { (my_opaque.dfltblk)(ob, orig_text, lang, @@ -248,9 +253,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { let s = if text.is_null() { "".to_string() } else { - let s = unsafe { - slice::from_raw_buf(&(*text).data, (*text).size as uint) - }; + let s = unsafe { (*text).as_bytes() }; str::from_utf8(s).unwrap().to_string() }; @@ -323,7 +326,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { }; if ret.is_ok() { - let buf = slice::from_raw_buf(&(*ob).data, (*ob).size as uint); + let buf = (*ob).as_bytes(); ret = w.write_str(str::from_utf8(buf).unwrap()); } hoedown_buffer_free(ob); @@ -341,13 +344,12 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { let block_info = if lang.is_null() { LangString::all_false() } else { - let lang = slice::from_raw_buf(&(*lang).data, - (*lang).size as uint); + let lang = (*lang).as_bytes(); let s = str::from_utf8(lang).unwrap(); LangString::parse(s) }; if !block_info.rust { return } - let text = slice::from_raw_buf(&(*text).data, (*text).size as uint); + let text = (*text).as_bytes(); let opaque = opaque as *mut hoedown_html_renderer_state; let tests = &mut *((*opaque).opaque as *mut ::test::Collector); let text = str::from_utf8(text).unwrap(); @@ -370,7 +372,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) { if text.is_null() { tests.register_header("", level as u32); } else { - let text = slice::from_raw_buf(&(*text).data, (*text).size as uint); + let text = (*text).as_bytes(); let text = str::from_utf8(text).unwrap(); tests.register_header(text, level as u32); } @@ -510,7 +512,7 @@ pub fn plain_summary_line(md: &str) -> String { hoedown_document_render(document, ob, md.as_ptr(), md.len() as libc::size_t); hoedown_document_free(document); - let plain_slice = slice::from_raw_buf(&(*ob).data, (*ob).size as uint); + let plain_slice = (*ob).as_bytes(); let plain = match str::from_utf8(plain_slice) { Ok(s) => s.to_string(), Err(_) => "".to_string(), diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 2e55c007b551b..fcc4509aa9417 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -162,7 +162,7 @@ impl fmt::Debug for CString { /// ``` pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { let len = libc::strlen(*raw); - slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint) + slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize) } /// Interpret a C string as a byte slice with the nul terminator. @@ -171,7 +171,7 @@ pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { /// will include the nul terminator of the string. pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { let len = libc::strlen(*raw) + 1; - slice::from_raw_buf(&*(raw as *const _ as *const *const u8), len as uint) + slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize) } #[cfg(test)] diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 64f9e16aee4fd..dcdd31639d39c 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -671,7 +671,7 @@ fn real_args() -> Vec { // Push it onto the list. let ptr = ptr as *const u16; - let buf = slice::from_raw_buf(&ptr, len); + let buf = slice::from_raw_parts(ptr, len); let opt_s = String::from_utf16(sys::truncate_utf16_at_nul(buf)); opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16") }).collect(); diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index c71e2d057c351..d8e3e6981df76 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -109,7 +109,7 @@ impl Iterator for Env { len += 1; } let p = p as *const u16; - let s = slice::from_raw_buf(&p, len as usize); + let s = slice::from_raw_parts(p, len as usize); self.cur = self.cur.offset(len + 1); let (k, v) = match s.iter().position(|&b| b == '=' as u16) { @@ -296,7 +296,7 @@ impl Iterator for Args { // Push it onto the list. let ptr = ptr as *const u16; - let buf = slice::from_raw_buf(&ptr, len as usize); + let buf = slice::from_raw_parts(ptr, len as usize); OsStringExt::from_wide(buf) }) } From fb6b970bf8d12182a69b1e7ae222f3e2ebbb9003 Mon Sep 17 00:00:00 2001 From: Mikhail Zabaluev Date: Thu, 5 Feb 2015 13:53:32 +0200 Subject: [PATCH 2/2] Replace one more slice::from_raw_mut_buf added with new io --- src/libstd/io/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 0832206a48b60..419bee1a624d3 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -24,7 +24,6 @@ use error::Error as StdError; use fmt; use iter::Iterator; use marker::Sized; -use mem; use ops::{Drop, FnOnce}; use option::Option::{self, Some, None}; use ptr::PtrExt; @@ -69,8 +68,8 @@ fn with_end_to_cap(v: &mut Vec, f: F) -> Result unsafe { let n = try!(f({ let base = v.as_mut_ptr().offset(v.len() as isize); - black_box(slice::from_raw_mut_buf(mem::copy_lifetime(v, &base), - v.capacity() - v.len())) + black_box(slice::from_raw_parts_mut(base, + v.capacity() - v.len())) })); // If the closure (typically a `read` implementation) reported that it