]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: look at runes, not bytes, when printing env vars
authorIan Lance Taylor <iant@golang.org>
Fri, 21 Feb 2025 06:20:38 +0000 (22:20 -0800)
committerGopher Robot <gobot@golang.org>
Sat, 22 Feb 2025 06:12:14 +0000 (22:12 -0800)
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>
src/cmd/go/internal/envcmd/env.go

index 7c370d427f9c2f81edc0ae444c1ab62542360905..f0a6989a579ccd4820f52a7caad3c32a63a9995f 100644 (file)
@@ -522,51 +522,56 @@ func PrintEnv(w io.Writer, env []cfg.EnvVar, onlyChanged bool) {
        }
 }
 
+// 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)
+}
+
 func hasNonGraphic(s string) bool {
-       for _, c := range []byte(s) {
-               if c == '\r' || c == '\n' || (!unicode.IsGraphic(rune(c)) && !unicode.IsSpace(rune(c))) {
-                       return true
-               }
-       }
-       return false
+       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) {