提交 bd908d4c 编写于 作者: E Erick Tryzelaar

std and rustc: explicitly pass c strings to c functions

When strings lose their trailing null, this pattern will become dangerous:

let foo = "bar";
let foo_ptr: *u8 = &foo[0];

Instead we should use c_strs to handle this correctly.
上级 3102b179
......@@ -2400,11 +2400,10 @@ fn create_entry_fn(ccx: @mut CrateContext,
(rust_main, args)
};
let result = llvm::LLVMBuildCall(bld,
start_fn,
&args[0],
args.len() as c_uint,
noname());
let result = do args.as_imm_buf |buf, len| {
llvm::LLVMBuildCall(bld, start_fn, buf, len as c_uint, noname())
};
llvm::LLVMBuildRet(bld, result);
}
}
......
......@@ -2652,7 +2652,7 @@ pub fn execve(prog: *c_char, argv: **c_char, envp: **c_char)
pub fn execvpe(c: *c_char, argv: **c_char, envp: **c_char)
-> c_int;
#[link_name = "_getcwd"]
pub fn getcwd(buf: *c_char, size: size_t) -> *c_char;
pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char;
#[link_name = "_getpid"]
pub fn getpid() -> c_int;
#[link_name = "_isatty"]
......@@ -2804,7 +2804,7 @@ pub fn execve(prog: *c_char, argv: **c_char, envp: **c_char)
pub fn execvp(c: *c_char, argv: **c_char) -> c_int;
pub fn fork() -> pid_t;
pub fn fpathconf(filedes: c_int, name: c_int) -> c_long;
pub fn getcwd(buf: *c_char, size: size_t) -> *c_char;
pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char;
pub fn getegid() -> gid_t;
pub fn geteuid() -> uid_t;
pub fn getgid() -> gid_t ;
......
......@@ -74,14 +74,15 @@ pub mod rustrt {
static BUF_BYTES : uint = 2048u;
pub fn getcwd() -> Path {
let buf = [0 as libc::c_char, ..BUF_BYTES];
unsafe {
if(0 as *libc::c_char == libc::getcwd(
&buf[0],
BUF_BYTES as libc::size_t)) {
fail!();
let mut buf = [0 as libc::c_char, ..BUF_BYTES];
do buf.as_mut_buf |buf, len| {
unsafe {
if libc::getcwd(buf, len as size_t).is_null() {
fail!()
}
Path(str::raw::from_c_str(buf as *c_char))
}
Path(str::raw::from_c_str(&buf[0]))
}
}
......@@ -464,18 +465,18 @@ fn load_self() -> Option<~str> {
unsafe {
use libc::funcs::posix01::unistd::readlink;
let mut path_str = str::with_capacity(TMPBUF_SZ);
let len = do path_str.to_c_str().with_ref |buf| {
let buf = buf as *mut c_char;
do "/proc/self/exe".to_c_str().with_ref |proc_self_buf| {
readlink(proc_self_buf, buf, TMPBUF_SZ as size_t)
let mut path = [0 as c_char, .. TMPBUF_SZ];
do path.as_mut_buf |buf, len| {
let len = do "/proc/self/exe".to_c_str.with_ref |proc_self_buf| {
readlink(proc_self_buf, buf, len as size_t) as uint
};
if len == -1 {
None
} else {
Some(str::raw::from_buf_len(buf as *u8, len))
}
};
if len == -1 {
None
} else {
str::raw::set_len(&mut path_str, len as uint);
Some(path_str)
}
}
}
......@@ -699,13 +700,15 @@ unsafe fn get_list(p: &Path) -> ~[~str] {
extern {
fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
}
let input = p.to_str();
let mut strings = ~[];
let input_ptr = ::cast::transmute(&input[0]);
debug!("os::list_dir -- BEFORE OPENDIR");
let dir_ptr = opendir(input_ptr);
let dir_ptr = do p.to_c_str().with_ref |buf| {
opendir(buf)
};
if (dir_ptr as uint != 0) {
debug!("os::list_dir -- opendir() SUCCESS");
debug!("os::list_dir -- opendir() SUCCESS");
let mut entry_ptr = readdir(dir_ptr);
while (entry_ptr as uint != 0) {
strings.push(str::raw::from_c_str(rust_list_dir_val(
......@@ -715,7 +718,7 @@ unsafe fn get_list(p: &Path) -> ~[~str] {
closedir(dir_ptr);
}
else {
debug!("os::list_dir -- opendir() FAILURE");
debug!("os::list_dir -- opendir() FAILURE");
}
debug!(
"os::list_dir -- AFTER -- #: %?",
......@@ -1043,14 +1046,15 @@ fn __xpg_strerror_r(errnum: c_int,
}
let mut buf = [0 as c_char, ..TMPBUF_SZ];
unsafe {
let err = strerror_r(errno() as c_int, &mut buf[0],
TMPBUF_SZ as size_t);
if err < 0 {
fail!("strerror_r failure");
}
str::raw::from_c_str(&buf[0])
do buf.as_mut_buf |buf, len| {
unsafe {
if strerror_r(errno() as c_int, buf, len as size_t) < 0 {
fail!("strerror_r failure");
}
str::raw::from_c_str(buf as *c_char)
}
}
}
......@@ -1076,23 +1080,29 @@ fn FormatMessageA(flags: DWORD,
static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
let mut buf = [0 as c_char, ..TMPBUF_SZ];
// This value is calculated from the macro
// MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
let langId = 0x0800 as DWORD;
let err = errno() as DWORD;
unsafe {
let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
ptr::mut_null(), err, langId,
&mut buf[0], TMPBUF_SZ as DWORD,
ptr::null());
if res == 0 {
fail!("[%?] FormatMessage failure", errno());
}
str::raw::from_c_str(&buf[0])
let mut buf = [0 as c_char, ..TMPBUF_SZ];
do buf.as_imm_buf |buf, len| {
unsafe {
let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
ptr::mut_null(),
err,
langId,
buf,
len as DWORD,
ptr::null());
if res == 0 {
fail!("[%?] FormatMessage failure", errno());
}
str::raw::from_c_str(buf)
}
}
}
......
......@@ -442,6 +442,7 @@ pub mod ptr_tests {
use super::*;
use prelude::*;
use c_str::ToCStr;
use cast;
use libc;
use str;
......@@ -486,7 +487,6 @@ struct Pair {
#[test]
fn test_position() {
use c_str::ToCStr;
use libc::c_char;
do "hello".to_c_str().with_ref |p| {
......@@ -500,8 +500,6 @@ fn test_position() {
#[test]
fn test_buf_len() {
use c_str::ToCStr;
do "hello".to_c_str().with_ref |p0| {
do "there".to_c_str().with_ref |p1| {
do "thing".to_c_str().with_ref |p2| {
......@@ -608,66 +606,75 @@ fn test_ptr_subtraction() {
#[test]
fn test_ptr_array_each_with_len() {
unsafe {
let one = ~"oneOne";
let two = ~"twoTwo";
let three = ~"threeThree";
let arr: ~[*i8] = ~[
::cast::transmute(&one[0]),
::cast::transmute(&two[0]),
::cast::transmute(&three[0]),
let one = "oneOne".to_c_str();
let two = "twoTwo".to_c_str();
let three = "threeThree".to_c_str();
let arr = ~[
one.with_ref(|buf| buf),
two.with_ref(|buf| buf),
three.with_ref(|buf| buf),
];
let expected_arr = [
one, two, three
];
let arr_ptr = &arr[0];
let mut ctr = 0;
let mut iteration_count = 0;
array_each_with_len(arr_ptr, arr.len(),
|e| {
let actual = str::raw::from_c_str(e);
let expected = expected_arr[ctr].clone();
debug!(
"test_ptr_array_each e: %s, a: %s",
expected, actual);
assert_eq!(actual, expected);
ctr += 1;
iteration_count += 1;
});
assert_eq!(iteration_count, 3u);
do arr.as_imm_buf |arr_ptr, arr_len| {
let mut ctr = 0;
let mut iteration_count = 0;
do array_each_with_len(arr_ptr, arr_len) |e| {
let actual = str::raw::from_c_str(e);
let expected = do expected_arr[ctr].with_ref |buf| {
str::raw::from_c_str(buf)
};
debug!(
"test_ptr_array_each_with_len e: %s, a: %s",
expected, actual);
assert_eq!(actual, expected);
ctr += 1;
iteration_count += 1;
}
assert_eq!(iteration_count, 3u);
}
}
}
#[test]
fn test_ptr_array_each() {
unsafe {
let one = ~"oneOne";
let two = ~"twoTwo";
let three = ~"threeThree";
let arr: ~[*i8] = ~[
::cast::transmute(&one[0]),
::cast::transmute(&two[0]),
::cast::transmute(&three[0]),
let one = "oneOne".to_c_str();
let two = "twoTwo".to_c_str();
let three = "threeThree".to_c_str();
let arr = ~[
one.with_ref(|buf| buf),
two.with_ref(|buf| buf),
three.with_ref(|buf| buf),
// fake a null terminator
0 as *i8
null(),
];
let expected_arr = [
one, two, three
];
let arr_ptr = &arr[0];
let mut ctr = 0;
let mut iteration_count = 0;
array_each(arr_ptr, |e| {
let actual = str::raw::from_c_str(e);
let expected = expected_arr[ctr].clone();
debug!(
"test_ptr_array_each e: %s, a: %s",
expected, actual);
assert_eq!(actual, expected);
ctr += 1;
iteration_count += 1;
});
assert_eq!(iteration_count, 3);
do arr.as_imm_buf |arr_ptr, arr_len| {
let mut ctr = 0;
let mut iteration_count = 0;
do array_each(arr_ptr) |e| {
let actual = str::raw::from_c_str(e);
let expected = do expected_arr[ctr].with_ref |buf| {
str::raw::from_c_str(buf)
};
debug!(
"test_ptr_array_each e: %s, a: %s",
expected, actual);
assert_eq!(actual, expected);
ctr += 1;
iteration_count += 1;
}
assert_eq!(iteration_count, 3);
}
}
}
#[test]
#[should_fail]
#[ignore(cfg(windows))]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册