Skip to content

Commit 06c9ccd

Browse files
committed
os/exec: always set SYSTEMROOT on Windows if not listed in Cmd.Env
Fixes #25210 Change-Id: If27b61776154dae9b9b67bf4e4f5faa785d98105 Reviewed-on: https://go-review.googlesource.com/c/go/+/174318 Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 8c1f785 commit 06c9ccd

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/os/exec/exec.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ type Cmd struct {
7171
// environment.
7272
// If Env contains duplicate environment keys, only the last
7373
// value in the slice for each duplicate key is used.
74+
// As a special case on Windows, SYSTEMROOT is always added if
75+
// missing and not explicitly set to the empty string.
7476
Env []string
7577

7678
// Dir specifies the working directory of the command.
@@ -412,7 +414,7 @@ func (c *Cmd) Start() error {
412414
c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
413415
Dir: c.Dir,
414416
Files: c.childFiles,
415-
Env: dedupEnv(c.envv()),
417+
Env: addCriticalEnv(dedupEnv(c.envv())),
416418
Sys: c.SysProcAttr,
417419
})
418420
if err != nil {
@@ -756,3 +758,24 @@ func dedupEnvCase(caseInsensitive bool, env []string) []string {
756758
}
757759
return out
758760
}
761+
762+
// addCriticalEnv adds any critical environment variables that are required
763+
// (or at least almost always required) on the operating system.
764+
// Currently this is only used for Windows.
765+
func addCriticalEnv(env []string) []string {
766+
if runtime.GOOS != "windows" {
767+
return env
768+
}
769+
for _, kv := range env {
770+
eq := strings.Index(kv, "=")
771+
if eq < 0 {
772+
continue
773+
}
774+
k := kv[:eq]
775+
if strings.EqualFold(k, "SYSTEMROOT") {
776+
// We already have it.
777+
return env
778+
}
779+
}
780+
return append(env, "SYSTEMROOT="+os.Getenv("SYSTEMROOT"))
781+
}

src/os/exec/exec_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,3 +1184,22 @@ func TestStringPathNotResolved(t *testing.T) {
11841184
t.Errorf("String(%q, %q) = %q, want %q", "makemeasandwich", "-lettuce", got, want)
11851185
}
11861186
}
1187+
1188+
// start a child process without the user code explicitly starting
1189+
// with a copy of the parent's. (The Windows SYSTEMROOT issue: Issue
1190+
// 25210)
1191+
func TestChildCriticalEnv(t *testing.T) {
1192+
testenv.MustHaveExec(t)
1193+
if runtime.GOOS != "windows" {
1194+
t.Skip("only testing on Windows")
1195+
}
1196+
cmd := helperCommand(t, "echoenv", "SYSTEMROOT")
1197+
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
1198+
out, err := cmd.CombinedOutput()
1199+
if err != nil {
1200+
t.Fatal(err)
1201+
}
1202+
if strings.TrimSpace(string(out)) == "" {
1203+
t.Error("no SYSTEMROOT found")
1204+
}
1205+
}

0 commit comments

Comments
 (0)