]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: for struct tags, reject control chars (including tabs) in keys,
authorNigel Tao <nigeltao@golang.org>
Thu, 5 Feb 2015 04:23:52 +0000 (15:23 +1100)
committerNigel Tao <nigeltao@golang.org>
Fri, 6 Feb 2015 02:27:27 +0000 (02:27 +0000)
and empty keys. Also reject malformed (quoted) values.

See also https://go-review.googlesource.com/3952

Change-Id: Ice6de33b09f9904b28e410a680a90aa6c8c76fed
Reviewed-on: https://go-review.googlesource.com/3953
Reviewed-by: Rob Pike <r@golang.org>
src/reflect/all_test.go
src/reflect/type.go

index 7d40f9a8b67f668f990820ad743b40c2ed03acc2..2be32f31b4f35014a36bc3172655fba9556f602a 100644 (file)
@@ -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) {
index ae7d165a68d2b2655b788b779261e130c7f14e14..0a8c40808a1cc2c8f2428386bfec81a75b2cdad4 100644 (file)
@@ -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
                }
        }