diff --git a/src/pkg/strconv/quote.go b/src/pkg/strconv/quote.go index aded7e5930..89dda99750 100644 --- a/src/pkg/strconv/quote.go +++ b/src/pkg/strconv/quote.go @@ -143,9 +143,16 @@ func AppendQuoteRuneToASCII(dst []byte, r rune) []byte { // unchanged as a single-line backquoted string without control // characters other than space and tab. func CanBackquote(s string) bool { - for i := 0; i < len(s); i++ { - c := s[i] - if (c < ' ' && c != '\t') || c == '`' || c == '\u007F' { + for len(s) > 0 { + r, wid := utf8.DecodeRuneInString(s) + s = s[wid:] + if wid > 1 { + continue // All multibyte runes are correctly encoded and assumed printable. + } + if r == utf8.RuneError { + return false + } + if (r < ' ' && r != '\t') || r == '`' || r == '\u007F' { return false } } diff --git a/src/pkg/strconv/quote_test.go b/src/pkg/strconv/quote_test.go index e4b5b6b9fd..24998191d7 100644 --- a/src/pkg/strconv/quote_test.go +++ b/src/pkg/strconv/quote_test.go @@ -146,6 +146,10 @@ var canbackquotetests = []canBackquoteTest{ {`ABCDEFGHIJKLMNOPQRSTUVWXYZ`, true}, {`abcdefghijklmnopqrstuvwxyz`, true}, {`☺`, true}, + {"\x80", false}, + {"a\xe0\xa0z", false}, + {"\ufeffabc", true}, + {"a\ufeffz", true}, } func TestCanBackquote(t *testing.T) {