Skip to content

text/template: panic when referencing field of parenthesized argument #21171

@mynameiswhm

Description

@mynameiswhm

Our team encountered this problem in the wild with Helm template like this one:

{{ (index .Values "non-existent-key").config.host }}

We've fixed it with multiple arguments call to index:

{{ index .Values "non-existent-key" "config" "host" }}

But after some investigation we've narrowed it down to simple case with parentheses and empty interface{} value:

var v interface{}
t.Execute(os.Stdout, v)
...
{{ .foo }} // works fine producing "<no value>"
{{ (.).foo }} // panics

What version of Go are you using (go version)?

go version go1.8.3 darwin/amd64

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN="/Users/iesaulenko/gocode/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/iesaulenko/gocode"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.8.3/libexec"
GOTOOLDIR="/usr/local/Cellar/go/1.8.3/libexec/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/lq/qclr1nvn4tzf_fcnl4xq5t_0fyxkg0/T/go-build885238657=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

What did you do?

package main

import (
	"log"
	"os"
	"text/template"
)

func main() {
	t, _ := template.New("test").Parse(`{{ (.).foo }}`)
	
	var v interface{}
	err := t.Execute(os.Stdout, v)
	if err != nil {
		log.Fatalf("execution failed: %s", err)
	}
}

https://play.golang.org/p/H2lI-3Taxq

What did you expect to see?

<no value>

(which is returned if you change template to {{ .foo }})

What did you see instead?

panic: reflect: Zero(nil) [recovered]
	panic: reflect: Zero(nil)

goroutine 1 [running]:
text/template.errRecover(0xc420099f00)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:146 +0x62
panic(0x10f8c60, 0xc42009c040)
	/usr/local/Cellar/go/1.8.3/libexec/src/runtime/panic.go:489 +0x2cf
reflect.Zero(0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/Cellar/go/1.8.3/libexec/src/reflect/value.go:2122 +0x134
text/template.(*state).validateType(0xc420099e80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:697 +0x700
text/template.(*state).evalArg(0xc420099e80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x11a64e0, 0xc42008e050, 0x100dc56, 0x1205858, ...)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:746 +0x870
text/template.(*state).evalChainNode(0xc420099e80, 0x0, 0x0, 0x0, 0xc4200a0000, 0xc42009c020, 0x1, 0x1, 0x0, 0x0, ...)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:502 +0xf2
text/template.(*state).evalCommand(0xc420099e80, 0x0, 0x0, 0x0, 0xc420090000, 0x0, 0x0, 0x0, 0xc42001d300, 0x1122b3c, ...)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:430 +0x5f3
text/template.(*state).evalPipeline(0xc420099e80, 0x0, 0x0, 0x0, 0xc42008e000, 0x100e162, 0xc420090090, 0x30)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:406 +0xf2
text/template.(*state).walk(0xc420099e80, 0x0, 0x0, 0x0, 0x11a60c0, 0xc420090060)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:232 +0x55a
text/template.(*state).walk(0xc420099e80, 0x0, 0x0, 0x0, 0x11a63c0, 0xc420018360)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:240 +0x139
text/template.(*Template).execute(0xc420012300, 0x11a5280, 0xc42000c018, 0x0, 0x0, 0x0, 0x0)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:195 +0x20a
text/template.(*Template).Execute(0xc420012300, 0x11a5280, 0xc42000c018, 0x0, 0x0, 0x0, 0xc420018240)
	/usr/local/Cellar/go/1.8.3/libexec/src/text/template/exec.go:178 +0x53
main.main()
	/Users/iesaulenko/_go_tmp/src/go.avito.ru/do/foo/main.go:13 +0xbe
exit status 2

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions