Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 23 additions & 37 deletions crates/host_env/src/winapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ pub fn create_file_w(
/// `startup_info` must point to a valid `STARTUPINFOW` (or extended).
unsafe fn create_process_w_raw(
app_name: Option<&widestring::WideCStr>,
command_line: Option<&mut [u16]>,
command_line: Option<&mut widestring::WideCStr>,
inherit_handles: i32,
creation_flags: u32,
env: Option<&[u16]>,
Expand All @@ -214,37 +214,6 @@ unsafe fn create_process_w_raw(
Ok(unsafe { procinfo.assume_init() })
}

/// Win32 `CreateProcessW` requires `lpCommandLine` to be NUL-terminated.
/// The buffer is passed `&mut [u16]` because `CreateProcessW` may modify it
/// in place.
#[inline]
fn validate_command_line_terminated(buf: &[u16]) -> io::Result<()> {
if buf.last() == Some(&0) {
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"command_line buffer passed to create_process must be NUL-terminated",
))
}
}

/// Win32 `CreateProcessW` with `CREATE_UNICODE_ENVIRONMENT` requires
/// `lpEnvironment` to be a sequence of `KEY=value\0` strings followed by a
/// final terminating `\0` — i.e. the block ends with two consecutive zero
/// `u16`s.
#[inline]
fn validate_environment_block_terminated(buf: &[u16]) -> io::Result<()> {
if buf.len() >= 2 && buf[buf.len() - 2..] == [0, 0] {
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"env block passed to create_process must end with a double NUL terminator",
))
}
}

#[allow(
clippy::too_many_arguments,
reason = "This is the semantic host wrapper for Win32 CreateProcess parameters."
Expand All @@ -259,11 +228,28 @@ pub fn create_process(
startup_info: StartupInfoData,
handle_list: Option<Vec<usize>>,
) -> io::Result<ProcessInfo> {
if let Some(cmd) = command_line.as_deref() {
validate_command_line_terminated(cmd)?;
}
if let Some(env_block) = env {
validate_environment_block_terminated(env_block)?;
// Win32 `CreateProcessW` requires `lpCommandLine` to be NUL-terminated.
// The buffer is passed `&mut [u16]` because `CreateProcessW` may modify it in place.
let command_line = command_line
.map(widestring::WideCStr::from_slice_mut)
.transpose()
.map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidInput,
"command_line buffer passed to create_process must be NUL-terminated",
)
})?;
// Win32 `CreateProcessW` with `CREATE_UNICODE_ENVIRONMENT` requires
// `lpEnvironment` to be a sequence of `KEY=value\0` strings followed by a
// final terminating `\0` — i.e. the block ends with two consecutive zero
// `u16`s.
if let Some(env_block) = env
&& !env_block.ends_with(&[0, 0])
{
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"env block passed to create_process must end with a double NUL terminator",
));
}

let mut si: windows_sys::Win32::System::Threading::STARTUPINFOEXW =
Expand Down
Loading