about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-06-24 17:37:29 +0000
committerbors <bors@rust-lang.org>2021-06-24 17:37:29 +0000
commitcbeda5cbeb9a3b92a1df997869a49d9584ca10c2 (patch)
tree4468f6468cc7227782bf6820c13c1241e442a08c /library/std/src
parentd95745e5fa39680d97a52d0e07ed7842b163bacc (diff)
parent16145a99528c862cfaca87e836fdd844ba155567 (diff)
downloadrust-cbeda5cbeb9a3b92a1df997869a49d9584ca10c2.tar.gz
rust-cbeda5cbeb9a3b92a1df997869a49d9584ca10c2.zip
Auto merge of #86467 - ChrisDenton:win-env-clear, r=JohnTitor
Windows: Fix `Command::env_clear` so it works if no variables are set

Previously, it would error unless at least one new environment variable was added. The missing null presumably meant that Windows was reading random memory in that case.

See: [CreateProcessW](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw) (scroll down to `lpEnvironment`). Essentially the environment block is a null terminated list of null terminated strings and an empty list is `\0\0` and not `\0`.

EDIT: Oh, [CreateEnvironmentBlock](https://docs.microsoft.com/en-gb/windows/win32/api/userenv/nf-userenv-createenvironmentblock) states this much more explicitly.

Fixes #31259
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/process/tests.rs9
-rw-r--r--library/std/src/sys/windows/process.rs6
2 files changed, 15 insertions, 0 deletions
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 05e093434be..bc71c150550 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -399,3 +399,12 @@ fn test_command_implements_send_sync() {
     fn take_send_sync_type<T: Send + Sync>(_: T) {}
     take_send_sync_type(Command::new(""))
 }
+
+// Ensure that starting a process with no environment variables works on Windows.
+// This will fail if the environment block is ill-formed.
+#[test]
+#[cfg(windows)]
+fn env_empty() {
+    let p = Command::new("cmd").args(&["/C", "exit 0"]).env_clear().spawn();
+    assert!(p.is_ok());
+}
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index 81dbea4a067..14de2530842 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -530,6 +530,12 @@ fn make_envp(maybe_env: Option<BTreeMap<EnvKey, OsString>>) -> io::Result<(*mut
     if let Some(env) = maybe_env {
         let mut blk = Vec::new();
 
+        // If there are no environment variables to set then signal this by
+        // pushing a null.
+        if env.is_empty() {
+            blk.push(0);
+        }
+
         for (k, v) in env {
             blk.extend(ensure_no_nuls(k.0)?.encode_wide());
             blk.push('=' as u16);