diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go index 7d40f9a8b67..2be32f31b4f 100644 --- a/src/reflect/all_test.go +++ b/src/reflect/all_test.go @@ -2735,6 +2735,8 @@ var tagGetTests = []struct { {`protobuf:"PB(1,2)"`, `rotobuf`, ``}, {`protobuf:"PB(1,2)" json:"name"`, `json`, `name`}, {`protobuf:"PB(1,2)" json:"name"`, `protobuf`, `PB(1,2)`}, + {`k0:"values contain spaces" k1:"and\ttabs"`, "k0", "values contain spaces"}, + {`k0:"values contain spaces" k1:"and\ttabs"`, "k1", "and\ttabs"}, } func TestTagGet(t *testing.T) { diff --git a/src/reflect/type.go b/src/reflect/type.go index ae7d165a68d..0a8c40808a1 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -762,8 +762,11 @@ type StructTag string // If the tag does not have the conventional format, the value // returned by Get is unspecified. func (tag StructTag) Get(key string) string { + // When modifying this code, also update the validateStructTag code + // in golang.org/x/tools/cmd/vet/structtag.go. + for tag != "" { - // skip leading space + // Skip leading space. i := 0 for i < len(tag) && tag[i] == ' ' { i++ @@ -773,19 +776,21 @@ func (tag StructTag) Get(key string) string { break } - // scan to colon. - // a space or a quote is a syntax error + // Scan to colon. A space, a quote or a control character is a syntax error. + // Strictly speaking, control chars include the range [0x7f, 0x9f], not just + // [0x00, 0x1f], but in practice, we ignore the multi-byte control characters + // as it is simpler to inspect the tag's bytes than the tag's runes. i = 0 - for i < len(tag) && tag[i] != ' ' && tag[i] != ':' && tag[i] != '"' { + for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f { i++ } - if i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' { + if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' { break } name := string(tag[:i]) tag = tag[i+1:] - // scan quoted string to find value + // Scan quoted string to find value. i = 1 for i < len(tag) && tag[i] != '"' { if tag[i] == '\\' { @@ -800,7 +805,10 @@ func (tag StructTag) Get(key string) string { tag = tag[i+1:] if key == name { - value, _ := strconv.Unquote(qvalue) + value, err := strconv.Unquote(qvalue) + if err != nil { + break + } return value } }