]> Cypherpunks repositories - gostls13.git/commitdiff
text/template/parse: fix data race on lexer initialization
authorEli Bendersky <eliben@golang.org>
Sat, 4 Jun 2022 16:43:40 +0000 (09:43 -0700)
committerEli Bendersky‎ <eliben@golang.org>
Mon, 6 Jun 2022 15:54:07 +0000 (15:54 +0000)
Before this change, `startParse` would write `lex.breakOK` and `lex.continueOK` when the lexer goroutine is already running, which is a potential race condition.

Makes `breakOK` and `continueOK` configuration flags passed when `lexer` is created, similarly to how `emitComment` works.

Fixes #53234

Change-Id: Ia65f6135509a758cd4c5a453b249a174f4fb3e21
Reviewed-on: https://go-review.googlesource.com/c/go/+/410414
Reviewed-by: Eli Bendersky <eliben@google.com>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>

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

index 4c32d261f25b5e353e139604e5873408ad093714..29403dd947c93c2904e3bae06b5c20c2d211e48f 100644 (file)
@@ -211,7 +211,7 @@ func (l *lexer) drain() {
 }
 
 // lex creates a new scanner for the input string.
-func lex(name, input, left, right string, emitComment bool) *lexer {
+func lex(name, input, left, right string, emitComment, breakOK, continueOK bool) *lexer {
        if left == "" {
                left = leftDelim
        }
@@ -224,6 +224,8 @@ func lex(name, input, left, right string, emitComment bool) *lexer {
                leftDelim:   left,
                rightDelim:  right,
                emitComment: emitComment,
+               breakOK:     breakOK,
+               continueOK:  continueOK,
                items:       make(chan item),
                line:        1,
                startLine:   1,
index fcb7e8eacddeb7a1fccbdfc30feec7daa4dc46d0..c5f429667c08c309593d53a52c68c8db00401e01 100644 (file)
@@ -394,7 +394,7 @@ var lexTests = []lexTest{
 
 // collect gathers the emitted items into a slice.
 func collect(t *lexTest, left, right string) (items []item) {
-       l := lex(t.name, t.input, left, right, true)
+       l := lex(t.name, t.input, left, right, true, true, true)
        for {
                item := l.nextItem()
                items = append(items, item)
@@ -550,7 +550,7 @@ func TestPos(t *testing.T) {
 func TestShutdown(t *testing.T) {
        // We need to duplicate template.Parse here to hold on to the lexer.
        const text = "erroneous{{define}}{{else}}1234"
-       lexer := lex("foo", text, "{{", "}}", false)
+       lexer := lex("foo", text, "{{", "}}", false, true, true)
        _, err := New("root").parseLexer(lexer)
        if err == nil {
                t.Fatalf("expected error")
index 67e2f5b2f4ab1a5d9c3a0ec852417dd76eb0aab5..00c258ad5deab67792cc5b9e467b407b11643157 100644 (file)
@@ -224,8 +224,6 @@ func (t *Tree) startParse(funcs []map[string]any, lex *lexer, treeSet map[string
        t.vars = []string{"$"}
        t.funcs = funcs
        t.treeSet = treeSet
-       lex.breakOK = !t.hasFunction("break")
-       lex.continueOK = !t.hasFunction("continue")
 }
 
 // stopParse terminates parsing.
@@ -244,7 +242,10 @@ func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tre
        defer t.recover(&err)
        t.ParseName = t.Name
        emitComment := t.Mode&ParseComments != 0
-       t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim, emitComment), treeSet)
+       breakOK := !t.hasFunction("break")
+       continueOK := !t.hasFunction("continue")
+       lexer := lex(t.Name, text, leftDelim, rightDelim, emitComment, breakOK, continueOK)
+       t.startParse(funcs, lexer, treeSet)
        t.text = text
        t.parse()
        t.add()