Skip to content

Commit b24c6fb

Browse files
committed
net/textproto: permit all valid token chars in CanonicalMIMEHeaderKey input
Fixes #13767 Change-Id: Ib743db7d9d72022ea911bc5ac535243489425642 Reviewed-on: https://go-review.googlesource.com/18725 Reviewed-by: Andrew Gerrand <[email protected]> Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 13d6414 commit b24c6fb

File tree

2 files changed

+92
-8
lines changed

2 files changed

+92
-8
lines changed

src/net/textproto/reader.go

+86-8
Original file line numberDiff line numberDiff line change
@@ -581,18 +581,14 @@ func CanonicalMIMEHeaderKey(s string) string {
581581
const toLower = 'a' - 'A'
582582

583583
// validHeaderFieldByte reports whether b is a valid byte in a header
584-
// field key. This is actually stricter than RFC 7230, which says:
584+
// field name. RFC 7230 says:
585+
// header-field = field-name ":" OWS field-value OWS
586+
// field-name = token
585587
// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
586588
// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
587589
// token = 1*tchar
588-
// TODO: revisit in Go 1.6+ and possibly expand this. But note that many
589-
// servers have historically dropped '_' to prevent ambiguities when mapping
590-
// to CGI environment variables.
591590
func validHeaderFieldByte(b byte) bool {
592-
return ('A' <= b && b <= 'Z') ||
593-
('a' <= b && b <= 'z') ||
594-
('0' <= b && b <= '9') ||
595-
b == '-'
591+
return int(b) < len(isTokenTable) && isTokenTable[b]
596592
}
597593

598594
// canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is
@@ -682,3 +678,85 @@ func init() {
682678
commonHeader[v] = v
683679
}
684680
}
681+
682+
// isTokenTable is a copy of net/http/lex.go's isTokenTable.
683+
// See https://httpwg.github.io/specs/rfc7230.html#rule.token.separators
684+
var isTokenTable = [127]bool{
685+
'!': true,
686+
'#': true,
687+
'$': true,
688+
'%': true,
689+
'&': true,
690+
'\'': true,
691+
'*': true,
692+
'+': true,
693+
'-': true,
694+
'.': true,
695+
'0': true,
696+
'1': true,
697+
'2': true,
698+
'3': true,
699+
'4': true,
700+
'5': true,
701+
'6': true,
702+
'7': true,
703+
'8': true,
704+
'9': true,
705+
'A': true,
706+
'B': true,
707+
'C': true,
708+
'D': true,
709+
'E': true,
710+
'F': true,
711+
'G': true,
712+
'H': true,
713+
'I': true,
714+
'J': true,
715+
'K': true,
716+
'L': true,
717+
'M': true,
718+
'N': true,
719+
'O': true,
720+
'P': true,
721+
'Q': true,
722+
'R': true,
723+
'S': true,
724+
'T': true,
725+
'U': true,
726+
'W': true,
727+
'V': true,
728+
'X': true,
729+
'Y': true,
730+
'Z': true,
731+
'^': true,
732+
'_': true,
733+
'`': true,
734+
'a': true,
735+
'b': true,
736+
'c': true,
737+
'd': true,
738+
'e': true,
739+
'f': true,
740+
'g': true,
741+
'h': true,
742+
'i': true,
743+
'j': true,
744+
'k': true,
745+
'l': true,
746+
'm': true,
747+
'n': true,
748+
'o': true,
749+
'p': true,
750+
'q': true,
751+
'r': true,
752+
's': true,
753+
't': true,
754+
'u': true,
755+
'v': true,
756+
'w': true,
757+
'x': true,
758+
'y': true,
759+
'z': true,
760+
'|': true,
761+
'~': true,
762+
}

src/net/textproto/reader_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ var canonicalHeaderKeyTests = []canonicalHeaderKeyTest{
2525
{"user-agent", "User-Agent"},
2626
{"USER-AGENT", "User-Agent"},
2727

28+
// Other valid tchar bytes in tokens:
29+
{"foo-bar_baz", "Foo-Bar_baz"},
30+
{"foo-bar$baz", "Foo-Bar$baz"},
31+
{"foo-bar~baz", "Foo-Bar~baz"},
32+
{"foo-bar*baz", "Foo-Bar*baz"},
33+
2834
// Non-ASCII or anything with spaces or non-token chars is unchanged:
2935
{"üser-agenT", "üser-agenT"},
3036
{"a B", "a B"},

0 commit comments

Comments
 (0)