Skip to content
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

Deprecate some unsafe functions in str::raw and remove OwnedStr trait #15807

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 13 additions & 79 deletions src/libcollections/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,67 +555,35 @@ impl<'a> fmt::Show for MaybeOwned<'a> {

/// Unsafe operations
pub mod raw {
use core::prelude::*;
use core::mem;
use core::raw::Slice;

use string;
use string::String;
use vec::Vec;

pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes};
pub use core::str::raw::{slice_unchecked};

/// Create a Rust string from a *u8 buffer of the given length
/// Deprecated. Replaced by `string::raw::from_buf_len`
#[deprecated = "Use string::raw::from_buf_len"]
pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> String {
let mut result = String::new();
result.push_bytes(mem::transmute(Slice {
data: buf,
len: len,
}));
result
string::raw::from_buf_len(buf, len)
}

/// Create a Rust string from a null-terminated C string
/// Deprecated. Use `string::raw::from_buf`
#[deprecated = "Use string::raw::from_buf"]
pub unsafe fn from_c_str(c_string: *const i8) -> String {
let mut buf = String::new();
let mut len = 0;
while *c_string.offset(len) != 0 {
len += 1;
}
buf.push_bytes(mem::transmute(Slice {
data: c_string,
len: len as uint,
}));
buf
string::raw::from_buf(c_string as *const u8)
}

/// Converts an owned vector of bytes to a new owned string. This assumes
/// that the utf-8-ness of the vector has already been validated
#[inline]
/// Deprecated. Replaced by `string::raw::from_utf8`
#[deprecated = "Use string::raw::from_utf8"]
pub unsafe fn from_utf8_owned(v: Vec<u8>) -> String {
mem::transmute(v)
string::raw::from_utf8(v)
}

/// Converts a byte to a string.
/// Deprecated. Use `string::raw::from_utf8`
#[deprecated = "Use string::raw::from_utf8"]
pub unsafe fn from_byte(u: u8) -> String {
from_utf8_owned(vec![u])
}

/// Sets the length of a string
///
/// This will explicitly set the size of the string, without actually
/// modifying its buffers, so it is up to the caller to ensure that
/// the string is actually the specified size.
#[test]
fn test_from_buf_len() {
use slice::ImmutableVector;

unsafe {
let a = vec![65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
let b = a.as_ptr();
let c = from_buf_len(b, 3u);
assert_eq!(c, String::from_str("AAA"));
}
string::raw::from_utf8(vec![u])
}
}

Expand Down Expand Up @@ -783,30 +751,6 @@ impl<'a> StrAllocating for &'a str {
}
}

/// Methods for owned strings
pub trait OwnedStr {
/// Consumes the string, returning the underlying byte buffer.
///
/// The buffer does not have a null terminator.
fn into_bytes(self) -> Vec<u8>;

/// Pushes the given string onto this string, returning the concatenation of the two strings.
fn append(self, rhs: &str) -> String;
}

impl OwnedStr for String {
#[inline]
fn into_bytes(self) -> Vec<u8> {
unsafe { mem::transmute(self) }
}

#[inline]
fn append(mut self, rhs: &str) -> String {
self.push_str(rhs);
self
}
}

#[cfg(test)]
mod tests {
use std::iter::AdditiveIterator;
Expand Down Expand Up @@ -1375,16 +1319,6 @@ mod tests {
[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]);
}

#[test]
fn test_raw_from_c_str() {
unsafe {
let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
let b = a.as_ptr();
let c = raw::from_c_str(b);
assert_eq!(c, String::from_str("AAAAAAA"));
}
}

#[test]
fn test_as_bytes() {
// no null
Expand Down
89 changes: 81 additions & 8 deletions src/libcollections/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,6 @@ impl String {
}
}

/// Creates a new string buffer from length, capacity, and a pointer.
#[inline]
pub unsafe fn from_raw_parts(length: uint, capacity: uint, ptr: *mut u8) -> String {
String {
vec: Vec::from_raw_parts(length, capacity, ptr),
}
}

/// Creates a new string buffer from the given string.
#[inline]
pub fn from_str(string: &str) -> String {
Expand All @@ -65,6 +57,13 @@ impl String {
}
}

/// Deprecated. Replaced by `string::raw::from_parts`
#[inline]
#[deprecated = "Replaced by string::raw::from_parts"]
pub unsafe fn from_raw_parts(length: uint, capacity: uint, ptr: *mut u8) -> String {
raw::from_parts(ptr, length, capacity)
}

#[allow(missing_doc)]
#[deprecated = "obsoleted by the removal of ~str"]
#[inline]
Expand Down Expand Up @@ -570,6 +569,62 @@ impl<S: Str> Add<S, String> for String {
}
}

pub mod raw {
use core::mem;
use core::ptr::RawPtr;
use core::raw::Slice;

use super::String;
use vec::Vec;

/// Creates a new `String` from length, capacity, and a pointer.
///
/// This is unsafe because:
/// * We call `Vec::from_raw_parts` to get a `Vec<u8>`
/// * We assume that the `Vec` contains valid UTF-8
#[inline]
pub unsafe fn from_parts(buf: *mut u8, length: uint, capacity: uint) -> String {
String {
vec: Vec::from_raw_parts(length, capacity, buf),
}
}

/// Create `String` from a *u8 buffer of the given length
///
/// This function is unsafe because of two reasons:
/// * A raw pointer is dereferenced and transmuted to `&[u8]`
/// * The slice is not checked to see whether it contains valid UTF-8
pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> String {
use slice::CloneableVector;
let slice: &[u8] = mem::transmute(Slice {
data: buf,
len: len,
});
self::from_utf8(slice.to_vec())
}

/// Create a `String` from a null-terminated *u8 buffer
///
/// This function is unsafe because we dereference memory until we find the NUL character,
/// which is not guaranteed to be present. Additionaly, the slice is not checked to see
/// whether it contains valid UTF-8
pub unsafe fn from_buf(buf: *const u8) -> String {
let mut len = 0;
while *buf.offset(len) != 0 {
len += 1;
}
self::from_buf_len(buf, len as uint)
}

/// Converts a vector of bytes to a new `String` without checking if
/// it contains valid UTF-8. This is unsafe because it assumes that
/// the utf-8-ness of the vector has already been validated.
#[inline]
pub unsafe fn from_utf8(bytes: Vec<u8>) -> String {
String { vec: bytes }
}
}

#[cfg(test)]
mod tests {
use std::prelude::*;
Expand Down Expand Up @@ -727,6 +782,24 @@ mod tests {
String::from_str("\uFFFD𐒋\uFFFD"));
}

#[test]
fn test_from_buf_len() {
unsafe {
let a = vec![65u8, 65, 65, 65, 65, 65, 65, 0];
assert_eq!(super::raw::from_buf_len(a.as_ptr(), 3), String::from_str("AAA"));
}
}

#[test]
fn test_from_buf() {
unsafe {
let a = vec![65, 65, 65, 65, 65, 65, 65, 0];
let b = a.as_ptr();
let c = super::raw::from_buf(b);
assert_eq!(c, String::from_str("AAAAAAA"));
}
}

#[test]
fn test_push_bytes() {
let mut s = String::from_str("ABC");
Expand Down
16 changes: 7 additions & 9 deletions src/libcoretest/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
use core::ptr::*;
use libc::c_char;
use core::mem;
use std::str;
use libc;
use std::c_str::CString;

#[test]
fn test() {
Expand Down Expand Up @@ -186,9 +186,8 @@ fn test_ptr_array_each_with_len() {
let mut ctr = 0;
let mut iteration_count = 0;
array_each_with_len(arr.as_ptr(), arr.len(), |e| {
let actual = str::raw::from_c_str(e);
let expected = str::raw::from_c_str(expected_arr[ctr].as_ptr());
assert_eq!(actual.as_slice(), expected.as_slice());
let actual = CString::new(e, false);
assert_eq!(actual.as_str(), expected_arr[ctr].as_str());
ctr += 1;
iteration_count += 1;
});
Expand Down Expand Up @@ -217,9 +216,8 @@ fn test_ptr_array_each() {
let mut ctr = 0u;
let mut iteration_count = 0u;
array_each(arr_ptr, |e| {
let actual = str::raw::from_c_str(e);
let expected = str::raw::from_c_str(expected_arr[ctr].as_ptr());
assert_eq!(actual.as_slice(), expected.as_slice());
let actual = CString::new(e, false);
assert_eq!(actual.as_str(), expected_arr[ctr].as_str());
ctr += 1;
iteration_count += 1;
});
Expand All @@ -232,7 +230,7 @@ fn test_ptr_array_each() {
fn test_ptr_array_each_with_len_null_ptr() {
unsafe {
array_each_with_len(0 as *const *const libc::c_char, 1, |e| {
str::raw::from_c_str(e);
CString::new(e, false).as_str().unwrap();
});
}
}
Expand All @@ -241,7 +239,7 @@ fn test_ptr_array_each_with_len_null_ptr() {
fn test_ptr_array_each_null_ptr() {
unsafe {
array_each(0 as *const *const libc::c_char, |e| {
str::raw::from_c_str(e);
CString::new(e, false).as_str().unwrap();
});
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/metadata/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ use std::io;
use std::mem;
use std::ptr;
use std::slice;
use std::str;
use std::string;

use std::collections::{HashMap, HashSet};
use flate;
Expand Down Expand Up @@ -772,7 +772,7 @@ fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result<MetadataBlob
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
let mut name_buf = ptr::null();
let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
let name = str::raw::from_buf_len(name_buf as *const u8,
let name = string::raw::from_buf_len(name_buf as *const u8,
name_len as uint);
debug!("get_metadata_section: name {}", name);
if read_meta_section_name(os).as_slice() == name.as_slice() {
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/middle/trans/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};

use std::c_str::ToCStr;
use std::mem;
use std::string;
use std::cell::RefCell;
use std::collections::HashMap;
use std::str::raw::from_c_str;

use libc::{c_uint, c_void, free};

Expand Down Expand Up @@ -334,9 +334,9 @@ impl TypeNames {
pub fn type_to_string(&self, ty: Type) -> String {
unsafe {
let s = llvm::LLVMTypeToString(ty.to_ref());
let ret = from_c_str(s);
let ret = string::raw::from_buf(s as *const u8);
free(s as *mut c_void);
ret.to_string()
ret
}
}

Expand All @@ -348,9 +348,9 @@ impl TypeNames {
pub fn val_to_string(&self, val: ValueRef) -> String {
unsafe {
let s = llvm::LLVMValueToString(val);
let ret = from_c_str(s);
let ret = string::raw::from_buf(s as *const u8);
free(s as *mut c_void);
ret.to_string()
ret
}
}
}
3 changes: 2 additions & 1 deletion src/librustdoc/html/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use std::cell::{RefCell, Cell};
use std::fmt;
use std::slice;
use std::str;
use std::string;
use std::collections::HashMap;

use html::toc::TocBuilder;
Expand Down Expand Up @@ -222,7 +223,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
"".to_string()
} else {
unsafe {
str::raw::from_buf_len((*text).data, (*text).size as uint)
string::raw::from_buf_len((*text).data, (*text).size as uint)
}
};

Expand Down
6 changes: 3 additions & 3 deletions src/librustuv/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ use libc::{c_int, c_void};
use std::fmt;
use std::mem;
use std::ptr;
use std::string;
use std::rt::local::Local;
use std::rt::rtio;
use std::rt::rtio::{IoResult, IoError};
use std::rt::task::{BlockedTask, Task};
use std::str::raw::from_c_str;
use std::task;

pub use self::async::AsyncWatcher;
Expand Down Expand Up @@ -363,7 +363,7 @@ impl UvError {
let inner = match self { &UvError(a) => a };
let name_str = uvll::uv_err_name(inner);
assert!(name_str.is_not_null());
from_c_str(name_str).to_string()
string::raw::from_buf(name_str as *const u8)
}
}

Expand All @@ -372,7 +372,7 @@ impl UvError {
let inner = match self { &UvError(a) => a };
let desc_str = uvll::uv_strerror(inner);
assert!(desc_str.is_not_null());
from_c_str(desc_str).to_string()
string::raw::from_buf(desc_str as *const u8)
}
}

Expand Down
Loading