blob: 7419cf3fc20e73db8b565991566e4452edf9d3d4 [file] [log] [blame]
// 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)
}
})
}