Skip to content

Commit a2335d0

Browse files
mdempskymknyszek
authored andcommitted
[release-branch.go1.19] 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. For #56544. Fixes #56551. 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]> Reviewed-on: https://go-review.googlesource.com/c/go/+/447799 Run-TryBot: David du Colombier <[email protected]>
1 parent 39ac1fb commit a2335d0

File tree

3 files changed

+20
-6
lines changed

3 files changed

+20
-6
lines changed

src/os/exec/env_test.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
func TestDedupEnv(t *testing.T) {
1313
tests := []struct {
1414
noCase bool
15+
nulOK bool
1516
in []string
1617
want []string
1718
wantErr bool
@@ -48,9 +49,15 @@ func TestDedupEnv(t *testing.T) {
4849
want: []string{"B=b"},
4950
wantErr: true,
5051
},
52+
{
53+
// Plan 9 needs to preserve environment variables with NUL (#56544).
54+
nulOK: true,
55+
in: []string{"path=one\x00two"},
56+
want: []string{"path=one\x00two"},
57+
},
5158
}
5259
for _, tt := range tests {
53-
got, err := dedupEnvCase(tt.noCase, tt.in)
60+
got, err := dedupEnvCase(tt.noCase, tt.nulOK, tt.in)
5461
if !reflect.DeepEqual(got, tt.want) || (err != nil) != tt.wantErr {
5562
t.Errorf("Dedup(%v, %q) = %q, %v; want %q, error:%v", tt.noCase, tt.in, got, err, tt.want, tt.wantErr)
5663
}

src/os/exec/exec.go

+9-5
Original file line numberDiff line numberDiff line change
@@ -930,15 +930,16 @@ func (c *Cmd) Environ() []string {
930930
// dedupEnv returns a copy of env with any duplicates removed, in favor of
931931
// later values.
932932
// Items not of the normal environment "key=value" form are preserved unchanged.
933-
// Items containing NUL characters are removed, and an error is returned along with
934-
// the remaining values.
933+
// Except on Plan 9, items containing NUL characters are removed, and
934+
// an error is returned along with the remaining values.
935935
func dedupEnv(env []string) ([]string, error) {
936-
return dedupEnvCase(runtime.GOOS == "windows", env)
936+
return dedupEnvCase(runtime.GOOS == "windows", runtime.GOOS == "plan9", env)
937937
}
938938

939939
// dedupEnvCase is dedupEnv with a case option for testing.
940940
// If caseInsensitive is true, the case of keys is ignored.
941-
func dedupEnvCase(caseInsensitive bool, env []string) ([]string, error) {
941+
// If nulOK is false, items containing NUL characters are allowed.
942+
func dedupEnvCase(caseInsensitive, nulOK bool, env []string) ([]string, error) {
942943
// Construct the output in reverse order, to preserve the
943944
// last occurrence of each key.
944945
var err error
@@ -947,10 +948,13 @@ func dedupEnvCase(caseInsensitive bool, env []string) ([]string, error) {
947948
for n := len(env); n > 0; n-- {
948949
kv := env[n-1]
949950

950-
if strings.IndexByte(kv, 0) != -1 {
951+
// Reject NUL in environment variables to prevent security issues (#56284);
952+
// except on Plan 9, which uses NUL as os.PathListSeparator (#56544).
953+
if !nulOK && strings.IndexByte(kv, 0) != -1 {
951954
err = errors.New("exec: environment variable contains NUL")
952955
continue
953956
}
957+
954958
i := strings.Index(kv, "=")
955959
if i == 0 {
956960
// We observe in practice keys with a single leading "=" on Windows.

src/os/exec/exec_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,9 @@ func TestDedupEnvEcho(t *testing.T) {
10541054
}
10551055

10561056
func TestEnvNULCharacter(t *testing.T) {
1057+
if runtime.GOOS == "plan9" {
1058+
t.Skip("plan9 explicitly allows NUL in the enviroment")
1059+
}
10571060
cmd := helperCommand(t, "echoenv", "FOO", "BAR")
10581061
cmd.Env = append(cmd.Environ(), "FOO=foo\x00BAR=bar")
10591062
out, err := cmd.CombinedOutput()

0 commit comments

Comments
 (0)