From 442a7bbedc37c589be490cfe21a74be5ea9de65b Mon Sep 17 00:00:00 2001 From: jD91mZM2 <me@krake.one> Date: Sat, 4 Aug 2018 07:14:07 +0200 Subject: [PATCH] Fix getcwd with a NULL argument --- src/platform/src/redox/mod.rs | 8 ++++++-- src/unistd/src/lib.rs | 31 ++++++++++++++++++++++++++++--- tests/Makefile | 1 + tests/unistd/getcwd.c | 22 ++++++++++++++++++++++ 4 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 tests/unistd/getcwd.c diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index 48585668..05afc235 100644 --- a/src/platform/src/redox/mod.rs +++ b/src/platform/src/redox/mod.rs @@ -346,10 +346,14 @@ pub fn utimens(path: *const c_char, times: *const timespec) -> c_int { } pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char { - let buf_slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size as usize) }; - if e(syscall::getcwd(buf_slice)) == !0 { + let buf_slice = unsafe { slice::from_raw_parts_mut(buf as *mut u8, size as usize - 1) }; + let read = e(syscall::getcwd(buf_slice)); + if read == !0 { ptr::null_mut() } else { + unsafe { + *buf.offset(read as isize + 1) = 0; + } buf } } diff --git a/src/unistd/src/lib.rs b/src/unistd/src/lib.rs index 95c3eac4..944d9726 100644 --- a/src/unistd/src/lib.rs +++ b/src/unistd/src/lib.rs @@ -38,6 +38,8 @@ pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; +const PATH_MAX: usize = 4096; + #[no_mangle] pub extern "C" fn _exit(status: c_int) { platform::exit(status) @@ -184,8 +186,31 @@ pub extern "C" fn ftruncate(fildes: c_int, length: off_t) -> c_int { } #[no_mangle] -pub extern "C" fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char { - platform::getcwd(buf, size) +pub extern "C" fn getcwd(mut buf: *mut c_char, mut size: size_t) -> *mut c_char { + let alloc = buf.is_null(); + let mut stack_buf = [0; PATH_MAX]; + if alloc { + buf = stack_buf.as_mut_ptr(); + size = stack_buf.len(); + } + + let ret = platform::getcwd(buf, size); + if ret == ptr::null_mut() { + return ptr::null_mut(); + } + + if alloc { + let mut len = stack_buf.iter().position(|b| *b == 0).expect("no nul-byte in getcwd string") + 1; + let mut heap_buf = unsafe { platform::alloc(len) as *mut c_char }; + for i in 0..len { + unsafe { + *heap_buf.offset(i as isize) = stack_buf[i]; + } + } + heap_buf + } else { + ret + } } // #[no_mangle] @@ -275,7 +300,7 @@ pub extern "C" fn getuid() -> uid_t { #[no_mangle] pub extern "C" fn getwd(path_name: *mut c_char) -> *mut c_char { - getcwd(path_name, 4096 /* PATH_MAX */) + getcwd(path_name, PATH_MAX) } #[no_mangle] diff --git a/tests/Makefile b/tests/Makefile index cad834e3..3ca98006 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -77,6 +77,7 @@ BINS=\ time/gettimeofday \ time/times \ unistd/chdir \ + unistd/getcwd \ unistd/gethostname \ unistd/getid \ unistd/link \ diff --git a/tests/unistd/getcwd.c b/tests/unistd/getcwd.c new file mode 100644 index 00000000..0d8e5f10 --- /dev/null +++ b/tests/unistd/getcwd.c @@ -0,0 +1,22 @@ +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +int main() { + char first[PATH_MAX]; + getcwd(first, PATH_MAX); + puts(first); + + char* second = getcwd(NULL, 0); + puts(second); + + if (strcmp(first, second)) { + puts("Not matching"); + free(second); + return 1; + } + + free(second); +} -- GitLab