diff --git a/wutil-rs/src/string.rs b/wutil-rs/src/string.rs index 92492e25..892f3f3f 100644 --- a/wutil-rs/src/string.rs +++ b/wutil-rs/src/string.rs @@ -20,18 +20,22 @@ pub unsafe extern "C" fn wstrdup(s: *const c_char) -> *mut c_char { alloc_string(unsafe { CStr::from_ptr(s) }) } -/// Returns a `wmalloc`-managed C-style string of the first `n` bytes of -/// `s`, which cannot be null. +/// Returns a `wmalloc`-managed C-style string of the first `len` bytes of `s`, +/// which cannot be null. /// -/// If `n` exceeds the length of `s`, uses the lesser value. +/// If `len` exceeds the length of `s`, uses the lesser value. #[unsafe(no_mangle)] pub unsafe extern "C" fn wstrndup(s: *const c_char, len: usize) -> *mut c_char { assert!(!s.is_null()); - let s = unsafe { CStr::from_ptr(s) }; - let len = usize::min(len, s.count_bytes()) + 1; + let len = unsafe { + slice::from_raw_parts(s, len) + .into_iter() + .position(|p| *p == 0) + .unwrap_or(len) + }; let copy: *mut c_char = alloc_bytes(len + 1).cast(); // Implicitly zeroed. unsafe { - ptr::copy_nonoverlapping(s.as_ptr(), copy, len); + ptr::copy_nonoverlapping(s, copy, len); } copy.cast::() }