cmd/go: look at runes, not bytes, when printing env vars

For #58508
Fixes #71863

Change-Id: Ib1ebaf751bcc6900da6ffd01a9462dd237e2c89a
Reviewed-on: https://go-review.googlesource.com/c/go/+/651295
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Ian Lance Taylor 2025-02-20 22:20:38 -08:00 committed by Gopher Robot
parent e15d14873f
commit f062d7b10b

View file

@ -522,51 +522,56 @@ func PrintEnv(w io.Writer, env []cfg.EnvVar, onlyChanged bool) {
}
}
func hasNonGraphic(s string) bool {
for _, c := range []byte(s) {
if c == '\r' || c == '\n' || (!unicode.IsGraphic(rune(c)) && !unicode.IsSpace(rune(c))) {
// isWindowsUnquotableRune reports whether r can't be quoted in a
// Windows "set" command.
// These runes will be replaced by the Unicode replacement character.
func isWindowsUnquotableRune(r rune) bool {
if r == '\r' || r == '\n' {
return true
}
return !unicode.IsGraphic(r) && !unicode.IsSpace(r)
}
return false
func hasNonGraphic(s string) bool {
return strings.ContainsFunc(s, isWindowsUnquotableRune)
}
func shellQuote(s string) string {
var b bytes.Buffer
b.WriteByte('\'')
for _, x := range []byte(s) {
if x == '\'' {
var sb strings.Builder
sb.WriteByte('\'')
for _, r := range s {
if r == '\'' {
// Close the single quoted string, add an escaped single quote,
// and start another single quoted string.
b.WriteString(`'\''`)
sb.WriteString(`'\''`)
} else {
b.WriteByte(x)
sb.WriteRune(r)
}
}
b.WriteByte('\'')
return b.String()
sb.WriteByte('\'')
return sb.String()
}
func batchEscape(s string) string {
var b bytes.Buffer
for _, x := range []byte(s) {
if x == '\r' || x == '\n' || (!unicode.IsGraphic(rune(x)) && !unicode.IsSpace(rune(x))) {
b.WriteRune(unicode.ReplacementChar)
var sb strings.Builder
for _, r := range s {
if isWindowsUnquotableRune(r) {
sb.WriteRune(unicode.ReplacementChar)
continue
}
switch x {
switch r {
case '%':
b.WriteString("%%")
sb.WriteString("%%")
case '<', '>', '|', '&', '^':
// These are special characters that need to be escaped with ^. See
// https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/set_1.
b.WriteByte('^')
b.WriteByte(x)
sb.WriteByte('^')
sb.WriteRune(r)
default:
b.WriteByte(x)
sb.WriteRune(r)
}
}
return b.String()
return sb.String()
}
func printEnvAsJSON(env []cfg.EnvVar, onlyChanged bool) {