summaryrefslogtreecommitdiff
path: root/src/pkg/text
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2012-04-12 15:57:09 +1000
committerRob Pike <r@golang.org>2012-04-12 15:57:09 +1000
commit1a61f028a3f1bdbf52de6c1fb82a5f7491f71247 (patch)
tree9100e8a3a59c5eba7a8438b0942ab5f7aa568777 /src/pkg/text
parent7839326e26deb718ff89e5635d44cb8f0f6d5779 (diff)
downloadgo-1a61f028a3f1bdbf52de6c1fb82a5f7491f71247.tar.gz
text/template: catch unexported fields during parse
It's a common error to reference unexported field names in templates, especially for newcomers. This catches the error at parse time rather than execute time so the rare few who check errors will notice right away. These were always an error, so the net behavior is unchanged. Should break no existing code, just identify the error earlier. R=golang-dev, dsymonds CC=golang-dev http://codereview.appspot.com/6009048
Diffstat (limited to 'src/pkg/text')
-rw-r--r--src/pkg/text/template/parse/lex.go2
-rw-r--r--src/pkg/text/template/parse/parse.go10
-rw-r--r--src/pkg/text/template/parse/parse_test.go1
3 files changed, 12 insertions, 1 deletions
diff --git a/src/pkg/text/template/parse/lex.go b/src/pkg/text/template/parse/lex.go
index 7705c0b88..5674a940b 100644
--- a/src/pkg/text/template/parse/lex.go
+++ b/src/pkg/text/template/parse/lex.go
@@ -348,7 +348,7 @@ Loop:
l.backup()
word := l.input[l.start:l.pos]
if !l.atTerminator() {
- return l.errorf("unexpected character %+U", r)
+ return l.errorf("bad character %+U", r)
}
switch {
case key[word] > itemKeyword:
diff --git a/src/pkg/text/template/parse/parse.go b/src/pkg/text/template/parse/parse.go
index c0087b278..fd8cf433f 100644
--- a/src/pkg/text/template/parse/parse.go
+++ b/src/pkg/text/template/parse/parse.go
@@ -14,6 +14,7 @@ import (
"runtime"
"strconv"
"unicode"
+ "unicode/utf8"
)
// Tree is the representation of a single parsed template.
@@ -473,6 +474,9 @@ Loop:
case itemVariable:
cmd.append(t.useVar(token.val))
case itemField:
+ if !isExported(token.val) {
+ t.errorf("field %q not exported; cannot be evaluated", token.val)
+ }
cmd.append(newField(token.val))
case itemBool:
cmd.append(newBool(token.val == "true"))
@@ -498,6 +502,12 @@ Loop:
return cmd
}
+// isExported reports whether the field name (which starts with a period) can be accessed.
+func isExported(fieldName string) bool {
+ r, _ := utf8.DecodeRuneInString(fieldName[1:]) // drop the period
+ return unicode.IsUpper(r)
+}
+
// hasFunction reports if a function name exists in the Tree's maps.
func (t *Tree) hasFunction(name string) bool {
for _, funcMap := range t.funcs {
diff --git a/src/pkg/text/template/parse/parse_test.go b/src/pkg/text/template/parse/parse_test.go
index b2e788238..fb98613fe 100644
--- a/src/pkg/text/template/parse/parse_test.go
+++ b/src/pkg/text/template/parse/parse_test.go
@@ -230,6 +230,7 @@ var parseTests = []parseTest{
{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
+ {"unexported field", "{{.local}}", hasError, ""},
// Equals (and other chars) do not assignments make (yet).
{"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
{"bug0b", "{{$x = 1}}{{$x}}", hasError, ""},