Skip to content

text/template: call with no arguments after a pipe crashes the program #70341

@ozelis

Description

@ozelis

Go version

go version go1.23.2 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/ao/.cache/go-build'
GOENV='/home/ao/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/ao/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/ao/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.23.2'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/ao/.config/go/telemetry'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build785295111=/tmp/go-build -gno-record-gcc-switches'

What did you do?

https://go.dev/play/p/RapayQaYsZw

package main

import "fmt"
import "text/template"
import "bytes"

func main() {
    tmpl, err := template.New("foo").Parse("{{ 1 | call }}")

    if err != nil {
      fmt.Println(err)
    } else {
      var buf bytes.Buffer
      tmpl.Execute(&buf, "whatever")
      fmt.Println(&buf)
    }
}

What did you see happen?

panic: runtime error: index out of range [0] with length 0 [recovered]
	panic: runtime error: index out of range [0] with length 0

goroutine 1 [running]:
text/template.errRecover(0xc00010ae48)
	/usr/lib/go/src/text/template/exec.go:170 +0x15a
panic({0x539c80?, 0xc00001a150?})
	/usr/lib/go/src/runtime/panic.go:785 +0x132
text/template.(*state).evalCall(0xc00010ae58, {0x51f500?, 0x57ffa0?, 0xc00010aac0?}, {0x525b40?, 0x553530?, 0x1?}, 0x1, {0x582240, 0xc000102270}, ...)
	/usr/lib/go/src/text/template/exec.go:806 +0xb65
text/template.(*state).evalFunction(0xc00010ae58, {0x51f500?, 0x57ffa0?, 0xc00010e1a0?}, 0xf?, {0x582240, 0xc000102270}, {0xc0000140d0, 0x1, 0x1}, ...)
	/usr/lib/go/src/text/template/exec.go:623 +0x1ff
text/template.(*state).evalCommand(0xc00010ae58, {0x51f500?, 0x57ffa0?, 0x0?}, 0xc000102270, {0x51f740?, 0x65b4e8?, 0x469485?})
	/usr/lib/go/src/text/template/exec.go:510 +0x1ce
text/template.(*state).evalPipeline(0xc000125e58, {0x51f500?, 0x57ffa0?, 0xc000102360?}, 0xc00002e1e0)
	/usr/lib/go/src/text/template/exec.go:479 +0x125
text/template.(*state).walk(0xc000125e58, {0x51f500?, 0x57ffa0?, 0x7e0d9f96b108?}, {0x582360?, 0xc0001022d0})
	/usr/lib/go/src/text/template/exec.go:267 +0x225
text/template.(*state).walk(0xc000125e58, {0x51f500?, 0x57ffa0?, 0xc00010aea0?}, {0x5822d0?, 0xc000102210?})
	/usr/lib/go/src/text/template/exec.go:280 +0x2e5
text/template.(*Template).execute(0xc0001040c0, {0x580b58?, 0xc000102330?}, {0x51f500?, 0x57ffa0?})
	/usr/lib/go/src/text/template/exec.go:224 +0x275
text/template.(*Template).Execute(...)
	/usr/lib/go/src/text/template/exec.go:207
main.main()
	/home/ao/proj/go_test/test.go:14 +0x185

What did you expect to see?

Previously it would report a normal error calling call: non-function of type int, but after changes in recent
commit c506f03

// ...
	if isBuiltin && name == "call" {
		calleeName := args[0].String()
		argv = append([]reflect.Value{reflect.ValueOf(calleeName)}, argv...)
		fun = reflect.ValueOf(call)
	}
// ...

it tries to access args[0] which in this case is empty and crashes the whole program.

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