]> Cypherpunks repositories - gostls13.git/commitdiff
html/template: reset templates orphaned by (*Template).New
authorSamuel Tan <samueltan@google.com>
Fri, 17 Nov 2017 23:47:33 +0000 (15:47 -0800)
committerIan Lance Taylor <iant@golang.org>
Fri, 8 Dec 2017 04:58:28 +0000 (04:58 +0000)
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: Rob Pike <r@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/html/template/escape_test.go
src/html/template/template.go

index 92f12ca0e078c2b48c5fb667c7b85b4c9a48b25e..2312c9c1c3aafdd5646ff6101b7df019f17a02a7 100644 (file)
@@ -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)
+       }
+}
index d77aa3d7df3745352546aecf46a779ce3e72b7d3..9dc066855f1b4d924f44b417df988dcaa2b0558b 100644 (file)
@@ -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
 }