Skip to content

Commit bd908d4

Browse files
committed
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.
1 parent 3102b17 commit bd908d4

File tree

4 files changed

+112
-96
lines changed

4 files changed

+112
-96
lines changed

src/librustc/middle/trans/base.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,11 +2400,10 @@ pub fn create_entry_wrapper(ccx: @mut CrateContext,
24002400
(rust_main, args)
24012401
};
24022402

2403-
let result = llvm::LLVMBuildCall(bld,
2404-
start_fn,
2405-
&args[0],
2406-
args.len() as c_uint,
2407-
noname());
2403+
let result = do args.as_imm_buf |buf, len| {
2404+
llvm::LLVMBuildCall(bld, start_fn, buf, len as c_uint, noname())
2405+
};
2406+
24082407
llvm::LLVMBuildRet(bld, result);
24092408
}
24102409
}

src/libstd/libc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,7 +2652,7 @@ pub mod funcs {
26522652
pub fn execvpe(c: *c_char, argv: **c_char, envp: **c_char)
26532653
-> c_int;
26542654
#[link_name = "_getcwd"]
2655-
pub fn getcwd(buf: *c_char, size: size_t) -> *c_char;
2655+
pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char;
26562656
#[link_name = "_getpid"]
26572657
pub fn getpid() -> c_int;
26582658
#[link_name = "_isatty"]
@@ -2804,7 +2804,7 @@ pub mod funcs {
28042804
pub fn execvp(c: *c_char, argv: **c_char) -> c_int;
28052805
pub fn fork() -> pid_t;
28062806
pub fn fpathconf(filedes: c_int, name: c_int) -> c_long;
2807-
pub fn getcwd(buf: *c_char, size: size_t) -> *c_char;
2807+
pub fn getcwd(buf: *mut c_char, size: size_t) -> *c_char;
28082808
pub fn getegid() -> gid_t;
28092809
pub fn geteuid() -> uid_t;
28102810
pub fn getgid() -> gid_t ;

src/libstd/os.rs

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,15 @@ pub static TMPBUF_SZ : uint = 1000u;
7474
static BUF_BYTES : uint = 2048u;
7575

7676
pub fn getcwd() -> Path {
77-
let buf = [0 as libc::c_char, ..BUF_BYTES];
78-
unsafe {
79-
if(0 as *libc::c_char == libc::getcwd(
80-
&buf[0],
81-
BUF_BYTES as libc::size_t)) {
82-
fail!();
77+
let mut buf = [0 as libc::c_char, ..BUF_BYTES];
78+
do buf.as_mut_buf |buf, len| {
79+
unsafe {
80+
if libc::getcwd(buf, len as size_t).is_null() {
81+
fail!()
82+
}
83+
84+
Path(str::raw::from_c_str(buf as *c_char))
8385
}
84-
Path(str::raw::from_c_str(&buf[0]))
8586
}
8687
}
8788

@@ -464,18 +465,18 @@ pub fn self_exe_path() -> Option<Path> {
464465
unsafe {
465466
use libc::funcs::posix01::unistd::readlink;
466467

467-
let mut path_str = str::with_capacity(TMPBUF_SZ);
468-
let len = do path_str.to_c_str().with_ref |buf| {
469-
let buf = buf as *mut c_char;
470-
do "/proc/self/exe".to_c_str().with_ref |proc_self_buf| {
471-
readlink(proc_self_buf, buf, TMPBUF_SZ as size_t)
468+
let mut path = [0 as c_char, .. TMPBUF_SZ];
469+
470+
do path.as_mut_buf |buf, len| {
471+
let len = do "/proc/self/exe".to_c_str.with_ref |proc_self_buf| {
472+
readlink(proc_self_buf, buf, len as size_t) as uint
473+
};
474+
475+
if len == -1 {
476+
None
477+
} else {
478+
Some(str::raw::from_buf_len(buf as *u8, len))
472479
}
473-
};
474-
if len == -1 {
475-
None
476-
} else {
477-
str::raw::set_len(&mut path_str, len as uint);
478-
Some(path_str)
479480
}
480481
}
481482
}
@@ -699,13 +700,15 @@ pub fn list_dir(p: &Path) -> ~[~str] {
699700
extern {
700701
fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
701702
}
702-
let input = p.to_str();
703703
let mut strings = ~[];
704-
let input_ptr = ::cast::transmute(&input[0]);
705704
debug!("os::list_dir -- BEFORE OPENDIR");
706-
let dir_ptr = opendir(input_ptr);
705+
706+
let dir_ptr = do p.to_c_str().with_ref |buf| {
707+
opendir(buf)
708+
};
709+
707710
if (dir_ptr as uint != 0) {
708-
debug!("os::list_dir -- opendir() SUCCESS");
711+
debug!("os::list_dir -- opendir() SUCCESS");
709712
let mut entry_ptr = readdir(dir_ptr);
710713
while (entry_ptr as uint != 0) {
711714
strings.push(str::raw::from_c_str(rust_list_dir_val(
@@ -715,7 +718,7 @@ pub fn list_dir(p: &Path) -> ~[~str] {
715718
closedir(dir_ptr);
716719
}
717720
else {
718-
debug!("os::list_dir -- opendir() FAILURE");
721+
debug!("os::list_dir -- opendir() FAILURE");
719722
}
720723
debug!(
721724
"os::list_dir -- AFTER -- #: %?",
@@ -1043,14 +1046,15 @@ pub fn last_os_error() -> ~str {
10431046
}
10441047

10451048
let mut buf = [0 as c_char, ..TMPBUF_SZ];
1046-
unsafe {
1047-
let err = strerror_r(errno() as c_int, &mut buf[0],
1048-
TMPBUF_SZ as size_t);
1049-
if err < 0 {
1050-
fail!("strerror_r failure");
1051-
}
10521049

1053-
str::raw::from_c_str(&buf[0])
1050+
do buf.as_mut_buf |buf, len| {
1051+
unsafe {
1052+
if strerror_r(errno() as c_int, buf, len as size_t) < 0 {
1053+
fail!("strerror_r failure");
1054+
}
1055+
1056+
str::raw::from_c_str(buf as *c_char)
1057+
}
10541058
}
10551059
}
10561060

@@ -1076,23 +1080,29 @@ pub fn last_os_error() -> ~str {
10761080
static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
10771081
static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
10781082

1079-
let mut buf = [0 as c_char, ..TMPBUF_SZ];
1080-
10811083
// This value is calculated from the macro
10821084
// MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
10831085
let langId = 0x0800 as DWORD;
10841086
let err = errno() as DWORD;
1085-
unsafe {
1086-
let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
1087-
FORMAT_MESSAGE_IGNORE_INSERTS,
1088-
ptr::mut_null(), err, langId,
1089-
&mut buf[0], TMPBUF_SZ as DWORD,
1090-
ptr::null());
1091-
if res == 0 {
1092-
fail!("[%?] FormatMessage failure", errno());
1093-
}
10941087

1095-
str::raw::from_c_str(&buf[0])
1088+
let mut buf = [0 as c_char, ..TMPBUF_SZ];
1089+
1090+
do buf.as_imm_buf |buf, len| {
1091+
unsafe {
1092+
let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
1093+
FORMAT_MESSAGE_IGNORE_INSERTS,
1094+
ptr::mut_null(),
1095+
err,
1096+
langId,
1097+
buf,
1098+
len as DWORD,
1099+
ptr::null());
1100+
if res == 0 {
1101+
fail!("[%?] FormatMessage failure", errno());
1102+
}
1103+
1104+
str::raw::from_c_str(buf)
1105+
}
10961106
}
10971107
}
10981108

src/libstd/ptr.rs

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ pub mod ptr_tests {
442442
use super::*;
443443
use prelude::*;
444444

445+
use c_str::ToCStr;
445446
use cast;
446447
use libc;
447448
use str;
@@ -486,7 +487,6 @@ pub mod ptr_tests {
486487

487488
#[test]
488489
fn test_position() {
489-
use c_str::ToCStr;
490490
use libc::c_char;
491491

492492
do "hello".to_c_str().with_ref |p| {
@@ -500,8 +500,6 @@ pub mod ptr_tests {
500500

501501
#[test]
502502
fn test_buf_len() {
503-
use c_str::ToCStr;
504-
505503
do "hello".to_c_str().with_ref |p0| {
506504
do "there".to_c_str().with_ref |p1| {
507505
do "thing".to_c_str().with_ref |p2| {
@@ -608,66 +606,75 @@ pub mod ptr_tests {
608606
#[test]
609607
fn test_ptr_array_each_with_len() {
610608
unsafe {
611-
let one = ~"oneOne";
612-
let two = ~"twoTwo";
613-
let three = ~"threeThree";
614-
let arr: ~[*i8] = ~[
615-
::cast::transmute(&one[0]),
616-
::cast::transmute(&two[0]),
617-
::cast::transmute(&three[0]),
609+
let one = "oneOne".to_c_str();
610+
let two = "twoTwo".to_c_str();
611+
let three = "threeThree".to_c_str();
612+
let arr = ~[
613+
one.with_ref(|buf| buf),
614+
two.with_ref(|buf| buf),
615+
three.with_ref(|buf| buf),
618616
];
619617
let expected_arr = [
620618
one, two, three
621619
];
622-
let arr_ptr = &arr[0];
623-
let mut ctr = 0;
624-
let mut iteration_count = 0;
625-
array_each_with_len(arr_ptr, arr.len(),
626-
|e| {
627-
let actual = str::raw::from_c_str(e);
628-
let expected = expected_arr[ctr].clone();
629-
debug!(
630-
"test_ptr_array_each e: %s, a: %s",
631-
expected, actual);
632-
assert_eq!(actual, expected);
633-
ctr += 1;
634-
iteration_count += 1;
635-
});
636-
assert_eq!(iteration_count, 3u);
620+
621+
do arr.as_imm_buf |arr_ptr, arr_len| {
622+
let mut ctr = 0;
623+
let mut iteration_count = 0;
624+
do array_each_with_len(arr_ptr, arr_len) |e| {
625+
let actual = str::raw::from_c_str(e);
626+
let expected = do expected_arr[ctr].with_ref |buf| {
627+
str::raw::from_c_str(buf)
628+
};
629+
debug!(
630+
"test_ptr_array_each_with_len e: %s, a: %s",
631+
expected, actual);
632+
assert_eq!(actual, expected);
633+
ctr += 1;
634+
iteration_count += 1;
635+
}
636+
assert_eq!(iteration_count, 3u);
637+
}
637638
}
638639
}
640+
639641
#[test]
640642
fn test_ptr_array_each() {
641643
unsafe {
642-
let one = ~"oneOne";
643-
let two = ~"twoTwo";
644-
let three = ~"threeThree";
645-
let arr: ~[*i8] = ~[
646-
::cast::transmute(&one[0]),
647-
::cast::transmute(&two[0]),
648-
::cast::transmute(&three[0]),
644+
let one = "oneOne".to_c_str();
645+
let two = "twoTwo".to_c_str();
646+
let three = "threeThree".to_c_str();
647+
let arr = ~[
648+
one.with_ref(|buf| buf),
649+
two.with_ref(|buf| buf),
650+
three.with_ref(|buf| buf),
649651
// fake a null terminator
650-
0 as *i8
652+
null(),
651653
];
652654
let expected_arr = [
653655
one, two, three
654656
];
655-
let arr_ptr = &arr[0];
656-
let mut ctr = 0;
657-
let mut iteration_count = 0;
658-
array_each(arr_ptr, |e| {
659-
let actual = str::raw::from_c_str(e);
660-
let expected = expected_arr[ctr].clone();
661-
debug!(
662-
"test_ptr_array_each e: %s, a: %s",
663-
expected, actual);
664-
assert_eq!(actual, expected);
665-
ctr += 1;
666-
iteration_count += 1;
667-
});
668-
assert_eq!(iteration_count, 3);
657+
658+
do arr.as_imm_buf |arr_ptr, arr_len| {
659+
let mut ctr = 0;
660+
let mut iteration_count = 0;
661+
do array_each(arr_ptr) |e| {
662+
let actual = str::raw::from_c_str(e);
663+
let expected = do expected_arr[ctr].with_ref |buf| {
664+
str::raw::from_c_str(buf)
665+
};
666+
debug!(
667+
"test_ptr_array_each e: %s, a: %s",
668+
expected, actual);
669+
assert_eq!(actual, expected);
670+
ctr += 1;
671+
iteration_count += 1;
672+
}
673+
assert_eq!(iteration_count, 3);
674+
}
669675
}
670676
}
677+
671678
#[test]
672679
#[should_fail]
673680
#[ignore(cfg(windows))]

0 commit comments

Comments
 (0)