@@ -42,7 +42,7 @@ pub fn truncate_str(s: &str, len: usize) -> &str {
4242}
4343
4444/// Converts a Rust string to a null terminated C string by appending a null
45- /// terminator. Returns `Err(())` if the input already contians a null byte.
45+ /// terminator. Returns `Err(())` if the input already contains a null byte.
4646pub fn str_to_cstr_vec ( input : & str ) -> Result < Vec < core:: ffi:: c_char > , ( ) > {
4747 let cstr = alloc:: ffi:: CString :: new ( input)
4848 . or ( Err ( ( ) ) ) ?
@@ -53,6 +53,23 @@ pub fn str_to_cstr_vec(input: &str) -> Result<Vec<core::ffi::c_char>, ()> {
5353 Ok ( cstr. into_iter ( ) . map ( |c| c as _ ) . collect ( ) )
5454}
5555
56+ /// Converts a Rust string to a null terminated C string by appending a null
57+ /// terminator. Returns `Err(())` if the input already contains a null byte.
58+ pub fn str_to_cstr_vec_zeroizing (
59+ input : & str ,
60+ ) -> Result < zeroize:: Zeroizing < Vec < core:: ffi:: c_char > > , ( ) > {
61+ let bytes = input. as_bytes ( ) ;
62+ if bytes. contains ( & 0 ) {
63+ return Err ( ( ) ) ;
64+ }
65+ let mut result: zeroize:: Zeroizing < Vec < core:: ffi:: c_char > > =
66+ zeroize:: Zeroizing :: new ( vec ! [ 0 ; bytes. len( ) + 1 ] ) ;
67+ for ( i, b) in bytes. iter ( ) . enumerate ( ) {
68+ result[ i] = * b as _ ;
69+ }
70+ Ok ( result)
71+ }
72+
5673#[ cfg( test) ]
5774mod tests {
5875 use super :: * ;
@@ -134,4 +151,18 @@ mod tests {
134151 ) ;
135152 assert_eq ! ( str_to_cstr_vec( "te\0 st" ) , Err ( ( ) ) ) ;
136153 }
154+
155+ #[ test]
156+ fn test_str_to_cstr_vec_zeroizing ( ) {
157+ assert_eq ! ( str_to_cstr_vec_zeroizing( "" ) . unwrap( ) . as_slice( ) , & [ 0 ] ) ;
158+ assert_eq ! (
159+ str_to_cstr_vec_zeroizing( "test" ) . unwrap( ) ,
160+ b"test\0 "
161+ . iter( )
162+ . map( |c| * c as _)
163+ . collect:: <Vec <core:: ffi:: c_char>>( )
164+ . into( ) ,
165+ ) ;
166+ assert_eq ! ( str_to_cstr_vec_zeroizing( "te\0 st" ) , Err ( ( ) ) ) ;
167+ }
137168}
0 commit comments