From 3bb3a3e3225f3488c796d1a9a5b03c053762f677 Mon Sep 17 00:00:00 2001 From: jD91mZM2 <me@krake.one> Date: Tue, 7 Aug 2018 11:35:23 +0200 Subject: [PATCH] Fix strcpy --- src/crt0/src/lib.rs | 46 +++++++++++++++++++++-------- src/string/src/lib.rs | 40 +++++++++++++++---------- tests/Makefile | 1 + tests/expected/string/strcpy.stderr | 0 tests/expected/string/strcpy.stdout | 3 ++ tests/string/strcpy.c | 17 +++++++++++ 6 files changed, 78 insertions(+), 29 deletions(-) create mode 100644 tests/expected/string/strcpy.stderr create mode 100644 tests/expected/string/strcpy.stdout create mode 100644 tests/string/strcpy.c diff --git a/src/crt0/src/lib.rs b/src/crt0/src/lib.rs index c9cc2739..2d2ce8f5 100644 --- a/src/crt0/src/lib.rs +++ b/src/crt0/src/lib.rs @@ -53,6 +53,7 @@ impl Stack { &self.argv0 as *const *const u8 } + #[cfg(not(target_os = "redox"))] fn envp(&self) -> *const *const u8 { unsafe { self.argv().offset(self.argc() + 1) } } @@ -62,30 +63,43 @@ impl Stack { #[no_mangle] pub unsafe extern "C" fn _start_rust(sp: &'static Stack) -> ! { extern "C" { + #[cfg(not(target_os = "redox"))] fn main(argc: isize, argv: *const *const c_char, envp: *const *const c_char) -> c_int; + #[cfg(target_os = "redox")] + fn main(argc: isize, argv: *const *const c_char) -> c_int; } let argc = sp.argc(); let argv = sp.argv(); - let envp = sp.envp(); - let mut len = 0; - while *envp.offset(len) != ptr::null() { - len += 1; + #[cfg(target_os = "redox")] + { + // TODO: Redox will support environ like on linux, eventually. + // We could implement it using the env: scheme here, but eh. + platform::inner_environ = Vec::with_capacity(1); } - platform::inner_environ = Vec::with_capacity(len as usize + 1); - for i in 0..len { - let mut item = *envp.offset(i); + #[cfg(not(target_os = "redox"))] + let envp = sp.envp(); + #[cfg(not(target_os = "redox"))] + { let mut len = 0; - while *item.offset(len) != 0 { + while *envp.offset(len) != ptr::null() { len += 1; } - - let buf = platform::alloc(len as usize + 1) as *mut c_char; - for i in 0..=len { - *buf.offset(i) = *item.offset(i) as c_char; + platform::inner_environ = Vec::with_capacity(len as usize + 1); + for i in 0..len { + let mut item = *envp.offset(i); + let mut len = 0; + while *item.offset(len) != 0 { + len += 1; + } + + let buf = platform::alloc(len as usize + 1) as *mut c_char; + for i in 0..=len { + *buf.offset(i) = *item.offset(i) as c_char; + } + platform::inner_environ.push(buf); } - platform::inner_environ.push(buf); } platform::inner_environ.push(ptr::null_mut()); platform::environ = platform::inner_environ.as_mut_ptr(); @@ -95,11 +109,17 @@ pub unsafe extern "C" fn _start_rust(sp: &'static Stack) -> ! { stdio::stdout = stdio::default_stdout.get(); stdio::stderr = stdio::default_stderr.get(); + #[cfg(not(target_os = "redox"))] platform::exit(main( argc, argv as *const *const c_char, envp as *const *const c_char, )); + #[cfg(target_os = "redox")] + platform::exit(main( + argc, + argv as *const *const c_char, + )); } #[panic_implementation] diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index ea9606dc..7960febb 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -150,8 +150,21 @@ pub unsafe extern "C" fn strcoll(s1: *const c_char, s2: *const c_char) -> c_int } #[no_mangle] -pub unsafe extern "C" fn strcpy(s1: *mut c_char, s2: *const c_char) -> *mut c_char { - strncpy(s1, s2, usize::MAX) +pub unsafe extern "C" fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char { + let mut i = 0; + + loop { + let byte = *src.offset(i); + *dst.offset(i) = byte; + + if byte == 0 { + break; + } + + i += 1; + } + + dst } pub unsafe fn inner_strspn(s1: *const c_char, s2: *const c_char, cmp: bool) -> size_t { @@ -270,24 +283,19 @@ pub unsafe extern "C" fn strncmp(s1: *const c_char, s2: *const c_char, n: usize) } #[no_mangle] -pub unsafe extern "C" fn strncpy(s1: *mut c_char, s2: *const c_char, n: usize) -> *mut c_char { - let s2_slice = platform::c_str_n(s2, n); - let s2_len = s2_slice.len(); - - //memcpy(s1 as *mut _, s2 as *const _, cmp::min(n, s2_len)); - let mut idx = 0; - for _ in 0..cmp::min(n, s2_len) { - *s1.offset(idx as isize) = s2_slice[idx] as c_char; - idx += 1; +pub unsafe extern "C" fn strncpy(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char { + let mut i = 0; + + while *src.offset(i) != 0 && (i as usize) < n { + *dst.offset(i) = *src.offset(i); + i += 1; } - // if length of s2 < n, pad s1 with zeroes - while idx < s2_len { - *s1.offset(idx as isize) = 0; - idx += 1; + for i in i..n as isize { + *dst.offset(i) = 0; } - s1 + dst } #[no_mangle] diff --git a/tests/Makefile b/tests/Makefile index 82bd1f80..de3e0b85 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -32,6 +32,7 @@ EXPECT_BINS=\ stdlib/system \ string/mem \ string/strchr \ + string/strcpy \ string/strcspn \ string/strncmp \ string/strpbrk \ diff --git a/tests/expected/string/strcpy.stderr b/tests/expected/string/strcpy.stderr new file mode 100644 index 00000000..e69de29b diff --git a/tests/expected/string/strcpy.stdout b/tests/expected/string/strcpy.stdout new file mode 100644 index 00000000..84caf120 --- /dev/null +++ b/tests/expected/string/strcpy.stdout @@ -0,0 +1,3 @@ +strcpy works! +strncpy works! +strncpy shaaaaaaaaa diff --git a/tests/string/strcpy.c b/tests/string/strcpy.c new file mode 100644 index 00000000..f0c7d792 --- /dev/null +++ b/tests/string/strcpy.c @@ -0,0 +1,17 @@ +#include <stdio.h> +#include <string.h> + +int main() { + char dst[20]; + + strcpy(dst, "strcpy works!"); + puts(dst); + strncpy(dst, "strncpy works!", 20); + puts(dst); + + // Make sure no NUL is placed + memset(dst, 'a', 20); + dst[19] = 0; + strncpy(dst, "strncpy should work here too", 10); + puts(dst); +} -- GitLab