From 122efd150c38bb0d32ba3b0e419f8b6643bd97e0 Mon Sep 17 00:00:00 2001 From: Sebastien Tardif Date: Wed, 24 Jun 2026 07:03:35 -0700 Subject: [PATCH] std: reject interior NULs in Windows junction_point target path Reparse substitute names are written as wide strings; embedded NULs would truncate the target. Reject early with InvalidInput. Signed-off-by: Sebastien Tardif --- library/std/src/sys/fs/windows.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index e3e7b081b47d5..ec941cd7a9f33 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -1645,6 +1645,14 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> { // We need to get an absolute, NT-style path. let path_bytes = original.as_os_str().as_encoded_bytes(); + // Interior NULs in the target would truncate the reparse substitute name + // (same class of bug as chdir / AF_UNIX without to_u16s). + if path_bytes.contains(&0) { + return Err(io::const_error!( + io::ErrorKind::InvalidInput, + "strings passed to WinAPI cannot contain NULs", + )); + } let abs_path: Vec = if path_bytes.starts_with(br"\\?\") || path_bytes.starts_with(br"\??\") { // It's already an absolute path, we just need to convert the prefix to `\??\` @@ -1653,6 +1661,12 @@ pub fn junction_point(original: &Path, link: &Path) -> io::Result<()> { } else { // Get an absolute path and then convert the prefix to `\??\` let abs_path = crate::path::absolute(original)?.into_os_string().into_encoded_bytes(); + if abs_path.contains(&0) { + return Err(io::const_error!( + io::ErrorKind::InvalidInput, + "strings passed to WinAPI cannot contain NULs", + )); + } if abs_path.len() > 0 && abs_path[1..].starts_with(br":\") { let bytes = unsafe { OsStr::from_encoded_bytes_unchecked(&abs_path) }; r"\??\".encode_utf16().chain(bytes.encode_wide()).collect()