aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gerrand <adg@golang.org>2011-09-08 11:12:11 +1000
committerAndrew Gerrand <adg@golang.org>2011-09-08 11:12:11 +1000
commit2800956682af70ec2fd79960c052b9aaeef2ad52 (patch)
treee4a67a59866c4203fc058098e3dc96e75a0264ed
parent1adba86fdd6ea9325235e6aa02da6f596651b6f8 (diff)
downloadgo-2800956682af70ec2fd79960c052b9aaeef2ad52.tar.gz
go-2800956682af70ec2fd79960c052b9aaeef2ad52.zip
[release-branch.r60] template: fix deadlock.
««« CL 4963054 / c581abafc917 template: fix deadlock. No need for lexInsideAction to loop. Fixes #2217. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/4963054 »»» R=dsymonds CC=golang-dev https://golang.org/cl/4974068
-rw-r--r--src/pkg/template/parse/lex.go84
-rw-r--r--src/pkg/template/parse/lex_test.go14
2 files changed, 55 insertions, 43 deletions
diff --git a/src/pkg/template/parse/lex.go b/src/pkg/template/parse/lex.go
index 7ec4e920bd..83ad6c628b 100644
--- a/src/pkg/template/parse/lex.go
+++ b/src/pkg/template/parse/lex.go
@@ -278,53 +278,51 @@ func lexInsideAction(l *lexer) stateFn {
// Either number, quoted string, or identifier.
// Spaces separate and are ignored.
// Pipe symbols separate and are emitted.
- for {
- if strings.HasPrefix(l.input[l.pos:], rightDelim) {
- return lexRightDelim
+ if strings.HasPrefix(l.input[l.pos:], rightDelim) {
+ return lexRightDelim
+ }
+ switch r := l.next(); {
+ case r == eof || r == '\n':
+ return l.errorf("unclosed action")
+ case isSpace(r):
+ l.ignore()
+ case r == ':':
+ if l.next() != '=' {
+ return l.errorf("expected :=")
}
- switch r := l.next(); {
- case r == eof || r == '\n':
- return l.errorf("unclosed action")
- case isSpace(r):
- l.ignore()
- case r == ':':
- if l.next() != '=' {
- return l.errorf("expected :=")
+ l.emit(itemColonEquals)
+ case r == '|':
+ l.emit(itemPipe)
+ case r == '"':
+ return lexQuote
+ case r == '`':
+ return lexRawQuote
+ case r == '$':
+ return lexIdentifier
+ case r == '\'':
+ return lexChar
+ case r == '.':
+ // special look-ahead for ".field" so we don't break l.backup().
+ if l.pos < len(l.input) {
+ r := l.input[l.pos]
+ if r < '0' || '9' < r {
+ return lexIdentifier // itemDot comes from the keyword table.
}
- l.emit(itemColonEquals)
- case r == '|':
- l.emit(itemPipe)
- case r == '"':
- return lexQuote
- case r == '`':
- return lexRawQuote
- case r == '$':
- return lexIdentifier
- case r == '\'':
- return lexChar
- case r == '.':
- // special look-ahead for ".field" so we don't break l.backup().
- if l.pos < len(l.input) {
- r := l.input[l.pos]
- if r < '0' || '9' < r {
- return lexIdentifier // itemDot comes from the keyword table.
- }
- }
- fallthrough // '.' can start a number.
- case r == '+' || r == '-' || ('0' <= r && r <= '9'):
- l.backup()
- return lexNumber
- case isAlphaNumeric(r):
- l.backup()
- return lexIdentifier
- case r <= unicode.MaxASCII && unicode.IsPrint(r):
- l.emit(itemChar)
- return lexInsideAction
- default:
- return l.errorf("unrecognized character in action: %#U", r)
}
+ fallthrough // '.' can start a number.
+ case r == '+' || r == '-' || ('0' <= r && r <= '9'):
+ l.backup()
+ return lexNumber
+ case isAlphaNumeric(r):
+ l.backup()
+ return lexIdentifier
+ case r <= unicode.MaxASCII && unicode.IsPrint(r):
+ l.emit(itemChar)
+ return lexInsideAction
+ default:
+ return l.errorf("unrecognized character in action: %#U", r)
}
- return nil
+ return lexInsideAction
}
// lexIdentifier scans an alphanumeric or field.
diff --git a/src/pkg/template/parse/lex_test.go b/src/pkg/template/parse/lex_test.go
index 2ad91d5fa4..d71c8e66df 100644
--- a/src/pkg/template/parse/lex_test.go
+++ b/src/pkg/template/parse/lex_test.go
@@ -184,6 +184,20 @@ var lexTests = []lexTest{
tLeft,
{itemError, `bad number syntax: "3k"`},
}},
+
+ // Fixed bugs
+ // Many elements in an action blew the lookahead until
+ // we made lexInsideAction not loop.
+ {"long pipeline deadlock", "{{|||||}}", []item{
+ tLeft,
+ tPipe,
+ tPipe,
+ tPipe,
+ tPipe,
+ tPipe,
+ tRight,
+ tEOF,
+ }},
}
// collect gathers the emitted items into a slice.