From c8205ea9aeaaa4b794ed4b73357a27182d14b8a0 Mon Sep 17 00:00:00 2001 From: Gustavo Niemeyer Date: Mon, 2 Sep 2024 10:46:35 +0100 Subject: [PATCH] src/templ.rs: fix handling of C string slices CommandLineParser is currently misbehaving due to improper data in its input argv parameter. The problem is caused by a blind cast of argv entries from &str into a C-like string, which does not offer the null termination guarantees. To fix that, create an actual CString and hold it while the pointer is in use. It's worth noting that the mutable version of the macro still relies on undefined behavior, but this time of CString which does not guarantee correctness if its data is written into. --- src/templ.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/templ.rs b/src/templ.rs index 6048dd898..1263178fe 100644 --- a/src/templ.rs +++ b/src/templ.rs @@ -79,7 +79,11 @@ macro_rules! string_array_arg { ($name: ident) => { let $name = $name .iter() - .map(|x| x.as_ptr().cast::<::std::ffi::c_char>()) + .map(|x| ::std::ffi::CString::new(*x).expect("invalid C string")) + .collect::<::std::vec::Vec<_>>(); + let $name = $name + .iter() + .map(|x| x.as_ptr()) .collect::<::std::vec::Vec<_>>(); }; } @@ -87,9 +91,14 @@ macro_rules! string_array_arg { #[allow(unused_macros)] macro_rules! string_array_arg_mut { ($name: ident) => { + let $name = $name + .iter() + .map(|x| ::std::ffi::CString::new(*x).expect("invalid C string")) + .collect::<::std::vec::Vec<_>>(); + // Casting to mut below trusts on undefined CString behavior. let mut $name = $name .iter() - .map(|x| x.as_ptr().cast::<::std::ffi::c_char>().cast_mut()) + .map(|x| x.as_ptr().cast_mut()) .collect::<::std::vec::Vec<_>>(); }; }