golang / go

The Go programming language

Home Page:https://go.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

html/template: invalid memory address or nil pointer dereference

dvyukov opened this issue · comments

package main

import (
    "html/template"
    "io/ioutil"
)

func main() {
    t, err := template.New("foo").Parse(string(data))
    if err != nil {
        return
    }
    t.Execute(ioutil.Discard, nil)
}

var data = "{{.0.E}}"
panic: runtime error: invalid memory address or nil pointer dereference

goroutine 1 [running]:
text/template.errRecover(0xc208041eb0)
    src/text/template/exec.go:100 +0xb2
text/template.(*state).evalArg(0xc2080105c0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f01b141c210, 0xc208020120, 0x0, 0x0, ...)
    src/text/template/exec.go:667 +0x46a
text/template.(*state).evalChainNode(0xc2080105c0, 0x0, 0x0, 0x0, 0xc208010500, 0xc20800a5b0, 0x1, 0x1, 0x0, 0x0, ...)
    src/text/template/exec.go:439 +0x28a
text/template.(*state).evalCommand(0xc2080105c0, 0x0, 0x0, 0x0, 0xc208014810, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
    src/text/template/exec.go:367 +0x31d
text/template.(*state).evalPipeline(0xc2080105c0, 0x0, 0x0, 0x0, 0xc208012190, 0x0, 0x0, 0x0)
    src/text/template/exec.go:343 +0x1a0
text/template.(*state).walk(0xc2080105c0, 0x0, 0x0, 0x0, 0x7f01b141c2a0, 0xc2080148a0)
    src/text/template/exec.go:178 +0x13b
text/template.(*state).walk(0xc2080105c0, 0x0, 0x0, 0x0, 0x7f01b141c2e8, 0xc2080147e0)
    src/text/template/exec.go:186 +0x766
text/template.(*Template).Execute(0xc208010440, 0x7f01b141c1c0, 0xc20800a4c0, 0x0, 0x0, 0x0, 0x0)
    src/text/template/exec.go:141 +0x429
html/template.(*Template).Execute(0xc2080146f0, 0x7f01b141c1c0, 0xc20800a4c0, 0x0, 0x0, 0x0, 0x0)
    src/html/template/template.go:104 +0x9d
main.main()
    /tmp/htmltempl.go:13 +0x290

on commit ccc76db

Actually, the problem happens when a dot immediately follows a literal. It can be reproduced also with {{true.E}} or {{'x'.any}}. I guess this could be caught at parsing time, providing the TODO in Tree.operand is addressed:

    // Compatibility with original API: If the term is of type NodeField
    // or NodeVariable, just put more fields on the original.
    // Otherwise, keep the Chain node.
    // TODO: Switch to Chains always when we can.
    switch node.Type() {
    case NodeField:
        node = t.newField(chain.Position(), chain.String())
    case NodeVariable:
        node = t.newVariable(chain.Position(), chain.String())
    default:
        node = chain
    }

Trying to prepare a CL.

CL https://golang.org/cl/9621 mentions this issue.