Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
mynameiswhm opened this issue Jul 25, 2017 · 4 comments
Closed

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

mynameiswhm opened this issue Jul 25, 2017 · 4 comments
Assignees
Milestone

Comments

@mynameiswhm
Copy link

@mynameiswhm mynameiswhm commented Jul 25, 2017

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
@odeke-em
Copy link
Member

@odeke-em odeke-em commented Jul 26, 2017

I can also reproduce this on go tip 3d9475c, not a regression so marking this for Go1.10.

@odeke-em odeke-em added this to the Go1.10 milestone Jul 26, 2017
@odeke-em
Copy link
Member

@odeke-em odeke-em commented Dec 11, 2017

Sorry @mynameiswhm that we didn't look at this issue during Go1.10. I'll move this to the Go1.11 milestone instead.

@odeke-em odeke-em modified the milestones: Go1.10, Go1.11 Dec 11, 2017
@mvdan mvdan self-assigned this Dec 17, 2017
@mvdan mvdan added NeedsFix and removed NeedsInvestigation labels Dec 17, 2017
@mvdan
Copy link
Member

@mvdan mvdan commented Dec 17, 2017

I believe I have found the fix for this - sending a CL now.

@gopherbot
Copy link

@gopherbot gopherbot commented Dec 17, 2017

Change https://golang.org/cl/84482 mentions this issue: text/template: never call reflect.Zero(nil)

@gopherbot gopherbot closed this in 618f88d Feb 13, 2018
@golang golang locked and limited conversation to collaborators Feb 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.