Closed
Description
The following program crashes with panic:
package main
import (
"errors"
"html/template"
"io/ioutil"
"os"
)
func main() {
data, _ := ioutil.ReadFile(os.Args[1])
t, err := template.New("foo").Funcs(funcs).Parse(string(data))
if err != nil {
if t != nil {
panic("non nil template on error")
}
return
}
d := &Data{
A: 42,
B: "foo",
C: []int{1, 2, 3},
D: map[int]string{1: "foo", 2: "bar"},
E: Data1{42, "foo"},
}
t.Execute(ioutil.Discard, d)
return
}
type Data struct {
A int
B string
C []int
D map[int]string
E Data1
}
type Data1 struct {
A int
B string
}
func (Data1) Q() string {
return "foo"
}
func (Data1) W() (string, error) {
return "foo", nil
}
func (Data1) E() (string, error) {
return "foo", errors.New("Data.E error")
}
func (Data1) R(v int) (string, error) {
return "foo", nil
}
func (Data1) T(s string) (string, error) {
return s, nil
}
var funcs = map[string]interface{}{
"Q": func1,
"W": func2,
"E": func3,
"R": func4,
"T": func5,
"Y": func6,
"U": func7,
"I": func8,
}
func func1(s string) string {
return s
}
func func2(s string) (string, error) {
return s, nil
}
func func3(s string) (string, error) {
return s, errors.New("func3 error")
}
func func4(v int) int {
return v
}
func func5(v int) (int, error) {
return v, nil
}
func func6() int {
return 42
}
func func7() (int, error) {
return 42, nil
}
func func8() (int, error) {
return 42, errors.New("func8 error")
}
panic: runtime error: slice bounds out of range [recovered]
panic: runtime error: slice bounds out of range
goroutine 1 [running]:
text/template.errRecover(0xc208041e50)
src/text/template/exec.go:100 +0xb2
html/template.htmlReplacer(0xc2080c0068, 0x2, 0x6d6ae0, 0x61, 0x61, 0x5be900, 0x0, 0x0)
src/html/template/html.go:144 +0x1d7
html/template.htmlNospaceEscaper(0xc20800eb20, 0x1, 0x1, 0x0, 0x0)
src/html/template/html.go:20 +0x129
reflect.Value.call(0x55d560, 0x631a98, 0x13, 0x5c24d0, 0x4, 0xc20800a840, 0x1, 0x1, 0x0, 0x0, ...)
src/reflect/value.go:432 +0x1253
reflect.Value.Call(0x55d560, 0x631a98, 0x13, 0xc20800a800, 0x1, 0x1, 0x0, 0x0, 0x0)
src/reflect/value.go:300 +0xb4
text/template.(*state).evalCall(0xc208041de0, 0x545f80, 0xc20800eb00, 0x58, 0x55d560, 0x631a98, 0x13, 0x7f3f2a955628, 0xc208015590, 0x609690, ...)
src/text/template/exec.go:592 +0xb04
text/template.(*state).evalFunction(0xc208041de0, 0x545f80, 0xc20800eb00, 0x58, 0xc208015560, 0x7f3f2a955628, 0xc208015590, 0xc20800e860, 0x1, 0x1, ...)
src/text/template/exec.go:473 +0x427
text/template.(*state).evalCommand(0xc208041de0, 0x545f80, 0xc20800eb00, 0x58, 0xc208015590, 0x545f80, 0xc20800eb10, 0x58, 0x0, 0x0, ...)
src/text/template/exec.go:370 +0x1eb
text/template.(*state).evalPipeline(0xc208041de0, 0x545f80, 0xc20800eb00, 0x58, 0xc208012320, 0x545f80, 0xc20800eb10, 0x58)
src/text/template/exec.go:343 +0x183
text/template.(*state).walk(0xc208041de0, 0x545f80, 0xc20800eb00, 0x58, 0x7f3f2a955430, 0xc208014a80)
src/text/template/exec.go:178 +0x137
text/template.(*state).walk(0xc208041de0, 0x545f80, 0xc20800eb00, 0x58, 0x7f3f2a955550, 0xc2080149c0)
src/text/template/exec.go:186 +0x784
text/template.(*state).walkIfOrWith(0xc208041de0, 0x13, 0x532c40, 0xc208012690, 0x16, 0xc2080122d0, 0xc2080149c0, 0x0)
src/text/template/exec.go:214 +0x29e
text/template.(*state).walk(0xc208041de0, 0x532c40, 0xc208012690, 0x16, 0x7f3f2a9554c0, 0xc2080106c0)
src/text/template/exec.go:197 +0x637
text/template.(*state).walk(0xc208041de0, 0x532c40, 0xc208012690, 0x16, 0x7f3f2a955550, 0xc208014870)
src/text/template/exec.go:186 +0x784
text/template.(*Template).Execute(0xc208010440, 0x7f3f2a9552b8, 0xc20800e500, 0x532c40, 0xc208012690, 0x0, 0x0)
src/text/template/exec.go:141 +0x3ea
html/template.(*Template).Execute(0xc208014780, 0x7f3f2a9552b8, 0xc20800e500, 0x532c40, 0xc208012690, 0x0, 0x0)
src/html/template/template.go:104 +0x9d
main.main()
/tmp/ht.go:26 +0x543
on commit abb818b