1
0
mirror of https://github.com/golang/go synced 2024-11-12 06:30:21 -07:00

exp/template/html: fix infinite loop in escapeText on bad input

The template
    "<a="
caused an infinite loop in escape text.

The change to tTag fixes that and the change to escape.go causes
escapeText to panic on any infinite loop that does not involve
a state cycle.

R=nigeltao
CC=golang-dev
https://golang.org/cl/5115041
This commit is contained in:
Mike Samuel 2011-09-26 00:56:49 -07:00
parent 66cdd02038
commit 3771415100
3 changed files with 28 additions and 17 deletions

View File

@ -598,6 +598,9 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
b.Write(s[written:cs])
written = i1
}
if i == i1 && c.state == c1.state {
panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
}
c, i = c1, i1
}

View File

@ -904,6 +904,10 @@ func TestErrors(t *testing.T) {
`<a style=font:'Arial'>`,
`exp/template/html:z: "'" in unquoted attr: "font:'Arial'"`,
},
{
`<a=foo>`,
`: expected space, attr name, or end of tag, but got "=foo>"`,
},
}
for _, test := range tests {

View File

@ -100,26 +100,30 @@ func tTag(c context, s []byte) (context, int) {
return context{state: stateError, err: err}, len(s)
}
state, attr := stateTag, attrNone
if i != j {
canonAttrName := strings.ToLower(string(s[i:j]))
switch attrType[canonAttrName] {
case contentTypeURL:
attr = attrURL
case contentTypeCSS:
attr = attrStyle
case contentTypeJS:
if i == j {
return context{
state: stateError,
err: errorf(ErrBadHTML, 0, "expected space, attr name, or end of tag, but got %q", s[i:]),
}, len(s)
}
canonAttrName := strings.ToLower(string(s[i:j]))
switch attrType[canonAttrName] {
case contentTypeURL:
attr = attrURL
case contentTypeCSS:
attr = attrStyle
case contentTypeJS:
attr = attrScript
default:
if strings.HasPrefix(canonAttrName, "on") {
attr = attrScript
default:
if strings.HasPrefix(canonAttrName, "on") {
attr = attrScript
}
}
if j == len(s) {
state = stateAttrName
} else {
state = stateAfterName
}
}
if j == len(s) {
state = stateAttrName
} else {
state = stateAfterName
}
return context{state: state, element: c.element, attr: attr}, j
}