Skip to content

Commit

Permalink
text/template: check for malformed pipelines
Browse files Browse the repository at this point in the history
Catch some malformed pipelines at parsing time.
The current code accepts pipelines such as:

{{12|.}}
{{"hello"|print|false}}
{{.|"blah blah"}}

Such pipelines generate panic in html/template at execution time.

Add an extra check to verify all the commands of the pipeline are executable
(except for the first one).

Fixes #10610

Change-Id: Id72236ba8f76a59fa284fe3d4c2cb073e50b51f1
Reviewed-on: https://go-review.googlesource.com/9626
Reviewed-by: Rob Pike <[email protected]>
  • Loading branch information
dspezia authored and robpike committed May 5, 2015
1 parent de6d5b0 commit 62fb472
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
20 changes: 17 additions & 3 deletions src/text/template/parse/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,8 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
for {
switch token := t.nextNonSpace(); token.typ {
case itemRightDelim, itemRightParen:
if len(pipe.Cmds) == 0 {
t.errorf("missing value for %s", context)
}
// At this point, the pipeline is complete
t.checkPipeline(pipe, context)
if token.typ == itemRightParen {
t.backup()
}
Expand All @@ -430,6 +429,21 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
}
}

func (t *Tree) checkPipeline(pipe *PipeNode, context string) {
// Reject empty pipelines
if len(pipe.Cmds) == 0 {
t.errorf("missing value for %s", context)
}
// Only the first command of a pipeline can start with a non executable operand
for i, c := range pipe.Cmds[1:] {
switch c.Args[0].Type() {
case NodeBool, NodeDot, NodeNil, NodeNumber, NodeString:
// With A|B|C, pipeline stage 2 is B
t.errorf("non executable command in pipeline stage %d", i+2)
}
}
}

func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
defer t.popVars(len(t.vars))
line = t.lex.lineNumber()
Expand Down
14 changes: 14 additions & 0 deletions src/text/template/parse/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,14 @@ var parseTests = []parseTest{
{"dot after string", `{{"hello".guys}}`, hasError, ""},
{"dot after dot", "{{..E}}", hasError, ""},
{"dot after nil", "{{nil.E}}", hasError, ""},
// Wrong pipeline
{"wrong pipeline dot", "{{12|.}}", hasError, ""},
{"wrong pipeline number", "{{.|12|printf}}", hasError, ""},
{"wrong pipeline string", "{{.|print|\"error\"}}", hasError, ""},
{"wrong pipeline char", "{{12|print|html|'e'}}", hasError, ""},
{"wrong pipeline boolean", "{{.|true}}", hasError, ""},
{"wrong pipeline nil", "{{'c'|nil}}", hasError, ""},
{"empty pipeline", `{{printf "%d" ( ) }}`, hasError, ""},
}

var builtins = map[string]interface{}{
Expand Down Expand Up @@ -422,6 +430,12 @@ var errorTests = []parseTest{
{"wrongdot",
"{{true.any}}",
hasError, `unexpected . after term`},
{"wrongpipeline",
"{{12|false}}",
hasError, `non executable command in pipeline`},
{"emptypipeline",
`{{ ( ) }}`,
hasError, `missing value for parenthesized pipeline`},
}

func TestErrors(t *testing.T) {
Expand Down

0 comments on commit 62fb472

Please sign in to comment.