Skip to content

Commit bc2dc23

Browse files
committed
os/exec: allow NUL in environment variables on Plan 9
Plan 9 uses NUL as os.PathListSeparator, so it's almost always going to appear in the environment variable list. Exempt GOOS=plan9 from the check for NUL in environment variables. For #56284. Fixes #56544. Change-Id: I23df233cdf20c0a9a606fd9253e15a9b5482575a Reviewed-on: https://go-review.googlesource.com/c/go/+/447715 Reviewed-by: David du Colombier <[email protected]> Run-TryBot: Matthew Dempsky <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Damien Neil <[email protected]>
1 parent c1c6b0c commit bc2dc23

File tree

3 files changed

+20
-6
lines changed

3 files changed

+20
-6
lines changed

src/os/exec/env_test.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ func TestDedupEnv(t *testing.T) {
1414

1515
tests := []struct {
1616
noCase bool
17+
nulOK bool
1718
in []string
1819
want []string
1920
wantErr bool
@@ -50,9 +51,15 @@ func TestDedupEnv(t *testing.T) {
5051
want: []string{"B=b"},
5152
wantErr: true,
5253
},
54+
{
55+
// Plan 9 needs to preserve environment variables with NUL (#56544).
56+
nulOK: true,
57+
in: []string{"path=one\x00two"},
58+
want: []string{"path=one\x00two"},
59+
},
5360
}
5461
for _, tt := range tests {
55-
got, err := dedupEnvCase(tt.noCase, tt.in)
62+
got, err := dedupEnvCase(tt.noCase, tt.nulOK, tt.in)
5663
if !reflect.DeepEqual(got, tt.want) || (err != nil) != tt.wantErr {
5764
t.Errorf("Dedup(%v, %q) = %q, %v; want %q, error:%v", tt.noCase, tt.in, got, err, tt.want, tt.wantErr)
5865
}

src/os/exec/exec.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,15 +1208,16 @@ func (c *Cmd) Environ() []string {
12081208
// dedupEnv returns a copy of env with any duplicates removed, in favor of
12091209
// later values.
12101210
// Items not of the normal environment "key=value" form are preserved unchanged.
1211-
// Items containing NUL characters are removed, and an error is returned along with
1212-
// the remaining values.
1211+
// Except on Plan 9, items containing NUL characters are removed, and
1212+
// an error is returned along with the remaining values.
12131213
func dedupEnv(env []string) ([]string, error) {
1214-
return dedupEnvCase(runtime.GOOS == "windows", env)
1214+
return dedupEnvCase(runtime.GOOS == "windows", runtime.GOOS == "plan9", env)
12151215
}
12161216

12171217
// dedupEnvCase is dedupEnv with a case option for testing.
12181218
// If caseInsensitive is true, the case of keys is ignored.
1219-
func dedupEnvCase(caseInsensitive bool, env []string) ([]string, error) {
1219+
// If nulOK is false, items containing NUL characters are allowed.
1220+
func dedupEnvCase(caseInsensitive, nulOK bool, env []string) ([]string, error) {
12201221
// Construct the output in reverse order, to preserve the
12211222
// last occurrence of each key.
12221223
var err error
@@ -1225,10 +1226,13 @@ func dedupEnvCase(caseInsensitive bool, env []string) ([]string, error) {
12251226
for n := len(env); n > 0; n-- {
12261227
kv := env[n-1]
12271228

1228-
if strings.IndexByte(kv, 0) != -1 {
1229+
// Reject NUL in environment variables to prevent security issues (#56284);
1230+
// except on Plan 9, which uses NUL as os.PathListSeparator (#56544).
1231+
if !nulOK && strings.IndexByte(kv, 0) != -1 {
12291232
err = errors.New("exec: environment variable contains NUL")
12301233
continue
12311234
}
1235+
12321236
i := strings.Index(kv, "=")
12331237
if i == 0 {
12341238
// We observe in practice keys with a single leading "=" on Windows.

src/os/exec/exec_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,9 @@ func TestDedupEnvEcho(t *testing.T) {
10381038
}
10391039

10401040
func TestEnvNULCharacter(t *testing.T) {
1041+
if runtime.GOOS == "plan9" {
1042+
t.Skip("plan9 explicitly allows NUL in the enviroment")
1043+
}
10411044
cmd := helperCommand(t, "echoenv", "FOO", "BAR")
10421045
cmd.Env = append(cmd.Environ(), "FOO=foo\x00BAR=bar")
10431046
out, err := cmd.CombinedOutput()

0 commit comments

Comments
 (0)