about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorErick Tryzelaar <erick.tryzelaar@gmail.com>2013-07-07 13:30:48 -0700
committerErick Tryzelaar <erick.tryzelaar@gmail.com>2013-08-04 15:45:16 -0700
commitbd908d4c0e9cc4717928e63d7ed64cd9ffe0bfce (patch)
tree320111032a4e6435c3e2a50421909249b8f49f37 /src/libstd
parent3102b1797e24b9dd8eef2f68a74ec83749d7b53d (diff)
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.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/libc.rs4
-rw-r--r--src/libstd/os.rs94
-rw-r--r--src/libstd/ptr.rs101
3 files changed, 108 insertions, 91 deletions
diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs
index f96d3ce263e..678704fe098 100644
--- a/src/libstd/libc.rs
+++ b/src/libstd/libc.rs
@@ -2652,7 +2652,7 @@ pub mod funcs {
                 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 mod funcs {
                 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 ;
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index fb4f14d33c6..48a14d6893e 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -74,14 +74,15 @@ pub static TMPBUF_SZ : uint = 1000u;
 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 @@ pub fn self_exe_path() -> Option<Path> {
         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 @@ pub fn list_dir(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 @@ pub fn list_dir(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 @@ pub fn last_os_error() -> ~str {
         }
 
         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 @@ pub fn last_os_error() -> ~str {
         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)
+            }
         }
     }
 
diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs
index 77222490f17..88a915a1e55 100644
--- a/src/libstd/ptr.rs
+++ b/src/libstd/ptr.rs
@@ -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 @@ pub mod ptr_tests {
 
     #[test]
     fn test_position() {
-        use c_str::ToCStr;
         use libc::c_char;
 
         do "hello".to_c_str().with_ref |p| {
@@ -500,8 +500,6 @@ pub mod ptr_tests {
 
     #[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 @@ pub mod ptr_tests {
     #[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))]