mirror of
https://github.com/golang/go
synced 2024-11-19 03:04:42 -07:00
html/template: fix crash when escaping incomplete template
text/template turned this into an error but html/template crashed. Refactor text/template.Execute to export a new function, text/template.DefinedTemplates, so html/template can get the same helpful error message in this case, and invoke it when there is no definition for a template being escaped. Fixes #10204. Change-Id: I1d04e9e7ebca829bc08509caeb65e75da969711f Reviewed-on: https://go-review.googlesource.com/7855 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
3f12d27133
commit
11dba2ec2d
@ -1686,6 +1686,21 @@ func TestPipeToMethodIsEscaped(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Unlike text/template, html/template crashed if given an incomplete
|
||||
// template, that is, a template that had been named but not given any content.
|
||||
// This is issue #10204.
|
||||
func TestErrorOnUndefined(t *testing.T) {
|
||||
tmpl := New("undefined")
|
||||
|
||||
err := tmpl.Execute(nil, nil)
|
||||
if err == nil {
|
||||
t.Error("expected error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "incomplete") {
|
||||
t.Errorf("expected error about incomplete template; got %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEscapedExecute(b *testing.B) {
|
||||
tmpl := Must(New("t").Parse(`<a onclick="alert('{{.}}')">{{.}}</a>`))
|
||||
var buf bytes.Buffer
|
||||
|
@ -56,6 +56,9 @@ func (t *Template) escape() error {
|
||||
t.nameSpace.mu.Lock()
|
||||
defer t.nameSpace.mu.Unlock()
|
||||
if t.escapeErr == nil {
|
||||
if t.Tree == nil {
|
||||
return fmt.Errorf("template: %q is an incomplete or empty template%s", t.Name(), t.text.DefinedTemplates())
|
||||
}
|
||||
if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -136,26 +136,37 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
|
||||
}
|
||||
t.init()
|
||||
if t.Tree == nil || t.Root == nil {
|
||||
var b bytes.Buffer
|
||||
for name, tmpl := range t.tmpl {
|
||||
if tmpl.Tree == nil || tmpl.Root == nil {
|
||||
continue
|
||||
}
|
||||
if b.Len() > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
fmt.Fprintf(&b, "%q", name)
|
||||
}
|
||||
var s string
|
||||
if b.Len() > 0 {
|
||||
s = "; defined templates are: " + b.String()
|
||||
}
|
||||
state.errorf("%q is an incomplete or empty template%s", t.Name(), s)
|
||||
state.errorf("%q is an incomplete or empty template%s", t.Name(), t.DefinedTemplates())
|
||||
}
|
||||
state.walk(value, t.Root)
|
||||
return
|
||||
}
|
||||
|
||||
// DefinedTemplates returns a string listing the defined templates,
|
||||
// prefixed by the string "defined templates are: ". If there are none,
|
||||
// it returns the empty string. For generating an error message here
|
||||
// and in html/template.
|
||||
func (t *Template) DefinedTemplates() string {
|
||||
if t.common == nil {
|
||||
return ""
|
||||
}
|
||||
var b bytes.Buffer
|
||||
for name, tmpl := range t.tmpl {
|
||||
if tmpl.Tree == nil || tmpl.Root == nil {
|
||||
continue
|
||||
}
|
||||
if b.Len() > 0 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
fmt.Fprintf(&b, "%q", name)
|
||||
}
|
||||
var s string
|
||||
if b.Len() > 0 {
|
||||
s = "; defined templates are: " + b.String()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Walk functions step through the major pieces of the template structure,
|
||||
// generating output as they go.
|
||||
func (s *state) walk(dot reflect.Value, node parse.Node) {
|
||||
|
Loading…
Reference in New Issue
Block a user