Commit 6af8c0d8 authored by Samuel Tan's avatar Samuel Tan Committed by Ian Lance Taylor

html/template: reset templates orphaned by (*Template).New

If (*Template).New replaces an existing template, reset the
existing template that is going to be replaced so that any
later attempt to execute this orphaned template will fail.

Fixes #22780

Change-Id: I0e058f42c1542c86d19dc5f6c4e1e859e670a4a2
Reviewed-on: https://go-review.googlesource.com/78542
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarRob Pike <r@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 4c800f03
......@@ -1903,3 +1903,25 @@ func BenchmarkEscapedExecute(b *testing.B) {
buf.Reset()
}
}
// Covers issue 22780.
func TestOrphanedTemplate(t *testing.T) {
t1 := Must(New("foo").Parse(`<a href="{{.}}">link1</a>`))
t2 := Must(t1.New("foo").Parse(`bar`))
var b bytes.Buffer
const wantError = `template: "foo" is an incomplete or empty template`
if err := t1.Execute(&b, "javascript:alert(1)"); err == nil {
t.Fatal("expected error executing t1")
} else if gotError := err.Error(); gotError != wantError {
t.Fatalf("got t1 execution error:\n\t%s\nwant:\n\t%s", gotError, wantError)
}
b.Reset()
if err := t2.Execute(&b, nil); err != nil {
t.Fatalf("error executing t1: %s", err)
}
const want = "bar"
if got := b.String(); got != want {
t.Fatalf("t2 rendered %q, want %q", got, want)
}
}
......@@ -300,6 +300,10 @@ func New(name string) *Template {
// New allocates a new HTML template associated with the given one
// and with the same delimiters. The association, which is transitive,
// allows one template to invoke another with a {{template}} action.
//
// If a template with the given name already exists, the new HTML template
// will replace it. The existing template will be reset and disassociated with
// t.
func (t *Template) New(name string) *Template {
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
......@@ -314,6 +318,10 @@ func (t *Template) new(name string) *Template {
nil,
t.nameSpace,
}
if existing, ok := tmpl.set[name]; ok {
emptyTmpl := New(existing.Name())
*existing = *emptyTmpl
}
tmpl.set[name] = tmpl
return tmpl
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment