summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShubham Kulkarni <skulkarni@mvista.com>2023-09-30 00:50:33 +0530
committerSteve Sakoman <steve@sakoman.com>2023-10-05 15:48:49 -1000
commit74b22a5e918b8d3a71748880e9ab2179f6486c71 (patch)
tree34e9308936273262d3e41baf73dff44bed960543
parent25073f9c0e0ca7ecfe8f38bf620147314c0d3ddc (diff)
downloadpoky-74b22a5e918b8d3a71748880e9ab2179f6486c71.tar.gz
go: Update fix for CVE-2023-24538 & CVE-2023-39318
Add missing files in fix for CVE-2023-24538 & CVE-2023-39318 Upstream Link - CVE-2023-24538: https://github.com/golang/go/commit/b1e3ecfa06b67014429a197ec5e134ce4303ad9b CVE-2023-39318: https://github.com/golang/go/commit/023b542edf38e2a1f87fcefb9f75ff2f99401b4c (From OE-Core rev: 0d8f7062d4fb5525f34427b1a7304f165bee0cfc) Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-devtools/go/go-1.17.13.inc3
-rw-r--r--meta/recipes-devtools/go/go-1.18/CVE-2023-24538_1.patch597
-rw-r--r--meta/recipes-devtools/go/go-1.18/CVE-2023-24538_2.patch (renamed from meta/recipes-devtools/go/go-1.18/CVE-2023-24538.patch)175
-rw-r--r--meta/recipes-devtools/go/go-1.21/CVE-2023-39318.patch44
4 files changed, 802 insertions, 17 deletions
diff --git a/meta/recipes-devtools/go/go-1.17.13.inc b/meta/recipes-devtools/go/go-1.17.13.inc
index ed2645bc12..461819d80f 100644
--- a/meta/recipes-devtools/go/go-1.17.13.inc
+++ b/meta/recipes-devtools/go/go-1.17.13.inc
@@ -29,7 +29,8 @@ SRC_URI += "\
29 file://CVE-2022-41722.patch \ 29 file://CVE-2022-41722.patch \
30 file://CVE-2023-24537.patch \ 30 file://CVE-2023-24537.patch \
31 file://CVE-2023-24534.patch \ 31 file://CVE-2023-24534.patch \
32 file://CVE-2023-24538.patch \ 32 file://CVE-2023-24538_1.patch \
33 file://CVE-2023-24538_2.patch \
33 file://CVE-2023-24540.patch \ 34 file://CVE-2023-24540.patch \
34 file://CVE-2023-24539.patch \ 35 file://CVE-2023-24539.patch \
35 file://CVE-2023-29404.patch \ 36 file://CVE-2023-29404.patch \
diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2023-24538_1.patch b/meta/recipes-devtools/go/go-1.18/CVE-2023-24538_1.patch
new file mode 100644
index 0000000000..bb0a416f46
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.18/CVE-2023-24538_1.patch
@@ -0,0 +1,597 @@
1From b1e4e8ec7e946ff2d3bb37ac99c5468ceb49c362 Mon Sep 17 00:00:00 2001
2From: Russ Cox <rsc@golang.org>
3Date: Thu, 20 May 2021 12:46:33 -0400
4Subject: [PATCH 1/2] html/template, text/template: implement break and
5 continue for range loops
6
7Break and continue for range loops was accepted as a proposal in June 2017.
8It was implemented in CL 66410 (Oct 2017)
9but then rolled back in CL 92155 (Feb 2018)
10because html/template changes had not been implemented.
11
12This CL reimplements break and continue in text/template
13and then adds support for them in html/template as well.
14
15Fixes #20531.
16
17Change-Id: I05330482a976f1c078b4b49c2287bd9031bb7616
18Reviewed-on: https://go-review.googlesource.com/c/go/+/321491
19Trust: Russ Cox <rsc@golang.org>
20Run-TryBot: Russ Cox <rsc@golang.org>
21TryBot-Result: Go Bot <gobot@golang.org>
22Reviewed-by: Rob Pike <r@golang.org>
23
24Upstream-Status: Backport from https://github.com/golang/go/commit/d0dd26a88c019d54f22463daae81e785f5867565
25CVE: CVE-2023-24538
26Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
27---
28 src/html/template/context.go | 4 ++
29 src/html/template/escape.go | 71 ++++++++++++++++++++++++++++++++++-
30 src/html/template/escape_test.go | 24 ++++++++++++
31 src/html/template/exec_test.go | 2 +
32 src/text/template/doc.go | 8 ++++
33 src/text/template/exec.go | 24 +++++++++++-
34 src/text/template/exec_test.go | 2 +
35 src/text/template/parse/lex.go | 13 ++++++-
36 src/text/template/parse/lex_test.go | 2 +
37 src/text/template/parse/node.go | 36 ++++++++++++++++++
38 src/text/template/parse/parse.go | 42 ++++++++++++++++++++-
39 src/text/template/parse/parse_test.go | 8 ++++
40 12 files changed, 232 insertions(+), 4 deletions(-)
41
42diff --git a/src/html/template/context.go b/src/html/template/context.go
43index f7d4849..aaa7d08 100644
44--- a/src/html/template/context.go
45+++ b/src/html/template/context.go
46@@ -6,6 +6,7 @@ package template
47
48 import (
49 "fmt"
50+ "text/template/parse"
51 )
52
53 // context describes the state an HTML parser must be in when it reaches the
54@@ -22,6 +23,7 @@ type context struct {
55 jsCtx jsCtx
56 attr attr
57 element element
58+ n parse.Node // for range break/continue
59 err *Error
60 }
61
62@@ -141,6 +143,8 @@ const (
63 // stateError is an infectious error state outside any valid
64 // HTML/CSS/JS construct.
65 stateError
66+ // stateDead marks unreachable code after a {{break}} or {{continue}}.
67+ stateDead
68 )
69
70 // isComment is true for any state that contains content meant for template
71diff --git a/src/html/template/escape.go b/src/html/template/escape.go
72index 8739735..6dea79c 100644
73--- a/src/html/template/escape.go
74+++ b/src/html/template/escape.go
75@@ -97,6 +97,15 @@ type escaper struct {
76 actionNodeEdits map[*parse.ActionNode][]string
77 templateNodeEdits map[*parse.TemplateNode]string
78 textNodeEdits map[*parse.TextNode][]byte
79+ // rangeContext holds context about the current range loop.
80+ rangeContext *rangeContext
81+}
82+
83+// rangeContext holds information about the current range loop.
84+type rangeContext struct {
85+ outer *rangeContext // outer loop
86+ breaks []context // context at each break action
87+ continues []context // context at each continue action
88 }
89
90 // makeEscaper creates a blank escaper for the given set.
91@@ -109,6 +118,7 @@ func makeEscaper(n *nameSpace) escaper {
92 map[*parse.ActionNode][]string{},
93 map[*parse.TemplateNode]string{},
94 map[*parse.TextNode][]byte{},
95+ nil,
96 }
97 }
98
99@@ -124,8 +134,16 @@ func (e *escaper) escape(c context, n parse.Node) context {
100 switch n := n.(type) {
101 case *parse.ActionNode:
102 return e.escapeAction(c, n)
103+ case *parse.BreakNode:
104+ c.n = n
105+ e.rangeContext.breaks = append(e.rangeContext.breaks, c)
106+ return context{state: stateDead}
107 case *parse.CommentNode:
108 return c
109+ case *parse.ContinueNode:
110+ c.n = n
111+ e.rangeContext.continues = append(e.rangeContext.breaks, c)
112+ return context{state: stateDead}
113 case *parse.IfNode:
114 return e.escapeBranch(c, &n.BranchNode, "if")
115 case *parse.ListNode:
116@@ -427,6 +445,12 @@ func join(a, b context, node parse.Node, nodeName string) context {
117 if b.state == stateError {
118 return b
119 }
120+ if a.state == stateDead {
121+ return b
122+ }
123+ if b.state == stateDead {
124+ return a
125+ }
126 if a.eq(b) {
127 return a
128 }
129@@ -466,14 +490,27 @@ func join(a, b context, node parse.Node, nodeName string) context {
130
131 // escapeBranch escapes a branch template node: "if", "range" and "with".
132 func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context {
133+ if nodeName == "range" {
134+ e.rangeContext = &rangeContext{outer: e.rangeContext}
135+ }
136 c0 := e.escapeList(c, n.List)
137- if nodeName == "range" && c0.state != stateError {
138+ if nodeName == "range" {
139+ if c0.state != stateError {
140+ c0 = joinRange(c0, e.rangeContext)
141+ }
142+ e.rangeContext = e.rangeContext.outer
143+ if c0.state == stateError {
144+ return c0
145+ }
146+
147 // The "true" branch of a "range" node can execute multiple times.
148 // We check that executing n.List once results in the same context
149 // as executing n.List twice.
150+ e.rangeContext = &rangeContext{outer: e.rangeContext}
151 c1, _ := e.escapeListConditionally(c0, n.List, nil)
152 c0 = join(c0, c1, n, nodeName)
153 if c0.state == stateError {
154+ e.rangeContext = e.rangeContext.outer
155 // Make clear that this is a problem on loop re-entry
156 // since developers tend to overlook that branch when
157 // debugging templates.
158@@ -481,11 +518,39 @@ func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string)
159 c0.err.Description = "on range loop re-entry: " + c0.err.Description
160 return c0
161 }
162+ c0 = joinRange(c0, e.rangeContext)
163+ e.rangeContext = e.rangeContext.outer
164+ if c0.state == stateError {
165+ return c0
166+ }
167 }
168 c1 := e.escapeList(c, n.ElseList)
169 return join(c0, c1, n, nodeName)
170 }
171
172+func joinRange(c0 context, rc *rangeContext) context {
173+ // Merge contexts at break and continue statements into overall body context.
174+ // In theory we could treat breaks differently from continues, but for now it is
175+ // enough to treat them both as going back to the start of the loop (which may then stop).
176+ for _, c := range rc.breaks {
177+ c0 = join(c0, c, c.n, "range")
178+ if c0.state == stateError {
179+ c0.err.Line = c.n.(*parse.BreakNode).Line
180+ c0.err.Description = "at range loop break: " + c0.err.Description
181+ return c0
182+ }
183+ }
184+ for _, c := range rc.continues {
185+ c0 = join(c0, c, c.n, "range")
186+ if c0.state == stateError {
187+ c0.err.Line = c.n.(*parse.ContinueNode).Line
188+ c0.err.Description = "at range loop continue: " + c0.err.Description
189+ return c0
190+ }
191+ }
192+ return c0
193+}
194+
195 // escapeList escapes a list template node.
196 func (e *escaper) escapeList(c context, n *parse.ListNode) context {
197 if n == nil {
198@@ -493,6 +558,9 @@ func (e *escaper) escapeList(c context, n *parse.ListNode) context {
199 }
200 for _, m := range n.Nodes {
201 c = e.escape(c, m)
202+ if c.state == stateDead {
203+ break
204+ }
205 }
206 return c
207 }
208@@ -503,6 +571,7 @@ func (e *escaper) escapeList(c context, n *parse.ListNode) context {
209 // which is the same as whether e was updated.
210 func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) {
211 e1 := makeEscaper(e.ns)
212+ e1.rangeContext = e.rangeContext
213 // Make type inferences available to f.
214 for k, v := range e.output {
215 e1.output[k] = v
216diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
217index fbc84a7..3b0aa8c 100644
218--- a/src/html/template/escape_test.go
219+++ b/src/html/template/escape_test.go
220@@ -920,6 +920,22 @@ func TestErrors(t *testing.T) {
221 "<a href='/foo?{{range .Items}}&{{.K}}={{.V}}{{end}}'>",
222 "",
223 },
224+ {
225+ "{{range .Items}}<a{{if .X}}{{end}}>{{end}}",
226+ "",
227+ },
228+ {
229+ "{{range .Items}}<a{{if .X}}{{end}}>{{continue}}{{end}}",
230+ "",
231+ },
232+ {
233+ "{{range .Items}}<a{{if .X}}{{end}}>{{break}}{{end}}",
234+ "",
235+ },
236+ {
237+ "{{range .Items}}<a{{if .X}}{{end}}>{{if .X}}{{break}}{{end}}{{end}}",
238+ "",
239+ },
240 // Error cases.
241 {
242 "{{if .Cond}}<a{{end}}",
243@@ -956,6 +972,14 @@ func TestErrors(t *testing.T) {
244 "z:2:8: on range loop re-entry: {{range}} branches",
245 },
246 {
247+ "{{range .Items}}<a{{if .X}}{{break}}{{end}}>{{end}}",
248+ "z:1:29: at range loop break: {{range}} branches end in different contexts",
249+ },
250+ {
251+ "{{range .Items}}<a{{if .X}}{{continue}}{{end}}>{{end}}",
252+ "z:1:29: at range loop continue: {{range}} branches end in different contexts",
253+ },
254+ {
255 "<a b=1 c={{.H}}",
256 "z: ends in a non-text context: {stateAttr delimSpaceOrTagEnd",
257 },
258diff --git a/src/html/template/exec_test.go b/src/html/template/exec_test.go
259index 8885873..523340b 100644
260--- a/src/html/template/exec_test.go
261+++ b/src/html/template/exec_test.go
262@@ -567,6 +567,8 @@ var execTests = []execTest{
263 {"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true},
264 {"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true},
265 {"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
266+ {"range []int break else", "{{range .SI}}-{{.}}-{{break}}NOTREACHED{{else}}EMPTY{{end}}", "-3-", tVal, true},
267+ {"range []int continue else", "{{range .SI}}-{{.}}-{{continue}}NOTREACHED{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true},
268 {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true},
269 {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true},
270 {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true},
271diff --git a/src/text/template/doc.go b/src/text/template/doc.go
272index 7b30294..0228b15 100644
273--- a/src/text/template/doc.go
274+++ b/src/text/template/doc.go
275@@ -112,6 +112,14 @@ data, defined in detail in the corresponding sections that follow.
276 T0 is executed; otherwise, dot is set to the successive elements
277 of the array, slice, or map and T1 is executed.
278
279+ {{break}}
280+ The innermost {{range pipeline}} loop is ended early, stopping the
281+ current iteration and bypassing all remaining iterations.
282+
283+ {{continue}}
284+ The current iteration of the innermost {{range pipeline}} loop is
285+ stopped, and the loop starts the next iteration.
286+
287 {{template "name"}}
288 The template with the specified name is executed with nil data.
289
290diff --git a/src/text/template/exec.go b/src/text/template/exec.go
291index 5ad3b4e..92fa9d9 100644
292--- a/src/text/template/exec.go
293+++ b/src/text/template/exec.go
294@@ -5,6 +5,7 @@
295 package template
296
297 import (
298+ "errors"
299 "fmt"
300 "internal/fmtsort"
301 "io"
302@@ -243,6 +244,12 @@ func (t *Template) DefinedTemplates() string {
303 return b.String()
304 }
305
306+// Sentinel errors for use with panic to signal early exits from range loops.
307+var (
308+ walkBreak = errors.New("break")
309+ walkContinue = errors.New("continue")
310+)
311+
312 // Walk functions step through the major pieces of the template structure,
313 // generating output as they go.
314 func (s *state) walk(dot reflect.Value, node parse.Node) {
315@@ -255,7 +262,11 @@ func (s *state) walk(dot reflect.Value, node parse.Node) {
316 if len(node.Pipe.Decl) == 0 {
317 s.printValue(node, val)
318 }
319+ case *parse.BreakNode:
320+ panic(walkBreak)
321 case *parse.CommentNode:
322+ case *parse.ContinueNode:
323+ panic(walkContinue)
324 case *parse.IfNode:
325 s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
326 case *parse.ListNode:
327@@ -334,6 +345,11 @@ func isTrue(val reflect.Value) (truth, ok bool) {
328
329 func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
330 s.at(r)
331+ defer func() {
332+ if r := recover(); r != nil && r != walkBreak {
333+ panic(r)
334+ }
335+ }()
336 defer s.pop(s.mark())
337 val, _ := indirect(s.evalPipeline(dot, r.Pipe))
338 // mark top of stack before any variables in the body are pushed.
339@@ -347,8 +363,14 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
340 if len(r.Pipe.Decl) > 1 {
341 s.setTopVar(2, index)
342 }
343+ defer s.pop(mark)
344+ defer func() {
345+ // Consume panic(walkContinue)
346+ if r := recover(); r != nil && r != walkContinue {
347+ panic(r)
348+ }
349+ }()
350 s.walk(elem, r.List)
351- s.pop(mark)
352 }
353 switch val.Kind() {
354 case reflect.Array, reflect.Slice:
355diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go
356index ef52164..586af55 100644
357--- a/src/text/template/exec_test.go
358+++ b/src/text/template/exec_test.go
359@@ -564,6 +564,8 @@ var execTests = []execTest{
360 {"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true},
361 {"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true},
362 {"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
363+ {"range []int break else", "{{range .SI}}-{{.}}-{{break}}NOTREACHED{{else}}EMPTY{{end}}", "-3-", tVal, true},
364+ {"range []int continue else", "{{range .SI}}-{{.}}-{{continue}}NOTREACHED{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true},
365 {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true},
366 {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true},
367 {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true},
368diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go
369index 6784071..95e3377 100644
370--- a/src/text/template/parse/lex.go
371+++ b/src/text/template/parse/lex.go
372@@ -62,6 +62,8 @@ const (
373 // Keywords appear after all the rest.
374 itemKeyword // used only to delimit the keywords
375 itemBlock // block keyword
376+ itemBreak // break keyword
377+ itemContinue // continue keyword
378 itemDot // the cursor, spelled '.'
379 itemDefine // define keyword
380 itemElse // else keyword
381@@ -76,6 +78,8 @@ const (
382 var key = map[string]itemType{
383 ".": itemDot,
384 "block": itemBlock,
385+ "break": itemBreak,
386+ "continue": itemContinue,
387 "define": itemDefine,
388 "else": itemElse,
389 "end": itemEnd,
390@@ -119,6 +123,8 @@ type lexer struct {
391 parenDepth int // nesting depth of ( ) exprs
392 line int // 1+number of newlines seen
393 startLine int // start line of this item
394+ breakOK bool // break keyword allowed
395+ continueOK bool // continue keyword allowed
396 }
397
398 // next returns the next rune in the input.
399@@ -461,7 +467,12 @@ Loop:
400 }
401 switch {
402 case key[word] > itemKeyword:
403- l.emit(key[word])
404+ item := key[word]
405+ if item == itemBreak && !l.breakOK || item == itemContinue && !l.continueOK {
406+ l.emit(itemIdentifier)
407+ } else {
408+ l.emit(item)
409+ }
410 case word[0] == '.':
411 l.emit(itemField)
412 case word == "true", word == "false":
413diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go
414index 6510eed..df6aabf 100644
415--- a/src/text/template/parse/lex_test.go
416+++ b/src/text/template/parse/lex_test.go
417@@ -35,6 +35,8 @@ var itemName = map[itemType]string{
418 // keywords
419 itemDot: ".",
420 itemBlock: "block",
421+ itemBreak: "break",
422+ itemContinue: "continue",
423 itemDefine: "define",
424 itemElse: "else",
425 itemIf: "if",
426diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go
427index 177482f..4726822 100644
428--- a/src/text/template/parse/node.go
429+++ b/src/text/template/parse/node.go
430@@ -71,6 +71,8 @@ const (
431 NodeVariable // A $ variable.
432 NodeWith // A with action.
433 NodeComment // A comment.
434+ NodeBreak // A break action.
435+ NodeContinue // A continue action.
436 )
437
438 // Nodes.
439@@ -907,6 +909,40 @@ func (i *IfNode) Copy() Node {
440 return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
441 }
442
443+// BreakNode represents a {{break}} action.
444+type BreakNode struct {
445+ tr *Tree
446+ NodeType
447+ Pos
448+ Line int
449+}
450+
451+func (t *Tree) newBreak(pos Pos, line int) *BreakNode {
452+ return &BreakNode{tr: t, NodeType: NodeBreak, Pos: pos, Line: line}
453+}
454+
455+func (b *BreakNode) Copy() Node { return b.tr.newBreak(b.Pos, b.Line) }
456+func (b *BreakNode) String() string { return "{{break}}" }
457+func (b *BreakNode) tree() *Tree { return b.tr }
458+func (b *BreakNode) writeTo(sb *strings.Builder) { sb.WriteString("{{break}}") }
459+
460+// ContinueNode represents a {{continue}} action.
461+type ContinueNode struct {
462+ tr *Tree
463+ NodeType
464+ Pos
465+ Line int
466+}
467+
468+func (t *Tree) newContinue(pos Pos, line int) *ContinueNode {
469+ return &ContinueNode{tr: t, NodeType: NodeContinue, Pos: pos, Line: line}
470+}
471+
472+func (c *ContinueNode) Copy() Node { return c.tr.newContinue(c.Pos, c.Line) }
473+func (c *ContinueNode) String() string { return "{{continue}}" }
474+func (c *ContinueNode) tree() *Tree { return c.tr }
475+func (c *ContinueNode) writeTo(sb *strings.Builder) { sb.WriteString("{{continue}}") }
476+
477 // RangeNode represents a {{range}} action and its commands.
478 type RangeNode struct {
479 BranchNode
480diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go
481index 1a63961..d92bed5 100644
482--- a/src/text/template/parse/parse.go
483+++ b/src/text/template/parse/parse.go
484@@ -31,6 +31,7 @@ type Tree struct {
485 vars []string // variables defined at the moment.
486 treeSet map[string]*Tree
487 actionLine int // line of left delim starting action
488+ rangeDepth int
489 mode Mode
490 }
491
492@@ -224,6 +225,8 @@ func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer, treeSet ma
493 t.vars = []string{"$"}
494 t.funcs = funcs
495 t.treeSet = treeSet
496+ lex.breakOK = !t.hasFunction("break")
497+ lex.continueOK = !t.hasFunction("continue")
498 }
499
500 // stopParse terminates parsing.
501@@ -386,6 +389,10 @@ func (t *Tree) action() (n Node) {
502 switch token := t.nextNonSpace(); token.typ {
503 case itemBlock:
504 return t.blockControl()
505+ case itemBreak:
506+ return t.breakControl(token.pos, token.line)
507+ case itemContinue:
508+ return t.continueControl(token.pos, token.line)
509 case itemElse:
510 return t.elseControl()
511 case itemEnd:
512@@ -405,6 +412,32 @@ func (t *Tree) action() (n Node) {
513 return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim))
514 }
515
516+// Break:
517+// {{break}}
518+// Break keyword is past.
519+func (t *Tree) breakControl(pos Pos, line int) Node {
520+ if token := t.next(); token.typ != itemRightDelim {
521+ t.unexpected(token, "in {{break}}")
522+ }
523+ if t.rangeDepth == 0 {
524+ t.errorf("{{break}} outside {{range}}")
525+ }
526+ return t.newBreak(pos, line)
527+}
528+
529+// Continue:
530+// {{continue}}
531+// Continue keyword is past.
532+func (t *Tree) continueControl(pos Pos, line int) Node {
533+ if token := t.next(); token.typ != itemRightDelim {
534+ t.unexpected(token, "in {{continue}}")
535+ }
536+ if t.rangeDepth == 0 {
537+ t.errorf("{{continue}} outside {{range}}")
538+ }
539+ return t.newContinue(pos, line)
540+}
541+
542 // Pipeline:
543 // declarations? command ('|' command)*
544 func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) {
545@@ -480,8 +513,14 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context string) {
546 func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
547 defer t.popVars(len(t.vars))
548 pipe = t.pipeline(context, itemRightDelim)
549+ if context == "range" {
550+ t.rangeDepth++
551+ }
552 var next Node
553 list, next = t.itemList()
554+ if context == "range" {
555+ t.rangeDepth--
556+ }
557 switch next.Type() {
558 case nodeEnd: //done
559 case nodeElse:
560@@ -523,7 +562,8 @@ func (t *Tree) ifControl() Node {
561 // {{range pipeline}} itemList {{else}} itemList {{end}}
562 // Range keyword is past.
563 func (t *Tree) rangeControl() Node {
564- return t.newRange(t.parseControl(false, "range"))
565+ r := t.newRange(t.parseControl(false, "range"))
566+ return r
567 }
568
569 // With:
570diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go
571index 9b1be27..c3679a0 100644
572--- a/src/text/template/parse/parse_test.go
573+++ b/src/text/template/parse/parse_test.go
574@@ -230,6 +230,10 @@ var parseTests = []parseTest{
575 `{{range $x := .SI}}{{.}}{{end}}`},
576 {"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
577 `{{range $x, $y := .SI}}{{.}}{{end}}`},
578+ {"range with break", "{{range .SI}}{{.}}{{break}}{{end}}", noError,
579+ `{{range .SI}}{{.}}{{break}}{{end}}`},
580+ {"range with continue", "{{range .SI}}{{.}}{{continue}}{{end}}", noError,
581+ `{{range .SI}}{{.}}{{continue}}{{end}}`},
582 {"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError,
583 `{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`},
584 {"template", "{{template `x`}}", noError,
585@@ -279,6 +283,10 @@ var parseTests = []parseTest{
586 {"adjacent args", "{{printf 3`x`}}", hasError, ""},
587 {"adjacent args with .", "{{printf `x`.}}", hasError, ""},
588 {"extra end after if", "{{if .X}}a{{else if .Y}}b{{end}}{{end}}", hasError, ""},
589+ {"break outside range", "{{range .}}{{end}} {{break}}", hasError, ""},
590+ {"continue outside range", "{{range .}}{{end}} {{continue}}", hasError, ""},
591+ {"break in range else", "{{range .}}{{else}}{{break}}{{end}}", hasError, ""},
592+ {"continue in range else", "{{range .}}{{else}}{{continue}}{{end}}", hasError, ""},
593 // Other kinds of assignments and operators aren't available yet.
594 {"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
595 {"bug0b", "{{$x += 1}}{{$x}}", hasError, ""},
596--
5972.7.4
diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2023-24538.patch b/meta/recipes-devtools/go/go-1.18/CVE-2023-24538_2.patch
index 502486befc..f94f0f55c7 100644
--- a/meta/recipes-devtools/go/go-1.18/CVE-2023-24538.patch
+++ b/meta/recipes-devtools/go/go-1.18/CVE-2023-24538_2.patch
@@ -1,7 +1,7 @@
1From 07cc3b8711a8efbb5885f56dd90d854049ad2f7d Mon Sep 17 00:00:00 2001 1From 07cc3b8711a8efbb5885f56dd90d854049ad2f7d Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com> 2From: Roland Shoemaker <bracewell@google.com>
3Date: Mon, 20 Mar 2023 11:01:13 -0700 3Date: Mon, 20 Mar 2023 11:01:13 -0700
4Subject: [PATCH] html/template: disallow actions in JS template literals 4Subject: [PATCH 2/2] html/template: disallow actions in JS template literals
5 5
6ECMAScript 6 introduced template literals[0][1] which are delimited with 6ECMAScript 6 introduced template literals[0][1] which are delimited with
7backticks. These need to be escaped in a similar fashion to the 7backticks. These need to be escaped in a similar fashion to the
@@ -52,12 +52,15 @@ CVE: CVE-2023-24538
52Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> 52Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
53--- 53---
54 src/html/template/context.go | 2 ++ 54 src/html/template/context.go | 2 ++
55 src/html/template/error.go | 13 +++++++++++++ 55 src/html/template/error.go | 13 ++++++++
56 src/html/template/escape.go | 11 +++++++++++ 56 src/html/template/escape.go | 11 +++++++
57 src/html/template/escape_test.go | 66 ++++++++++++++++++++++-----------------
57 src/html/template/js.go | 2 ++ 58 src/html/template/js.go | 2 ++
58 src/html/template/jsctx_string.go | 9 +++++++++ 59 src/html/template/js_test.go | 2 +-
59 src/html/template/transition.go | 7 ++++++- 60 src/html/template/jsctx_string.go | 9 ++++++
60 6 files changed, 43 insertions(+), 1 deletion(-) 61 src/html/template/state_string.go | 37 ++++++++++++++++++++--
62 src/html/template/transition.go | 7 ++++-
63 9 files changed, 116 insertions(+), 33 deletions(-)
61 64
62diff --git a/src/html/template/context.go b/src/html/template/context.go 65diff --git a/src/html/template/context.go b/src/html/template/context.go
63index f7d4849..0b65313 100644 66index f7d4849..0b65313 100644
@@ -125,6 +128,104 @@ index 8739735..ca078f4 100644
125 case stateJSRegexp: 128 case stateJSRegexp:
126 s = append(s, "_html_template_jsregexpescaper") 129 s = append(s, "_html_template_jsregexpescaper")
127 case stateCSS: 130 case stateCSS:
131diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
132index 3b0aa8c..a695b17 100644
133--- a/src/html/template/escape_test.go
134+++ b/src/html/template/escape_test.go
135@@ -681,35 +681,31 @@ func TestEscape(t *testing.T) {
136 }
137
138 for _, test := range tests {
139- tmpl := New(test.name)
140- tmpl = Must(tmpl.Parse(test.input))
141- // Check for bug 6459: Tree field was not set in Parse.
142- if tmpl.Tree != tmpl.text.Tree {
143- t.Errorf("%s: tree not set properly", test.name)
144- continue
145- }
146- b := new(bytes.Buffer)
147- if err := tmpl.Execute(b, data); err != nil {
148- t.Errorf("%s: template execution failed: %s", test.name, err)
149- continue
150- }
151- if w, g := test.output, b.String(); w != g {
152- t.Errorf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
153- continue
154- }
155- b.Reset()
156- if err := tmpl.Execute(b, pdata); err != nil {
157- t.Errorf("%s: template execution failed for pointer: %s", test.name, err)
158- continue
159- }
160- if w, g := test.output, b.String(); w != g {
161- t.Errorf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g)
162- continue
163- }
164- if tmpl.Tree != tmpl.text.Tree {
165- t.Errorf("%s: tree mismatch", test.name)
166- continue
167- }
168+ t.Run(test.name, func(t *testing.T) {
169+ tmpl := New(test.name)
170+ tmpl = Must(tmpl.Parse(test.input))
171+ // Check for bug 6459: Tree field was not set in Parse.
172+ if tmpl.Tree != tmpl.text.Tree {
173+ t.Fatalf("%s: tree not set properly", test.name)
174+ }
175+ b := new(strings.Builder)
176+ if err := tmpl.Execute(b, data); err != nil {
177+ t.Fatalf("%s: template execution failed: %s", test.name, err)
178+ }
179+ if w, g := test.output, b.String(); w != g {
180+ t.Fatalf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
181+ }
182+ b.Reset()
183+ if err := tmpl.Execute(b, pdata); err != nil {
184+ t.Fatalf("%s: template execution failed for pointer: %s", test.name, err)
185+ }
186+ if w, g := test.output, b.String(); w != g {
187+ t.Fatalf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g)
188+ }
189+ if tmpl.Tree != tmpl.text.Tree {
190+ t.Fatalf("%s: tree mismatch", test.name)
191+ }
192+ })
193 }
194 }
195
196@@ -936,6 +932,10 @@ func TestErrors(t *testing.T) {
197 "{{range .Items}}<a{{if .X}}{{end}}>{{if .X}}{{break}}{{end}}{{end}}",
198 "",
199 },
200+ {
201+ "<script>var a = `${a+b}`</script>`",
202+ "",
203+ },
204 // Error cases.
205 {
206 "{{if .Cond}}<a{{end}}",
207@@ -1082,6 +1082,10 @@ func TestErrors(t *testing.T) {
208 // html is allowed since it is the last command in the pipeline, but urlquery is not.
209 `predefined escaper "urlquery" disallowed in template`,
210 },
211+ {
212+ "<script>var tmpl = `asd {{.}}`;</script>",
213+ `{{.}} appears in a JS template literal`,
214+ },
215 }
216 for _, test := range tests {
217 buf := new(bytes.Buffer)
218@@ -1304,6 +1308,10 @@ func TestEscapeText(t *testing.T) {
219 context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
220 },
221 {
222+ "<a onclick=\"`foo",
223+ context{state: stateJSBqStr, delim: delimDoubleQuote, attr: attrScript},
224+ },
225+ {
226 `<A ONCLICK="'`,
227 context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
228 },
128diff --git a/src/html/template/js.go b/src/html/template/js.go 229diff --git a/src/html/template/js.go b/src/html/template/js.go
129index ea9c183..b888eaf 100644 230index ea9c183..b888eaf 100644
130--- a/src/html/template/js.go 231--- a/src/html/template/js.go
@@ -145,6 +246,19 @@ index ea9c183..b888eaf 100644
145 '+': `\u002b`, 246 '+': `\u002b`,
146 '/': `\/`, 247 '/': `\/`,
147 '<': `\u003c`, 248 '<': `\u003c`,
249diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go
250index d7ee47b..7d963ae 100644
251--- a/src/html/template/js_test.go
252+++ b/src/html/template/js_test.go
253@@ -292,7 +292,7 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
254 `0123456789:;\u003c=\u003e?` +
255 `@ABCDEFGHIJKLMNO` +
256 `PQRSTUVWXYZ[\\]^_` +
257- "`abcdefghijklmno" +
258+ "\\u0060abcdefghijklmno" +
259 "pqrstuvwxyz{|}~\u007f" +
260 "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
261 },
148diff --git a/src/html/template/jsctx_string.go b/src/html/template/jsctx_string.go 262diff --git a/src/html/template/jsctx_string.go b/src/html/template/jsctx_string.go
149index dd1d87e..2394893 100644 263index dd1d87e..2394893 100644
150--- a/src/html/template/jsctx_string.go 264--- a/src/html/template/jsctx_string.go
@@ -165,6 +279,55 @@ index dd1d87e..2394893 100644
165 const _jsCtx_name = "jsCtxRegexpjsCtxDivOpjsCtxUnknown" 279 const _jsCtx_name = "jsCtxRegexpjsCtxDivOpjsCtxUnknown"
166 280
167 var _jsCtx_index = [...]uint8{0, 11, 21, 33} 281 var _jsCtx_index = [...]uint8{0, 11, 21, 33}
282diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go
283index 05104be..6fb1a6e 100644
284--- a/src/html/template/state_string.go
285+++ b/src/html/template/state_string.go
286@@ -4,9 +4,42 @@ package template
287
288 import "strconv"
289
290-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateError"
291+func _() {
292+ // An "invalid array index" compiler error signifies that the constant values have changed.
293+ // Re-run the stringer command to generate them again.
294+ var x [1]struct{}
295+ _ = x[stateText-0]
296+ _ = x[stateTag-1]
297+ _ = x[stateAttrName-2]
298+ _ = x[stateAfterName-3]
299+ _ = x[stateBeforeValue-4]
300+ _ = x[stateHTMLCmt-5]
301+ _ = x[stateRCDATA-6]
302+ _ = x[stateAttr-7]
303+ _ = x[stateURL-8]
304+ _ = x[stateSrcset-9]
305+ _ = x[stateJS-10]
306+ _ = x[stateJSDqStr-11]
307+ _ = x[stateJSSqStr-12]
308+ _ = x[stateJSBqStr-13]
309+ _ = x[stateJSRegexp-14]
310+ _ = x[stateJSBlockCmt-15]
311+ _ = x[stateJSLineCmt-16]
312+ _ = x[stateCSS-17]
313+ _ = x[stateCSSDqStr-18]
314+ _ = x[stateCSSSqStr-19]
315+ _ = x[stateCSSDqURL-20]
316+ _ = x[stateCSSSqURL-21]
317+ _ = x[stateCSSURL-22]
318+ _ = x[stateCSSBlockCmt-23]
319+ _ = x[stateCSSLineCmt-24]
320+ _ = x[stateError-25]
321+ _ = x[stateDead-26]
322+}
323+
324+const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
325
326-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 155, 170, 184, 192, 205, 218, 231, 244, 255, 271, 286, 296}
327+var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 204, 217, 230, 243, 256, 267, 283, 298, 308, 317}
328
329 func (i state) String() string {
330 if i >= state(len(_state_index)-1) {
168diff --git a/src/html/template/transition.go b/src/html/template/transition.go 331diff --git a/src/html/template/transition.go b/src/html/template/transition.go
169index 06df679..92eb351 100644 332index 06df679..92eb351 100644
170--- a/src/html/template/transition.go 333--- a/src/html/template/transition.go
diff --git a/meta/recipes-devtools/go/go-1.21/CVE-2023-39318.patch b/meta/recipes-devtools/go/go-1.21/CVE-2023-39318.patch
index 85c6ec97c8..503a4a288a 100644
--- a/meta/recipes-devtools/go/go-1.21/CVE-2023-39318.patch
+++ b/meta/recipes-devtools/go/go-1.21/CVE-2023-39318.patch
@@ -32,11 +32,11 @@ CVE: CVE-2023-39318
32Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> 32Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
33--- 33---
34 src/html/template/context.go | 6 ++- 34 src/html/template/context.go | 6 ++-
35 src/html/template/escape.go | 5 +- 35 src/html/template/escape.go | 5 ++-
36 src/html/template/escape_test.go | 10 ++++ 36 src/html/template/escape_test.go | 10 +++++
37 src/html/template/state_string.go | 4 +- 37 src/html/template/state_string.go | 26 +++++++------
38 src/html/template/transition.go | 80 ++++++++++++++++++++----------- 38 src/html/template/transition.go | 80 +++++++++++++++++++++++++--------------
39 5 files changed, 72 insertions(+), 33 deletions(-) 39 5 files changed, 84 insertions(+), 43 deletions(-)
40 40
41diff --git a/src/html/template/context.go b/src/html/template/context.go 41diff --git a/src/html/template/context.go b/src/html/template/context.go
42index f5f44a1..feb6517 100644 42index f5f44a1..feb6517 100644
@@ -105,14 +105,38 @@ diff --git a/src/html/template/state_string.go b/src/html/template/state_string.
105index 05104be..b5cfe70 100644 105index 05104be..b5cfe70 100644
106--- a/src/html/template/state_string.go 106--- a/src/html/template/state_string.go
107+++ b/src/html/template/state_string.go 107+++ b/src/html/template/state_string.go
108@@ -4,9 +4,9 @@ package template 108@@ -25,21 +25,23 @@ func _() {
109 109 _ = x[stateJSRegexp-14]
110 import "strconv" 110 _ = x[stateJSBlockCmt-15]
111 _ = x[stateJSLineCmt-16]
112- _ = x[stateCSS-17]
113- _ = x[stateCSSDqStr-18]
114- _ = x[stateCSSSqStr-19]
115- _ = x[stateCSSDqURL-20]
116- _ = x[stateCSSSqURL-21]
117- _ = x[stateCSSURL-22]
118- _ = x[stateCSSBlockCmt-23]
119- _ = x[stateCSSLineCmt-24]
120- _ = x[stateError-25]
121- _ = x[stateDead-26]
122+ _ = x[stateJSHTMLOpenCmt-17]
123+ _ = x[stateJSHTMLCloseCmt-18]
124+ _ = x[stateCSS-19]
125+ _ = x[stateCSSDqStr-20]
126+ _ = x[stateCSSSqStr-21]
127+ _ = x[stateCSSDqURL-22]
128+ _ = x[stateCSSSqURL-23]
129+ _ = x[stateCSSURL-24]
130+ _ = x[stateCSSBlockCmt-25]
131+ _ = x[stateCSSLineCmt-26]
132+ _ = x[stateError-27]
133+ _ = x[stateDead-28]
134 }
111 135
112-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateError" 136-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
113+const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead" 137+const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
114 138
115-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 155, 170, 184, 192, 205, 218, 231, 244, 255, 271, 286, 296} 139-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 204, 217, 230, 243, 256, 267, 283, 298, 308, 317}
116+var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 214, 233, 241, 254, 267, 280, 293, 304, 320, 335, 345, 354} 140+var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 214, 233, 241, 254, 267, 280, 293, 304, 320, 335, 345, 354}
117 141
118 func (i state) String() string { 142 func (i state) String() string {