src/html/template/escape_test.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++---
src/html/template/transition.go | 4 ++++
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
index 5ff173420207dd703908420b9abb67a3d54cd0ad..3b26f7815fee377bb6d768629f7a76f45a8b5736 100644
--- a/src/html/template/escape_test.go
+++ b/src/html/template/escape_test.go
@@ -985,7 +985,6 @@ if got := b.String(); test.want != got {
t.Errorf("want\n\t%q\ngot\n\t%q", test.want, got)
}
}
-
}
func TestErrors(t *testing.T) {
@@ -1259,7 +1258,6 @@ }
// Check that we get the same error if we call Execute again.
if err := tmpl.Execute(buf, nil); err == nil || err.Error() != got {
t.Errorf("input=%q: unexpected error on second call %q", test.input, err)
-
}
}
}
@@ -1864,7 +1862,7 @@ context{state: stateJS, element: elementScript, jsCtx: jsCtxDivOp},
},
{
"`,
+ input: "a.b",
+ want: ``,
+ },
+ {
+ name: "regexp after close brace",
+ tmpl: ``,
+ input: "a.b",
+ want: ``,
+ },
+ {
+ name: "regexp pathological attacker input",
+ tmpl: ``,
+ input: `./;alert(1);var q=/.`,
+ want: ``,
+ },
+ {
+ name: "regexp after open brace in template literal",
+ tmpl: "",
+ input: "a.b",
+ want: "",
+ },
+ {
+ name: "regexp after close brace in template literal",
+ tmpl: "",
+ input: "a.b",
+ want: "",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ tmpl := Must(New("test").Parse(tt.tmpl))
+ var buf bytes.Buffer
+ if err := tmpl.Execute(&buf, tt.input); err != nil {
+ t.Fatalf("Execute: %v", err)
+ }
+ if got := buf.String(); got != tt.want {
+ t.Errorf("got: %s\nwant: %s", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/src/html/template/transition.go b/src/html/template/transition.go
index 05b6abd03d1772926a45a387bdca6116026d0ec4..d9d4f63beba80737fc4e5e1edc1a9f42cc122263 100644
--- a/src/html/template/transition.go
+++ b/src/html/template/transition.go
@@ -336,11 +336,14 @@ case '{':
// We only care about tracking brace depth if we are inside of a
// template literal.
if len(c.jsBraceDepth) == 0 {
+ c.jsCtx = nextJSCtx(s[i:i+1], c.jsCtx)
return c, i + 1
}
c.jsBraceDepth[len(c.jsBraceDepth)-1]++
+ c.jsCtx = nextJSCtx(s[i:i+1], c.jsCtx)
case '}':
if len(c.jsBraceDepth) == 0 {
+ c.jsCtx = nextJSCtx(s[i:i+1], c.jsCtx)
return c, i + 1
}
// There are no cases where a brace can be escaped in the JS context
@@ -349,6 +352,7 @@ // count "\}" as "}" and move on, the script is already broken as
// fully fledged parsers will just fail anyway.
c.jsBraceDepth[len(c.jsBraceDepth)-1]--
if c.jsBraceDepth[len(c.jsBraceDepth)-1] >= 0 {
+ c.jsCtx = nextJSCtx(s[i:i+1], c.jsCtx)
return c, i + 1
}
c.jsBraceDepth = c.jsBraceDepth[:len(c.jsBraceDepth)-1]