aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/text/template/parse
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
commit2d0d3d8f9efadcad71537b046e31f45a4b0a7844 (patch)
tree3208060580605171c62eb48f5d6ac10a02a9afef /src/pkg/text/template/parse
parente6c5e2a36358465ab5038d8af9e70f3b98d5ba88 (diff)
downloadgo-2d0d3d8f9efadcad71537b046e31f45a4b0a7844.tar.xz
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 https://golang.org/cl/6009048
Diffstat (limited to 'src/pkg/text/template/parse')
-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 7705c0b88f..5674a940b1 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 c0087b2785..fd8cf433fa 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 b2e788238d..fb98613fe1 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, ""},