| // Copyright 2022 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| //go:build unix || windows |
| |
| package envcmd |
| |
| import ( |
| "bytes" |
| "cmd/go/internal/cfg" |
| "fmt" |
| "internal/testenv" |
| "os" |
| "os/exec" |
| "path/filepath" |
| "runtime" |
| "testing" |
| "unicode" |
| ) |
| |
| func FuzzPrintEnvEscape(f *testing.F) { |
| f.Add(`$(echo 'cc"'; echo 'OOPS="oops')`) |
| f.Add("$(echo shell expansion 1>&2)") |
| f.Add("''") |
| f.Add(`C:\"Program Files"\`) |
| f.Add(`\\"Quoted Host"\\share`) |
| f.Add("\xfb") |
| f.Add("0") |
| f.Add("") |
| f.Add("''''''''") |
| f.Add("\r") |
| f.Add("\n") |
| f.Add("E,%") |
| f.Fuzz(func(t *testing.T, s string) { |
| t.Parallel() |
| |
| for _, c := range []byte(s) { |
| if c == 0 { |
| t.Skipf("skipping %q: contains a null byte. Null bytes can't occur in the environment"+ |
| " outside of Plan 9, which has different code path than Windows and Unix that this test"+ |
| " isn't testing.", s) |
| } |
| if c > unicode.MaxASCII { |
| t.Skipf("skipping %#q: contains a non-ASCII character %q", s, c) |
| } |
| if !unicode.IsGraphic(rune(c)) && !unicode.IsSpace(rune(c)) { |
| t.Skipf("skipping %#q: contains non-graphic character %q", s, c) |
| } |
| if runtime.GOOS == "windows" && c == '\r' || c == '\n' { |
| t.Skipf("skipping %#q on Windows: contains unescapable character %q", s, c) |
| } |
| } |
| |
| var b bytes.Buffer |
| if runtime.GOOS == "windows" { |
| b.WriteString("@echo off\n") |
| } |
| PrintEnv(&b, []cfg.EnvVar{{Name: "var", Value: s}}) |
| var want string |
| if runtime.GOOS == "windows" { |
| fmt.Fprintf(&b, "echo \"%%var%%\"\n") |
| want += "\"" + s + "\"\r\n" |
| } else { |
| fmt.Fprintf(&b, "printf '%%s\\n' \"$var\"\n") |
| want += s + "\n" |
| } |
| scriptfilename := "script.sh" |
| if runtime.GOOS == "windows" { |
| scriptfilename = "script.bat" |
| } |
| var cmd *exec.Cmd |
| if runtime.GOOS == "windows" { |
| scriptfile := filepath.Join(t.TempDir(), scriptfilename) |
| if err := os.WriteFile(scriptfile, b.Bytes(), 0777); err != nil { |
| t.Fatal(err) |
| } |
| cmd = testenv.Command(t, "cmd.exe", "/C", scriptfile) |
| } else { |
| cmd = testenv.Command(t, "sh", "-c", b.String()) |
| } |
| out, err := cmd.Output() |
| t.Log(string(out)) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| if string(out) != want { |
| t.Fatalf("output of running PrintEnv script and echoing variable: got: %q, want: %q", |
| string(out), want) |
| } |
| }) |
| } |