diff options
author | Shubham Kulkarni <skulkarni@mvista.com> | 2023-10-03 23:28:51 +0530 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2023-10-13 05:47:07 -1000 |
commit | 43ffc2a5e70f8936742b632263d06f1f63e326fb (patch) | |
tree | 67c097a7aca6cc0c093f419a099fe94b1970374c /meta/recipes-devtools/go | |
parent | a9d6f0c153acf62ff7eae3141e337194e2429e09 (diff) | |
download | poky-43ffc2a5e70f8936742b632263d06f1f63e326fb.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: cc6f7a8e8805058aababb65e10da7ed2e3d77461)
Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta/recipes-devtools/go')
-rw-r--r-- | meta/recipes-devtools/go/go-1.14.inc | 5 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch | 4 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch | 447 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-24538_3.patch | 393 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch | 497 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-24538_5.patch | 585 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch (renamed from meta/recipes-devtools/go/go-1.14/CVE-2023-24538-3.patch) | 175 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-39318.patch | 38 |
8 files changed, 2124 insertions, 20 deletions
diff --git a/meta/recipes-devtools/go/go-1.14.inc b/meta/recipes-devtools/go/go-1.14.inc index be63f64825..091b778de8 100644 --- a/meta/recipes-devtools/go/go-1.14.inc +++ b/meta/recipes-devtools/go/go-1.14.inc | |||
@@ -60,7 +60,10 @@ SRC_URI += "\ | |||
60 | file://CVE-2023-24534.patch \ | 60 | file://CVE-2023-24534.patch \ |
61 | file://CVE-2023-24538-1.patch \ | 61 | file://CVE-2023-24538-1.patch \ |
62 | file://CVE-2023-24538-2.patch \ | 62 | file://CVE-2023-24538-2.patch \ |
63 | file://CVE-2023-24538-3.patch \ | 63 | file://CVE-2023-24538_3.patch \ |
64 | file://CVE-2023-24538_4.patch \ | ||
65 | file://CVE-2023-24538_5.patch \ | ||
66 | file://CVE-2023-24538_6.patch \ | ||
64 | file://CVE-2023-24539.patch \ | 67 | file://CVE-2023-24539.patch \ |
65 | file://CVE-2023-24540.patch \ | 68 | file://CVE-2023-24540.patch \ |
66 | file://CVE-2023-29405-1.patch \ | 69 | file://CVE-2023-29405-1.patch \ |
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch index eda26e5ff6..23c5075e41 100644 --- a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch | |||
@@ -1,7 +1,7 @@ | |||
1 | From 8acd01094d9ee17f6e763a61e49a8a808b3a9ddb Mon Sep 17 00:00:00 2001 | 1 | From 8acd01094d9ee17f6e763a61e49a8a808b3a9ddb Mon Sep 17 00:00:00 2001 |
2 | From: Brad Fitzpatrick <bradfitz@golang.org> | 2 | From: Brad Fitzpatrick <bradfitz@golang.org> |
3 | Date: Mon, 2 Aug 2021 14:55:51 -0700 | 3 | Date: Mon, 2 Aug 2021 14:55:51 -0700 |
4 | Subject: [PATCH 1/3] net/netip: add new IP address package | 4 | Subject: [PATCH 1/6] net/netip: add new IP address package |
5 | 5 | ||
6 | Co-authored-by: Alex Willmer <alex@moreati.org.uk> (GitHub @moreati) | 6 | Co-authored-by: Alex Willmer <alex@moreati.org.uk> (GitHub @moreati) |
7 | Co-authored-by: Alexander Yastrebov <yastrebov.alex@gmail.com> | 7 | Co-authored-by: Alexander Yastrebov <yastrebov.alex@gmail.com> |
@@ -31,7 +31,7 @@ Trust: Brad Fitzpatrick <bradfitz@golang.org> | |||
31 | 31 | ||
32 | Dependency Patch #1 | 32 | Dependency Patch #1 |
33 | 33 | ||
34 | Upstream-Status: Backport [https://github.com/golang/go/commit/a59e33224e42d60a97fa720a45e1b74eb6aaa3d0] | 34 | Upstream-Status: Backport from https://github.com/golang/go/commit/a59e33224e42d60a97fa720a45e1b74eb6aaa3d0 |
35 | CVE: CVE-2023-24538 | 35 | CVE: CVE-2023-24538 |
36 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> | 36 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> |
37 | --- | 37 | --- |
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch index 5036f2890b..f200c41e16 100644 --- a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch | |||
@@ -1,7 +1,7 @@ | |||
1 | From 6fc21505614f36178df0dad7034b6b8e3f7588d5 Mon Sep 17 00:00:00 2001 | 1 | From 6fc21505614f36178df0dad7034b6b8e3f7588d5 Mon Sep 17 00:00:00 2001 |
2 | From: empijei <robclap8@gmail.com> | 2 | From: empijei <robclap8@gmail.com> |
3 | Date: Fri, 27 Mar 2020 19:27:55 +0100 | 3 | Date: Fri, 27 Mar 2020 19:27:55 +0100 |
4 | Subject: [PATCH 2/3] html/template,text/template: switch to Unicode escapes | 4 | Subject: [PATCH 2/6] html/template,text/template: switch to Unicode escapes |
5 | for JSON compatibility | 5 | for JSON compatibility |
6 | MIME-Version: 1.0 | 6 | MIME-Version: 1.0 |
7 | Content-Type: text/plain; charset=UTF-8 | 7 | Content-Type: text/plain; charset=UTF-8 |
@@ -31,10 +31,238 @@ Upstream-Status: Backport from https://github.com/golang/go/commit/d4d298040d072 | |||
31 | CVE: CVE-2023-24538 | 31 | CVE: CVE-2023-24538 |
32 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> | 32 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> |
33 | --- | 33 | --- |
34 | src/html/template/js.go | 70 +++++++++++++++++++++++++++------------------- | 34 | src/html/template/content_test.go | 70 +++++++++++++++++++------------------- |
35 | src/text/template/funcs.go | 8 +++--- | 35 | src/html/template/escape_test.go | 6 ++-- |
36 | 2 files changed, 46 insertions(+), 32 deletions(-) | 36 | src/html/template/example_test.go | 6 ++-- |
37 | src/html/template/js.go | 70 +++++++++++++++++++++++--------------- | ||
38 | src/html/template/js_test.go | 68 ++++++++++++++++++------------------ | ||
39 | src/html/template/template_test.go | 39 +++++++++++++++++++++ | ||
40 | src/text/template/exec_test.go | 6 ++-- | ||
41 | src/text/template/funcs.go | 8 ++--- | ||
42 | 8 files changed, 163 insertions(+), 110 deletions(-) | ||
37 | 43 | ||
44 | diff --git a/src/html/template/content_test.go b/src/html/template/content_test.go | ||
45 | index 72d56f5..bd86527 100644 | ||
46 | --- a/src/html/template/content_test.go | ||
47 | +++ b/src/html/template/content_test.go | ||
48 | @@ -18,7 +18,7 @@ func TestTypedContent(t *testing.T) { | ||
49 | HTML(`Hello, <b>World</b> &tc!`), | ||
50 | HTMLAttr(` dir="ltr"`), | ||
51 | JS(`c && alert("Hello, World!");`), | ||
52 | - JSStr(`Hello, World & O'Reilly\x21`), | ||
53 | + JSStr(`Hello, World & O'Reilly\u0021`), | ||
54 | URL(`greeting=H%69,&addressee=(World)`), | ||
55 | Srcset(`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`), | ||
56 | URL(`,foo/,`), | ||
57 | @@ -70,7 +70,7 @@ func TestTypedContent(t *testing.T) { | ||
58 | `Hello, <b>World</b> &tc!`, | ||
59 | ` dir="ltr"`, | ||
60 | `c && alert("Hello, World!");`, | ||
61 | - `Hello, World & O'Reilly\x21`, | ||
62 | + `Hello, World & O'Reilly\u0021`, | ||
63 | `greeting=H%69,&addressee=(World)`, | ||
64 | `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, | ||
65 | `,foo/,`, | ||
66 | @@ -100,7 +100,7 @@ func TestTypedContent(t *testing.T) { | ||
67 | `Hello, World &tc!`, | ||
68 | ` dir="ltr"`, | ||
69 | `c && alert("Hello, World!");`, | ||
70 | - `Hello, World & O'Reilly\x21`, | ||
71 | + `Hello, World & O'Reilly\u0021`, | ||
72 | `greeting=H%69,&addressee=(World)`, | ||
73 | `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, | ||
74 | `,foo/,`, | ||
75 | @@ -115,7 +115,7 @@ func TestTypedContent(t *testing.T) { | ||
76 | `Hello, World &tc!`, | ||
77 | ` dir="ltr"`, | ||
78 | `c && alert("Hello, World!");`, | ||
79 | - `Hello, World & O'Reilly\x21`, | ||
80 | + `Hello, World & O'Reilly\u0021`, | ||
81 | `greeting=H%69,&addressee=(World)`, | ||
82 | `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, | ||
83 | `,foo/,`, | ||
84 | @@ -130,7 +130,7 @@ func TestTypedContent(t *testing.T) { | ||
85 | `Hello, <b>World</b> &tc!`, | ||
86 | ` dir="ltr"`, | ||
87 | `c && alert("Hello, World!");`, | ||
88 | - `Hello, World & O'Reilly\x21`, | ||
89 | + `Hello, World & O'Reilly\u0021`, | ||
90 | `greeting=H%69,&addressee=(World)`, | ||
91 | `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, | ||
92 | `,foo/,`, | ||
93 | @@ -146,7 +146,7 @@ func TestTypedContent(t *testing.T) { | ||
94 | // Not escaped. | ||
95 | `c && alert("Hello, World!");`, | ||
96 | // Escape sequence not over-escaped. | ||
97 | - `"Hello, World & O'Reilly\x21"`, | ||
98 | + `"Hello, World & O'Reilly\u0021"`, | ||
99 | `"greeting=H%69,\u0026addressee=(World)"`, | ||
100 | `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`, | ||
101 | `",foo/,"`, | ||
102 | @@ -162,7 +162,7 @@ func TestTypedContent(t *testing.T) { | ||
103 | // Not JS escaped but HTML escaped. | ||
104 | `c && alert("Hello, World!");`, | ||
105 | // Escape sequence not over-escaped. | ||
106 | - `"Hello, World & O'Reilly\x21"`, | ||
107 | + `"Hello, World & O'Reilly\u0021"`, | ||
108 | `"greeting=H%69,\u0026addressee=(World)"`, | ||
109 | `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`, | ||
110 | `",foo/,"`, | ||
111 | @@ -171,30 +171,30 @@ func TestTypedContent(t *testing.T) { | ||
112 | { | ||
113 | `<script>alert("{{.}}")</script>`, | ||
114 | []string{ | ||
115 | - `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`, | ||
116 | - `a[href =~ \x22\/\/example.com\x22]#foo`, | ||
117 | - `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`, | ||
118 | - ` dir=\x22ltr\x22`, | ||
119 | - `c \x26\x26 alert(\x22Hello, World!\x22);`, | ||
120 | + `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`, | ||
121 | + `a[href =~ \u0022\/\/example.com\u0022]#foo`, | ||
122 | + `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`, | ||
123 | + ` dir=\u0022ltr\u0022`, | ||
124 | + `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`, | ||
125 | // Escape sequence not over-escaped. | ||
126 | - `Hello, World \x26 O\x27Reilly\x21`, | ||
127 | - `greeting=H%69,\x26addressee=(World)`, | ||
128 | - `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, | ||
129 | + `Hello, World \u0026 O\u0027Reilly\u0021`, | ||
130 | + `greeting=H%69,\u0026addressee=(World)`, | ||
131 | + `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, | ||
132 | `,foo\/,`, | ||
133 | }, | ||
134 | }, | ||
135 | { | ||
136 | `<script type="text/javascript">alert("{{.}}")</script>`, | ||
137 | []string{ | ||
138 | - `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`, | ||
139 | - `a[href =~ \x22\/\/example.com\x22]#foo`, | ||
140 | - `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`, | ||
141 | - ` dir=\x22ltr\x22`, | ||
142 | - `c \x26\x26 alert(\x22Hello, World!\x22);`, | ||
143 | + `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`, | ||
144 | + `a[href =~ \u0022\/\/example.com\u0022]#foo`, | ||
145 | + `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`, | ||
146 | + ` dir=\u0022ltr\u0022`, | ||
147 | + `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`, | ||
148 | // Escape sequence not over-escaped. | ||
149 | - `Hello, World \x26 O\x27Reilly\x21`, | ||
150 | - `greeting=H%69,\x26addressee=(World)`, | ||
151 | - `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, | ||
152 | + `Hello, World \u0026 O\u0027Reilly\u0021`, | ||
153 | + `greeting=H%69,\u0026addressee=(World)`, | ||
154 | + `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, | ||
155 | `,foo\/,`, | ||
156 | }, | ||
157 | }, | ||
158 | @@ -208,7 +208,7 @@ func TestTypedContent(t *testing.T) { | ||
159 | // Not escaped. | ||
160 | `c && alert("Hello, World!");`, | ||
161 | // Escape sequence not over-escaped. | ||
162 | - `"Hello, World & O'Reilly\x21"`, | ||
163 | + `"Hello, World & O'Reilly\u0021"`, | ||
164 | `"greeting=H%69,\u0026addressee=(World)"`, | ||
165 | `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`, | ||
166 | `",foo/,"`, | ||
167 | @@ -224,7 +224,7 @@ func TestTypedContent(t *testing.T) { | ||
168 | `Hello, <b>World</b> &tc!`, | ||
169 | ` dir="ltr"`, | ||
170 | `c && alert("Hello, World!");`, | ||
171 | - `Hello, World & O'Reilly\x21`, | ||
172 | + `Hello, World & O'Reilly\u0021`, | ||
173 | `greeting=H%69,&addressee=(World)`, | ||
174 | `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, | ||
175 | `,foo/,`, | ||
176 | @@ -233,15 +233,15 @@ func TestTypedContent(t *testing.T) { | ||
177 | { | ||
178 | `<button onclick='alert("{{.}}")'>`, | ||
179 | []string{ | ||
180 | - `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`, | ||
181 | - `a[href =~ \x22\/\/example.com\x22]#foo`, | ||
182 | - `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`, | ||
183 | - ` dir=\x22ltr\x22`, | ||
184 | - `c \x26\x26 alert(\x22Hello, World!\x22);`, | ||
185 | + `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`, | ||
186 | + `a[href =~ \u0022\/\/example.com\u0022]#foo`, | ||
187 | + `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`, | ||
188 | + ` dir=\u0022ltr\u0022`, | ||
189 | + `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`, | ||
190 | // Escape sequence not over-escaped. | ||
191 | - `Hello, World \x26 O\x27Reilly\x21`, | ||
192 | - `greeting=H%69,\x26addressee=(World)`, | ||
193 | - `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, | ||
194 | + `Hello, World \u0026 O\u0027Reilly\u0021`, | ||
195 | + `greeting=H%69,\u0026addressee=(World)`, | ||
196 | + `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`, | ||
197 | `,foo\/,`, | ||
198 | }, | ||
199 | }, | ||
200 | @@ -253,7 +253,7 @@ func TestTypedContent(t *testing.T) { | ||
201 | `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`, | ||
202 | `%20dir%3d%22ltr%22`, | ||
203 | `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`, | ||
204 | - `Hello%2c%20World%20%26%20O%27Reilly%5cx21`, | ||
205 | + `Hello%2c%20World%20%26%20O%27Reilly%5cu0021`, | ||
206 | // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is done. | ||
207 | `greeting=H%69,&addressee=%28World%29`, | ||
208 | `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`, | ||
209 | @@ -268,7 +268,7 @@ func TestTypedContent(t *testing.T) { | ||
210 | `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`, | ||
211 | `%20dir%3d%22ltr%22`, | ||
212 | `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`, | ||
213 | - `Hello%2c%20World%20%26%20O%27Reilly%5cx21`, | ||
214 | + `Hello%2c%20World%20%26%20O%27Reilly%5cu0021`, | ||
215 | // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is not done. | ||
216 | `greeting=H%69,&addressee=%28World%29`, | ||
217 | `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`, | ||
218 | diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go | ||
219 | index e72a9ba..c709660 100644 | ||
220 | --- a/src/html/template/escape_test.go | ||
221 | +++ b/src/html/template/escape_test.go | ||
222 | @@ -238,7 +238,7 @@ func TestEscape(t *testing.T) { | ||
223 | { | ||
224 | "jsStr", | ||
225 | "<button onclick='alert("{{.H}}")'>", | ||
226 | - `<button onclick='alert("\x3cHello\x3e")'>`, | ||
227 | + `<button onclick='alert("\u003cHello\u003e")'>`, | ||
228 | }, | ||
229 | { | ||
230 | "badMarshaler", | ||
231 | @@ -259,7 +259,7 @@ func TestEscape(t *testing.T) { | ||
232 | { | ||
233 | "jsRe", | ||
234 | `<button onclick='alert(/{{"foo+bar"}}/.test(""))'>`, | ||
235 | - `<button onclick='alert(/foo\x2bbar/.test(""))'>`, | ||
236 | + `<button onclick='alert(/foo\u002bbar/.test(""))'>`, | ||
237 | }, | ||
238 | { | ||
239 | "jsReBlank", | ||
240 | @@ -825,7 +825,7 @@ func TestEscapeSet(t *testing.T) { | ||
241 | "main": `<button onclick="title='{{template "helper"}}'; ...">{{template "helper"}}</button>`, | ||
242 | "helper": `{{11}} of {{"<100>"}}`, | ||
243 | }, | ||
244 | - `<button onclick="title='11 of \x3c100\x3e'; ...">11 of <100></button>`, | ||
245 | + `<button onclick="title='11 of \u003c100\u003e'; ...">11 of <100></button>`, | ||
246 | }, | ||
247 | // A non-recursive template that ends in a different context. | ||
248 | // helper starts in jsCtxRegexp and ends in jsCtxDivOp. | ||
249 | diff --git a/src/html/template/example_test.go b/src/html/template/example_test.go | ||
250 | index 9d965f1..6cf936f 100644 | ||
251 | --- a/src/html/template/example_test.go | ||
252 | +++ b/src/html/template/example_test.go | ||
253 | @@ -116,9 +116,9 @@ func Example_escape() { | ||
254 | // "Fran & Freddie's Diner" <tasty@example.com> | ||
255 | // "Fran & Freddie's Diner" <tasty@example.com> | ||
256 | // "Fran & Freddie's Diner"32<tasty@example.com> | ||
257 | - // \"Fran \x26 Freddie\'s Diner\" \x3Ctasty@example.com\x3E | ||
258 | - // \"Fran \x26 Freddie\'s Diner\" \x3Ctasty@example.com\x3E | ||
259 | - // \"Fran \x26 Freddie\'s Diner\"32\x3Ctasty@example.com\x3E | ||
260 | + // \"Fran \u0026 Freddie\'s Diner\" \u003Ctasty@example.com\u003E | ||
261 | + // \"Fran \u0026 Freddie\'s Diner\" \u003Ctasty@example.com\u003E | ||
262 | + // \"Fran \u0026 Freddie\'s Diner\"32\u003Ctasty@example.com\u003E | ||
263 | // %22Fran+%26+Freddie%27s+Diner%2232%3Ctasty%40example.com%3E | ||
264 | |||
265 | } | ||
38 | diff --git a/src/html/template/js.go b/src/html/template/js.go | 266 | diff --git a/src/html/template/js.go b/src/html/template/js.go |
39 | index 0e91458..ea9c183 100644 | 267 | index 0e91458..ea9c183 100644 |
40 | --- a/src/html/template/js.go | 268 | --- a/src/html/template/js.go |
@@ -173,6 +401,217 @@ index 0e91458..ea9c183 100644 | |||
173 | '?': `\?`, | 401 | '?': `\?`, |
174 | '[': `\[`, | 402 | '[': `\[`, |
175 | '\\': `\\`, | 403 | '\\': `\\`, |
404 | diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go | ||
405 | index 075adaa..d7ee47b 100644 | ||
406 | --- a/src/html/template/js_test.go | ||
407 | +++ b/src/html/template/js_test.go | ||
408 | @@ -137,7 +137,7 @@ func TestJSValEscaper(t *testing.T) { | ||
409 | {"foo", `"foo"`}, | ||
410 | // Newlines. | ||
411 | {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`}, | ||
412 | - // "\v" == "v" on IE 6 so use "\x0b" instead. | ||
413 | + // "\v" == "v" on IE 6 so use "\u000b" instead. | ||
414 | {"\t\x0b", `"\t\u000b"`}, | ||
415 | {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`}, | ||
416 | {[]interface{}{}, "[]"}, | ||
417 | @@ -173,7 +173,7 @@ func TestJSStrEscaper(t *testing.T) { | ||
418 | }{ | ||
419 | {"", ``}, | ||
420 | {"foo", `foo`}, | ||
421 | - {"\u0000", `\0`}, | ||
422 | + {"\u0000", `\u0000`}, | ||
423 | {"\t", `\t`}, | ||
424 | {"\n", `\n`}, | ||
425 | {"\r", `\r`}, | ||
426 | @@ -183,14 +183,14 @@ func TestJSStrEscaper(t *testing.T) { | ||
427 | {"\\n", `\\n`}, | ||
428 | {"foo\r\nbar", `foo\r\nbar`}, | ||
429 | // Preserve attribute boundaries. | ||
430 | - {`"`, `\x22`}, | ||
431 | - {`'`, `\x27`}, | ||
432 | + {`"`, `\u0022`}, | ||
433 | + {`'`, `\u0027`}, | ||
434 | // Allow embedding in HTML without further escaping. | ||
435 | - {`&`, `\x26amp;`}, | ||
436 | + {`&`, `\u0026amp;`}, | ||
437 | // Prevent breaking out of text node and element boundaries. | ||
438 | - {"</script>", `\x3c\/script\x3e`}, | ||
439 | - {"<![CDATA[", `\x3c![CDATA[`}, | ||
440 | - {"]]>", `]]\x3e`}, | ||
441 | + {"</script>", `\u003c\/script\u003e`}, | ||
442 | + {"<![CDATA[", `\u003c![CDATA[`}, | ||
443 | + {"]]>", `]]\u003e`}, | ||
444 | // https://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span | ||
445 | // "The text in style, script, title, and textarea elements | ||
446 | // must not have an escaping text span start that is not | ||
447 | @@ -201,11 +201,11 @@ func TestJSStrEscaper(t *testing.T) { | ||
448 | // allow regular text content to be interpreted as script | ||
449 | // allowing script execution via a combination of a JS string | ||
450 | // injection followed by an HTML text injection. | ||
451 | - {"<!--", `\x3c!--`}, | ||
452 | - {"-->", `--\x3e`}, | ||
453 | + {"<!--", `\u003c!--`}, | ||
454 | + {"-->", `--\u003e`}, | ||
455 | // From https://code.google.com/p/doctype/wiki/ArticleUtf7 | ||
456 | {"+ADw-script+AD4-alert(1)+ADw-/script+AD4-", | ||
457 | - `\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`, | ||
458 | + `\u002bADw-script\u002bAD4-alert(1)\u002bADw-\/script\u002bAD4-`, | ||
459 | }, | ||
460 | // Invalid UTF-8 sequence | ||
461 | {"foo\xA0bar", "foo\xA0bar"}, | ||
462 | @@ -228,7 +228,7 @@ func TestJSRegexpEscaper(t *testing.T) { | ||
463 | }{ | ||
464 | {"", `(?:)`}, | ||
465 | {"foo", `foo`}, | ||
466 | - {"\u0000", `\0`}, | ||
467 | + {"\u0000", `\u0000`}, | ||
468 | {"\t", `\t`}, | ||
469 | {"\n", `\n`}, | ||
470 | {"\r", `\r`}, | ||
471 | @@ -238,19 +238,19 @@ func TestJSRegexpEscaper(t *testing.T) { | ||
472 | {"\\n", `\\n`}, | ||
473 | {"foo\r\nbar", `foo\r\nbar`}, | ||
474 | // Preserve attribute boundaries. | ||
475 | - {`"`, `\x22`}, | ||
476 | - {`'`, `\x27`}, | ||
477 | + {`"`, `\u0022`}, | ||
478 | + {`'`, `\u0027`}, | ||
479 | // Allow embedding in HTML without further escaping. | ||
480 | - {`&`, `\x26amp;`}, | ||
481 | + {`&`, `\u0026amp;`}, | ||
482 | // Prevent breaking out of text node and element boundaries. | ||
483 | - {"</script>", `\x3c\/script\x3e`}, | ||
484 | - {"<![CDATA[", `\x3c!\[CDATA\[`}, | ||
485 | - {"]]>", `\]\]\x3e`}, | ||
486 | + {"</script>", `\u003c\/script\u003e`}, | ||
487 | + {"<![CDATA[", `\u003c!\[CDATA\[`}, | ||
488 | + {"]]>", `\]\]\u003e`}, | ||
489 | // Escaping text spans. | ||
490 | - {"<!--", `\x3c!\-\-`}, | ||
491 | - {"-->", `\-\-\x3e`}, | ||
492 | + {"<!--", `\u003c!\-\-`}, | ||
493 | + {"-->", `\-\-\u003e`}, | ||
494 | {"*", `\*`}, | ||
495 | - {"+", `\x2b`}, | ||
496 | + {"+", `\u002b`}, | ||
497 | {"?", `\?`}, | ||
498 | {"[](){}", `\[\]\(\)\{\}`}, | ||
499 | {"$foo|x.y", `\$foo\|x\.y`}, | ||
500 | @@ -284,27 +284,27 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) { | ||
501 | { | ||
502 | "jsStrEscaper", | ||
503 | jsStrEscaper, | ||
504 | - "\\0\x01\x02\x03\x04\x05\x06\x07" + | ||
505 | - "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" + | ||
506 | - "\x10\x11\x12\x13\x14\x15\x16\x17" + | ||
507 | - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + | ||
508 | - ` !\x22#$%\x26\x27()*\x2b,-.\/` + | ||
509 | - `0123456789:;\x3c=\x3e?` + | ||
510 | + `\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007` + | ||
511 | + `\u0008\t\n\u000b\f\r\u000e\u000f` + | ||
512 | + `\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017` + | ||
513 | + `\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f` + | ||
514 | + ` !\u0022#$%\u0026\u0027()*\u002b,-.\/` + | ||
515 | + `0123456789:;\u003c=\u003e?` + | ||
516 | `@ABCDEFGHIJKLMNO` + | ||
517 | `PQRSTUVWXYZ[\\]^_` + | ||
518 | "`abcdefghijklmno" + | ||
519 | - "pqrstuvwxyz{|}~\x7f" + | ||
520 | + "pqrstuvwxyz{|}~\u007f" + | ||
521 | "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E", | ||
522 | }, | ||
523 | { | ||
524 | "jsRegexpEscaper", | ||
525 | jsRegexpEscaper, | ||
526 | - "\\0\x01\x02\x03\x04\x05\x06\x07" + | ||
527 | - "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" + | ||
528 | - "\x10\x11\x12\x13\x14\x15\x16\x17" + | ||
529 | - "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + | ||
530 | - ` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` + | ||
531 | - `0123456789:;\x3c=\x3e\?` + | ||
532 | + `\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007` + | ||
533 | + `\u0008\t\n\u000b\f\r\u000e\u000f` + | ||
534 | + `\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017` + | ||
535 | + `\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f` + | ||
536 | + ` !\u0022#\$%\u0026\u0027\(\)\*\u002b,\-\.\/` + | ||
537 | + `0123456789:;\u003c=\u003e\?` + | ||
538 | `@ABCDEFGHIJKLMNO` + | ||
539 | `PQRSTUVWXYZ\[\\\]\^_` + | ||
540 | "`abcdefghijklmno" + | ||
541 | diff --git a/src/html/template/template_test.go b/src/html/template/template_test.go | ||
542 | index 13e6ba4..86bd4db 100644 | ||
543 | --- a/src/html/template/template_test.go | ||
544 | +++ b/src/html/template/template_test.go | ||
545 | @@ -6,6 +6,7 @@ package template_test | ||
546 | |||
547 | import ( | ||
548 | "bytes" | ||
549 | + "encoding/json" | ||
550 | . "html/template" | ||
551 | "strings" | ||
552 | "testing" | ||
553 | @@ -121,6 +122,44 @@ func TestNumbers(t *testing.T) { | ||
554 | c.mustExecute(c.root, nil, "12.34 7.5") | ||
555 | } | ||
556 | |||
557 | +func TestStringsInScriptsWithJsonContentTypeAreCorrectlyEscaped(t *testing.T) { | ||
558 | + // See #33671 and #37634 for more context on this. | ||
559 | + tests := []struct{ name, in string }{ | ||
560 | + {"empty", ""}, | ||
561 | + {"invalid", string(rune(-1))}, | ||
562 | + {"null", "\u0000"}, | ||
563 | + {"unit separator", "\u001F"}, | ||
564 | + {"tab", "\t"}, | ||
565 | + {"gt and lt", "<>"}, | ||
566 | + {"quotes", `'"`}, | ||
567 | + {"ASCII letters", "ASCII letters"}, | ||
568 | + {"Unicode", "ʕ⊙ϖ⊙ʔ"}, | ||
569 | + {"Pizza", "P"}, | ||
570 | + } | ||
571 | + const ( | ||
572 | + prefix = `<script type="application/ld+json">` | ||
573 | + suffix = `</script>` | ||
574 | + templ = prefix + `"{{.}}"` + suffix | ||
575 | + ) | ||
576 | + tpl := Must(New("JS string is JSON string").Parse(templ)) | ||
577 | + for _, tt := range tests { | ||
578 | + t.Run(tt.name, func(t *testing.T) { | ||
579 | + var buf bytes.Buffer | ||
580 | + if err := tpl.Execute(&buf, tt.in); err != nil { | ||
581 | + t.Fatalf("Cannot render template: %v", err) | ||
582 | + } | ||
583 | + trimmed := bytes.TrimSuffix(bytes.TrimPrefix(buf.Bytes(), []byte(prefix)), []byte(suffix)) | ||
584 | + var got string | ||
585 | + if err := json.Unmarshal(trimmed, &got); err != nil { | ||
586 | + t.Fatalf("Cannot parse JS string %q as JSON: %v", trimmed[1:len(trimmed)-1], err) | ||
587 | + } | ||
588 | + if got != tt.in { | ||
589 | + t.Errorf("Serialization changed the string value: got %q want %q", got, tt.in) | ||
590 | + } | ||
591 | + }) | ||
592 | + } | ||
593 | +} | ||
594 | + | ||
595 | type testCase struct { | ||
596 | t *testing.T | ||
597 | root *Template | ||
598 | diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go | ||
599 | index 77294ed..b8a809e 100644 | ||
600 | --- a/src/text/template/exec_test.go | ||
601 | +++ b/src/text/template/exec_test.go | ||
602 | @@ -911,9 +911,9 @@ func TestJSEscaping(t *testing.T) { | ||
603 | {`Go "jump" \`, `Go \"jump\" \\`}, | ||
604 | {`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`}, | ||
605 | {"unprintable \uFDFF", `unprintable \uFDFF`}, | ||
606 | - {`<html>`, `\x3Chtml\x3E`}, | ||
607 | - {`no = in attributes`, `no \x3D in attributes`}, | ||
608 | - {`' does not become HTML entity`, `\x26#x27; does not become HTML entity`}, | ||
609 | + {`<html>`, `\u003Chtml\u003E`}, | ||
610 | + {`no = in attributes`, `no \u003D in attributes`}, | ||
611 | + {`' does not become HTML entity`, `\u0026#x27; does not become HTML entity`}, | ||
612 | } | ||
613 | for _, tc := range testCases { | ||
614 | s := JSEscapeString(tc.in) | ||
176 | diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go | 615 | diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go |
177 | index 46125bc..f3de9fb 100644 | 616 | index 46125bc..f3de9fb 100644 |
178 | --- a/src/text/template/funcs.go | 617 | --- a/src/text/template/funcs.go |
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_3.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_3.patch new file mode 100644 index 0000000000..cd7dd0957c --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_3.patch | |||
@@ -0,0 +1,393 @@ | |||
1 | From 7ddce23c7d5b728acf8482f5006497c7b9915f8a Mon Sep 17 00:00:00 2001 | ||
2 | From: Ariel Mashraki <ariel@mashraki.co.il> | ||
3 | Date: Wed, 22 Apr 2020 22:17:56 +0300 | ||
4 | Subject: [PATCH 3/6] text/template: add CommentNode to template parse tree | ||
5 | MIME-Version: 1.0 | ||
6 | Content-Type: text/plain; charset=UTF-8 | ||
7 | Content-Transfer-Encoding: 8bit | ||
8 | |||
9 | Fixes #34652 | ||
10 | |||
11 | Change-Id: Icf6e3eda593fed826736f34f95a9d66f5450cc98 | ||
12 | Reviewed-on: https://go-review.googlesource.com/c/go/+/229398 | ||
13 | Reviewed-by: Daniel Martí <mvdan@mvdan.cc> | ||
14 | Run-TryBot: Daniel Martí <mvdan@mvdan.cc> | ||
15 | TryBot-Result: Gobot Gobot <gobot@golang.org> | ||
16 | |||
17 | Dependency Patch #3 | ||
18 | |||
19 | Upstream-Status: Backport from https://github.com/golang/go/commit/c8ea03828b0645b1fd5725888e44873b75fcfbb6 | ||
20 | CVE: CVE-2023-24538 | ||
21 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> | ||
22 | --- | ||
23 | api/next.txt | 19 +++++++++++++++++++ | ||
24 | src/html/template/escape.go | 2 ++ | ||
25 | src/html/template/template_test.go | 16 ++++++++++++++++ | ||
26 | src/text/template/exec.go | 1 + | ||
27 | src/text/template/parse/lex.go | 8 +++++++- | ||
28 | src/text/template/parse/lex_test.go | 7 +++++-- | ||
29 | src/text/template/parse/node.go | 33 +++++++++++++++++++++++++++++++++ | ||
30 | src/text/template/parse/parse.go | 22 +++++++++++++++++++--- | ||
31 | src/text/template/parse/parse_test.go | 25 +++++++++++++++++++++++++ | ||
32 | 9 files changed, 127 insertions(+), 6 deletions(-) | ||
33 | |||
34 | diff --git a/api/next.txt b/api/next.txt | ||
35 | index e69de29..076f39e 100644 | ||
36 | --- a/api/next.txt | ||
37 | +++ b/api/next.txt | ||
38 | @@ -0,0 +1,19 @@ | ||
39 | +pkg unicode, const Version = "13.0.0" | ||
40 | +pkg unicode, var Chorasmian *RangeTable | ||
41 | +pkg unicode, var Dives_Akuru *RangeTable | ||
42 | +pkg unicode, var Khitan_Small_Script *RangeTable | ||
43 | +pkg unicode, var Yezidi *RangeTable | ||
44 | +pkg text/template/parse, const NodeComment = 20 | ||
45 | +pkg text/template/parse, const NodeComment NodeType | ||
46 | +pkg text/template/parse, const ParseComments = 1 | ||
47 | +pkg text/template/parse, const ParseComments Mode | ||
48 | +pkg text/template/parse, method (*CommentNode) Copy() Node | ||
49 | +pkg text/template/parse, method (*CommentNode) String() string | ||
50 | +pkg text/template/parse, method (CommentNode) Position() Pos | ||
51 | +pkg text/template/parse, method (CommentNode) Type() NodeType | ||
52 | +pkg text/template/parse, type CommentNode struct | ||
53 | +pkg text/template/parse, type CommentNode struct, Text string | ||
54 | +pkg text/template/parse, type CommentNode struct, embedded NodeType | ||
55 | +pkg text/template/parse, type CommentNode struct, embedded Pos | ||
56 | +pkg text/template/parse, type Mode uint | ||
57 | +pkg text/template/parse, type Tree struct, Mode Mode | ||
58 | diff --git a/src/html/template/escape.go b/src/html/template/escape.go | ||
59 | index f12dafa..8739735 100644 | ||
60 | --- a/src/html/template/escape.go | ||
61 | +++ b/src/html/template/escape.go | ||
62 | @@ -124,6 +124,8 @@ func (e *escaper) escape(c context, n parse.Node) context { | ||
63 | switch n := n.(type) { | ||
64 | case *parse.ActionNode: | ||
65 | return e.escapeAction(c, n) | ||
66 | + case *parse.CommentNode: | ||
67 | + return c | ||
68 | case *parse.IfNode: | ||
69 | return e.escapeBranch(c, &n.BranchNode, "if") | ||
70 | case *parse.ListNode: | ||
71 | diff --git a/src/html/template/template_test.go b/src/html/template/template_test.go | ||
72 | index 86bd4db..1f2c888 100644 | ||
73 | --- a/src/html/template/template_test.go | ||
74 | +++ b/src/html/template/template_test.go | ||
75 | @@ -10,6 +10,7 @@ import ( | ||
76 | . "html/template" | ||
77 | "strings" | ||
78 | "testing" | ||
79 | + "text/template/parse" | ||
80 | ) | ||
81 | |||
82 | func TestTemplateClone(t *testing.T) { | ||
83 | @@ -160,6 +161,21 @@ func TestStringsInScriptsWithJsonContentTypeAreCorrectlyEscaped(t *testing.T) { | ||
84 | } | ||
85 | } | ||
86 | |||
87 | +func TestSkipEscapeComments(t *testing.T) { | ||
88 | + c := newTestCase(t) | ||
89 | + tr := parse.New("root") | ||
90 | + tr.Mode = parse.ParseComments | ||
91 | + newT, err := tr.Parse("{{/* A comment */}}{{ 1 }}{{/* Another comment */}}", "", "", make(map[string]*parse.Tree)) | ||
92 | + if err != nil { | ||
93 | + t.Fatalf("Cannot parse template text: %v", err) | ||
94 | + } | ||
95 | + c.root, err = c.root.AddParseTree("root", newT) | ||
96 | + if err != nil { | ||
97 | + t.Fatalf("Cannot add parse tree to template: %v", err) | ||
98 | + } | ||
99 | + c.mustExecute(c.root, nil, "1") | ||
100 | +} | ||
101 | + | ||
102 | type testCase struct { | ||
103 | t *testing.T | ||
104 | root *Template | ||
105 | diff --git a/src/text/template/exec.go b/src/text/template/exec.go | ||
106 | index ac3e741..7ac5175 100644 | ||
107 | --- a/src/text/template/exec.go | ||
108 | +++ b/src/text/template/exec.go | ||
109 | @@ -256,6 +256,7 @@ func (s *state) walk(dot reflect.Value, node parse.Node) { | ||
110 | if len(node.Pipe.Decl) == 0 { | ||
111 | s.printValue(node, val) | ||
112 | } | ||
113 | + case *parse.CommentNode: | ||
114 | case *parse.IfNode: | ||
115 | s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList) | ||
116 | case *parse.ListNode: | ||
117 | diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go | ||
118 | index 30371f2..e41373a 100644 | ||
119 | --- a/src/text/template/parse/lex.go | ||
120 | +++ b/src/text/template/parse/lex.go | ||
121 | @@ -41,6 +41,7 @@ const ( | ||
122 | itemBool // boolean constant | ||
123 | itemChar // printable ASCII character; grab bag for comma etc. | ||
124 | itemCharConstant // character constant | ||
125 | + itemComment // comment text | ||
126 | itemComplex // complex constant (1+2i); imaginary is just a number | ||
127 | itemAssign // equals ('=') introducing an assignment | ||
128 | itemDeclare // colon-equals (':=') introducing a declaration | ||
129 | @@ -112,6 +113,7 @@ type lexer struct { | ||
130 | leftDelim string // start of action | ||
131 | rightDelim string // end of action | ||
132 | trimRightDelim string // end of action with trim marker | ||
133 | + emitComment bool // emit itemComment tokens. | ||
134 | pos Pos // current position in the input | ||
135 | start Pos // start position of this item | ||
136 | width Pos // width of last rune read from input | ||
137 | @@ -203,7 +205,7 @@ func (l *lexer) drain() { | ||
138 | } | ||
139 | |||
140 | // lex creates a new scanner for the input string. | ||
141 | -func lex(name, input, left, right string) *lexer { | ||
142 | +func lex(name, input, left, right string, emitComment bool) *lexer { | ||
143 | if left == "" { | ||
144 | left = leftDelim | ||
145 | } | ||
146 | @@ -216,6 +218,7 @@ func lex(name, input, left, right string) *lexer { | ||
147 | leftDelim: left, | ||
148 | rightDelim: right, | ||
149 | trimRightDelim: rightTrimMarker + right, | ||
150 | + emitComment: emitComment, | ||
151 | items: make(chan item), | ||
152 | line: 1, | ||
153 | startLine: 1, | ||
154 | @@ -323,6 +326,9 @@ func lexComment(l *lexer) stateFn { | ||
155 | if !delim { | ||
156 | return l.errorf("comment ends before closing delimiter") | ||
157 | } | ||
158 | + if l.emitComment { | ||
159 | + l.emit(itemComment) | ||
160 | + } | ||
161 | if trimSpace { | ||
162 | l.pos += trimMarkerLen | ||
163 | } | ||
164 | diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go | ||
165 | index 563c4fc..f6d5f28 100644 | ||
166 | --- a/src/text/template/parse/lex_test.go | ||
167 | +++ b/src/text/template/parse/lex_test.go | ||
168 | @@ -15,6 +15,7 @@ var itemName = map[itemType]string{ | ||
169 | itemBool: "bool", | ||
170 | itemChar: "char", | ||
171 | itemCharConstant: "charconst", | ||
172 | + itemComment: "comment", | ||
173 | itemComplex: "complex", | ||
174 | itemDeclare: ":=", | ||
175 | itemEOF: "EOF", | ||
176 | @@ -90,6 +91,7 @@ var lexTests = []lexTest{ | ||
177 | {"text", `now is the time`, []item{mkItem(itemText, "now is the time"), tEOF}}, | ||
178 | {"text with comment", "hello-{{/* this is a comment */}}-world", []item{ | ||
179 | mkItem(itemText, "hello-"), | ||
180 | + mkItem(itemComment, "/* this is a comment */"), | ||
181 | mkItem(itemText, "-world"), | ||
182 | tEOF, | ||
183 | }}, | ||
184 | @@ -311,6 +313,7 @@ var lexTests = []lexTest{ | ||
185 | }}, | ||
186 | {"trimming spaces before and after comment", "hello- {{- /* hello */ -}} -world", []item{ | ||
187 | mkItem(itemText, "hello-"), | ||
188 | + mkItem(itemComment, "/* hello */"), | ||
189 | mkItem(itemText, "-world"), | ||
190 | tEOF, | ||
191 | }}, | ||
192 | @@ -389,7 +392,7 @@ var lexTests = []lexTest{ | ||
193 | |||
194 | // collect gathers the emitted items into a slice. | ||
195 | func collect(t *lexTest, left, right string) (items []item) { | ||
196 | - l := lex(t.name, t.input, left, right) | ||
197 | + l := lex(t.name, t.input, left, right, true) | ||
198 | for { | ||
199 | item := l.nextItem() | ||
200 | items = append(items, item) | ||
201 | @@ -529,7 +532,7 @@ func TestPos(t *testing.T) { | ||
202 | func TestShutdown(t *testing.T) { | ||
203 | // We need to duplicate template.Parse here to hold on to the lexer. | ||
204 | const text = "erroneous{{define}}{{else}}1234" | ||
205 | - lexer := lex("foo", text, "{{", "}}") | ||
206 | + lexer := lex("foo", text, "{{", "}}", false) | ||
207 | _, err := New("root").parseLexer(lexer) | ||
208 | if err == nil { | ||
209 | t.Fatalf("expected error") | ||
210 | diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go | ||
211 | index 1c116ea..a9dad5e 100644 | ||
212 | --- a/src/text/template/parse/node.go | ||
213 | +++ b/src/text/template/parse/node.go | ||
214 | @@ -70,6 +70,7 @@ const ( | ||
215 | NodeTemplate // A template invocation action. | ||
216 | NodeVariable // A $ variable. | ||
217 | NodeWith // A with action. | ||
218 | + NodeComment // A comment. | ||
219 | ) | ||
220 | |||
221 | // Nodes. | ||
222 | @@ -149,6 +150,38 @@ func (t *TextNode) Copy() Node { | ||
223 | return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)} | ||
224 | } | ||
225 | |||
226 | +// CommentNode holds a comment. | ||
227 | +type CommentNode struct { | ||
228 | + NodeType | ||
229 | + Pos | ||
230 | + tr *Tree | ||
231 | + Text string // Comment text. | ||
232 | +} | ||
233 | + | ||
234 | +func (t *Tree) newComment(pos Pos, text string) *CommentNode { | ||
235 | + return &CommentNode{tr: t, NodeType: NodeComment, Pos: pos, Text: text} | ||
236 | +} | ||
237 | + | ||
238 | +func (c *CommentNode) String() string { | ||
239 | + var sb strings.Builder | ||
240 | + c.writeTo(&sb) | ||
241 | + return sb.String() | ||
242 | +} | ||
243 | + | ||
244 | +func (c *CommentNode) writeTo(sb *strings.Builder) { | ||
245 | + sb.WriteString("{{") | ||
246 | + sb.WriteString(c.Text) | ||
247 | + sb.WriteString("}}") | ||
248 | +} | ||
249 | + | ||
250 | +func (c *CommentNode) tree() *Tree { | ||
251 | + return c.tr | ||
252 | +} | ||
253 | + | ||
254 | +func (c *CommentNode) Copy() Node { | ||
255 | + return &CommentNode{tr: c.tr, NodeType: NodeComment, Pos: c.Pos, Text: c.Text} | ||
256 | +} | ||
257 | + | ||
258 | // PipeNode holds a pipeline with optional declaration | ||
259 | type PipeNode struct { | ||
260 | NodeType | ||
261 | diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go | ||
262 | index c9b80f4..496d8bf 100644 | ||
263 | --- a/src/text/template/parse/parse.go | ||
264 | +++ b/src/text/template/parse/parse.go | ||
265 | @@ -21,6 +21,7 @@ type Tree struct { | ||
266 | Name string // name of the template represented by the tree. | ||
267 | ParseName string // name of the top-level template during parsing, for error messages. | ||
268 | Root *ListNode // top-level root of the tree. | ||
269 | + Mode Mode // parsing mode. | ||
270 | text string // text parsed to create the template (or its parent) | ||
271 | // Parsing only; cleared after parse. | ||
272 | funcs []map[string]interface{} | ||
273 | @@ -29,8 +30,16 @@ type Tree struct { | ||
274 | peekCount int | ||
275 | vars []string // variables defined at the moment. | ||
276 | treeSet map[string]*Tree | ||
277 | + mode Mode | ||
278 | } | ||
279 | |||
280 | +// A mode value is a set of flags (or 0). Modes control parser behavior. | ||
281 | +type Mode uint | ||
282 | + | ||
283 | +const ( | ||
284 | + ParseComments Mode = 1 << iota // parse comments and add them to AST | ||
285 | +) | ||
286 | + | ||
287 | // Copy returns a copy of the Tree. Any parsing state is discarded. | ||
288 | func (t *Tree) Copy() *Tree { | ||
289 | if t == nil { | ||
290 | @@ -220,7 +229,8 @@ func (t *Tree) stopParse() { | ||
291 | func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) { | ||
292 | defer t.recover(&err) | ||
293 | t.ParseName = t.Name | ||
294 | - t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim), treeSet) | ||
295 | + emitComment := t.Mode&ParseComments != 0 | ||
296 | + t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim, emitComment), treeSet) | ||
297 | t.text = text | ||
298 | t.parse() | ||
299 | t.add() | ||
300 | @@ -240,12 +250,14 @@ func (t *Tree) add() { | ||
301 | } | ||
302 | } | ||
303 | |||
304 | -// IsEmptyTree reports whether this tree (node) is empty of everything but space. | ||
305 | +// IsEmptyTree reports whether this tree (node) is empty of everything but space or comments. | ||
306 | func IsEmptyTree(n Node) bool { | ||
307 | switch n := n.(type) { | ||
308 | case nil: | ||
309 | return true | ||
310 | case *ActionNode: | ||
311 | + case *CommentNode: | ||
312 | + return true | ||
313 | case *IfNode: | ||
314 | case *ListNode: | ||
315 | for _, node := range n.Nodes { | ||
316 | @@ -276,6 +288,7 @@ func (t *Tree) parse() { | ||
317 | if t.nextNonSpace().typ == itemDefine { | ||
318 | newT := New("definition") // name will be updated once we know it. | ||
319 | newT.text = t.text | ||
320 | + newT.Mode = t.Mode | ||
321 | newT.ParseName = t.ParseName | ||
322 | newT.startParse(t.funcs, t.lex, t.treeSet) | ||
323 | newT.parseDefinition() | ||
324 | @@ -331,13 +344,15 @@ func (t *Tree) itemList() (list *ListNode, next Node) { | ||
325 | } | ||
326 | |||
327 | // textOrAction: | ||
328 | -// text | action | ||
329 | +// text | comment | action | ||
330 | func (t *Tree) textOrAction() Node { | ||
331 | switch token := t.nextNonSpace(); token.typ { | ||
332 | case itemText: | ||
333 | return t.newText(token.pos, token.val) | ||
334 | case itemLeftDelim: | ||
335 | return t.action() | ||
336 | + case itemComment: | ||
337 | + return t.newComment(token.pos, token.val) | ||
338 | default: | ||
339 | t.unexpected(token, "input") | ||
340 | } | ||
341 | @@ -539,6 +554,7 @@ func (t *Tree) blockControl() Node { | ||
342 | |||
343 | block := New(name) // name will be updated once we know it. | ||
344 | block.text = t.text | ||
345 | + block.Mode = t.Mode | ||
346 | block.ParseName = t.ParseName | ||
347 | block.startParse(t.funcs, t.lex, t.treeSet) | ||
348 | var end Node | ||
349 | diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go | ||
350 | index 4e09a78..d9c13c5 100644 | ||
351 | --- a/src/text/template/parse/parse_test.go | ||
352 | +++ b/src/text/template/parse/parse_test.go | ||
353 | @@ -348,6 +348,30 @@ func TestParseCopy(t *testing.T) { | ||
354 | testParse(true, t) | ||
355 | } | ||
356 | |||
357 | +func TestParseWithComments(t *testing.T) { | ||
358 | + textFormat = "%q" | ||
359 | + defer func() { textFormat = "%s" }() | ||
360 | + tests := [...]parseTest{ | ||
361 | + {"comment", "{{/*\n\n\n*/}}", noError, "{{/*\n\n\n*/}}"}, | ||
362 | + {"comment trim left", "x \r\n\t{{- /* hi */}}", noError, `"x"{{/* hi */}}`}, | ||
363 | + {"comment trim right", "{{/* hi */ -}}\n\n\ty", noError, `{{/* hi */}}"y"`}, | ||
364 | + {"comment trim left and right", "x \r\n\t{{- /* */ -}}\n\n\ty", noError, `"x"{{/* */}}"y"`}, | ||
365 | + } | ||
366 | + for _, test := range tests { | ||
367 | + t.Run(test.name, func(t *testing.T) { | ||
368 | + tr := New(test.name) | ||
369 | + tr.Mode = ParseComments | ||
370 | + tmpl, err := tr.Parse(test.input, "", "", make(map[string]*Tree)) | ||
371 | + if err != nil { | ||
372 | + t.Errorf("%q: expected error; got none", test.name) | ||
373 | + } | ||
374 | + if result := tmpl.Root.String(); result != test.result { | ||
375 | + t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result) | ||
376 | + } | ||
377 | + }) | ||
378 | + } | ||
379 | +} | ||
380 | + | ||
381 | type isEmptyTest struct { | ||
382 | name string | ||
383 | input string | ||
384 | @@ -358,6 +382,7 @@ var isEmptyTests = []isEmptyTest{ | ||
385 | {"empty", ``, true}, | ||
386 | {"nonempty", `hello`, false}, | ||
387 | {"spaces only", " \t\n \t\n", true}, | ||
388 | + {"comment only", "{{/* comment */}}", true}, | ||
389 | {"definition", `{{define "x"}}something{{end}}`, true}, | ||
390 | {"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true}, | ||
391 | {"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n", false}, | ||
392 | -- | ||
393 | 2.7.4 | ||
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch new file mode 100644 index 0000000000..d5e2eb6684 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch | |||
@@ -0,0 +1,497 @@ | |||
1 | From 760d88497091fb5d6d231a18e6f4e06ecb9af9b2 Mon Sep 17 00:00:00 2001 | ||
2 | From: Russ Cox <rsc@golang.org> | ||
3 | Date: Thu, 10 Sep 2020 18:53:26 -0400 | ||
4 | Subject: [PATCH 4/6] text/template: allow newlines inside action delimiters | ||
5 | |||
6 | This allows multiline constructs like: | ||
7 | |||
8 | {{"hello" | | ||
9 | printf}} | ||
10 | |||
11 | Now that unclosed actions can span multiple lines, | ||
12 | track and report the start of the action when reporting errors. | ||
13 | |||
14 | Also clean up a few "unexpected <error message>" to be just "<error message>". | ||
15 | |||
16 | Fixes #29770. | ||
17 | |||
18 | Change-Id: I54c6c016029a8328b7902a4b6d85eab713ec3285 | ||
19 | Reviewed-on: https://go-review.googlesource.com/c/go/+/254257 | ||
20 | Trust: Russ Cox <rsc@golang.org> | ||
21 | Run-TryBot: Russ Cox <rsc@golang.org> | ||
22 | TryBot-Result: Go Bot <gobot@golang.org> | ||
23 | Reviewed-by: Rob Pike <r@golang.org> | ||
24 | |||
25 | Dependency Patch #4 | ||
26 | |||
27 | Upstream-Status: Backport from https://github.com/golang/go/commit/9384d34c58099657bb1b133beaf3ff37ada9b017 | ||
28 | CVE: CVE-2023-24538 | ||
29 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> | ||
30 | --- | ||
31 | src/text/template/doc.go | 21 ++++----- | ||
32 | src/text/template/exec_test.go | 2 +- | ||
33 | src/text/template/parse/lex.go | 84 +++++++++++++++++------------------ | ||
34 | src/text/template/parse/lex_test.go | 2 +- | ||
35 | src/text/template/parse/parse.go | 59 +++++++++++++----------- | ||
36 | src/text/template/parse/parse_test.go | 36 ++++++++++++--- | ||
37 | 6 files changed, 117 insertions(+), 87 deletions(-) | ||
38 | |||
39 | diff --git a/src/text/template/doc.go b/src/text/template/doc.go | ||
40 | index 4b0efd2..7b30294 100644 | ||
41 | --- a/src/text/template/doc.go | ||
42 | +++ b/src/text/template/doc.go | ||
43 | @@ -40,16 +40,17 @@ More intricate examples appear below. | ||
44 | Text and spaces | ||
45 | |||
46 | By default, all text between actions is copied verbatim when the template is | ||
47 | -executed. For example, the string " items are made of " in the example above appears | ||
48 | -on standard output when the program is run. | ||
49 | - | ||
50 | -However, to aid in formatting template source code, if an action's left delimiter | ||
51 | -(by default "{{") is followed immediately by a minus sign and ASCII space character | ||
52 | -("{{- "), all trailing white space is trimmed from the immediately preceding text. | ||
53 | -Similarly, if the right delimiter ("}}") is preceded by a space and minus sign | ||
54 | -(" -}}"), all leading white space is trimmed from the immediately following text. | ||
55 | -In these trim markers, the ASCII space must be present; "{{-3}}" parses as an | ||
56 | -action containing the number -3. | ||
57 | +executed. For example, the string " items are made of " in the example above | ||
58 | +appears on standard output when the program is run. | ||
59 | + | ||
60 | +However, to aid in formatting template source code, if an action's left | ||
61 | +delimiter (by default "{{") is followed immediately by a minus sign and white | ||
62 | +space, all trailing white space is trimmed from the immediately preceding text. | ||
63 | +Similarly, if the right delimiter ("}}") is preceded by white space and a minus | ||
64 | +sign, all leading white space is trimmed from the immediately following text. | ||
65 | +In these trim markers, the white space must be present: | ||
66 | +"{{- 3}}" is like "{{3}}" but trims the immediately preceding text, while | ||
67 | +"{{-3}}" parses as an action containing the number -3. | ||
68 | |||
69 | For instance, when executing the template whose source is | ||
70 | |||
71 | diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go | ||
72 | index b8a809e..3309b33 100644 | ||
73 | --- a/src/text/template/exec_test.go | ||
74 | +++ b/src/text/template/exec_test.go | ||
75 | @@ -1295,7 +1295,7 @@ func TestUnterminatedStringError(t *testing.T) { | ||
76 | t.Fatal("expected error") | ||
77 | } | ||
78 | str := err.Error() | ||
79 | - if !strings.Contains(str, "X:3: unexpected unterminated raw quoted string") { | ||
80 | + if !strings.Contains(str, "X:3: unterminated raw quoted string") { | ||
81 | t.Fatalf("unexpected error: %s", str) | ||
82 | } | ||
83 | } | ||
84 | diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go | ||
85 | index e41373a..6784071 100644 | ||
86 | --- a/src/text/template/parse/lex.go | ||
87 | +++ b/src/text/template/parse/lex.go | ||
88 | @@ -92,15 +92,14 @@ const eof = -1 | ||
89 | // If the action begins "{{- " rather than "{{", then all space/tab/newlines | ||
90 | // preceding the action are trimmed; conversely if it ends " -}}" the | ||
91 | // leading spaces are trimmed. This is done entirely in the lexer; the | ||
92 | -// parser never sees it happen. We require an ASCII space to be | ||
93 | -// present to avoid ambiguity with things like "{{-3}}". It reads | ||
94 | +// parser never sees it happen. We require an ASCII space (' ', \t, \r, \n) | ||
95 | +// to be present to avoid ambiguity with things like "{{-3}}". It reads | ||
96 | // better with the space present anyway. For simplicity, only ASCII | ||
97 | -// space does the job. | ||
98 | +// does the job. | ||
99 | const ( | ||
100 | - spaceChars = " \t\r\n" // These are the space characters defined by Go itself. | ||
101 | - leftTrimMarker = "- " // Attached to left delimiter, trims trailing spaces from preceding text. | ||
102 | - rightTrimMarker = " -" // Attached to right delimiter, trims leading spaces from following text. | ||
103 | - trimMarkerLen = Pos(len(leftTrimMarker)) | ||
104 | + spaceChars = " \t\r\n" // These are the space characters defined by Go itself. | ||
105 | + trimMarker = '-' // Attached to left/right delimiter, trims trailing spaces from preceding/following text. | ||
106 | + trimMarkerLen = Pos(1 + 1) // marker plus space before or after | ||
107 | ) | ||
108 | |||
109 | // stateFn represents the state of the scanner as a function that returns the next state. | ||
110 | @@ -108,19 +107,18 @@ type stateFn func(*lexer) stateFn | ||
111 | |||
112 | // lexer holds the state of the scanner. | ||
113 | type lexer struct { | ||
114 | - name string // the name of the input; used only for error reports | ||
115 | - input string // the string being scanned | ||
116 | - leftDelim string // start of action | ||
117 | - rightDelim string // end of action | ||
118 | - trimRightDelim string // end of action with trim marker | ||
119 | - emitComment bool // emit itemComment tokens. | ||
120 | - pos Pos // current position in the input | ||
121 | - start Pos // start position of this item | ||
122 | - width Pos // width of last rune read from input | ||
123 | - items chan item // channel of scanned items | ||
124 | - parenDepth int // nesting depth of ( ) exprs | ||
125 | - line int // 1+number of newlines seen | ||
126 | - startLine int // start line of this item | ||
127 | + name string // the name of the input; used only for error reports | ||
128 | + input string // the string being scanned | ||
129 | + leftDelim string // start of action | ||
130 | + rightDelim string // end of action | ||
131 | + emitComment bool // emit itemComment tokens. | ||
132 | + pos Pos // current position in the input | ||
133 | + start Pos // start position of this item | ||
134 | + width Pos // width of last rune read from input | ||
135 | + items chan item // channel of scanned items | ||
136 | + parenDepth int // nesting depth of ( ) exprs | ||
137 | + line int // 1+number of newlines seen | ||
138 | + startLine int // start line of this item | ||
139 | } | ||
140 | |||
141 | // next returns the next rune in the input. | ||
142 | @@ -213,15 +211,14 @@ func lex(name, input, left, right string, emitComment bool) *lexer { | ||
143 | right = rightDelim | ||
144 | } | ||
145 | l := &lexer{ | ||
146 | - name: name, | ||
147 | - input: input, | ||
148 | - leftDelim: left, | ||
149 | - rightDelim: right, | ||
150 | - trimRightDelim: rightTrimMarker + right, | ||
151 | - emitComment: emitComment, | ||
152 | - items: make(chan item), | ||
153 | - line: 1, | ||
154 | - startLine: 1, | ||
155 | + name: name, | ||
156 | + input: input, | ||
157 | + leftDelim: left, | ||
158 | + rightDelim: right, | ||
159 | + emitComment: emitComment, | ||
160 | + items: make(chan item), | ||
161 | + line: 1, | ||
162 | + startLine: 1, | ||
163 | } | ||
164 | go l.run() | ||
165 | return l | ||
166 | @@ -251,7 +248,7 @@ func lexText(l *lexer) stateFn { | ||
167 | ldn := Pos(len(l.leftDelim)) | ||
168 | l.pos += Pos(x) | ||
169 | trimLength := Pos(0) | ||
170 | - if strings.HasPrefix(l.input[l.pos+ldn:], leftTrimMarker) { | ||
171 | + if hasLeftTrimMarker(l.input[l.pos+ldn:]) { | ||
172 | trimLength = rightTrimLength(l.input[l.start:l.pos]) | ||
173 | } | ||
174 | l.pos -= trimLength | ||
175 | @@ -280,7 +277,7 @@ func rightTrimLength(s string) Pos { | ||
176 | |||
177 | // atRightDelim reports whether the lexer is at a right delimiter, possibly preceded by a trim marker. | ||
178 | func (l *lexer) atRightDelim() (delim, trimSpaces bool) { | ||
179 | - if strings.HasPrefix(l.input[l.pos:], l.trimRightDelim) { // With trim marker. | ||
180 | + if hasRightTrimMarker(l.input[l.pos:]) && strings.HasPrefix(l.input[l.pos+trimMarkerLen:], l.rightDelim) { // With trim marker. | ||
181 | return true, true | ||
182 | } | ||
183 | if strings.HasPrefix(l.input[l.pos:], l.rightDelim) { // Without trim marker. | ||
184 | @@ -297,7 +294,7 @@ func leftTrimLength(s string) Pos { | ||
185 | // lexLeftDelim scans the left delimiter, which is known to be present, possibly with a trim marker. | ||
186 | func lexLeftDelim(l *lexer) stateFn { | ||
187 | l.pos += Pos(len(l.leftDelim)) | ||
188 | - trimSpace := strings.HasPrefix(l.input[l.pos:], leftTrimMarker) | ||
189 | + trimSpace := hasLeftTrimMarker(l.input[l.pos:]) | ||
190 | afterMarker := Pos(0) | ||
191 | if trimSpace { | ||
192 | afterMarker = trimMarkerLen | ||
193 | @@ -342,7 +339,7 @@ func lexComment(l *lexer) stateFn { | ||
194 | |||
195 | // lexRightDelim scans the right delimiter, which is known to be present, possibly with a trim marker. | ||
196 | func lexRightDelim(l *lexer) stateFn { | ||
197 | - trimSpace := strings.HasPrefix(l.input[l.pos:], rightTrimMarker) | ||
198 | + trimSpace := hasRightTrimMarker(l.input[l.pos:]) | ||
199 | if trimSpace { | ||
200 | l.pos += trimMarkerLen | ||
201 | l.ignore() | ||
202 | @@ -369,7 +366,7 @@ func lexInsideAction(l *lexer) stateFn { | ||
203 | return l.errorf("unclosed left paren") | ||
204 | } | ||
205 | switch r := l.next(); { | ||
206 | - case r == eof || isEndOfLine(r): | ||
207 | + case r == eof: | ||
208 | return l.errorf("unclosed action") | ||
209 | case isSpace(r): | ||
210 | l.backup() // Put space back in case we have " -}}". | ||
211 | @@ -439,7 +436,7 @@ func lexSpace(l *lexer) stateFn { | ||
212 | } | ||
213 | // Be careful about a trim-marked closing delimiter, which has a minus | ||
214 | // after a space. We know there is a space, so check for the '-' that might follow. | ||
215 | - if strings.HasPrefix(l.input[l.pos-1:], l.trimRightDelim) { | ||
216 | + if hasRightTrimMarker(l.input[l.pos-1:]) && strings.HasPrefix(l.input[l.pos-1+trimMarkerLen:], l.rightDelim) { | ||
217 | l.backup() // Before the space. | ||
218 | if numSpaces == 1 { | ||
219 | return lexRightDelim // On the delim, so go right to that. | ||
220 | @@ -526,7 +523,7 @@ func lexFieldOrVariable(l *lexer, typ itemType) stateFn { | ||
221 | // day to implement arithmetic. | ||
222 | func (l *lexer) atTerminator() bool { | ||
223 | r := l.peek() | ||
224 | - if isSpace(r) || isEndOfLine(r) { | ||
225 | + if isSpace(r) { | ||
226 | return true | ||
227 | } | ||
228 | switch r { | ||
229 | @@ -657,15 +654,18 @@ Loop: | ||
230 | |||
231 | // isSpace reports whether r is a space character. | ||
232 | func isSpace(r rune) bool { | ||
233 | - return r == ' ' || r == '\t' | ||
234 | -} | ||
235 | - | ||
236 | -// isEndOfLine reports whether r is an end-of-line character. | ||
237 | -func isEndOfLine(r rune) bool { | ||
238 | - return r == '\r' || r == '\n' | ||
239 | + return r == ' ' || r == '\t' || r == '\r' || r == '\n' | ||
240 | } | ||
241 | |||
242 | // isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. | ||
243 | func isAlphaNumeric(r rune) bool { | ||
244 | return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) | ||
245 | } | ||
246 | + | ||
247 | +func hasLeftTrimMarker(s string) bool { | ||
248 | + return len(s) >= 2 && s[0] == trimMarker && isSpace(rune(s[1])) | ||
249 | +} | ||
250 | + | ||
251 | +func hasRightTrimMarker(s string) bool { | ||
252 | + return len(s) >= 2 && isSpace(rune(s[0])) && s[1] == trimMarker | ||
253 | +} | ||
254 | diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go | ||
255 | index f6d5f28..6510eed 100644 | ||
256 | --- a/src/text/template/parse/lex_test.go | ||
257 | +++ b/src/text/template/parse/lex_test.go | ||
258 | @@ -323,7 +323,7 @@ var lexTests = []lexTest{ | ||
259 | tLeft, | ||
260 | mkItem(itemError, "unrecognized character in action: U+0001"), | ||
261 | }}, | ||
262 | - {"unclosed action", "{{\n}}", []item{ | ||
263 | + {"unclosed action", "{{", []item{ | ||
264 | tLeft, | ||
265 | mkItem(itemError, "unclosed action"), | ||
266 | }}, | ||
267 | diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go | ||
268 | index 496d8bf..5e6e512 100644 | ||
269 | --- a/src/text/template/parse/parse.go | ||
270 | +++ b/src/text/template/parse/parse.go | ||
271 | @@ -24,13 +24,14 @@ type Tree struct { | ||
272 | Mode Mode // parsing mode. | ||
273 | text string // text parsed to create the template (or its parent) | ||
274 | // Parsing only; cleared after parse. | ||
275 | - funcs []map[string]interface{} | ||
276 | - lex *lexer | ||
277 | - token [3]item // three-token lookahead for parser. | ||
278 | - peekCount int | ||
279 | - vars []string // variables defined at the moment. | ||
280 | - treeSet map[string]*Tree | ||
281 | - mode Mode | ||
282 | + funcs []map[string]interface{} | ||
283 | + lex *lexer | ||
284 | + token [3]item // three-token lookahead for parser. | ||
285 | + peekCount int | ||
286 | + vars []string // variables defined at the moment. | ||
287 | + treeSet map[string]*Tree | ||
288 | + actionLine int // line of left delim starting action | ||
289 | + mode Mode | ||
290 | } | ||
291 | |||
292 | // A mode value is a set of flags (or 0). Modes control parser behavior. | ||
293 | @@ -187,6 +188,16 @@ func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item { | ||
294 | |||
295 | // unexpected complains about the token and terminates processing. | ||
296 | func (t *Tree) unexpected(token item, context string) { | ||
297 | + if token.typ == itemError { | ||
298 | + extra := "" | ||
299 | + if t.actionLine != 0 && t.actionLine != token.line { | ||
300 | + extra = fmt.Sprintf(" in action started at %s:%d", t.ParseName, t.actionLine) | ||
301 | + if strings.HasSuffix(token.val, " action") { | ||
302 | + extra = extra[len(" in action"):] // avoid "action in action" | ||
303 | + } | ||
304 | + } | ||
305 | + t.errorf("%s%s", token, extra) | ||
306 | + } | ||
307 | t.errorf("unexpected %s in %s", token, context) | ||
308 | } | ||
309 | |||
310 | @@ -350,6 +361,8 @@ func (t *Tree) textOrAction() Node { | ||
311 | case itemText: | ||
312 | return t.newText(token.pos, token.val) | ||
313 | case itemLeftDelim: | ||
314 | + t.actionLine = token.line | ||
315 | + defer t.clearActionLine() | ||
316 | return t.action() | ||
317 | case itemComment: | ||
318 | return t.newComment(token.pos, token.val) | ||
319 | @@ -359,6 +372,10 @@ func (t *Tree) textOrAction() Node { | ||
320 | return nil | ||
321 | } | ||
322 | |||
323 | +func (t *Tree) clearActionLine() { | ||
324 | + t.actionLine = 0 | ||
325 | +} | ||
326 | + | ||
327 | // Action: | ||
328 | // control | ||
329 | // command ("|" command)* | ||
330 | @@ -384,12 +401,12 @@ func (t *Tree) action() (n Node) { | ||
331 | t.backup() | ||
332 | token := t.peek() | ||
333 | // Do not pop variables; they persist until "end". | ||
334 | - return t.newAction(token.pos, token.line, t.pipeline("command")) | ||
335 | + return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim)) | ||
336 | } | ||
337 | |||
338 | // Pipeline: | ||
339 | // declarations? command ('|' command)* | ||
340 | -func (t *Tree) pipeline(context string) (pipe *PipeNode) { | ||
341 | +func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) { | ||
342 | token := t.peekNonSpace() | ||
343 | pipe = t.newPipeline(token.pos, token.line, nil) | ||
344 | // Are there declarations or assignments? | ||
345 | @@ -430,12 +447,9 @@ decls: | ||
346 | } | ||
347 | for { | ||
348 | switch token := t.nextNonSpace(); token.typ { | ||
349 | - case itemRightDelim, itemRightParen: | ||
350 | + case end: | ||
351 | // At this point, the pipeline is complete | ||
352 | t.checkPipeline(pipe, context) | ||
353 | - if token.typ == itemRightParen { | ||
354 | - t.backup() | ||
355 | - } | ||
356 | return | ||
357 | case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier, | ||
358 | itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen: | ||
359 | @@ -464,7 +478,7 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context string) { | ||
360 | |||
361 | func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) { | ||
362 | defer t.popVars(len(t.vars)) | ||
363 | - pipe = t.pipeline(context) | ||
364 | + pipe = t.pipeline(context, itemRightDelim) | ||
365 | var next Node | ||
366 | list, next = t.itemList() | ||
367 | switch next.Type() { | ||
368 | @@ -550,7 +564,7 @@ func (t *Tree) blockControl() Node { | ||
369 | |||
370 | token := t.nextNonSpace() | ||
371 | name := t.parseTemplateName(token, context) | ||
372 | - pipe := t.pipeline(context) | ||
373 | + pipe := t.pipeline(context, itemRightDelim) | ||
374 | |||
375 | block := New(name) // name will be updated once we know it. | ||
376 | block.text = t.text | ||
377 | @@ -580,7 +594,7 @@ func (t *Tree) templateControl() Node { | ||
378 | if t.nextNonSpace().typ != itemRightDelim { | ||
379 | t.backup() | ||
380 | // Do not pop variables; they persist until "end". | ||
381 | - pipe = t.pipeline(context) | ||
382 | + pipe = t.pipeline(context, itemRightDelim) | ||
383 | } | ||
384 | return t.newTemplate(token.pos, token.line, name, pipe) | ||
385 | } | ||
386 | @@ -614,13 +628,12 @@ func (t *Tree) command() *CommandNode { | ||
387 | switch token := t.next(); token.typ { | ||
388 | case itemSpace: | ||
389 | continue | ||
390 | - case itemError: | ||
391 | - t.errorf("%s", token.val) | ||
392 | case itemRightDelim, itemRightParen: | ||
393 | t.backup() | ||
394 | case itemPipe: | ||
395 | + // nothing here; break loop below | ||
396 | default: | ||
397 | - t.errorf("unexpected %s in operand", token) | ||
398 | + t.unexpected(token, "operand") | ||
399 | } | ||
400 | break | ||
401 | } | ||
402 | @@ -675,8 +688,6 @@ func (t *Tree) operand() Node { | ||
403 | // A nil return means the next item is not a term. | ||
404 | func (t *Tree) term() Node { | ||
405 | switch token := t.nextNonSpace(); token.typ { | ||
406 | - case itemError: | ||
407 | - t.errorf("%s", token.val) | ||
408 | case itemIdentifier: | ||
409 | if !t.hasFunction(token.val) { | ||
410 | t.errorf("function %q not defined", token.val) | ||
411 | @@ -699,11 +710,7 @@ func (t *Tree) term() Node { | ||
412 | } | ||
413 | return number | ||
414 | case itemLeftParen: | ||
415 | - pipe := t.pipeline("parenthesized pipeline") | ||
416 | - if token := t.next(); token.typ != itemRightParen { | ||
417 | - t.errorf("unclosed right paren: unexpected %s", token) | ||
418 | - } | ||
419 | - return pipe | ||
420 | + return t.pipeline("parenthesized pipeline", itemRightParen) | ||
421 | case itemString, itemRawString: | ||
422 | s, err := strconv.Unquote(token.val) | ||
423 | if err != nil { | ||
424 | diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go | ||
425 | index d9c13c5..220f984 100644 | ||
426 | --- a/src/text/template/parse/parse_test.go | ||
427 | +++ b/src/text/template/parse/parse_test.go | ||
428 | @@ -250,6 +250,13 @@ var parseTests = []parseTest{ | ||
429 | {"comment trim left and right", "x \r\n\t{{- /* */ -}}\n\n\ty", noError, `"x""y"`}, | ||
430 | {"block definition", `{{block "foo" .}}hello{{end}}`, noError, | ||
431 | `{{template "foo" .}}`}, | ||
432 | + | ||
433 | + {"newline in assignment", "{{ $x \n := \n 1 \n }}", noError, "{{$x := 1}}"}, | ||
434 | + {"newline in empty action", "{{\n}}", hasError, "{{\n}}"}, | ||
435 | + {"newline in pipeline", "{{\n\"x\"\n|\nprintf\n}}", noError, `{{"x" | printf}}`}, | ||
436 | + {"newline in comment", "{{/*\nhello\n*/}}", noError, ""}, | ||
437 | + {"newline in comment", "{{-\n/*\nhello\n*/\n-}}", noError, ""}, | ||
438 | + | ||
439 | // Errors. | ||
440 | {"unclosed action", "hello{{range", hasError, ""}, | ||
441 | {"unmatched end", "{{end}}", hasError, ""}, | ||
442 | @@ -426,23 +433,38 @@ var errorTests = []parseTest{ | ||
443 | // Check line numbers are accurate. | ||
444 | {"unclosed1", | ||
445 | "line1\n{{", | ||
446 | - hasError, `unclosed1:2: unexpected unclosed action in command`}, | ||
447 | + hasError, `unclosed1:2: unclosed action`}, | ||
448 | {"unclosed2", | ||
449 | "line1\n{{define `x`}}line2\n{{", | ||
450 | - hasError, `unclosed2:3: unexpected unclosed action in command`}, | ||
451 | + hasError, `unclosed2:3: unclosed action`}, | ||
452 | + {"unclosed3", | ||
453 | + "line1\n{{\"x\"\n\"y\"\n", | ||
454 | + hasError, `unclosed3:4: unclosed action started at unclosed3:2`}, | ||
455 | + {"unclosed4", | ||
456 | + "{{\n\n\n\n\n", | ||
457 | + hasError, `unclosed4:6: unclosed action started at unclosed4:1`}, | ||
458 | + {"var1", | ||
459 | + "line1\n{{\nx\n}}", | ||
460 | + hasError, `var1:3: function "x" not defined`}, | ||
461 | // Specific errors. | ||
462 | {"function", | ||
463 | "{{foo}}", | ||
464 | hasError, `function "foo" not defined`}, | ||
465 | - {"comment", | ||
466 | + {"comment1", | ||
467 | "{{/*}}", | ||
468 | - hasError, `unclosed comment`}, | ||
469 | + hasError, `comment1:1: unclosed comment`}, | ||
470 | + {"comment2", | ||
471 | + "{{/*\nhello\n}}", | ||
472 | + hasError, `comment2:1: unclosed comment`}, | ||
473 | {"lparen", | ||
474 | "{{.X (1 2 3}}", | ||
475 | hasError, `unclosed left paren`}, | ||
476 | {"rparen", | ||
477 | - "{{.X 1 2 3)}}", | ||
478 | - hasError, `unexpected ")"`}, | ||
479 | + "{{.X 1 2 3 ) }}", | ||
480 | + hasError, `unexpected ")" in command`}, | ||
481 | + {"rparen2", | ||
482 | + "{{(.X 1 2 3", | ||
483 | + hasError, `unclosed action`}, | ||
484 | {"space", | ||
485 | "{{`x`3}}", | ||
486 | hasError, `in operand`}, | ||
487 | @@ -488,7 +510,7 @@ var errorTests = []parseTest{ | ||
488 | hasError, `missing value for parenthesized pipeline`}, | ||
489 | {"multilinerawstring", | ||
490 | "{{ $v := `\n` }} {{", | ||
491 | - hasError, `multilinerawstring:2: unexpected unclosed action`}, | ||
492 | + hasError, `multilinerawstring:2: unclosed action`}, | ||
493 | {"rangeundefvar", | ||
494 | "{{range $k}}{{end}}", | ||
495 | hasError, `undefined variable`}, | ||
496 | -- | ||
497 | 2.7.4 | ||
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_5.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_5.patch new file mode 100644 index 0000000000..fc38929648 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_5.patch | |||
@@ -0,0 +1,585 @@ | |||
1 | From e0e6bca6ddc0e6d9fa3a5b644af9b446924fbf83 Mon Sep 17 00:00:00 2001 | ||
2 | From: Russ Cox <rsc@golang.org> | ||
3 | Date: Thu, 20 May 2021 12:46:33 -0400 | ||
4 | Subject: [PATCH 5/6] html/template, text/template: implement break and | ||
5 | continue for range loops | ||
6 | |||
7 | Break and continue for range loops was accepted as a proposal in June 2017. | ||
8 | It was implemented in CL 66410 (Oct 2017) | ||
9 | but then rolled back in CL 92155 (Feb 2018) | ||
10 | because html/template changes had not been implemented. | ||
11 | |||
12 | This CL reimplements break and continue in text/template | ||
13 | and then adds support for them in html/template as well. | ||
14 | |||
15 | Fixes #20531. | ||
16 | |||
17 | Change-Id: I05330482a976f1c078b4b49c2287bd9031bb7616 | ||
18 | Reviewed-on: https://go-review.googlesource.com/c/go/+/321491 | ||
19 | Trust: Russ Cox <rsc@golang.org> | ||
20 | Run-TryBot: Russ Cox <rsc@golang.org> | ||
21 | TryBot-Result: Go Bot <gobot@golang.org> | ||
22 | Reviewed-by: Rob Pike <r@golang.org> | ||
23 | |||
24 | Dependency Patch #5 | ||
25 | |||
26 | Upstream-Status: Backport from https://github.com/golang/go/commit/d0dd26a88c019d54f22463daae81e785f5867565 | ||
27 | CVE: CVE-2023-24538 | ||
28 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> | ||
29 | --- | ||
30 | src/html/template/context.go | 4 ++ | ||
31 | src/html/template/escape.go | 71 ++++++++++++++++++++++++++++++++++- | ||
32 | src/html/template/escape_test.go | 24 ++++++++++++ | ||
33 | src/text/template/doc.go | 8 ++++ | ||
34 | src/text/template/exec.go | 24 +++++++++++- | ||
35 | src/text/template/exec_test.go | 2 + | ||
36 | src/text/template/parse/lex.go | 13 ++++++- | ||
37 | src/text/template/parse/lex_test.go | 2 + | ||
38 | src/text/template/parse/node.go | 36 ++++++++++++++++++ | ||
39 | src/text/template/parse/parse.go | 42 ++++++++++++++++++++- | ||
40 | src/text/template/parse/parse_test.go | 8 ++++ | ||
41 | 11 files changed, 230 insertions(+), 4 deletions(-) | ||
42 | |||
43 | diff --git a/src/html/template/context.go b/src/html/template/context.go | ||
44 | index f7d4849..aaa7d08 100644 | ||
45 | --- a/src/html/template/context.go | ||
46 | +++ b/src/html/template/context.go | ||
47 | @@ -6,6 +6,7 @@ package template | ||
48 | |||
49 | import ( | ||
50 | "fmt" | ||
51 | + "text/template/parse" | ||
52 | ) | ||
53 | |||
54 | // context describes the state an HTML parser must be in when it reaches the | ||
55 | @@ -22,6 +23,7 @@ type context struct { | ||
56 | jsCtx jsCtx | ||
57 | attr attr | ||
58 | element element | ||
59 | + n parse.Node // for range break/continue | ||
60 | err *Error | ||
61 | } | ||
62 | |||
63 | @@ -141,6 +143,8 @@ const ( | ||
64 | // stateError is an infectious error state outside any valid | ||
65 | // HTML/CSS/JS construct. | ||
66 | stateError | ||
67 | + // stateDead marks unreachable code after a {{break}} or {{continue}}. | ||
68 | + stateDead | ||
69 | ) | ||
70 | |||
71 | // isComment is true for any state that contains content meant for template | ||
72 | diff --git a/src/html/template/escape.go b/src/html/template/escape.go | ||
73 | index 8739735..6dea79c 100644 | ||
74 | --- a/src/html/template/escape.go | ||
75 | +++ b/src/html/template/escape.go | ||
76 | @@ -97,6 +97,15 @@ type escaper struct { | ||
77 | actionNodeEdits map[*parse.ActionNode][]string | ||
78 | templateNodeEdits map[*parse.TemplateNode]string | ||
79 | textNodeEdits map[*parse.TextNode][]byte | ||
80 | + // rangeContext holds context about the current range loop. | ||
81 | + rangeContext *rangeContext | ||
82 | +} | ||
83 | + | ||
84 | +// rangeContext holds information about the current range loop. | ||
85 | +type rangeContext struct { | ||
86 | + outer *rangeContext // outer loop | ||
87 | + breaks []context // context at each break action | ||
88 | + continues []context // context at each continue action | ||
89 | } | ||
90 | |||
91 | // makeEscaper creates a blank escaper for the given set. | ||
92 | @@ -109,6 +118,7 @@ func makeEscaper(n *nameSpace) escaper { | ||
93 | map[*parse.ActionNode][]string{}, | ||
94 | map[*parse.TemplateNode]string{}, | ||
95 | map[*parse.TextNode][]byte{}, | ||
96 | + nil, | ||
97 | } | ||
98 | } | ||
99 | |||
100 | @@ -124,8 +134,16 @@ func (e *escaper) escape(c context, n parse.Node) context { | ||
101 | switch n := n.(type) { | ||
102 | case *parse.ActionNode: | ||
103 | return e.escapeAction(c, n) | ||
104 | + case *parse.BreakNode: | ||
105 | + c.n = n | ||
106 | + e.rangeContext.breaks = append(e.rangeContext.breaks, c) | ||
107 | + return context{state: stateDead} | ||
108 | case *parse.CommentNode: | ||
109 | return c | ||
110 | + case *parse.ContinueNode: | ||
111 | + c.n = n | ||
112 | + e.rangeContext.continues = append(e.rangeContext.breaks, c) | ||
113 | + return context{state: stateDead} | ||
114 | case *parse.IfNode: | ||
115 | return e.escapeBranch(c, &n.BranchNode, "if") | ||
116 | case *parse.ListNode: | ||
117 | @@ -427,6 +445,12 @@ func join(a, b context, node parse.Node, nodeName string) context { | ||
118 | if b.state == stateError { | ||
119 | return b | ||
120 | } | ||
121 | + if a.state == stateDead { | ||
122 | + return b | ||
123 | + } | ||
124 | + if b.state == stateDead { | ||
125 | + return a | ||
126 | + } | ||
127 | if a.eq(b) { | ||
128 | return a | ||
129 | } | ||
130 | @@ -466,14 +490,27 @@ func join(a, b context, node parse.Node, nodeName string) context { | ||
131 | |||
132 | // escapeBranch escapes a branch template node: "if", "range" and "with". | ||
133 | func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context { | ||
134 | + if nodeName == "range" { | ||
135 | + e.rangeContext = &rangeContext{outer: e.rangeContext} | ||
136 | + } | ||
137 | c0 := e.escapeList(c, n.List) | ||
138 | - if nodeName == "range" && c0.state != stateError { | ||
139 | + if nodeName == "range" { | ||
140 | + if c0.state != stateError { | ||
141 | + c0 = joinRange(c0, e.rangeContext) | ||
142 | + } | ||
143 | + e.rangeContext = e.rangeContext.outer | ||
144 | + if c0.state == stateError { | ||
145 | + return c0 | ||
146 | + } | ||
147 | + | ||
148 | // The "true" branch of a "range" node can execute multiple times. | ||
149 | // We check that executing n.List once results in the same context | ||
150 | // as executing n.List twice. | ||
151 | + e.rangeContext = &rangeContext{outer: e.rangeContext} | ||
152 | c1, _ := e.escapeListConditionally(c0, n.List, nil) | ||
153 | c0 = join(c0, c1, n, nodeName) | ||
154 | if c0.state == stateError { | ||
155 | + e.rangeContext = e.rangeContext.outer | ||
156 | // Make clear that this is a problem on loop re-entry | ||
157 | // since developers tend to overlook that branch when | ||
158 | // debugging templates. | ||
159 | @@ -481,11 +518,39 @@ func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) | ||
160 | c0.err.Description = "on range loop re-entry: " + c0.err.Description | ||
161 | return c0 | ||
162 | } | ||
163 | + c0 = joinRange(c0, e.rangeContext) | ||
164 | + e.rangeContext = e.rangeContext.outer | ||
165 | + if c0.state == stateError { | ||
166 | + return c0 | ||
167 | + } | ||
168 | } | ||
169 | c1 := e.escapeList(c, n.ElseList) | ||
170 | return join(c0, c1, n, nodeName) | ||
171 | } | ||
172 | |||
173 | +func joinRange(c0 context, rc *rangeContext) context { | ||
174 | + // Merge contexts at break and continue statements into overall body context. | ||
175 | + // In theory we could treat breaks differently from continues, but for now it is | ||
176 | + // enough to treat them both as going back to the start of the loop (which may then stop). | ||
177 | + for _, c := range rc.breaks { | ||
178 | + c0 = join(c0, c, c.n, "range") | ||
179 | + if c0.state == stateError { | ||
180 | + c0.err.Line = c.n.(*parse.BreakNode).Line | ||
181 | + c0.err.Description = "at range loop break: " + c0.err.Description | ||
182 | + return c0 | ||
183 | + } | ||
184 | + } | ||
185 | + for _, c := range rc.continues { | ||
186 | + c0 = join(c0, c, c.n, "range") | ||
187 | + if c0.state == stateError { | ||
188 | + c0.err.Line = c.n.(*parse.ContinueNode).Line | ||
189 | + c0.err.Description = "at range loop continue: " + c0.err.Description | ||
190 | + return c0 | ||
191 | + } | ||
192 | + } | ||
193 | + return c0 | ||
194 | +} | ||
195 | + | ||
196 | // escapeList escapes a list template node. | ||
197 | func (e *escaper) escapeList(c context, n *parse.ListNode) context { | ||
198 | if n == nil { | ||
199 | @@ -493,6 +558,9 @@ func (e *escaper) escapeList(c context, n *parse.ListNode) context { | ||
200 | } | ||
201 | for _, m := range n.Nodes { | ||
202 | c = e.escape(c, m) | ||
203 | + if c.state == stateDead { | ||
204 | + break | ||
205 | + } | ||
206 | } | ||
207 | return c | ||
208 | } | ||
209 | @@ -503,6 +571,7 @@ func (e *escaper) escapeList(c context, n *parse.ListNode) context { | ||
210 | // which is the same as whether e was updated. | ||
211 | func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) { | ||
212 | e1 := makeEscaper(e.ns) | ||
213 | + e1.rangeContext = e.rangeContext | ||
214 | // Make type inferences available to f. | ||
215 | for k, v := range e.output { | ||
216 | e1.output[k] = v | ||
217 | diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go | ||
218 | index c709660..fa2b84a 100644 | ||
219 | --- a/src/html/template/escape_test.go | ||
220 | +++ b/src/html/template/escape_test.go | ||
221 | @@ -920,6 +920,22 @@ func TestErrors(t *testing.T) { | ||
222 | "<a href='/foo?{{range .Items}}&{{.K}}={{.V}}{{end}}'>", | ||
223 | "", | ||
224 | }, | ||
225 | + { | ||
226 | + "{{range .Items}}<a{{if .X}}{{end}}>{{end}}", | ||
227 | + "", | ||
228 | + }, | ||
229 | + { | ||
230 | + "{{range .Items}}<a{{if .X}}{{end}}>{{continue}}{{end}}", | ||
231 | + "", | ||
232 | + }, | ||
233 | + { | ||
234 | + "{{range .Items}}<a{{if .X}}{{end}}>{{break}}{{end}}", | ||
235 | + "", | ||
236 | + }, | ||
237 | + { | ||
238 | + "{{range .Items}}<a{{if .X}}{{end}}>{{if .X}}{{break}}{{end}}{{end}}", | ||
239 | + "", | ||
240 | + }, | ||
241 | // Error cases. | ||
242 | { | ||
243 | "{{if .Cond}}<a{{end}}", | ||
244 | @@ -956,6 +972,14 @@ func TestErrors(t *testing.T) { | ||
245 | "z:2:8: on range loop re-entry: {{range}} branches", | ||
246 | }, | ||
247 | { | ||
248 | + "{{range .Items}}<a{{if .X}}{{break}}{{end}}>{{end}}", | ||
249 | + "z:1:29: at range loop break: {{range}} branches end in different contexts", | ||
250 | + }, | ||
251 | + { | ||
252 | + "{{range .Items}}<a{{if .X}}{{continue}}{{end}}>{{end}}", | ||
253 | + "z:1:29: at range loop continue: {{range}} branches end in different contexts", | ||
254 | + }, | ||
255 | + { | ||
256 | "<a b=1 c={{.H}}", | ||
257 | "z: ends in a non-text context: {stateAttr delimSpaceOrTagEnd", | ||
258 | }, | ||
259 | diff --git a/src/text/template/doc.go b/src/text/template/doc.go | ||
260 | index 7b30294..0228b15 100644 | ||
261 | --- a/src/text/template/doc.go | ||
262 | +++ b/src/text/template/doc.go | ||
263 | @@ -112,6 +112,14 @@ data, defined in detail in the corresponding sections that follow. | ||
264 | T0 is executed; otherwise, dot is set to the successive elements | ||
265 | of the array, slice, or map and T1 is executed. | ||
266 | |||
267 | + {{break}} | ||
268 | + The innermost {{range pipeline}} loop is ended early, stopping the | ||
269 | + current iteration and bypassing all remaining iterations. | ||
270 | + | ||
271 | + {{continue}} | ||
272 | + The current iteration of the innermost {{range pipeline}} loop is | ||
273 | + stopped, and the loop starts the next iteration. | ||
274 | + | ||
275 | {{template "name"}} | ||
276 | The template with the specified name is executed with nil data. | ||
277 | |||
278 | diff --git a/src/text/template/exec.go b/src/text/template/exec.go | ||
279 | index 7ac5175..6cb140a 100644 | ||
280 | --- a/src/text/template/exec.go | ||
281 | +++ b/src/text/template/exec.go | ||
282 | @@ -5,6 +5,7 @@ | ||
283 | package template | ||
284 | |||
285 | import ( | ||
286 | + "errors" | ||
287 | "fmt" | ||
288 | "internal/fmtsort" | ||
289 | "io" | ||
290 | @@ -244,6 +245,12 @@ func (t *Template) DefinedTemplates() string { | ||
291 | return b.String() | ||
292 | } | ||
293 | |||
294 | +// Sentinel errors for use with panic to signal early exits from range loops. | ||
295 | +var ( | ||
296 | + walkBreak = errors.New("break") | ||
297 | + walkContinue = errors.New("continue") | ||
298 | +) | ||
299 | + | ||
300 | // Walk functions step through the major pieces of the template structure, | ||
301 | // generating output as they go. | ||
302 | func (s *state) walk(dot reflect.Value, node parse.Node) { | ||
303 | @@ -256,7 +263,11 @@ func (s *state) walk(dot reflect.Value, node parse.Node) { | ||
304 | if len(node.Pipe.Decl) == 0 { | ||
305 | s.printValue(node, val) | ||
306 | } | ||
307 | + case *parse.BreakNode: | ||
308 | + panic(walkBreak) | ||
309 | case *parse.CommentNode: | ||
310 | + case *parse.ContinueNode: | ||
311 | + panic(walkContinue) | ||
312 | case *parse.IfNode: | ||
313 | s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList) | ||
314 | case *parse.ListNode: | ||
315 | @@ -335,6 +346,11 @@ func isTrue(val reflect.Value) (truth, ok bool) { | ||
316 | |||
317 | func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { | ||
318 | s.at(r) | ||
319 | + defer func() { | ||
320 | + if r := recover(); r != nil && r != walkBreak { | ||
321 | + panic(r) | ||
322 | + } | ||
323 | + }() | ||
324 | defer s.pop(s.mark()) | ||
325 | val, _ := indirect(s.evalPipeline(dot, r.Pipe)) | ||
326 | // mark top of stack before any variables in the body are pushed. | ||
327 | @@ -348,8 +364,14 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { | ||
328 | if len(r.Pipe.Decl) > 1 { | ||
329 | s.setTopVar(2, index) | ||
330 | } | ||
331 | + defer s.pop(mark) | ||
332 | + defer func() { | ||
333 | + // Consume panic(walkContinue) | ||
334 | + if r := recover(); r != nil && r != walkContinue { | ||
335 | + panic(r) | ||
336 | + } | ||
337 | + }() | ||
338 | s.walk(elem, r.List) | ||
339 | - s.pop(mark) | ||
340 | } | ||
341 | switch val.Kind() { | ||
342 | case reflect.Array, reflect.Slice: | ||
343 | diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go | ||
344 | index 3309b33..a639f44 100644 | ||
345 | --- a/src/text/template/exec_test.go | ||
346 | +++ b/src/text/template/exec_test.go | ||
347 | @@ -563,6 +563,8 @@ var execTests = []execTest{ | ||
348 | {"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true}, | ||
349 | {"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true}, | ||
350 | {"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, | ||
351 | + {"range []int break else", "{{range .SI}}-{{.}}-{{break}}NOTREACHED{{else}}EMPTY{{end}}", "-3-", tVal, true}, | ||
352 | + {"range []int continue else", "{{range .SI}}-{{.}}-{{continue}}NOTREACHED{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true}, | ||
353 | {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true}, | ||
354 | {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true}, | ||
355 | {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true}, | ||
356 | diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go | ||
357 | index 6784071..95e3377 100644 | ||
358 | --- a/src/text/template/parse/lex.go | ||
359 | +++ b/src/text/template/parse/lex.go | ||
360 | @@ -62,6 +62,8 @@ const ( | ||
361 | // Keywords appear after all the rest. | ||
362 | itemKeyword // used only to delimit the keywords | ||
363 | itemBlock // block keyword | ||
364 | + itemBreak // break keyword | ||
365 | + itemContinue // continue keyword | ||
366 | itemDot // the cursor, spelled '.' | ||
367 | itemDefine // define keyword | ||
368 | itemElse // else keyword | ||
369 | @@ -76,6 +78,8 @@ const ( | ||
370 | var key = map[string]itemType{ | ||
371 | ".": itemDot, | ||
372 | "block": itemBlock, | ||
373 | + "break": itemBreak, | ||
374 | + "continue": itemContinue, | ||
375 | "define": itemDefine, | ||
376 | "else": itemElse, | ||
377 | "end": itemEnd, | ||
378 | @@ -119,6 +123,8 @@ type lexer struct { | ||
379 | parenDepth int // nesting depth of ( ) exprs | ||
380 | line int // 1+number of newlines seen | ||
381 | startLine int // start line of this item | ||
382 | + breakOK bool // break keyword allowed | ||
383 | + continueOK bool // continue keyword allowed | ||
384 | } | ||
385 | |||
386 | // next returns the next rune in the input. | ||
387 | @@ -461,7 +467,12 @@ Loop: | ||
388 | } | ||
389 | switch { | ||
390 | case key[word] > itemKeyword: | ||
391 | - l.emit(key[word]) | ||
392 | + item := key[word] | ||
393 | + if item == itemBreak && !l.breakOK || item == itemContinue && !l.continueOK { | ||
394 | + l.emit(itemIdentifier) | ||
395 | + } else { | ||
396 | + l.emit(item) | ||
397 | + } | ||
398 | case word[0] == '.': | ||
399 | l.emit(itemField) | ||
400 | case word == "true", word == "false": | ||
401 | diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go | ||
402 | index 6510eed..df6aabf 100644 | ||
403 | --- a/src/text/template/parse/lex_test.go | ||
404 | +++ b/src/text/template/parse/lex_test.go | ||
405 | @@ -35,6 +35,8 @@ var itemName = map[itemType]string{ | ||
406 | // keywords | ||
407 | itemDot: ".", | ||
408 | itemBlock: "block", | ||
409 | + itemBreak: "break", | ||
410 | + itemContinue: "continue", | ||
411 | itemDefine: "define", | ||
412 | itemElse: "else", | ||
413 | itemIf: "if", | ||
414 | diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go | ||
415 | index a9dad5e..c398da0 100644 | ||
416 | --- a/src/text/template/parse/node.go | ||
417 | +++ b/src/text/template/parse/node.go | ||
418 | @@ -71,6 +71,8 @@ const ( | ||
419 | NodeVariable // A $ variable. | ||
420 | NodeWith // A with action. | ||
421 | NodeComment // A comment. | ||
422 | + NodeBreak // A break action. | ||
423 | + NodeContinue // A continue action. | ||
424 | ) | ||
425 | |||
426 | // Nodes. | ||
427 | @@ -907,6 +909,40 @@ func (i *IfNode) Copy() Node { | ||
428 | return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList()) | ||
429 | } | ||
430 | |||
431 | +// BreakNode represents a {{break}} action. | ||
432 | +type BreakNode struct { | ||
433 | + tr *Tree | ||
434 | + NodeType | ||
435 | + Pos | ||
436 | + Line int | ||
437 | +} | ||
438 | + | ||
439 | +func (t *Tree) newBreak(pos Pos, line int) *BreakNode { | ||
440 | + return &BreakNode{tr: t, NodeType: NodeBreak, Pos: pos, Line: line} | ||
441 | +} | ||
442 | + | ||
443 | +func (b *BreakNode) Copy() Node { return b.tr.newBreak(b.Pos, b.Line) } | ||
444 | +func (b *BreakNode) String() string { return "{{break}}" } | ||
445 | +func (b *BreakNode) tree() *Tree { return b.tr } | ||
446 | +func (b *BreakNode) writeTo(sb *strings.Builder) { sb.WriteString("{{break}}") } | ||
447 | + | ||
448 | +// ContinueNode represents a {{continue}} action. | ||
449 | +type ContinueNode struct { | ||
450 | + tr *Tree | ||
451 | + NodeType | ||
452 | + Pos | ||
453 | + Line int | ||
454 | +} | ||
455 | + | ||
456 | +func (t *Tree) newContinue(pos Pos, line int) *ContinueNode { | ||
457 | + return &ContinueNode{tr: t, NodeType: NodeContinue, Pos: pos, Line: line} | ||
458 | +} | ||
459 | + | ||
460 | +func (c *ContinueNode) Copy() Node { return c.tr.newContinue(c.Pos, c.Line) } | ||
461 | +func (c *ContinueNode) String() string { return "{{continue}}" } | ||
462 | +func (c *ContinueNode) tree() *Tree { return c.tr } | ||
463 | +func (c *ContinueNode) writeTo(sb *strings.Builder) { sb.WriteString("{{continue}}") } | ||
464 | + | ||
465 | // RangeNode represents a {{range}} action and its commands. | ||
466 | type RangeNode struct { | ||
467 | BranchNode | ||
468 | diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go | ||
469 | index 5e6e512..7f78b56 100644 | ||
470 | --- a/src/text/template/parse/parse.go | ||
471 | +++ b/src/text/template/parse/parse.go | ||
472 | @@ -31,6 +31,7 @@ type Tree struct { | ||
473 | vars []string // variables defined at the moment. | ||
474 | treeSet map[string]*Tree | ||
475 | actionLine int // line of left delim starting action | ||
476 | + rangeDepth int | ||
477 | mode Mode | ||
478 | } | ||
479 | |||
480 | @@ -223,6 +224,8 @@ func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer, treeSet ma | ||
481 | t.vars = []string{"$"} | ||
482 | t.funcs = funcs | ||
483 | t.treeSet = treeSet | ||
484 | + lex.breakOK = !t.hasFunction("break") | ||
485 | + lex.continueOK = !t.hasFunction("continue") | ||
486 | } | ||
487 | |||
488 | // stopParse terminates parsing. | ||
489 | @@ -385,6 +388,10 @@ func (t *Tree) action() (n Node) { | ||
490 | switch token := t.nextNonSpace(); token.typ { | ||
491 | case itemBlock: | ||
492 | return t.blockControl() | ||
493 | + case itemBreak: | ||
494 | + return t.breakControl(token.pos, token.line) | ||
495 | + case itemContinue: | ||
496 | + return t.continueControl(token.pos, token.line) | ||
497 | case itemElse: | ||
498 | return t.elseControl() | ||
499 | case itemEnd: | ||
500 | @@ -404,6 +411,32 @@ func (t *Tree) action() (n Node) { | ||
501 | return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim)) | ||
502 | } | ||
503 | |||
504 | +// Break: | ||
505 | +// {{break}} | ||
506 | +// Break keyword is past. | ||
507 | +func (t *Tree) breakControl(pos Pos, line int) Node { | ||
508 | + if token := t.next(); token.typ != itemRightDelim { | ||
509 | + t.unexpected(token, "in {{break}}") | ||
510 | + } | ||
511 | + if t.rangeDepth == 0 { | ||
512 | + t.errorf("{{break}} outside {{range}}") | ||
513 | + } | ||
514 | + return t.newBreak(pos, line) | ||
515 | +} | ||
516 | + | ||
517 | +// Continue: | ||
518 | +// {{continue}} | ||
519 | +// Continue keyword is past. | ||
520 | +func (t *Tree) continueControl(pos Pos, line int) Node { | ||
521 | + if token := t.next(); token.typ != itemRightDelim { | ||
522 | + t.unexpected(token, "in {{continue}}") | ||
523 | + } | ||
524 | + if t.rangeDepth == 0 { | ||
525 | + t.errorf("{{continue}} outside {{range}}") | ||
526 | + } | ||
527 | + return t.newContinue(pos, line) | ||
528 | +} | ||
529 | + | ||
530 | // Pipeline: | ||
531 | // declarations? command ('|' command)* | ||
532 | func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) { | ||
533 | @@ -479,8 +512,14 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context string) { | ||
534 | func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) { | ||
535 | defer t.popVars(len(t.vars)) | ||
536 | pipe = t.pipeline(context, itemRightDelim) | ||
537 | + if context == "range" { | ||
538 | + t.rangeDepth++ | ||
539 | + } | ||
540 | var next Node | ||
541 | list, next = t.itemList() | ||
542 | + if context == "range" { | ||
543 | + t.rangeDepth-- | ||
544 | + } | ||
545 | switch next.Type() { | ||
546 | case nodeEnd: //done | ||
547 | case nodeElse: | ||
548 | @@ -522,7 +561,8 @@ func (t *Tree) ifControl() Node { | ||
549 | // {{range pipeline}} itemList {{else}} itemList {{end}} | ||
550 | // Range keyword is past. | ||
551 | func (t *Tree) rangeControl() Node { | ||
552 | - return t.newRange(t.parseControl(false, "range")) | ||
553 | + r := t.newRange(t.parseControl(false, "range")) | ||
554 | + return r | ||
555 | } | ||
556 | |||
557 | // With: | ||
558 | diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go | ||
559 | index 220f984..ba45636 100644 | ||
560 | --- a/src/text/template/parse/parse_test.go | ||
561 | +++ b/src/text/template/parse/parse_test.go | ||
562 | @@ -230,6 +230,10 @@ var parseTests = []parseTest{ | ||
563 | `{{range $x := .SI}}{{.}}{{end}}`}, | ||
564 | {"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError, | ||
565 | `{{range $x, $y := .SI}}{{.}}{{end}}`}, | ||
566 | + {"range with break", "{{range .SI}}{{.}}{{break}}{{end}}", noError, | ||
567 | + `{{range .SI}}{{.}}{{break}}{{end}}`}, | ||
568 | + {"range with continue", "{{range .SI}}{{.}}{{continue}}{{end}}", noError, | ||
569 | + `{{range .SI}}{{.}}{{continue}}{{end}}`}, | ||
570 | {"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError, | ||
571 | `{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`}, | ||
572 | {"template", "{{template `x`}}", noError, | ||
573 | @@ -279,6 +283,10 @@ var parseTests = []parseTest{ | ||
574 | {"adjacent args", "{{printf 3`x`}}", hasError, ""}, | ||
575 | {"adjacent args with .", "{{printf `x`.}}", hasError, ""}, | ||
576 | {"extra end after if", "{{if .X}}a{{else if .Y}}b{{end}}{{end}}", hasError, ""}, | ||
577 | + {"break outside range", "{{range .}}{{end}} {{break}}", hasError, ""}, | ||
578 | + {"continue outside range", "{{range .}}{{end}} {{continue}}", hasError, ""}, | ||
579 | + {"break in range else", "{{range .}}{{else}}{{break}}{{end}}", hasError, ""}, | ||
580 | + {"continue in range else", "{{range .}}{{else}}{{continue}}{{end}}", hasError, ""}, | ||
581 | // Other kinds of assignments and operators aren't available yet. | ||
582 | {"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"}, | ||
583 | {"bug0b", "{{$x += 1}}{{$x}}", hasError, ""}, | ||
584 | -- | ||
585 | 2.7.4 | ||
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-3.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch index d5bb33e091..baf400b891 100644 --- a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-3.patch +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch | |||
@@ -1,7 +1,7 @@ | |||
1 | From 16f4882984569f179d73967c9eee679bb9b098c5 Mon Sep 17 00:00:00 2001 | 1 | From 16f4882984569f179d73967c9eee679bb9b098c5 Mon Sep 17 00:00:00 2001 |
2 | From: Roland Shoemaker <bracewell@google.com> | 2 | From: Roland Shoemaker <bracewell@google.com> |
3 | Date: Mon, 20 Mar 2023 11:01:13 -0700 | 3 | Date: Mon, 20 Mar 2023 11:01:13 -0700 |
4 | Subject: [PATCH 3/3] html/template: disallow actions in JS template literals | 4 | Subject: [PATCH 6/6] html/template: disallow actions in JS template literals |
5 | 5 | ||
6 | ECMAScript 6 introduced template literals[0][1] which are delimited with | 6 | ECMAScript 6 introduced template literals[0][1] which are delimited with |
7 | backticks. These need to be escaped in a similar fashion to the | 7 | backticks. These need to be escaped in a similar fashion to the |
@@ -52,12 +52,15 @@ CVE: CVE-2023-24538 | |||
52 | Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com> | 52 | Signed-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 | ||
62 | diff --git a/src/html/template/context.go b/src/html/template/context.go | 65 | diff --git a/src/html/template/context.go b/src/html/template/context.go |
63 | index f7d4849..0b65313 100644 | 66 | index f7d4849..0b65313 100644 |
@@ -125,6 +128,104 @@ index f12dafa..29ca5b3 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: |
131 | diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go | ||
132 | index fa2b84a..1b150e9 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 | }, | ||
128 | diff --git a/src/html/template/js.go b/src/html/template/js.go | 229 | diff --git a/src/html/template/js.go b/src/html/template/js.go |
129 | index ea9c183..b888eaf 100644 | 230 | index 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`, |
249 | diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go | ||
250 | index 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 | }, | ||
148 | diff --git a/src/html/template/jsctx_string.go b/src/html/template/jsctx_string.go | 262 | diff --git a/src/html/template/jsctx_string.go b/src/html/template/jsctx_string.go |
149 | index dd1d87e..2394893 100644 | 263 | index 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} |
282 | diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go | ||
283 | index 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) { | ||
168 | diff --git a/src/html/template/transition.go b/src/html/template/transition.go | 331 | diff --git a/src/html/template/transition.go b/src/html/template/transition.go |
169 | index 06df679..92eb351 100644 | 332 | index 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.14/CVE-2023-39318.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-39318.patch index 20e70c0485..00def8fcda 100644 --- a/meta/recipes-devtools/go/go-1.14/CVE-2023-39318.patch +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-39318.patch | |||
@@ -34,9 +34,9 @@ Signed-off-by: Siddharth Doshi <sdoshi@mvista.com> | |||
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 | ||
41 | diff --git a/src/html/template/context.go b/src/html/template/context.go | 41 | diff --git a/src/html/template/context.go b/src/html/template/context.go |
42 | index 0b65313..4eb7891 100644 | 42 | index 0b65313..4eb7891 100644 |
@@ -105,14 +105,38 @@ diff --git a/src/html/template/state_string.go b/src/html/template/state_string. | |||
105 | index 05104be..b5cfe70 100644 | 105 | index 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 { |