mirror of
https://github.com/golang/go
synced 2024-11-21 22:24:40 -07:00
template: give "unexported" error when accessing an unexported field.
R=adg, rsc CC=golang-dev https://golang.org/cl/3903043
This commit is contained in:
parent
e3c9565b43
commit
29cbad6c72
@ -596,7 +596,7 @@ func (t *Template) parse() {
|
||||
|
||||
// Evaluate interfaces and pointers looking for a value that can look up the name, via a
|
||||
// struct field, method, or map key, and return the result of the lookup.
|
||||
func lookup(v reflect.Value, name string) reflect.Value {
|
||||
func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value {
|
||||
for v != nil {
|
||||
typ := v.Type()
|
||||
if n := v.Type().NumMethod(); n > 0 {
|
||||
@ -605,7 +605,7 @@ func lookup(v reflect.Value, name string) reflect.Value {
|
||||
mtyp := m.Type
|
||||
if m.Name == name && mtyp.NumIn() == 1 && mtyp.NumOut() == 1 {
|
||||
if !isExported(name) {
|
||||
return nil
|
||||
t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
|
||||
}
|
||||
return v.Method(i).Call(nil)[0]
|
||||
}
|
||||
@ -618,7 +618,7 @@ func lookup(v reflect.Value, name string) reflect.Value {
|
||||
v = av.Elem()
|
||||
case *reflect.StructValue:
|
||||
if !isExported(name) {
|
||||
return nil
|
||||
t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type())
|
||||
}
|
||||
return av.FieldByName(name)
|
||||
case *reflect.MapValue:
|
||||
@ -652,14 +652,14 @@ loop:
|
||||
// The value coming in (st.data) might need indirecting to reach
|
||||
// a struct while the return value is not indirected - that is,
|
||||
// it represents the actual named field.
|
||||
func (st *state) findVar(s string) reflect.Value {
|
||||
func (t *Template) findVar(st *state, s string) reflect.Value {
|
||||
if s == "@" {
|
||||
return st.data
|
||||
}
|
||||
data := st.data
|
||||
for _, elem := range strings.Split(s, ".", -1) {
|
||||
// Look up field; data must be a struct or map.
|
||||
data = lookup(data, elem)
|
||||
data = t.lookup(st, data, elem)
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
@ -692,7 +692,7 @@ func empty(v reflect.Value) bool {
|
||||
|
||||
// Look up a variable or method, up through the parent if necessary.
|
||||
func (t *Template) varValue(name string, st *state) reflect.Value {
|
||||
field := st.findVar(name)
|
||||
field := t.findVar(st, name)
|
||||
if field == nil {
|
||||
if st.parent == nil {
|
||||
t.execError(st, t.linenum, "name not found: %s in type %s", name, st.data.Type())
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
"io/ioutil"
|
||||
"json"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -635,3 +636,25 @@ func TestHTMLFormatterWithByte(t *testing.T) {
|
||||
t.Errorf("munged []byte, expected: %s got: %s", s, bs)
|
||||
}
|
||||
}
|
||||
|
||||
type UF struct {
|
||||
I int
|
||||
s string
|
||||
}
|
||||
|
||||
func TestReferenceToUnexported(t *testing.T) {
|
||||
u := &UF{3, "hello"}
|
||||
var buf bytes.Buffer
|
||||
input := "{.section @}{I}{s}{.end}"
|
||||
tmpl, err := Parse(input, nil)
|
||||
if err != nil {
|
||||
t.Fatal("unexpected parse error:", err)
|
||||
}
|
||||
err = tmpl.Execute(u, &buf)
|
||||
if err == nil {
|
||||
t.Fatal("expected execute error, got none")
|
||||
}
|
||||
if strings.Index(err.String(), "not exported") < 0 {
|
||||
t.Fatal("expected unexported error; got", err)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user