]> Cypherpunks repositories - gostls13.git/commitdiff
template: fix deadlock.
authorRob Pike <r@golang.org>
Fri, 2 Sep 2011 01:00:46 +0000 (11:00 +1000)
committerRob Pike <r@golang.org>
Fri, 2 Sep 2011 01:00:46 +0000 (11:00 +1000)
No need for lexInsideAction to loop.
Fixes #2217.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/4963054

src/pkg/template/parse/lex.go
src/pkg/template/parse/lex_test.go

index 7ec4e920bd9a70d702ef2d4cd6587251ec649f08..83ad6c628bfa3c98ee7676d75fe849a8bbf5282e 100644 (file)
@@ -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.
index 2ad91d5fa4629d430c0393d9f6b2aeb030f6fc12..d71c8e66df29afbf844430639807b587e4fb68fc 100644 (file)
@@ -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.