diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go index aef5e01957..5ff1734202 100644 --- a/src/html/template/escape_test.go +++ b/src/html/template/escape_test.go @@ -760,6 +760,26 @@ func TestEscape(t *testing.T) { ``, ``, }, + { + "meta content url with whitespace before equals", + ``, + ``, + }, + { + "meta content url with tab before equals", + "", + "", + }, + { + "meta content url with space after equals", + ``, + ``, + }, + { + "meta content url with whitespace both sides of equals", + "", + "", + }, } for _, test := range tests { diff --git a/src/html/template/transition.go b/src/html/template/transition.go index 7fbab1df7b..ea4b272cc2 100644 --- a/src/html/template/transition.go +++ b/src/html/template/transition.go @@ -626,10 +626,12 @@ func tError(c context, s []byte) (context, int) { // tMetaContent is the context transition function for the meta content attribute state. func tMetaContent(c context, s []byte) (context, int) { - for i := 0; i < len(s); i++ { - if i+3 <= len(s)-1 && bytes.Equal(bytes.ToLower(s[i:i+4]), []byte("url=")) { - c.state = stateMetaContentURL - return c, i + 4 + for i := range len(s) { + if i+3 <= len(s)-1 && bytes.EqualFold(s[i:i+3], []byte("url")) { + if j := eatWhiteSpace(s, i+3); j < len(s) && s[j] == '=' { + c.state = stateMetaContentURL + return c, j + 1 + } } } return c, len(s) @@ -637,7 +639,7 @@ func tMetaContent(c context, s []byte) (context, int) { // tMetaContentURL is the context transition function for the "url=" part of a meta content attribute state. func tMetaContentURL(c context, s []byte) (context, int) { - for i := 0; i < len(s); i++ { + for i := range len(s) { if s[i] == ';' { c.state = stateMetaContent return c, i + 1