On Fri, Sep 29, 2023 at 9:06 AM Shubham Kulkarni <skulka...@mvista.com> wrote: > > Hi Steve, > > Can you please check, if you are able to get these patches I sent for the > Kirkstone & Dunfell branch. > It is not generating the group links/Topic id links like > https://lists.openembedded.org/g/openembedded-devel/message/. > > I have sent a v2 version for both the dunfell and kirkstone, but still it > didn't generate the links. > If you are able to get these patches, you can take either original or v2 for > both Dunfell and Kirkstone. Both v1 & v2 are the same, just resent for link > generation. Apologies for the inconvenience caused.
No, I'm not seeing these on the list :-( Steve > On Sat, Sep 30, 2023 at 12:23 AM Shubham Kulkarni <skulka...@mvista.com> > wrote: >> >> From: Shubham Kulkarni <skulka...@mvista.com> >> >> 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 >> >> Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> >> --- >> meta/recipes-devtools/go/go-1.14.inc | 5 +- >> .../go/go-1.14/CVE-2023-24538-1.patch | 4 +- >> .../go/go-1.14/CVE-2023-24538-2.patch | 447 ++++++++++++- >> .../go/go-1.14/CVE-2023-24538_3.patch | 393 ++++++++++++ >> .../go/go-1.14/CVE-2023-24538_4.patch | 497 +++++++++++++++ >> .../go/go-1.14/CVE-2023-24538_5.patch | 585 ++++++++++++++++++ >> ...3-24538-3.patch => CVE-2023-24538_6.patch} | 175 +++++- >> .../go/go-1.14/CVE-2023-39318.patch | 38 +- >> 8 files changed, 2124 insertions(+), 20 deletions(-) >> create mode 100644 meta/recipes-devtools/go/go-1.14/CVE-2023-24538_3.patch >> create mode 100644 meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch >> create mode 100644 meta/recipes-devtools/go/go-1.14/CVE-2023-24538_5.patch >> rename meta/recipes-devtools/go/go-1.14/{CVE-2023-24538-3.patch => >> CVE-2023-24538_6.patch} (53%) >> >> 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 += "\ >> file://CVE-2023-24534.patch \ >> file://CVE-2023-24538-1.patch \ >> file://CVE-2023-24538-2.patch \ >> - file://CVE-2023-24538-3.patch \ >> + file://CVE-2023-24538_3.patch \ >> + file://CVE-2023-24538_4.patch \ >> + file://CVE-2023-24538_5.patch \ >> + file://CVE-2023-24538_6.patch \ >> file://CVE-2023-24539.patch \ >> file://CVE-2023-24540.patch \ >> 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 @@ >> From 8acd01094d9ee17f6e763a61e49a8a808b3a9ddb Mon Sep 17 00:00:00 2001 >> From: Brad Fitzpatrick <bradf...@golang.org> >> Date: Mon, 2 Aug 2021 14:55:51 -0700 >> -Subject: [PATCH 1/3] net/netip: add new IP address package >> +Subject: [PATCH 1/6] net/netip: add new IP address package >> >> Co-authored-by: Alex Willmer <a...@moreati.org.uk> (GitHub @moreati) >> Co-authored-by: Alexander Yastrebov <yastrebov.a...@gmail.com> >> @@ -31,7 +31,7 @@ Trust: Brad Fitzpatrick <bradf...@golang.org> >> >> Dependency Patch #1 >> >> -Upstream-Status: Backport >> [https://github.com/golang/go/commit/a59e33224e42d60a97fa720a45e1b74eb6aaa3d0] >> +Upstream-Status: Backport from >> https://github.com/golang/go/commit/a59e33224e42d60a97fa720a45e1b74eb6aaa3d0 >> CVE: CVE-2023-24538 >> Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> >> --- >> 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..3840617a32 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 @@ >> From 6fc21505614f36178df0dad7034b6b8e3f7588d5 Mon Sep 17 00:00:00 2001 >> From: empijei <robcl...@gmail.com> >> Date: Fri, 27 Mar 2020 19:27:55 +0100 >> -Subject: [PATCH 2/3] html/template,text/template: switch to Unicode escapes >> +Subject: [PATCH 2/6] html/template,text/template: switch to Unicode escapes >> for JSON compatibility >> MIME-Version: 1.0 >> Content-Type: text/plain; charset=UTF-8 >> @@ -31,10 +31,238 @@ Upstream-Status: Backport from >> https://github.com/golang/go/commit/d4d298040d072 >> CVE: CVE-2023-24538 >> Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> >> --- >> - src/html/template/js.go | 70 >> +++++++++++++++++++++++++++------------------- >> - src/text/template/funcs.go | 8 +++--- >> - 2 files changed, 46 insertions(+), 32 deletions(-) >> + src/html/template/content_test.go | 70 >> +++++++++++++++++++------------------- >> + src/html/template/escape_test.go | 6 ++-- >> + src/html/template/example_test.go | 6 ++-- >> + src/html/template/js.go | 70 >> +++++++++++++++++++++++--------------- >> + src/html/template/js_test.go | 68 >> ++++++++++++++++++------------------ >> + src/html/template/template_test.go | 39 +++++++++++++++++++++ >> + src/text/template/exec_test.go | 6 ++-- >> + src/text/template/funcs.go | 8 ++--- >> + 8 files changed, 163 insertions(+), 110 deletions(-) >> >> +diff --git a/src/html/template/content_test.go >> b/src/html/template/content_test.go >> +index 72d56f5..bd86527 100644 >> +--- a/src/html/template/content_test.go >> ++++ b/src/html/template/content_test.go >> +@@ -18,7 +18,7 @@ func TestTypedContent(t *testing.T) { >> + HTML(`Hello, <b>World</b> &tc!`), >> + HTMLAttr(` dir="ltr"`), >> + JS(`c && alert("Hello, World!");`), >> +- JSStr(`Hello, World & O'Reilly\x21`), >> ++ JSStr(`Hello, World & O'Reilly\u0021`), >> + URL(`greeting=H%69,&addressee=(World)`), >> + Srcset(`greeting=H%69,&addressee=(World) 2x, >> https://golang.org/favicon.ico 500.5w`), >> + URL(`,foo/,`), >> +@@ -70,7 +70,7 @@ func TestTypedContent(t *testing.T) { >> + `Hello, <b>World</b> &tc!`, >> + ` dir="ltr"`, >> + `c && alert("Hello, >> World!");`, >> +- `Hello, World & O'Reilly\x21`, >> ++ `Hello, World & O'Reilly\u0021`, >> + `greeting=H%69,&addressee=(World)`, >> + `greeting=H%69,&addressee=(World) 2x, >> https://golang.org/favicon.ico 500.5w`, >> + `,foo/,`, >> +@@ -100,7 +100,7 @@ func TestTypedContent(t *testing.T) { >> + `Hello, World &tc!`, >> + ` dir="ltr"`, >> + >> `c && alert("Hello, World!");`, >> +- >> `Hello, World & O'Reilly\x21`, >> ++ >> `Hello, World & O'Reilly\u0021`, >> + >> `greeting=H%69,&addressee=(World)`, >> + >> `greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`, >> + `,foo/,`, >> +@@ -115,7 +115,7 @@ func TestTypedContent(t *testing.T) { >> + `Hello, World &tc!`, >> + ` dir="ltr"`, >> + `c && alert("Hello, >> World!");`, >> +- `Hello, World & O'Reilly\x21`, >> ++ `Hello, World & O'Reilly\u0021`, >> + `greeting=H%69,&addressee=(World)`, >> + `greeting=H%69,&addressee=(World) 2x, >> https://golang.org/favicon.ico 500.5w`, >> + `,foo/,`, >> +@@ -130,7 +130,7 @@ func TestTypedContent(t *testing.T) { >> + `Hello, <b>World</b> &tc!`, >> + ` dir="ltr"`, >> + `c && alert("Hello, >> World!");`, >> +- `Hello, World & O'Reilly\x21`, >> ++ `Hello, World & O'Reilly\u0021`, >> + `greeting=H%69,&addressee=(World)`, >> + `greeting=H%69,&addressee=(World) 2x, >> https://golang.org/favicon.ico 500.5w`, >> + `,foo/,`, >> +@@ -146,7 +146,7 @@ func TestTypedContent(t *testing.T) { >> + // Not escaped. >> + `c && alert("Hello, World!");`, >> + // Escape sequence not over-escaped. >> +- `"Hello, World & O'Reilly\x21"`, >> ++ `"Hello, World & O'Reilly\u0021"`, >> + `"greeting=H%69,\u0026addressee=(World)"`, >> + `"greeting=H%69,\u0026addressee=(World) 2x, >> https://golang.org/favicon.ico 500.5w"`, >> + `",foo/,"`, >> +@@ -162,7 +162,7 @@ func TestTypedContent(t *testing.T) { >> + // Not JS escaped but HTML escaped. >> + `c && alert("Hello, >> World!");`, >> + // Escape sequence not over-escaped. >> +- `"Hello, World & >> O'Reilly\x21"`, >> ++ `"Hello, World & >> O'Reilly\u0021"`, >> + >> `"greeting=H%69,\u0026addressee=(World)"`, >> + `"greeting=H%69,\u0026addressee=(World) >> 2x, https://golang.org/favicon.ico 500.5w"`, >> + `",foo/,"`, >> +@@ -171,30 +171,30 @@ func TestTypedContent(t *testing.T) { >> + { >> + `<script>alert("{{.}}")</script>`, >> + []string{ >> +- `\x3cb\x3e \x22foo%\x22 O\x27Reilly >> \x26bar;`, >> +- `a[href =~ \x22\/\/example.com\x22]#foo`, >> +- `Hello, \x3cb\x3eWorld\x3c\/b\x3e >> \x26amp;tc!`, >> +- ` dir=\x22ltr\x22`, >> +- `c \x26\x26 alert(\x22Hello, World!\x22);`, >> ++ `\u003cb\u003e \u0022foo%\u0022 >> O\u0027Reilly \u0026bar;`, >> ++ `a[href =~ \u0022\/\/example.com\u0022]#foo`, >> ++ `Hello, \u003cb\u003eWorld\u003c\/b\u003e >> \u0026amp;tc!`, >> ++ ` dir=\u0022ltr\u0022`, >> ++ `c \u0026\u0026 alert(\u0022Hello, >> World!\u0022);`, >> + // Escape sequence not over-escaped. >> +- `Hello, World \x26 O\x27Reilly\x21`, >> +- `greeting=H%69,\x26addressee=(World)`, >> +- `greeting=H%69,\x26addressee=(World) 2x, >> https:\/\/golang.org\/favicon.ico 500.5w`, >> ++ `Hello, World \u0026 O\u0027Reilly\u0021`, >> ++ `greeting=H%69,\u0026addressee=(World)`, >> ++ `greeting=H%69,\u0026addressee=(World) 2x, >> https:\/\/golang.org\/favicon.ico 500.5w`, >> + `,foo\/,`, >> + }, >> + }, >> + { >> + `<script >> type="text/javascript">alert("{{.}}")</script>`, >> + []string{ >> +- `\x3cb\x3e \x22foo%\x22 O\x27Reilly >> \x26bar;`, >> +- `a[href =~ \x22\/\/example.com\x22]#foo`, >> +- `Hello, \x3cb\x3eWorld\x3c\/b\x3e >> \x26amp;tc!`, >> +- ` dir=\x22ltr\x22`, >> +- `c \x26\x26 alert(\x22Hello, World!\x22);`, >> ++ `\u003cb\u003e \u0022foo%\u0022 >> O\u0027Reilly \u0026bar;`, >> ++ `a[href =~ \u0022\/\/example.com\u0022]#foo`, >> ++ `Hello, \u003cb\u003eWorld\u003c\/b\u003e >> \u0026amp;tc!`, >> ++ ` dir=\u0022ltr\u0022`, >> ++ `c \u0026\u0026 alert(\u0022Hello, >> World!\u0022);`, >> + // Escape sequence not over-escaped. >> +- `Hello, World \x26 O\x27Reilly\x21`, >> +- `greeting=H%69,\x26addressee=(World)`, >> +- `greeting=H%69,\x26addressee=(World) 2x, >> https:\/\/golang.org\/favicon.ico 500.5w`, >> ++ `Hello, World \u0026 O\u0027Reilly\u0021`, >> ++ `greeting=H%69,\u0026addressee=(World)`, >> ++ `greeting=H%69,\u0026addressee=(World) 2x, >> https:\/\/golang.org\/favicon.ico 500.5w`, >> + `,foo\/,`, >> + }, >> + }, >> +@@ -208,7 +208,7 @@ func TestTypedContent(t *testing.T) { >> + // Not escaped. >> + `c && alert("Hello, World!");`, >> + // Escape sequence not over-escaped. >> +- `"Hello, World & O'Reilly\x21"`, >> ++ `"Hello, World & O'Reilly\u0021"`, >> + `"greeting=H%69,\u0026addressee=(World)"`, >> + `"greeting=H%69,\u0026addressee=(World) 2x, >> https://golang.org/favicon.ico 500.5w"`, >> + `",foo/,"`, >> +@@ -224,7 +224,7 @@ func TestTypedContent(t *testing.T) { >> + `Hello, <b>World</b> &tc!`, >> + ` dir="ltr"`, >> + `c && alert("Hello, >> World!");`, >> +- `Hello, World & O'Reilly\x21`, >> ++ `Hello, World & O'Reilly\u0021`, >> + `greeting=H%69,&addressee=(World)`, >> + `greeting=H%69,&addressee=(World) 2x, >> https://golang.org/favicon.ico 500.5w`, >> + `,foo/,`, >> +@@ -233,15 +233,15 @@ func TestTypedContent(t *testing.T) { >> + { >> + `<button onclick='alert("{{.}}")'>`, >> + []string{ >> +- `\x3cb\x3e \x22foo%\x22 O\x27Reilly >> \x26bar;`, >> +- `a[href =~ \x22\/\/example.com\x22]#foo`, >> +- `Hello, \x3cb\x3eWorld\x3c\/b\x3e >> \x26amp;tc!`, >> +- ` dir=\x22ltr\x22`, >> +- `c \x26\x26 alert(\x22Hello, World!\x22);`, >> ++ `\u003cb\u003e \u0022foo%\u0022 >> O\u0027Reilly \u0026bar;`, >> ++ `a[href =~ \u0022\/\/example.com\u0022]#foo`, >> ++ `Hello, \u003cb\u003eWorld\u003c\/b\u003e >> \u0026amp;tc!`, >> ++ ` dir=\u0022ltr\u0022`, >> ++ `c \u0026\u0026 alert(\u0022Hello, >> World!\u0022);`, >> + // Escape sequence not over-escaped. >> +- `Hello, World \x26 O\x27Reilly\x21`, >> +- `greeting=H%69,\x26addressee=(World)`, >> +- `greeting=H%69,\x26addressee=(World) 2x, >> https:\/\/golang.org\/favicon.ico 500.5w`, >> ++ `Hello, World \u0026 O\u0027Reilly\u0021`, >> ++ `greeting=H%69,\u0026addressee=(World)`, >> ++ `greeting=H%69,\u0026addressee=(World) 2x, >> https:\/\/golang.org\/favicon.ico 500.5w`, >> + `,foo\/,`, >> + }, >> + }, >> +@@ -253,7 +253,7 @@ func TestTypedContent(t *testing.T) { >> + >> `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`, >> + `%20dir%3d%22ltr%22`, >> + >> `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`, >> +- `Hello%2c%20World%20%26%20O%27Reilly%5cx21`, >> ++ >> `Hello%2c%20World%20%26%20O%27Reilly%5cu0021`, >> + // Quotes and parens are escaped but %69 is >> not over-escaped. HTML escaping is done. >> + `greeting=H%69,&addressee=%28World%29`, >> + >> `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`, >> +@@ -268,7 +268,7 @@ func TestTypedContent(t *testing.T) { >> + >> `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`, >> + `%20dir%3d%22ltr%22`, >> + >> `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`, >> +- `Hello%2c%20World%20%26%20O%27Reilly%5cx21`, >> ++ >> `Hello%2c%20World%20%26%20O%27Reilly%5cu0021`, >> + // Quotes and parens are escaped but %69 is >> not over-escaped. HTML escaping is not done. >> + `greeting=H%69,&addressee=%28World%29`, >> + >> `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`, >> +diff --git a/src/html/template/escape_test.go >> b/src/html/template/escape_test.go >> +index e72a9ba..c709660 100644 >> +--- a/src/html/template/escape_test.go >> ++++ b/src/html/template/escape_test.go >> +@@ -238,7 +238,7 @@ func TestEscape(t *testing.T) { >> + { >> + "jsStr", >> + "<button onclick='alert("{{.H}}")'>", >> +- `<button >> onclick='alert("\x3cHello\x3e")'>`, >> ++ `<button >> onclick='alert("\u003cHello\u003e")'>`, >> + }, >> + { >> + "badMarshaler", >> +@@ -259,7 +259,7 @@ func TestEscape(t *testing.T) { >> + { >> + "jsRe", >> + `<button onclick='alert(/{{"foo+bar"}}/.test(""))'>`, >> +- `<button onclick='alert(/foo\x2bbar/.test(""))'>`, >> ++ `<button onclick='alert(/foo\u002bbar/.test(""))'>`, >> + }, >> + { >> + "jsReBlank", >> +@@ -825,7 +825,7 @@ func TestEscapeSet(t *testing.T) { >> + "main": `<button >> onclick="title='{{template "helper"}}'; ...">{{template "helper"}}</button>`, >> + "helper": `{{11}} of {{"<100>"}}`, >> + }, >> +- `<button onclick="title='11 of \x3c100\x3e'; ...">11 >> of <100></button>`, >> ++ `<button onclick="title='11 of \u003c100\u003e'; >> ...">11 of <100></button>`, >> + }, >> + // A non-recursive template that ends in a different context. >> + // helper starts in jsCtxRegexp and ends in jsCtxDivOp. >> +diff --git a/src/html/template/example_test.go >> b/src/html/template/example_test.go >> +index 9d965f1..6cf936f 100644 >> +--- a/src/html/template/example_test.go >> ++++ b/src/html/template/example_test.go >> +@@ -116,9 +116,9 @@ func Example_escape() { >> + // "Fran & Freddie's Diner" <ta...@example.com> >> + // "Fran & Freddie's Diner" <ta...@example.com> >> + // "Fran & Freddie's >> Diner"32<ta...@example.com> >> +- // \"Fran \x26 Freddie\'s Diner\" \x3cta...@example.com\x3E >> +- // \"Fran \x26 Freddie\'s Diner\" \x3cta...@example.com\x3E >> +- // \"Fran \x26 Freddie\'s Diner\"32\x3cta...@example.com\x3E >> ++ // \"Fran \u0026 Freddie\'s Diner\" \u003cta...@example.com\u003E >> ++ // \"Fran \u0026 Freddie\'s Diner\" \u003cta...@example.com\u003E >> ++ // \"Fran \u0026 Freddie\'s Diner\"32\u003cta...@example.com\u003E >> + // %22Fran+%26+Freddie%27s+Diner%2232%3Ctasty%40example.com%3E >> + >> + } >> diff --git a/src/html/template/js.go b/src/html/template/js.go >> index 0e91458..ea9c183 100644 >> --- a/src/html/template/js.go >> @@ -173,6 +401,217 @@ index 0e91458..ea9c183 100644 >> '?': `\?`, >> '[': `\[`, >> '\\': `\\`, >> +diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go >> +index 075adaa..d7ee47b 100644 >> +--- a/src/html/template/js_test.go >> ++++ b/src/html/template/js_test.go >> +@@ -137,7 +137,7 @@ func TestJSValEscaper(t *testing.T) { >> + {"foo", `"foo"`}, >> + // Newlines. >> + {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`}, >> +- // "\v" == "v" on IE 6 so use "\x0b" instead. >> ++ // "\v" == "v" on IE 6 so use "\u000b" instead. >> + {"\t\x0b", `"\t\u000b"`}, >> + {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`}, >> + {[]interface{}{}, "[]"}, >> +@@ -173,7 +173,7 @@ func TestJSStrEscaper(t *testing.T) { >> + }{ >> + {"", ``}, >> + {"foo", `foo`}, >> +- {"\u0000", `\0`}, >> ++ {"\u0000", `\u0000`}, >> + {"\t", `\t`}, >> + {"\n", `\n`}, >> + {"\r", `\r`}, >> +@@ -183,14 +183,14 @@ func TestJSStrEscaper(t *testing.T) { >> + {"\\n", `\\n`}, >> + {"foo\r\nbar", `foo\r\nbar`}, >> + // Preserve attribute boundaries. >> +- {`"`, `\x22`}, >> +- {`'`, `\x27`}, >> ++ {`"`, `\u0022`}, >> ++ {`'`, `\u0027`}, >> + // Allow embedding in HTML without further escaping. >> +- {`&`, `\x26amp;`}, >> ++ {`&`, `\u0026amp;`}, >> + // Prevent breaking out of text node and element boundaries. >> +- {"</script>", `\x3c\/script\x3e`}, >> +- {"<![CDATA[", `\x3c![CDATA[`}, >> +- {"]]>", `]]\x3e`}, >> ++ {"</script>", `\u003c\/script\u003e`}, >> ++ {"<![CDATA[", `\u003c![CDATA[`}, >> ++ {"]]>", `]]\u003e`}, >> + // >> https://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span >> + // "The text in style, script, title, and textarea elements >> + // must not have an escaping text span start that is not >> +@@ -201,11 +201,11 @@ func TestJSStrEscaper(t *testing.T) { >> + // allow regular text content to be interpreted as script >> + // allowing script execution via a combination of a JS string >> + // injection followed by an HTML text injection. >> +- {"<!--", `\x3c!--`}, >> +- {"-->", `--\x3e`}, >> ++ {"<!--", `\u003c!--`}, >> ++ {"-->", `--\u003e`}, >> + // From https://code.google.com/p/doctype/wiki/ArticleUtf7 >> + {"+ADw-script+AD4-alert(1)+ADw-/script+AD4-", >> +- >> `\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`, >> ++ >> `\u002bADw-script\u002bAD4-alert(1)\u002bADw-\/script\u002bAD4-`, >> + }, >> + // Invalid UTF-8 sequence >> + {"foo\xA0bar", "foo\xA0bar"}, >> +@@ -228,7 +228,7 @@ func TestJSRegexpEscaper(t *testing.T) { >> + }{ >> + {"", `(?:)`}, >> + {"foo", `foo`}, >> +- {"\u0000", `\0`}, >> ++ {"\u0000", `\u0000`}, >> + {"\t", `\t`}, >> + {"\n", `\n`}, >> + {"\r", `\r`}, >> +@@ -238,19 +238,19 @@ func TestJSRegexpEscaper(t *testing.T) { >> + {"\\n", `\\n`}, >> + {"foo\r\nbar", `foo\r\nbar`}, >> + // Preserve attribute boundaries. >> +- {`"`, `\x22`}, >> +- {`'`, `\x27`}, >> ++ {`"`, `\u0022`}, >> ++ {`'`, `\u0027`}, >> + // Allow embedding in HTML without further escaping. >> +- {`&`, `\x26amp;`}, >> ++ {`&`, `\u0026amp;`}, >> + // Prevent breaking out of text node and element boundaries. >> +- {"</script>", `\x3c\/script\x3e`}, >> +- {"<![CDATA[", `\x3c!\[CDATA\[`}, >> +- {"]]>", `\]\]\x3e`}, >> ++ {"</script>", `\u003c\/script\u003e`}, >> ++ {"<![CDATA[", `\u003c!\[CDATA\[`}, >> ++ {"]]>", `\]\]\u003e`}, >> + // Escaping text spans. >> +- {"<!--", `\x3c!\-\-`}, >> +- {"-->", `\-\-\x3e`}, >> ++ {"<!--", `\u003c!\-\-`}, >> ++ {"-->", `\-\-\u003e`}, >> + {"*", `\*`}, >> +- {"+", `\x2b`}, >> ++ {"+", `\u002b`}, >> + {"?", `\?`}, >> + {"[](){}", `\[\]\(\)\{\}`}, >> + {"$foo|x.y", `\$foo\|x\.y`}, >> +@@ -284,27 +284,27 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t >> *testing.T) { >> + { >> + "jsStrEscaper", >> + jsStrEscaper, >> +- "\\0\x01\x02\x03\x04\x05\x06\x07" + >> +- "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" + >> +- "\x10\x11\x12\x13\x14\x15\x16\x17" + >> +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + >> +- ` !\x22#$%\x26\x27()*\x2b,-.\/` + >> +- `0123456789:;\x3c=\x3e?` + >> ++ `\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007` + >> ++ `\u0008\t\n\u000b\f\r\u000e\u000f` + >> ++ >> `\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017` + >> ++ >> `\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f` + >> ++ ` !\u0022#$%\u0026\u0027()*\u002b,-.\/` + >> ++ `0123456789:;\u003c=\u003e?` + >> + `@ABCDEFGHIJKLMNO` + >> + `PQRSTUVWXYZ[\\]^_` + >> + "`abcdefghijklmno" + >> +- "pqrstuvwxyz{|}~\x7f" + >> ++ "pqrstuvwxyz{|}~\u007f" + >> + "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E", >> + }, >> + { >> + "jsRegexpEscaper", >> + jsRegexpEscaper, >> +- "\\0\x01\x02\x03\x04\x05\x06\x07" + >> +- "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" + >> +- "\x10\x11\x12\x13\x14\x15\x16\x17" + >> +- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" + >> +- ` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` + >> +- `0123456789:;\x3c=\x3e\?` + >> ++ `\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007` + >> ++ `\u0008\t\n\u000b\f\r\u000e\u000f` + >> ++ >> `\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017` + >> ++ >> `\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f` + >> ++ ` >> !\u0022#\$%\u0026\u0027\(\)\*\u002b,\-\.\/` + >> ++ `0123456789:;\u003c=\u003e\?` + >> + `@ABCDEFGHIJKLMNO` + >> + `PQRSTUVWXYZ\[\\\]\^_` + >> + "`abcdefghijklmno" + >> +diff --git a/src/html/template/template_test.go >> b/src/html/template/template_test.go >> +index 13e6ba4..86bd4db 100644 >> +--- a/src/html/template/template_test.go >> ++++ b/src/html/template/template_test.go >> +@@ -6,6 +6,7 @@ package template_test >> + >> + import ( >> + "bytes" >> ++ "encoding/json" >> + . "html/template" >> + "strings" >> + "testing" >> +@@ -121,6 +122,44 @@ func TestNumbers(t *testing.T) { >> + c.mustExecute(c.root, nil, "12.34 7.5") >> + } >> + >> ++func TestStringsInScriptsWithJsonContentTypeAreCorrectlyEscaped(t >> *testing.T) { >> ++ // See #33671 and #37634 for more context on this. >> ++ tests := []struct{ name, in string }{ >> ++ {"empty", ""}, >> ++ {"invalid", string(rune(-1))}, >> ++ {"null", "\u0000"}, >> ++ {"unit separator", "\u001F"}, >> ++ {"tab", "\t"}, >> ++ {"gt and lt", "<>"}, >> ++ {"quotes", `'"`}, >> ++ {"ASCII letters", "ASCII letters"}, >> ++ {"Unicode", "ʕ⊙ϖ⊙ʔ"}, >> ++ {"Pizza", "🍕"}, >> ++ } >> ++ const ( >> ++ prefix = `<script type="application/ld+json">` >> ++ suffix = `</script>` >> ++ templ = prefix + `"{{.}}"` + suffix >> ++ ) >> ++ tpl := Must(New("JS string is JSON string").Parse(templ)) >> ++ for _, tt := range tests { >> ++ t.Run(tt.name, func(t *testing.T) { >> ++ var buf bytes.Buffer >> ++ if err := tpl.Execute(&buf, tt.in); err != nil { >> ++ t.Fatalf("Cannot render template: %v", err) >> ++ } >> ++ trimmed := >> bytes.TrimSuffix(bytes.TrimPrefix(buf.Bytes(), []byte(prefix)), >> []byte(suffix)) >> ++ var got string >> ++ if err := json.Unmarshal(trimmed, &got); err != nil { >> ++ t.Fatalf("Cannot parse JS string %q as JSON: >> %v", trimmed[1:len(trimmed)-1], err) >> ++ } >> ++ if got != tt.in { >> ++ t.Errorf("Serialization changed the string >> value: got %q want %q", got, tt.in) >> ++ } >> ++ }) >> ++ } >> ++} >> ++ >> + type testCase struct { >> + t *testing.T >> + root *Template >> +diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go >> +index 77294ed..b8a809e 100644 >> +--- a/src/text/template/exec_test.go >> ++++ b/src/text/template/exec_test.go >> +@@ -911,9 +911,9 @@ func TestJSEscaping(t *testing.T) { >> + {`Go "jump" \`, `Go \"jump\" \\`}, >> + {`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`}, >> + {"unprintable \uFDFF", `unprintable \uFDFF`}, >> +- {`<html>`, `\x3Chtml\x3E`}, >> +- {`no = in attributes`, `no \x3D in attributes`}, >> +- {`' does not become HTML entity`, `\x26#x27; does not >> become HTML entity`}, >> ++ {`<html>`, `\u003Chtml\u003E`}, >> ++ {`no = in attributes`, `no \u003D in attributes`}, >> ++ {`' does not become HTML entity`, `\u0026#x27; does not >> become HTML entity`}, >> + } >> + for _, tc := range testCases { >> + s := JSEscapeString(tc.in) >> diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go >> index 46125bc..f3de9fb 100644 >> --- 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 @@ >> +From 7ddce23c7d5b728acf8482f5006497c7b9915f8a Mon Sep 17 00:00:00 2001 >> +From: Ariel Mashraki <ar...@mashraki.co.il> >> +Date: Wed, 22 Apr 2020 22:17:56 +0300 >> +Subject: [PATCH 3/6] text/template: add CommentNode to template parse tree >> +MIME-Version: 1.0 >> +Content-Type: text/plain; charset=UTF-8 >> +Content-Transfer-Encoding: 8bit >> + >> +Fixes #34652 >> + >> +Change-Id: Icf6e3eda593fed826736f34f95a9d66f5450cc98 >> +Reviewed-on: https://go-review.googlesource.com/c/go/+/229398 >> +Reviewed-by: Daniel Martí <mv...@mvdan.cc> >> +Run-TryBot: Daniel Martí <mv...@mvdan.cc> >> +TryBot-Result: Gobot Gobot <go...@golang.org> >> + >> +Dependency Patch #3 >> + >> +Upstream-Status: Backport from >> https://github.com/golang/go/commit/c8ea03828b0645b1fd5725888e44873b75fcfbb6 >> +CVE: CVE-2023-24538 >> +Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> >> +--- >> + api/next.txt | 19 +++++++++++++++++++ >> + src/html/template/escape.go | 2 ++ >> + src/html/template/template_test.go | 16 ++++++++++++++++ >> + src/text/template/exec.go | 1 + >> + src/text/template/parse/lex.go | 8 +++++++- >> + src/text/template/parse/lex_test.go | 7 +++++-- >> + src/text/template/parse/node.go | 33 >> +++++++++++++++++++++++++++++++++ >> + src/text/template/parse/parse.go | 22 +++++++++++++++++++--- >> + src/text/template/parse/parse_test.go | 25 +++++++++++++++++++++++++ >> + 9 files changed, 127 insertions(+), 6 deletions(-) >> + >> +diff --git a/api/next.txt b/api/next.txt >> +index e69de29..076f39e 100644 >> +--- a/api/next.txt >> ++++ b/api/next.txt >> +@@ -0,0 +1,19 @@ >> ++pkg unicode, const Version = "13.0.0" >> ++pkg unicode, var Chorasmian *RangeTable >> ++pkg unicode, var Dives_Akuru *RangeTable >> ++pkg unicode, var Khitan_Small_Script *RangeTable >> ++pkg unicode, var Yezidi *RangeTable >> ++pkg text/template/parse, const NodeComment = 20 >> ++pkg text/template/parse, const NodeComment NodeType >> ++pkg text/template/parse, const ParseComments = 1 >> ++pkg text/template/parse, const ParseComments Mode >> ++pkg text/template/parse, method (*CommentNode) Copy() Node >> ++pkg text/template/parse, method (*CommentNode) String() string >> ++pkg text/template/parse, method (CommentNode) Position() Pos >> ++pkg text/template/parse, method (CommentNode) Type() NodeType >> ++pkg text/template/parse, type CommentNode struct >> ++pkg text/template/parse, type CommentNode struct, Text string >> ++pkg text/template/parse, type CommentNode struct, embedded NodeType >> ++pkg text/template/parse, type CommentNode struct, embedded Pos >> ++pkg text/template/parse, type Mode uint >> ++pkg text/template/parse, type Tree struct, Mode Mode >> +diff --git a/src/html/template/escape.go b/src/html/template/escape.go >> +index f12dafa..8739735 100644 >> +--- a/src/html/template/escape.go >> ++++ b/src/html/template/escape.go >> +@@ -124,6 +124,8 @@ func (e *escaper) escape(c context, n parse.Node) >> context { >> + switch n := n.(type) { >> + case *parse.ActionNode: >> + return e.escapeAction(c, n) >> ++ case *parse.CommentNode: >> ++ return c >> + case *parse.IfNode: >> + return e.escapeBranch(c, &n.BranchNode, "if") >> + case *parse.ListNode: >> +diff --git a/src/html/template/template_test.go >> b/src/html/template/template_test.go >> +index 86bd4db..1f2c888 100644 >> +--- a/src/html/template/template_test.go >> ++++ b/src/html/template/template_test.go >> +@@ -10,6 +10,7 @@ import ( >> + . "html/template" >> + "strings" >> + "testing" >> ++ "text/template/parse" >> + ) >> + >> + func TestTemplateClone(t *testing.T) { >> +@@ -160,6 +161,21 @@ func >> TestStringsInScriptsWithJsonContentTypeAreCorrectlyEscaped(t *testing.T) { >> + } >> + } >> + >> ++func TestSkipEscapeComments(t *testing.T) { >> ++ c := newTestCase(t) >> ++ tr := parse.New("root") >> ++ tr.Mode = parse.ParseComments >> ++ newT, err := tr.Parse("{{/* A comment */}}{{ 1 }}{{/* Another >> comment */}}", "", "", make(map[string]*parse.Tree)) >> ++ if err != nil { >> ++ t.Fatalf("Cannot parse template text: %v", err) >> ++ } >> ++ c.root, err = c.root.AddParseTree("root", newT) >> ++ if err != nil { >> ++ t.Fatalf("Cannot add parse tree to template: %v", err) >> ++ } >> ++ c.mustExecute(c.root, nil, "1") >> ++} >> ++ >> + type testCase struct { >> + t *testing.T >> + root *Template >> +diff --git a/src/text/template/exec.go b/src/text/template/exec.go >> +index ac3e741..7ac5175 100644 >> +--- a/src/text/template/exec.go >> ++++ b/src/text/template/exec.go >> +@@ -256,6 +256,7 @@ func (s *state) walk(dot reflect.Value, node >> parse.Node) { >> + if len(node.Pipe.Decl) == 0 { >> + s.printValue(node, val) >> + } >> ++ case *parse.CommentNode: >> + case *parse.IfNode: >> + s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, >> node.ElseList) >> + case *parse.ListNode: >> +diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go >> +index 30371f2..e41373a 100644 >> +--- a/src/text/template/parse/lex.go >> ++++ b/src/text/template/parse/lex.go >> +@@ -41,6 +41,7 @@ const ( >> + itemBool // boolean constant >> + itemChar // printable ASCII character; grab >> bag for comma etc. >> + itemCharConstant // character constant >> ++ itemComment // comment text >> + itemComplex // complex constant (1+2i); >> imaginary is just a number >> + itemAssign // equals ('=') introducing an >> assignment >> + itemDeclare // colon-equals (':=') introducing >> a declaration >> +@@ -112,6 +113,7 @@ type lexer struct { >> + leftDelim string // start of action >> + rightDelim string // end of action >> + trimRightDelim string // end of action with trim marker >> ++ emitComment bool // emit itemComment tokens. >> + pos Pos // current position in the input >> + start Pos // start position of this item >> + width Pos // width of last rune read from input >> +@@ -203,7 +205,7 @@ func (l *lexer) drain() { >> + } >> + >> + // lex creates a new scanner for the input string. >> +-func lex(name, input, left, right string) *lexer { >> ++func lex(name, input, left, right string, emitComment bool) *lexer { >> + if left == "" { >> + left = leftDelim >> + } >> +@@ -216,6 +218,7 @@ func lex(name, input, left, right string) *lexer { >> + leftDelim: left, >> + rightDelim: right, >> + trimRightDelim: rightTrimMarker + right, >> ++ emitComment: emitComment, >> + items: make(chan item), >> + line: 1, >> + startLine: 1, >> +@@ -323,6 +326,9 @@ func lexComment(l *lexer) stateFn { >> + if !delim { >> + return l.errorf("comment ends before closing delimiter") >> + } >> ++ if l.emitComment { >> ++ l.emit(itemComment) >> ++ } >> + if trimSpace { >> + l.pos += trimMarkerLen >> + } >> +diff --git a/src/text/template/parse/lex_test.go >> b/src/text/template/parse/lex_test.go >> +index 563c4fc..f6d5f28 100644 >> +--- a/src/text/template/parse/lex_test.go >> ++++ b/src/text/template/parse/lex_test.go >> +@@ -15,6 +15,7 @@ var itemName = map[itemType]string{ >> + itemBool: "bool", >> + itemChar: "char", >> + itemCharConstant: "charconst", >> ++ itemComment: "comment", >> + itemComplex: "complex", >> + itemDeclare: ":=", >> + itemEOF: "EOF", >> +@@ -90,6 +91,7 @@ var lexTests = []lexTest{ >> + {"text", `now is the time`, []item{mkItem(itemText, "now is the >> time"), tEOF}}, >> + {"text with comment", "hello-{{/* this is a comment */}}-world", >> []item{ >> + mkItem(itemText, "hello-"), >> ++ mkItem(itemComment, "/* this is a comment */"), >> + mkItem(itemText, "-world"), >> + tEOF, >> + }}, >> +@@ -311,6 +313,7 @@ var lexTests = []lexTest{ >> + }}, >> + {"trimming spaces before and after comment", "hello- {{- /* hello */ >> -}} -world", []item{ >> + mkItem(itemText, "hello-"), >> ++ mkItem(itemComment, "/* hello */"), >> + mkItem(itemText, "-world"), >> + tEOF, >> + }}, >> +@@ -389,7 +392,7 @@ var lexTests = []lexTest{ >> + >> + // collect gathers the emitted items into a slice. >> + func collect(t *lexTest, left, right string) (items []item) { >> +- l := lex(t.name, t.input, left, right) >> ++ l := lex(t.name, t.input, left, right, true) >> + for { >> + item := l.nextItem() >> + items = append(items, item) >> +@@ -529,7 +532,7 @@ func TestPos(t *testing.T) { >> + func TestShutdown(t *testing.T) { >> + // We need to duplicate template.Parse here to hold on to the lexer. >> + const text = "erroneous{{define}}{{else}}1234" >> +- lexer := lex("foo", text, "{{", "}}") >> ++ lexer := lex("foo", text, "{{", "}}", false) >> + _, err := New("root").parseLexer(lexer) >> + if err == nil { >> + t.Fatalf("expected error") >> +diff --git a/src/text/template/parse/node.go >> b/src/text/template/parse/node.go >> +index 1c116ea..a9dad5e 100644 >> +--- a/src/text/template/parse/node.go >> ++++ b/src/text/template/parse/node.go >> +@@ -70,6 +70,7 @@ const ( >> + NodeTemplate // A template invocation action. >> + NodeVariable // A $ variable. >> + NodeWith // A with action. >> ++ NodeComment // A comment. >> + ) >> + >> + // Nodes. >> +@@ -149,6 +150,38 @@ func (t *TextNode) Copy() Node { >> + return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: >> append([]byte{}, t.Text...)} >> + } >> + >> ++// CommentNode holds a comment. >> ++type CommentNode struct { >> ++ NodeType >> ++ Pos >> ++ tr *Tree >> ++ Text string // Comment text. >> ++} >> ++ >> ++func (t *Tree) newComment(pos Pos, text string) *CommentNode { >> ++ return &CommentNode{tr: t, NodeType: NodeComment, Pos: pos, Text: >> text} >> ++} >> ++ >> ++func (c *CommentNode) String() string { >> ++ var sb strings.Builder >> ++ c.writeTo(&sb) >> ++ return sb.String() >> ++} >> ++ >> ++func (c *CommentNode) writeTo(sb *strings.Builder) { >> ++ sb.WriteString("{{") >> ++ sb.WriteString(c.Text) >> ++ sb.WriteString("}}") >> ++} >> ++ >> ++func (c *CommentNode) tree() *Tree { >> ++ return c.tr >> ++} >> ++ >> ++func (c *CommentNode) Copy() Node { >> ++ return &CommentNode{tr: c.tr, NodeType: NodeComment, Pos: c.Pos, >> Text: c.Text} >> ++} >> ++ >> + // PipeNode holds a pipeline with optional declaration >> + type PipeNode struct { >> + NodeType >> +diff --git a/src/text/template/parse/parse.go >> b/src/text/template/parse/parse.go >> +index c9b80f4..496d8bf 100644 >> +--- a/src/text/template/parse/parse.go >> ++++ b/src/text/template/parse/parse.go >> +@@ -21,6 +21,7 @@ type Tree struct { >> + Name string // name of the template represented by the tree. >> + ParseName string // name of the top-level template during >> parsing, for error messages. >> + Root *ListNode // top-level root of the tree. >> ++ Mode Mode // parsing mode. >> + text string // text parsed to create the template (or its >> parent) >> + // Parsing only; cleared after parse. >> + funcs []map[string]interface{} >> +@@ -29,8 +30,16 @@ type Tree struct { >> + peekCount int >> + vars []string // variables defined at the moment. >> + treeSet map[string]*Tree >> ++ mode Mode >> + } >> + >> ++// A mode value is a set of flags (or 0). Modes control parser behavior. >> ++type Mode uint >> ++ >> ++const ( >> ++ ParseComments Mode = 1 << iota // parse comments and add them to AST >> ++) >> ++ >> + // Copy returns a copy of the Tree. Any parsing state is discarded. >> + func (t *Tree) Copy() *Tree { >> + if t == nil { >> +@@ -220,7 +229,8 @@ func (t *Tree) stopParse() { >> + func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet >> map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) { >> + defer t.recover(&err) >> + t.ParseName = t.Name >> +- t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim), >> treeSet) >> ++ emitComment := t.Mode&ParseComments != 0 >> ++ t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim, >> emitComment), treeSet) >> + t.text = text >> + t.parse() >> + t.add() >> +@@ -240,12 +250,14 @@ func (t *Tree) add() { >> + } >> + } >> + >> +-// IsEmptyTree reports whether this tree (node) is empty of everything but >> space. >> ++// IsEmptyTree reports whether this tree (node) is empty of everything but >> space or comments. >> + func IsEmptyTree(n Node) bool { >> + switch n := n.(type) { >> + case nil: >> + return true >> + case *ActionNode: >> ++ case *CommentNode: >> ++ return true >> + case *IfNode: >> + case *ListNode: >> + for _, node := range n.Nodes { >> +@@ -276,6 +288,7 @@ func (t *Tree) parse() { >> + if t.nextNonSpace().typ == itemDefine { >> + newT := New("definition") // name will be >> updated once we know it. >> + newT.text = t.text >> ++ newT.Mode = t.Mode >> + newT.ParseName = t.ParseName >> + newT.startParse(t.funcs, t.lex, t.treeSet) >> + newT.parseDefinition() >> +@@ -331,13 +344,15 @@ func (t *Tree) itemList() (list *ListNode, next Node) >> { >> + } >> + >> + // textOrAction: >> +-// text | action >> ++// text | comment | action >> + func (t *Tree) textOrAction() Node { >> + switch token := t.nextNonSpace(); token.typ { >> + case itemText: >> + return t.newText(token.pos, token.val) >> + case itemLeftDelim: >> + return t.action() >> ++ case itemComment: >> ++ return t.newComment(token.pos, token.val) >> + default: >> + t.unexpected(token, "input") >> + } >> +@@ -539,6 +554,7 @@ func (t *Tree) blockControl() Node { >> + >> + block := New(name) // name will be updated once we know it. >> + block.text = t.text >> ++ block.Mode = t.Mode >> + block.ParseName = t.ParseName >> + block.startParse(t.funcs, t.lex, t.treeSet) >> + var end Node >> +diff --git a/src/text/template/parse/parse_test.go >> b/src/text/template/parse/parse_test.go >> +index 4e09a78..d9c13c5 100644 >> +--- a/src/text/template/parse/parse_test.go >> ++++ b/src/text/template/parse/parse_test.go >> +@@ -348,6 +348,30 @@ func TestParseCopy(t *testing.T) { >> + testParse(true, t) >> + } >> + >> ++func TestParseWithComments(t *testing.T) { >> ++ textFormat = "%q" >> ++ defer func() { textFormat = "%s" }() >> ++ tests := [...]parseTest{ >> ++ {"comment", "{{/*\n\n\n*/}}", noError, "{{/*\n\n\n*/}}"}, >> ++ {"comment trim left", "x \r\n\t{{- /* hi */}}", noError, >> `"x"{{/* hi */}}`}, >> ++ {"comment trim right", "{{/* hi */ -}}\n\n\ty", noError, >> `{{/* hi */}}"y"`}, >> ++ {"comment trim left and right", "x \r\n\t{{- /* */ >> -}}\n\n\ty", noError, `"x"{{/* */}}"y"`}, >> ++ } >> ++ for _, test := range tests { >> ++ t.Run(test.name, func(t *testing.T) { >> ++ tr := New(test.name) >> ++ tr.Mode = ParseComments >> ++ tmpl, err := tr.Parse(test.input, "", "", >> make(map[string]*Tree)) >> ++ if err != nil { >> ++ t.Errorf("%q: expected error; got none", >> test.name) >> ++ } >> ++ if result := tmpl.Root.String(); result != >> test.result { >> ++ t.Errorf("%s=(%q): >> got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result) >> ++ } >> ++ }) >> ++ } >> ++} >> ++ >> + type isEmptyTest struct { >> + name string >> + input string >> +@@ -358,6 +382,7 @@ var isEmptyTests = []isEmptyTest{ >> + {"empty", ``, true}, >> + {"nonempty", `hello`, false}, >> + {"spaces only", " \t\n \t\n", true}, >> ++ {"comment only", "{{/* comment */}}", true}, >> + {"definition", `{{define "x"}}something{{end}}`, true}, >> + {"definitions and space", "{{define >> `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true}, >> + {"definitions and text", "{{define >> `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n", false}, >> +-- >> +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 @@ >> +From 760d88497091fb5d6d231a18e6f4e06ecb9af9b2 Mon Sep 17 00:00:00 2001 >> +From: Russ Cox <r...@golang.org> >> +Date: Thu, 10 Sep 2020 18:53:26 -0400 >> +Subject: [PATCH 4/6] text/template: allow newlines inside action delimiters >> + >> +This allows multiline constructs like: >> + >> + {{"hello" | >> + printf}} >> + >> +Now that unclosed actions can span multiple lines, >> +track and report the start of the action when reporting errors. >> + >> +Also clean up a few "unexpected <error message>" to be just "<error >> message>". >> + >> +Fixes #29770. >> + >> +Change-Id: I54c6c016029a8328b7902a4b6d85eab713ec3285 >> +Reviewed-on: https://go-review.googlesource.com/c/go/+/254257 >> +Trust: Russ Cox <r...@golang.org> >> +Run-TryBot: Russ Cox <r...@golang.org> >> +TryBot-Result: Go Bot <go...@golang.org> >> +Reviewed-by: Rob Pike <r...@golang.org> >> + >> +Dependency Patch #4 >> + >> +Upstream-Status: Backport from >> https://github.com/golang/go/commit/9384d34c58099657bb1b133beaf3ff37ada9b017 >> +CVE: CVE-2023-24538 >> +Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> >> +--- >> + src/text/template/doc.go | 21 ++++----- >> + src/text/template/exec_test.go | 2 +- >> + src/text/template/parse/lex.go | 84 >> +++++++++++++++++------------------ >> + src/text/template/parse/lex_test.go | 2 +- >> + src/text/template/parse/parse.go | 59 +++++++++++++----------- >> + src/text/template/parse/parse_test.go | 36 ++++++++++++--- >> + 6 files changed, 117 insertions(+), 87 deletions(-) >> + >> +diff --git a/src/text/template/doc.go b/src/text/template/doc.go >> +index 4b0efd2..7b30294 100644 >> +--- a/src/text/template/doc.go >> ++++ b/src/text/template/doc.go >> +@@ -40,16 +40,17 @@ More intricate examples appear below. >> + Text and spaces >> + >> + By default, all text between actions is copied verbatim when the template >> is >> +-executed. For example, the string " items are made of " in the example >> above appears >> +-on standard output when the program is run. >> +- >> +-However, to aid in formatting template source code, if an action's left >> delimiter >> +-(by default "{{") is followed immediately by a minus sign and ASCII space >> character >> +-("{{- "), all trailing white space is trimmed from the immediately >> preceding text. >> +-Similarly, if the right delimiter ("}}") is preceded by a space and minus >> sign >> +-(" -}}"), all leading white space is trimmed from the immediately >> following text. >> +-In these trim markers, the ASCII space must be present; "{{-3}}" parses as >> an >> +-action containing the number -3. >> ++executed. For example, the string " items are made of " in the example >> above >> ++appears on standard output when the program is run. >> ++ >> ++However, to aid in formatting template source code, if an action's left >> ++delimiter (by default "{{") is followed immediately by a minus sign and >> white >> ++space, all trailing white space is trimmed from the immediately preceding >> text. >> ++Similarly, if the right delimiter ("}}") is preceded by white space and a >> minus >> ++sign, all leading white space is trimmed from the immediately following >> text. >> ++In these trim markers, the white space must be present: >> ++"{{- 3}}" is like "{{3}}" but trims the immediately preceding text, while >> ++"{{-3}}" parses as an action containing the number -3. >> + >> + For instance, when executing the template whose source is >> + >> +diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go >> +index b8a809e..3309b33 100644 >> +--- a/src/text/template/exec_test.go >> ++++ b/src/text/template/exec_test.go >> +@@ -1295,7 +1295,7 @@ func TestUnterminatedStringError(t *testing.T) { >> + t.Fatal("expected error") >> + } >> + str := err.Error() >> +- if !strings.Contains(str, "X:3: unexpected unterminated raw quoted >> string") { >> ++ if !strings.Contains(str, "X:3: unterminated raw quoted string") { >> + t.Fatalf("unexpected error: %s", str) >> + } >> + } >> +diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go >> +index e41373a..6784071 100644 >> +--- a/src/text/template/parse/lex.go >> ++++ b/src/text/template/parse/lex.go >> +@@ -92,15 +92,14 @@ const eof = -1 >> + // If the action begins "{{- " rather than "{{", then all >> space/tab/newlines >> + // preceding the action are trimmed; conversely if it ends " -}}" the >> + // leading spaces are trimmed. This is done entirely in the lexer; the >> +-// parser never sees it happen. We require an ASCII space to be >> +-// present to avoid ambiguity with things like "{{-3}}". It reads >> ++// parser never sees it happen. We require an ASCII space (' ', \t, \r, \n) >> ++// to be present to avoid ambiguity with things like "{{-3}}". It reads >> + // better with the space present anyway. For simplicity, only ASCII >> +-// space does the job. >> ++// does the job. >> + const ( >> +- spaceChars = " \t\r\n" // These are the space characters >> defined by Go itself. >> +- leftTrimMarker = "- " // Attached to left delimiter, trims >> trailing spaces from preceding text. >> +- rightTrimMarker = " -" // Attached to right delimiter, trims >> leading spaces from following text. >> +- trimMarkerLen = Pos(len(leftTrimMarker)) >> ++ spaceChars = " \t\r\n" // These are the space characters defined >> by Go itself. >> ++ trimMarker = '-' // Attached to left/right delimiter, >> trims trailing spaces from preceding/following text. >> ++ trimMarkerLen = Pos(1 + 1) // marker plus space before or after >> + ) >> + >> + // stateFn represents the state of the scanner as a function that returns >> the next state. >> +@@ -108,19 +107,18 @@ type stateFn func(*lexer) stateFn >> + >> + // lexer holds the state of the scanner. >> + type lexer struct { >> +- name string // the name of the input; used only for >> error reports >> +- input string // the string being scanned >> +- leftDelim string // start of action >> +- rightDelim string // end of action >> +- trimRightDelim string // end of action with trim marker >> +- emitComment bool // emit itemComment tokens. >> +- pos Pos // current position in the input >> +- start Pos // start position of this item >> +- width Pos // width of last rune read from input >> +- items chan item // channel of scanned items >> +- parenDepth int // nesting depth of ( ) exprs >> +- line int // 1+number of newlines seen >> +- startLine int // start line of this item >> ++ name string // the name of the input; used only for error >> reports >> ++ input string // the string being scanned >> ++ leftDelim string // start of action >> ++ rightDelim string // end of action >> ++ emitComment bool // emit itemComment tokens. >> ++ pos Pos // current position in the input >> ++ start Pos // start position of this item >> ++ width Pos // width of last rune read from input >> ++ items chan item // channel of scanned items >> ++ parenDepth int // nesting depth of ( ) exprs >> ++ line int // 1+number of newlines seen >> ++ startLine int // start line of this item >> + } >> + >> + // next returns the next rune in the input. >> +@@ -213,15 +211,14 @@ func lex(name, input, left, right string, emitComment >> bool) *lexer { >> + right = rightDelim >> + } >> + l := &lexer{ >> +- name: name, >> +- input: input, >> +- leftDelim: left, >> +- rightDelim: right, >> +- trimRightDelim: rightTrimMarker + right, >> +- emitComment: emitComment, >> +- items: make(chan item), >> +- line: 1, >> +- startLine: 1, >> ++ name: name, >> ++ input: input, >> ++ leftDelim: left, >> ++ rightDelim: right, >> ++ emitComment: emitComment, >> ++ items: make(chan item), >> ++ line: 1, >> ++ startLine: 1, >> + } >> + go l.run() >> + return l >> +@@ -251,7 +248,7 @@ func lexText(l *lexer) stateFn { >> + ldn := Pos(len(l.leftDelim)) >> + l.pos += Pos(x) >> + trimLength := Pos(0) >> +- if strings.HasPrefix(l.input[l.pos+ldn:], leftTrimMarker) { >> ++ if hasLeftTrimMarker(l.input[l.pos+ldn:]) { >> + trimLength = rightTrimLength(l.input[l.start:l.pos]) >> + } >> + l.pos -= trimLength >> +@@ -280,7 +277,7 @@ func rightTrimLength(s string) Pos { >> + >> + // atRightDelim reports whether the lexer is at a right delimiter, >> possibly preceded by a trim marker. >> + func (l *lexer) atRightDelim() (delim, trimSpaces bool) { >> +- if strings.HasPrefix(l.input[l.pos:], l.trimRightDelim) { // With >> trim marker. >> ++ if hasRightTrimMarker(l.input[l.pos:]) && >> strings.HasPrefix(l.input[l.pos+trimMarkerLen:], l.rightDelim) { // With >> trim marker. >> + return true, true >> + } >> + if strings.HasPrefix(l.input[l.pos:], l.rightDelim) { // Without >> trim marker. >> +@@ -297,7 +294,7 @@ func leftTrimLength(s string) Pos { >> + // lexLeftDelim scans the left delimiter, which is known to be present, >> possibly with a trim marker. >> + func lexLeftDelim(l *lexer) stateFn { >> + l.pos += Pos(len(l.leftDelim)) >> +- trimSpace := strings.HasPrefix(l.input[l.pos:], leftTrimMarker) >> ++ trimSpace := hasLeftTrimMarker(l.input[l.pos:]) >> + afterMarker := Pos(0) >> + if trimSpace { >> + afterMarker = trimMarkerLen >> +@@ -342,7 +339,7 @@ func lexComment(l *lexer) stateFn { >> + >> + // lexRightDelim scans the right delimiter, which is known to be present, >> possibly with a trim marker. >> + func lexRightDelim(l *lexer) stateFn { >> +- trimSpace := strings.HasPrefix(l.input[l.pos:], rightTrimMarker) >> ++ trimSpace := hasRightTrimMarker(l.input[l.pos:]) >> + if trimSpace { >> + l.pos += trimMarkerLen >> + l.ignore() >> +@@ -369,7 +366,7 @@ func lexInsideAction(l *lexer) stateFn { >> + return l.errorf("unclosed left paren") >> + } >> + switch r := l.next(); { >> +- case r == eof || isEndOfLine(r): >> ++ case r == eof: >> + return l.errorf("unclosed action") >> + case isSpace(r): >> + l.backup() // Put space back in case we have " -}}". >> +@@ -439,7 +436,7 @@ func lexSpace(l *lexer) stateFn { >> + } >> + // Be careful about a trim-marked closing delimiter, which has a >> minus >> + // after a space. We know there is a space, so check for the '-' >> that might follow. >> +- if strings.HasPrefix(l.input[l.pos-1:], l.trimRightDelim) { >> ++ if hasRightTrimMarker(l.input[l.pos-1:]) && >> strings.HasPrefix(l.input[l.pos-1+trimMarkerLen:], l.rightDelim) { >> + l.backup() // Before the space. >> + if numSpaces == 1 { >> + return lexRightDelim // On the delim, so go right to >> that. >> +@@ -526,7 +523,7 @@ func lexFieldOrVariable(l *lexer, typ itemType) stateFn >> { >> + // day to implement arithmetic. >> + func (l *lexer) atTerminator() bool { >> + r := l.peek() >> +- if isSpace(r) || isEndOfLine(r) { >> ++ if isSpace(r) { >> + return true >> + } >> + switch r { >> +@@ -657,15 +654,18 @@ Loop: >> + >> + // isSpace reports whether r is a space character. >> + func isSpace(r rune) bool { >> +- return r == ' ' || r == '\t' >> +-} >> +- >> +-// isEndOfLine reports whether r is an end-of-line character. >> +-func isEndOfLine(r rune) bool { >> +- return r == '\r' || r == '\n' >> ++ return r == ' ' || r == '\t' || r == '\r' || r == '\n' >> + } >> + >> + // isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. >> + func isAlphaNumeric(r rune) bool { >> + return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) >> + } >> ++ >> ++func hasLeftTrimMarker(s string) bool { >> ++ return len(s) >= 2 && s[0] == trimMarker && isSpace(rune(s[1])) >> ++} >> ++ >> ++func hasRightTrimMarker(s string) bool { >> ++ return len(s) >= 2 && isSpace(rune(s[0])) && s[1] == trimMarker >> ++} >> +diff --git a/src/text/template/parse/lex_test.go >> b/src/text/template/parse/lex_test.go >> +index f6d5f28..6510eed 100644 >> +--- a/src/text/template/parse/lex_test.go >> ++++ b/src/text/template/parse/lex_test.go >> +@@ -323,7 +323,7 @@ var lexTests = []lexTest{ >> + tLeft, >> + mkItem(itemError, "unrecognized character in action: >> U+0001"), >> + }}, >> +- {"unclosed action", "{{\n}}", []item{ >> ++ {"unclosed action", "{{", []item{ >> + tLeft, >> + mkItem(itemError, "unclosed action"), >> + }}, >> +diff --git a/src/text/template/parse/parse.go >> b/src/text/template/parse/parse.go >> +index 496d8bf..5e6e512 100644 >> +--- a/src/text/template/parse/parse.go >> ++++ b/src/text/template/parse/parse.go >> +@@ -24,13 +24,14 @@ type Tree struct { >> + Mode Mode // parsing mode. >> + text string // text parsed to create the template (or its >> parent) >> + // Parsing only; cleared after parse. >> +- funcs []map[string]interface{} >> +- lex *lexer >> +- token [3]item // three-token lookahead for parser. >> +- peekCount int >> +- vars []string // variables defined at the moment. >> +- treeSet map[string]*Tree >> +- mode Mode >> ++ funcs []map[string]interface{} >> ++ lex *lexer >> ++ token [3]item // three-token lookahead for parser. >> ++ peekCount int >> ++ vars []string // variables defined at the moment. >> ++ treeSet map[string]*Tree >> ++ actionLine int // line of left delim starting action >> ++ mode Mode >> + } >> + >> + // A mode value is a set of flags (or 0). Modes control parser behavior. >> +@@ -187,6 +188,16 @@ func (t *Tree) expectOneOf(expected1, expected2 >> itemType, context string) item { >> + >> + // unexpected complains about the token and terminates processing. >> + func (t *Tree) unexpected(token item, context string) { >> ++ if token.typ == itemError { >> ++ extra := "" >> ++ if t.actionLine != 0 && t.actionLine != token.line { >> ++ extra = fmt.Sprintf(" in action started at %s:%d", >> t.ParseName, t.actionLine) >> ++ if strings.HasSuffix(token.val, " action") { >> ++ extra = extra[len(" in action"):] // avoid >> "action in action" >> ++ } >> ++ } >> ++ t.errorf("%s%s", token, extra) >> ++ } >> + t.errorf("unexpected %s in %s", token, context) >> + } >> + >> +@@ -350,6 +361,8 @@ func (t *Tree) textOrAction() Node { >> + case itemText: >> + return t.newText(token.pos, token.val) >> + case itemLeftDelim: >> ++ t.actionLine = token.line >> ++ defer t.clearActionLine() >> + return t.action() >> + case itemComment: >> + return t.newComment(token.pos, token.val) >> +@@ -359,6 +372,10 @@ func (t *Tree) textOrAction() Node { >> + return nil >> + } >> + >> ++func (t *Tree) clearActionLine() { >> ++ t.actionLine = 0 >> ++} >> ++ >> + // Action: >> + // control >> + // command ("|" command)* >> +@@ -384,12 +401,12 @@ func (t *Tree) action() (n Node) { >> + t.backup() >> + token := t.peek() >> + // Do not pop variables; they persist until "end". >> +- return t.newAction(token.pos, token.line, t.pipeline("command")) >> ++ return t.newAction(token.pos, token.line, t.pipeline("command", >> itemRightDelim)) >> + } >> + >> + // Pipeline: >> + // declarations? command ('|' command)* >> +-func (t *Tree) pipeline(context string) (pipe *PipeNode) { >> ++func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) { >> + token := t.peekNonSpace() >> + pipe = t.newPipeline(token.pos, token.line, nil) >> + // Are there declarations or assignments? >> +@@ -430,12 +447,9 @@ decls: >> + } >> + for { >> + switch token := t.nextNonSpace(); token.typ { >> +- case itemRightDelim, itemRightParen: >> ++ case end: >> + // At this point, the pipeline is complete >> + t.checkPipeline(pipe, context) >> +- if token.typ == itemRightParen { >> +- t.backup() >> +- } >> + return >> + case itemBool, itemCharConstant, itemComplex, itemDot, >> itemField, itemIdentifier, >> + itemNumber, itemNil, itemRawString, itemString, >> itemVariable, itemLeftParen: >> +@@ -464,7 +478,7 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context >> string) { >> + >> + func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, >> line int, pipe *PipeNode, list, elseList *ListNode) { >> + defer t.popVars(len(t.vars)) >> +- pipe = t.pipeline(context) >> ++ pipe = t.pipeline(context, itemRightDelim) >> + var next Node >> + list, next = t.itemList() >> + switch next.Type() { >> +@@ -550,7 +564,7 @@ func (t *Tree) blockControl() Node { >> + >> + token := t.nextNonSpace() >> + name := t.parseTemplateName(token, context) >> +- pipe := t.pipeline(context) >> ++ pipe := t.pipeline(context, itemRightDelim) >> + >> + block := New(name) // name will be updated once we know it. >> + block.text = t.text >> +@@ -580,7 +594,7 @@ func (t *Tree) templateControl() Node { >> + if t.nextNonSpace().typ != itemRightDelim { >> + t.backup() >> + // Do not pop variables; they persist until "end". >> +- pipe = t.pipeline(context) >> ++ pipe = t.pipeline(context, itemRightDelim) >> + } >> + return t.newTemplate(token.pos, token.line, name, pipe) >> + } >> +@@ -614,13 +628,12 @@ func (t *Tree) command() *CommandNode { >> + switch token := t.next(); token.typ { >> + case itemSpace: >> + continue >> +- case itemError: >> +- t.errorf("%s", token.val) >> + case itemRightDelim, itemRightParen: >> + t.backup() >> + case itemPipe: >> ++ // nothing here; break loop below >> + default: >> +- t.errorf("unexpected %s in operand", token) >> ++ t.unexpected(token, "operand") >> + } >> + break >> + } >> +@@ -675,8 +688,6 @@ func (t *Tree) operand() Node { >> + // A nil return means the next item is not a term. >> + func (t *Tree) term() Node { >> + switch token := t.nextNonSpace(); token.typ { >> +- case itemError: >> +- t.errorf("%s", token.val) >> + case itemIdentifier: >> + if !t.hasFunction(token.val) { >> + t.errorf("function %q not defined", token.val) >> +@@ -699,11 +710,7 @@ func (t *Tree) term() Node { >> + } >> + return number >> + case itemLeftParen: >> +- pipe := t.pipeline("parenthesized pipeline") >> +- if token := t.next(); token.typ != itemRightParen { >> +- t.errorf("unclosed right paren: unexpected %s", >> token) >> +- } >> +- return pipe >> ++ return t.pipeline("parenthesized pipeline", itemRightParen) >> + case itemString, itemRawString: >> + s, err := strconv.Unquote(token.val) >> + if err != nil { >> +diff --git a/src/text/template/parse/parse_test.go >> b/src/text/template/parse/parse_test.go >> +index d9c13c5..220f984 100644 >> +--- a/src/text/template/parse/parse_test.go >> ++++ b/src/text/template/parse/parse_test.go >> +@@ -250,6 +250,13 @@ var parseTests = []parseTest{ >> + {"comment trim left and right", "x \r\n\t{{- /* */ -}}\n\n\ty", >> noError, `"x""y"`}, >> + {"block definition", `{{block "foo" .}}hello{{end}}`, noError, >> + `{{template "foo" .}}`}, >> ++ >> ++ {"newline in assignment", "{{ $x \n := \n 1 \n }}", noError, "{{$x >> := 1}}"}, >> ++ {"newline in empty action", "{{\n}}", hasError, "{{\n}}"}, >> ++ {"newline in pipeline", "{{\n\"x\"\n|\nprintf\n}}", noError, `{{"x" >> | printf}}`}, >> ++ {"newline in comment", "{{/*\nhello\n*/}}", noError, ""}, >> ++ {"newline in comment", "{{-\n/*\nhello\n*/\n-}}", noError, ""}, >> ++ >> + // Errors. >> + {"unclosed action", "hello{{range", hasError, ""}, >> + {"unmatched end", "{{end}}", hasError, ""}, >> +@@ -426,23 +433,38 @@ var errorTests = []parseTest{ >> + // Check line numbers are accurate. >> + {"unclosed1", >> + "line1\n{{", >> +- hasError, `unclosed1:2: unexpected unclosed action in >> command`}, >> ++ hasError, `unclosed1:2: unclosed action`}, >> + {"unclosed2", >> + "line1\n{{define `x`}}line2\n{{", >> +- hasError, `unclosed2:3: unexpected unclosed action in >> command`}, >> ++ hasError, `unclosed2:3: unclosed action`}, >> ++ {"unclosed3", >> ++ "line1\n{{\"x\"\n\"y\"\n", >> ++ hasError, `unclosed3:4: unclosed action started at >> unclosed3:2`}, >> ++ {"unclosed4", >> ++ "{{\n\n\n\n\n", >> ++ hasError, `unclosed4:6: unclosed action started at >> unclosed4:1`}, >> ++ {"var1", >> ++ "line1\n{{\nx\n}}", >> ++ hasError, `var1:3: function "x" not defined`}, >> + // Specific errors. >> + {"function", >> + "{{foo}}", >> + hasError, `function "foo" not defined`}, >> +- {"comment", >> ++ {"comment1", >> + "{{/*}}", >> +- hasError, `unclosed comment`}, >> ++ hasError, `comment1:1: unclosed comment`}, >> ++ {"comment2", >> ++ "{{/*\nhello\n}}", >> ++ hasError, `comment2:1: unclosed comment`}, >> + {"lparen", >> + "{{.X (1 2 3}}", >> + hasError, `unclosed left paren`}, >> + {"rparen", >> +- "{{.X 1 2 3)}}", >> +- hasError, `unexpected ")"`}, >> ++ "{{.X 1 2 3 ) }}", >> ++ hasError, `unexpected ")" in command`}, >> ++ {"rparen2", >> ++ "{{(.X 1 2 3", >> ++ hasError, `unclosed action`}, >> + {"space", >> + "{{`x`3}}", >> + hasError, `in operand`}, >> +@@ -488,7 +510,7 @@ var errorTests = []parseTest{ >> + hasError, `missing value for parenthesized pipeline`}, >> + {"multilinerawstring", >> + "{{ $v := `\n` }} {{", >> +- hasError, `multilinerawstring:2: unexpected unclosed >> action`}, >> ++ hasError, `multilinerawstring:2: unclosed action`}, >> + {"rangeundefvar", >> + "{{range $k}}{{end}}", >> + hasError, `undefined variable`}, >> +-- >> +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 @@ >> +From e0e6bca6ddc0e6d9fa3a5b644af9b446924fbf83 Mon Sep 17 00:00:00 2001 >> +From: Russ Cox <r...@golang.org> >> +Date: Thu, 20 May 2021 12:46:33 -0400 >> +Subject: [PATCH 5/6] html/template, text/template: implement break and >> + continue for range loops >> + >> +Break and continue for range loops was accepted as a proposal in June 2017. >> +It was implemented in CL 66410 (Oct 2017) >> +but then rolled back in CL 92155 (Feb 2018) >> +because html/template changes had not been implemented. >> + >> +This CL reimplements break and continue in text/template >> +and then adds support for them in html/template as well. >> + >> +Fixes #20531. >> + >> +Change-Id: I05330482a976f1c078b4b49c2287bd9031bb7616 >> +Reviewed-on: https://go-review.googlesource.com/c/go/+/321491 >> +Trust: Russ Cox <r...@golang.org> >> +Run-TryBot: Russ Cox <r...@golang.org> >> +TryBot-Result: Go Bot <go...@golang.org> >> +Reviewed-by: Rob Pike <r...@golang.org> >> + >> +Dependency Patch #5 >> + >> +Upstream-Status: Backport from >> https://github.com/golang/go/commit/d0dd26a88c019d54f22463daae81e785f5867565 >> +CVE: CVE-2023-24538 >> +Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> >> +--- >> + src/html/template/context.go | 4 ++ >> + src/html/template/escape.go | 71 >> ++++++++++++++++++++++++++++++++++- >> + src/html/template/escape_test.go | 24 ++++++++++++ >> + src/text/template/doc.go | 8 ++++ >> + src/text/template/exec.go | 24 +++++++++++- >> + src/text/template/exec_test.go | 2 + >> + src/text/template/parse/lex.go | 13 ++++++- >> + src/text/template/parse/lex_test.go | 2 + >> + src/text/template/parse/node.go | 36 ++++++++++++++++++ >> + src/text/template/parse/parse.go | 42 ++++++++++++++++++++- >> + src/text/template/parse/parse_test.go | 8 ++++ >> + 11 files changed, 230 insertions(+), 4 deletions(-) >> + >> +diff --git a/src/html/template/context.go b/src/html/template/context.go >> +index f7d4849..aaa7d08 100644 >> +--- a/src/html/template/context.go >> ++++ b/src/html/template/context.go >> +@@ -6,6 +6,7 @@ package template >> + >> + import ( >> + "fmt" >> ++ "text/template/parse" >> + ) >> + >> + // context describes the state an HTML parser must be in when it reaches >> the >> +@@ -22,6 +23,7 @@ type context struct { >> + jsCtx jsCtx >> + attr attr >> + element element >> ++ n parse.Node // for range break/continue >> + err *Error >> + } >> + >> +@@ -141,6 +143,8 @@ const ( >> + // stateError is an infectious error state outside any valid >> + // HTML/CSS/JS construct. >> + stateError >> ++ // stateDead marks unreachable code after a {{break}} or >> {{continue}}. >> ++ stateDead >> + ) >> + >> + // isComment is true for any state that contains content meant for template >> +diff --git a/src/html/template/escape.go b/src/html/template/escape.go >> +index 8739735..6dea79c 100644 >> +--- a/src/html/template/escape.go >> ++++ b/src/html/template/escape.go >> +@@ -97,6 +97,15 @@ type escaper struct { >> + actionNodeEdits map[*parse.ActionNode][]string >> + templateNodeEdits map[*parse.TemplateNode]string >> + textNodeEdits map[*parse.TextNode][]byte >> ++ // rangeContext holds context about the current range loop. >> ++ rangeContext *rangeContext >> ++} >> ++ >> ++// rangeContext holds information about the current range loop. >> ++type rangeContext struct { >> ++ outer *rangeContext // outer loop >> ++ breaks []context // context at each break action >> ++ continues []context // context at each continue action >> + } >> + >> + // makeEscaper creates a blank escaper for the given set. >> +@@ -109,6 +118,7 @@ func makeEscaper(n *nameSpace) escaper { >> + map[*parse.ActionNode][]string{}, >> + map[*parse.TemplateNode]string{}, >> + map[*parse.TextNode][]byte{}, >> ++ nil, >> + } >> + } >> + >> +@@ -124,8 +134,16 @@ func (e *escaper) escape(c context, n parse.Node) >> context { >> + switch n := n.(type) { >> + case *parse.ActionNode: >> + return e.escapeAction(c, n) >> ++ case *parse.BreakNode: >> ++ c.n = n >> ++ e.rangeContext.breaks = append(e.rangeContext.breaks, c) >> ++ return context{state: stateDead} >> + case *parse.CommentNode: >> + return c >> ++ case *parse.ContinueNode: >> ++ c.n = n >> ++ e.rangeContext.continues = append(e.rangeContext.breaks, c) >> ++ return context{state: stateDead} >> + case *parse.IfNode: >> + return e.escapeBranch(c, &n.BranchNode, "if") >> + case *parse.ListNode: >> +@@ -427,6 +445,12 @@ func join(a, b context, node parse.Node, nodeName >> string) context { >> + if b.state == stateError { >> + return b >> + } >> ++ if a.state == stateDead { >> ++ return b >> ++ } >> ++ if b.state == stateDead { >> ++ return a >> ++ } >> + if a.eq(b) { >> + return a >> + } >> +@@ -466,14 +490,27 @@ func join(a, b context, node parse.Node, nodeName >> string) context { >> + >> + // escapeBranch escapes a branch template node: "if", "range" and "with". >> + func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName >> string) context { >> ++ if nodeName == "range" { >> ++ e.rangeContext = &rangeContext{outer: e.rangeContext} >> ++ } >> + c0 := e.escapeList(c, n.List) >> +- if nodeName == "range" && c0.state != stateError { >> ++ if nodeName == "range" { >> ++ if c0.state != stateError { >> ++ c0 = joinRange(c0, e.rangeContext) >> ++ } >> ++ e.rangeContext = e.rangeContext.outer >> ++ if c0.state == stateError { >> ++ return c0 >> ++ } >> ++ >> + // The "true" branch of a "range" node can execute multiple >> times. >> + // We check that executing n.List once results in the same >> context >> + // as executing n.List twice. >> ++ e.rangeContext = &rangeContext{outer: e.rangeContext} >> + c1, _ := e.escapeListConditionally(c0, n.List, nil) >> + c0 = join(c0, c1, n, nodeName) >> + if c0.state == stateError { >> ++ e.rangeContext = e.rangeContext.outer >> + // Make clear that this is a problem on loop re-entry >> + // since developers tend to overlook that branch when >> + // debugging templates. >> +@@ -481,11 +518,39 @@ func (e *escaper) escapeBranch(c context, n >> *parse.BranchNode, nodeName string) >> + c0.err.Description = "on range loop re-entry: " + >> c0.err.Description >> + return c0 >> + } >> ++ c0 = joinRange(c0, e.rangeContext) >> ++ e.rangeContext = e.rangeContext.outer >> ++ if c0.state == stateError { >> ++ return c0 >> ++ } >> + } >> + c1 := e.escapeList(c, n.ElseList) >> + return join(c0, c1, n, nodeName) >> + } >> + >> ++func joinRange(c0 context, rc *rangeContext) context { >> ++ // Merge contexts at break and continue statements into overall body >> context. >> ++ // In theory we could treat breaks differently from continues, but >> for now it is >> ++ // enough to treat them both as going back to the start of the loop >> (which may then stop). >> ++ for _, c := range rc.breaks { >> ++ c0 = join(c0, c, c.n, "range") >> ++ if c0.state == stateError { >> ++ c0.err.Line = c.n.(*parse.BreakNode).Line >> ++ c0.err.Description = "at range loop break: " + >> c0.err.Description >> ++ return c0 >> ++ } >> ++ } >> ++ for _, c := range rc.continues { >> ++ c0 = join(c0, c, c.n, "range") >> ++ if c0.state == stateError { >> ++ c0.err.Line = c.n.(*parse.ContinueNode).Line >> ++ c0.err.Description = "at range loop continue: " + >> c0.err.Description >> ++ return c0 >> ++ } >> ++ } >> ++ return c0 >> ++} >> ++ >> + // escapeList escapes a list template node. >> + func (e *escaper) escapeList(c context, n *parse.ListNode) context { >> + if n == nil { >> +@@ -493,6 +558,9 @@ func (e *escaper) escapeList(c context, n >> *parse.ListNode) context { >> + } >> + for _, m := range n.Nodes { >> + c = e.escape(c, m) >> ++ if c.state == stateDead { >> ++ break >> ++ } >> + } >> + return c >> + } >> +@@ -503,6 +571,7 @@ func (e *escaper) escapeList(c context, n >> *parse.ListNode) context { >> + // which is the same as whether e was updated. >> + func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, >> filter func(*escaper, context) bool) (context, bool) { >> + e1 := makeEscaper(e.ns) >> ++ e1.rangeContext = e.rangeContext >> + // Make type inferences available to f. >> + for k, v := range e.output { >> + e1.output[k] = v >> +diff --git a/src/html/template/escape_test.go >> b/src/html/template/escape_test.go >> +index c709660..fa2b84a 100644 >> +--- a/src/html/template/escape_test.go >> ++++ b/src/html/template/escape_test.go >> +@@ -920,6 +920,22 @@ func TestErrors(t *testing.T) { >> + "<a href='/foo?{{range >> .Items}}&{{.K}}={{.V}}{{end}}'>", >> + "", >> + }, >> ++ { >> ++ "{{range .Items}}<a{{if .X}}{{end}}>{{end}}", >> ++ "", >> ++ }, >> ++ { >> ++ "{{range .Items}}<a{{if >> .X}}{{end}}>{{continue}}{{end}}", >> ++ "", >> ++ }, >> ++ { >> ++ "{{range .Items}}<a{{if >> .X}}{{end}}>{{break}}{{end}}", >> ++ "", >> ++ }, >> ++ { >> ++ "{{range .Items}}<a{{if .X}}{{end}}>{{if >> .X}}{{break}}{{end}}{{end}}", >> ++ "", >> ++ }, >> + // Error cases. >> + { >> + "{{if .Cond}}<a{{end}}", >> +@@ -956,6 +972,14 @@ func TestErrors(t *testing.T) { >> + "z:2:8: on range loop re-entry: {{range}} branches", >> + }, >> + { >> ++ "{{range .Items}}<a{{if >> .X}}{{break}}{{end}}>{{end}}", >> ++ "z:1:29: at range loop break: {{range}} branches end >> in different contexts", >> ++ }, >> ++ { >> ++ "{{range .Items}}<a{{if >> .X}}{{continue}}{{end}}>{{end}}", >> ++ "z:1:29: at range loop continue: {{range}} branches >> end in different contexts", >> ++ }, >> ++ { >> + "<a b=1 c={{.H}}", >> + "z: ends in a non-text context: {stateAttr >> delimSpaceOrTagEnd", >> + }, >> +diff --git a/src/text/template/doc.go b/src/text/template/doc.go >> +index 7b30294..0228b15 100644 >> +--- a/src/text/template/doc.go >> ++++ b/src/text/template/doc.go >> +@@ -112,6 +112,14 @@ data, defined in detail in the corresponding sections >> that follow. >> + T0 is executed; otherwise, dot is set to the successive >> elements >> + of the array, slice, or map and T1 is executed. >> + >> ++ {{break}} >> ++ The innermost {{range pipeline}} loop is ended early, >> stopping the >> ++ current iteration and bypassing all remaining iterations. >> ++ >> ++ {{continue}} >> ++ The current iteration of the innermost {{range pipeline}} >> loop is >> ++ stopped, and the loop starts the next iteration. >> ++ >> + {{template "name"}} >> + The template with the specified name is executed with nil >> data. >> + >> +diff --git a/src/text/template/exec.go b/src/text/template/exec.go >> +index 7ac5175..6cb140a 100644 >> +--- a/src/text/template/exec.go >> ++++ b/src/text/template/exec.go >> +@@ -5,6 +5,7 @@ >> + package template >> + >> + import ( >> ++ "errors" >> + "fmt" >> + "internal/fmtsort" >> + "io" >> +@@ -244,6 +245,12 @@ func (t *Template) DefinedTemplates() string { >> + return b.String() >> + } >> + >> ++// Sentinel errors for use with panic to signal early exits from range >> loops. >> ++var ( >> ++ walkBreak = errors.New("break") >> ++ walkContinue = errors.New("continue") >> ++) >> ++ >> + // Walk functions step through the major pieces of the template structure, >> + // generating output as they go. >> + func (s *state) walk(dot reflect.Value, node parse.Node) { >> +@@ -256,7 +263,11 @@ func (s *state) walk(dot reflect.Value, node >> parse.Node) { >> + if len(node.Pipe.Decl) == 0 { >> + s.printValue(node, val) >> + } >> ++ case *parse.BreakNode: >> ++ panic(walkBreak) >> + case *parse.CommentNode: >> ++ case *parse.ContinueNode: >> ++ panic(walkContinue) >> + case *parse.IfNode: >> + s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, >> node.ElseList) >> + case *parse.ListNode: >> +@@ -335,6 +346,11 @@ func isTrue(val reflect.Value) (truth, ok bool) { >> + >> + func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { >> + s.at(r) >> ++ defer func() { >> ++ if r := recover(); r != nil && r != walkBreak { >> ++ panic(r) >> ++ } >> ++ }() >> + defer s.pop(s.mark()) >> + val, _ := indirect(s.evalPipeline(dot, r.Pipe)) >> + // mark top of stack before any variables in the body are pushed. >> +@@ -348,8 +364,14 @@ func (s *state) walkRange(dot reflect.Value, r >> *parse.RangeNode) { >> + if len(r.Pipe.Decl) > 1 { >> + s.setTopVar(2, index) >> + } >> ++ defer s.pop(mark) >> ++ defer func() { >> ++ // Consume panic(walkContinue) >> ++ if r := recover(); r != nil && r != walkContinue { >> ++ panic(r) >> ++ } >> ++ }() >> + s.walk(elem, r.List) >> +- s.pop(mark) >> + } >> + switch val.Kind() { >> + case reflect.Array, reflect.Slice: >> +diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go >> +index 3309b33..a639f44 100644 >> +--- a/src/text/template/exec_test.go >> ++++ b/src/text/template/exec_test.go >> +@@ -563,6 +563,8 @@ var execTests = []execTest{ >> + {"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", >> tVal, true}, >> + {"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", >> "-3--4--5-", tVal, true}, >> + {"range empty else", "{{range >> .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, >> ++ {"range []int break else", "{{range >> .SI}}-{{.}}-{{break}}NOTREACHED{{else}}EMPTY{{end}}", "-3-", tVal, true}, >> ++ {"range []int continue else", "{{range >> .SI}}-{{.}}-{{continue}}NOTREACHED{{else}}EMPTY{{end}}", "-3--4--5-", tVal, >> true}, >> + {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", >> tVal, true}, >> + {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", >> "-20--21--22-", tVal, true}, >> + {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, >> true}, >> +diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go >> +index 6784071..95e3377 100644 >> +--- a/src/text/template/parse/lex.go >> ++++ b/src/text/template/parse/lex.go >> +@@ -62,6 +62,8 @@ const ( >> + // Keywords appear after all the rest. >> + itemKeyword // used only to delimit the keywords >> + itemBlock // block keyword >> ++ itemBreak // break keyword >> ++ itemContinue // continue keyword >> + itemDot // the cursor, spelled '.' >> + itemDefine // define keyword >> + itemElse // else keyword >> +@@ -76,6 +78,8 @@ const ( >> + var key = map[string]itemType{ >> + ".": itemDot, >> + "block": itemBlock, >> ++ "break": itemBreak, >> ++ "continue": itemContinue, >> + "define": itemDefine, >> + "else": itemElse, >> + "end": itemEnd, >> +@@ -119,6 +123,8 @@ type lexer struct { >> + parenDepth int // nesting depth of ( ) exprs >> + line int // 1+number of newlines seen >> + startLine int // start line of this item >> ++ breakOK bool // break keyword allowed >> ++ continueOK bool // continue keyword allowed >> + } >> + >> + // next returns the next rune in the input. >> +@@ -461,7 +467,12 @@ Loop: >> + } >> + switch { >> + case key[word] > itemKeyword: >> +- l.emit(key[word]) >> ++ item := key[word] >> ++ if item == itemBreak && !l.breakOK || item >> == itemContinue && !l.continueOK { >> ++ l.emit(itemIdentifier) >> ++ } else { >> ++ l.emit(item) >> ++ } >> + case word[0] == '.': >> + l.emit(itemField) >> + case word == "true", word == "false": >> +diff --git a/src/text/template/parse/lex_test.go >> b/src/text/template/parse/lex_test.go >> +index 6510eed..df6aabf 100644 >> +--- a/src/text/template/parse/lex_test.go >> ++++ b/src/text/template/parse/lex_test.go >> +@@ -35,6 +35,8 @@ var itemName = map[itemType]string{ >> + // keywords >> + itemDot: ".", >> + itemBlock: "block", >> ++ itemBreak: "break", >> ++ itemContinue: "continue", >> + itemDefine: "define", >> + itemElse: "else", >> + itemIf: "if", >> +diff --git a/src/text/template/parse/node.go >> b/src/text/template/parse/node.go >> +index a9dad5e..c398da0 100644 >> +--- a/src/text/template/parse/node.go >> ++++ b/src/text/template/parse/node.go >> +@@ -71,6 +71,8 @@ const ( >> + NodeVariable // A $ variable. >> + NodeWith // A with action. >> + NodeComment // A comment. >> ++ NodeBreak // A break action. >> ++ NodeContinue // A continue action. >> + ) >> + >> + // Nodes. >> +@@ -907,6 +909,40 @@ func (i *IfNode) Copy() Node { >> + return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), >> i.List.CopyList(), i.ElseList.CopyList()) >> + } >> + >> ++// BreakNode represents a {{break}} action. >> ++type BreakNode struct { >> ++ tr *Tree >> ++ NodeType >> ++ Pos >> ++ Line int >> ++} >> ++ >> ++func (t *Tree) newBreak(pos Pos, line int) *BreakNode { >> ++ return &BreakNode{tr: t, NodeType: NodeBreak, Pos: pos, Line: line} >> ++} >> ++ >> ++func (b *BreakNode) Copy() Node { return >> b.tr.newBreak(b.Pos, b.Line) } >> ++func (b *BreakNode) String() string { return "{{break}}" } >> ++func (b *BreakNode) tree() *Tree { return b.tr } >> ++func (b *BreakNode) writeTo(sb *strings.Builder) { >> sb.WriteString("{{break}}") } >> ++ >> ++// ContinueNode represents a {{continue}} action. >> ++type ContinueNode struct { >> ++ tr *Tree >> ++ NodeType >> ++ Pos >> ++ Line int >> ++} >> ++ >> ++func (t *Tree) newContinue(pos Pos, line int) *ContinueNode { >> ++ return &ContinueNode{tr: t, NodeType: NodeContinue, Pos: pos, Line: >> line} >> ++} >> ++ >> ++func (c *ContinueNode) Copy() Node { return >> c.tr.newContinue(c.Pos, c.Line) } >> ++func (c *ContinueNode) String() string { return >> "{{continue}}" } >> ++func (c *ContinueNode) tree() *Tree { return c.tr } >> ++func (c *ContinueNode) writeTo(sb *strings.Builder) { >> sb.WriteString("{{continue}}") } >> ++ >> + // RangeNode represents a {{range}} action and its commands. >> + type RangeNode struct { >> + BranchNode >> +diff --git a/src/text/template/parse/parse.go >> b/src/text/template/parse/parse.go >> +index 5e6e512..7f78b56 100644 >> +--- a/src/text/template/parse/parse.go >> ++++ b/src/text/template/parse/parse.go >> +@@ -31,6 +31,7 @@ type Tree struct { >> + vars []string // variables defined at the moment. >> + treeSet map[string]*Tree >> + actionLine int // line of left delim starting action >> ++ rangeDepth int >> + mode Mode >> + } >> + >> +@@ -223,6 +224,8 @@ func (t *Tree) startParse(funcs >> []map[string]interface{}, lex *lexer, treeSet ma >> + t.vars = []string{"$"} >> + t.funcs = funcs >> + t.treeSet = treeSet >> ++ lex.breakOK = !t.hasFunction("break") >> ++ lex.continueOK = !t.hasFunction("continue") >> + } >> + >> + // stopParse terminates parsing. >> +@@ -385,6 +388,10 @@ func (t *Tree) action() (n Node) { >> + switch token := t.nextNonSpace(); token.typ { >> + case itemBlock: >> + return t.blockControl() >> ++ case itemBreak: >> ++ return t.breakControl(token.pos, token.line) >> ++ case itemContinue: >> ++ return t.continueControl(token.pos, token.line) >> + case itemElse: >> + return t.elseControl() >> + case itemEnd: >> +@@ -404,6 +411,32 @@ func (t *Tree) action() (n Node) { >> + return t.newAction(token.pos, token.line, t.pipeline("command", >> itemRightDelim)) >> + } >> + >> ++// Break: >> ++// {{break}} >> ++// Break keyword is past. >> ++func (t *Tree) breakControl(pos Pos, line int) Node { >> ++ if token := t.next(); token.typ != itemRightDelim { >> ++ t.unexpected(token, "in {{break}}") >> ++ } >> ++ if t.rangeDepth == 0 { >> ++ t.errorf("{{break}} outside {{range}}") >> ++ } >> ++ return t.newBreak(pos, line) >> ++} >> ++ >> ++// Continue: >> ++// {{continue}} >> ++// Continue keyword is past. >> ++func (t *Tree) continueControl(pos Pos, line int) Node { >> ++ if token := t.next(); token.typ != itemRightDelim { >> ++ t.unexpected(token, "in {{continue}}") >> ++ } >> ++ if t.rangeDepth == 0 { >> ++ t.errorf("{{continue}} outside {{range}}") >> ++ } >> ++ return t.newContinue(pos, line) >> ++} >> ++ >> + // Pipeline: >> + // declarations? command ('|' command)* >> + func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) { >> +@@ -479,8 +512,14 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context >> string) { >> + func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, >> line int, pipe *PipeNode, list, elseList *ListNode) { >> + defer t.popVars(len(t.vars)) >> + pipe = t.pipeline(context, itemRightDelim) >> ++ if context == "range" { >> ++ t.rangeDepth++ >> ++ } >> + var next Node >> + list, next = t.itemList() >> ++ if context == "range" { >> ++ t.rangeDepth-- >> ++ } >> + switch next.Type() { >> + case nodeEnd: //done >> + case nodeElse: >> +@@ -522,7 +561,8 @@ func (t *Tree) ifControl() Node { >> + // {{range pipeline}} itemList {{else}} itemList {{end}} >> + // Range keyword is past. >> + func (t *Tree) rangeControl() Node { >> +- return t.newRange(t.parseControl(false, "range")) >> ++ r := t.newRange(t.parseControl(false, "range")) >> ++ return r >> + } >> + >> + // With: >> +diff --git a/src/text/template/parse/parse_test.go >> b/src/text/template/parse/parse_test.go >> +index 220f984..ba45636 100644 >> +--- a/src/text/template/parse/parse_test.go >> ++++ b/src/text/template/parse/parse_test.go >> +@@ -230,6 +230,10 @@ var parseTests = []parseTest{ >> + `{{range $x := .SI}}{{.}}{{end}}`}, >> + {"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError, >> + `{{range $x, $y := .SI}}{{.}}{{end}}`}, >> ++ {"range with break", "{{range .SI}}{{.}}{{break}}{{end}}", noError, >> ++ `{{range .SI}}{{.}}{{break}}{{end}}`}, >> ++ {"range with continue", "{{range .SI}}{{.}}{{continue}}{{end}}", >> noError, >> ++ `{{range .SI}}{{.}}{{continue}}{{end}}`}, >> + {"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", >> noError, >> + `{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`}, >> + {"template", "{{template `x`}}", noError, >> +@@ -279,6 +283,10 @@ var parseTests = []parseTest{ >> + {"adjacent args", "{{printf 3`x`}}", hasError, ""}, >> + {"adjacent args with .", "{{printf `x`.}}", hasError, ""}, >> + {"extra end after if", "{{if .X}}a{{else if .Y}}b{{end}}{{end}}", >> hasError, ""}, >> ++ {"break outside range", "{{range .}}{{end}} {{break}}", hasError, >> ""}, >> ++ {"continue outside range", "{{range .}}{{end}} {{continue}}", >> hasError, ""}, >> ++ {"break in range else", "{{range .}}{{else}}{{break}}{{end}}", >> hasError, ""}, >> ++ {"continue in range else", "{{range .}}{{else}}{{continue}}{{end}}", >> hasError, ""}, >> + // Other kinds of assignments and operators aren't available yet. >> + {"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"}, >> + {"bug0b", "{{$x += 1}}{{$x}}", hasError, ""}, >> +-- >> +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 >> similarity index 53% >> rename from meta/recipes-devtools/go/go-1.14/CVE-2023-24538-3.patch >> rename to 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 @@ >> From 16f4882984569f179d73967c9eee679bb9b098c5 Mon Sep 17 00:00:00 2001 >> From: Roland Shoemaker <bracew...@google.com> >> Date: Mon, 20 Mar 2023 11:01:13 -0700 >> -Subject: [PATCH 3/3] html/template: disallow actions in JS template literals >> +Subject: [PATCH 6/6] html/template: disallow actions in JS template literals >> >> ECMAScript 6 introduced template literals[0][1] which are delimited with >> backticks. These need to be escaped in a similar fashion to the >> @@ -52,12 +52,15 @@ CVE: CVE-2023-24538 >> Signed-off-by: Shubham Kulkarni <skulka...@mvista.com> >> --- >> src/html/template/context.go | 2 ++ >> - src/html/template/error.go | 13 +++++++++++++ >> - src/html/template/escape.go | 11 +++++++++++ >> + src/html/template/error.go | 13 ++++++++ >> + src/html/template/escape.go | 11 +++++++ >> + src/html/template/escape_test.go | 66 >> ++++++++++++++++++++++----------------- >> src/html/template/js.go | 2 ++ >> - src/html/template/jsctx_string.go | 9 +++++++++ >> - src/html/template/transition.go | 7 ++++++- >> - 6 files changed, 43 insertions(+), 1 deletion(-) >> + src/html/template/js_test.go | 2 +- >> + src/html/template/jsctx_string.go | 9 ++++++ >> + src/html/template/state_string.go | 37 ++++++++++++++++++++-- >> + src/html/template/transition.go | 7 ++++- >> + 9 files changed, 116 insertions(+), 33 deletions(-) >> >> diff --git a/src/html/template/context.go b/src/html/template/context.go >> index f7d4849..0b65313 100644 >> @@ -125,6 +128,104 @@ index f12dafa..29ca5b3 100644 >> case stateJSRegexp: >> s = append(s, "_html_template_jsregexpescaper") >> case stateCSS: >> +diff --git a/src/html/template/escape_test.go >> b/src/html/template/escape_test.go >> +index fa2b84a..1b150e9 100644 >> +--- a/src/html/template/escape_test.go >> ++++ b/src/html/template/escape_test.go >> +@@ -681,35 +681,31 @@ func TestEscape(t *testing.T) { >> + } >> + >> + for _, test := range tests { >> +- tmpl := New(test.name) >> +- tmpl = Must(tmpl.Parse(test.input)) >> +- // Check for bug 6459: Tree field was not set in Parse. >> +- if tmpl.Tree != tmpl.text.Tree { >> +- t.Errorf("%s: tree not set properly", test.name) >> +- continue >> +- } >> +- b := new(bytes.Buffer) >> +- if err := tmpl.Execute(b, data); err != nil { >> +- t.Errorf("%s: template execution failed: %s", >> test.name, err) >> +- continue >> +- } >> +- if w, g := test.output, b.String(); w != g { >> +- t.Errorf("%s: escaped output: >> want\n\t%q\ngot\n\t%q", test.name, w, g) >> +- continue >> +- } >> +- b.Reset() >> +- if err := tmpl.Execute(b, pdata); err != nil { >> +- t.Errorf("%s: template execution failed for pointer: >> %s", test.name, err) >> +- continue >> +- } >> +- if w, g := test.output, b.String(); w != g { >> +- t.Errorf("%s: escaped output for pointer: >> want\n\t%q\ngot\n\t%q", test.name, w, g) >> +- continue >> +- } >> +- if tmpl.Tree != tmpl.text.Tree { >> +- t.Errorf("%s: tree mismatch", test.name) >> +- continue >> +- } >> ++ t.Run(test.name, func(t *testing.T) { >> ++ tmpl := New(test.name) >> ++ tmpl = Must(tmpl.Parse(test.input)) >> ++ // Check for bug 6459: Tree field was not set in >> Parse. >> ++ if tmpl.Tree != tmpl.text.Tree { >> ++ t.Fatalf("%s: tree not set properly", >> test.name) >> ++ } >> ++ b := new(strings.Builder) >> ++ if err := tmpl.Execute(b, data); err != nil { >> ++ t.Fatalf("%s: template execution failed: >> %s", test.name, err) >> ++ } >> ++ if w, g := test.output, b.String(); w != g { >> ++ t.Fatalf("%s: escaped output: >> want\n\t%q\ngot\n\t%q", test.name, w, g) >> ++ } >> ++ b.Reset() >> ++ if err := tmpl.Execute(b, pdata); err != nil { >> ++ t.Fatalf("%s: template execution failed for >> pointer: %s", test.name, err) >> ++ } >> ++ if w, g := test.output, b.String(); w != g { >> ++ t.Fatalf("%s: escaped output for pointer: >> want\n\t%q\ngot\n\t%q", test.name, w, g) >> ++ } >> ++ if tmpl.Tree != tmpl.text.Tree { >> ++ t.Fatalf("%s: tree mismatch", test.name) >> ++ } >> ++ }) >> + } >> + } >> + >> +@@ -936,6 +932,10 @@ func TestErrors(t *testing.T) { >> + "{{range .Items}}<a{{if .X}}{{end}}>{{if >> .X}}{{break}}{{end}}{{end}}", >> + "", >> + }, >> ++ { >> ++ "<script>var a = `${a+b}`</script>`", >> ++ "", >> ++ }, >> + // Error cases. >> + { >> + "{{if .Cond}}<a{{end}}", >> +@@ -1082,6 +1082,10 @@ func TestErrors(t *testing.T) { >> + // html is allowed since it is the last command in >> the pipeline, but urlquery is not. >> + `predefined escaper "urlquery" disallowed in >> template`, >> + }, >> ++ { >> ++ "<script>var tmpl = `asd {{.}}`;</script>", >> ++ `{{.}} appears in a JS template literal`, >> ++ }, >> + } >> + for _, test := range tests { >> + buf := new(bytes.Buffer) >> +@@ -1304,6 +1308,10 @@ func TestEscapeText(t *testing.T) { >> + context{state: stateJSSqStr, delim: >> delimDoubleQuote, attr: attrScript}, >> + }, >> + { >> ++ "<a onclick=\"`foo", >> ++ context{state: stateJSBqStr, delim: >> delimDoubleQuote, attr: attrScript}, >> ++ }, >> ++ { >> + `<A ONCLICK="'`, >> + context{state: stateJSSqStr, delim: >> delimDoubleQuote, attr: attrScript}, >> + }, >> diff --git a/src/html/template/js.go b/src/html/template/js.go >> index ea9c183..b888eaf 100644 >> --- a/src/html/template/js.go >> @@ -145,6 +246,19 @@ index ea9c183..b888eaf 100644 >> '+': `\u002b`, >> '/': `\/`, >> '<': `\u003c`, >> +diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go >> +index d7ee47b..7d963ae 100644 >> +--- a/src/html/template/js_test.go >> ++++ b/src/html/template/js_test.go >> +@@ -292,7 +292,7 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t >> *testing.T) { >> + `0123456789:;\u003c=\u003e?` + >> + `@ABCDEFGHIJKLMNO` + >> + `PQRSTUVWXYZ[\\]^_` + >> +- "`abcdefghijklmno" + >> ++ "\\u0060abcdefghijklmno" + >> + "pqrstuvwxyz{|}~\u007f" + >> + "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E", >> + }, >> diff --git a/src/html/template/jsctx_string.go >> b/src/html/template/jsctx_string.go >> index dd1d87e..2394893 100644 >> --- a/src/html/template/jsctx_string.go >> @@ -165,6 +279,55 @@ index dd1d87e..2394893 100644 >> const _jsCtx_name = "jsCtxRegexpjsCtxDivOpjsCtxUnknown" >> >> var _jsCtx_index = [...]uint8{0, 11, 21, 33} >> +diff --git a/src/html/template/state_string.go >> b/src/html/template/state_string.go >> +index 05104be..6fb1a6e 100644 >> +--- a/src/html/template/state_string.go >> ++++ b/src/html/template/state_string.go >> +@@ -4,9 +4,42 @@ package template >> + >> + import "strconv" >> + >> +-const _state_name = >> "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateError" >> ++func _() { >> ++ // An "invalid array index" compiler error signifies that the >> constant values have changed. >> ++ // Re-run the stringer command to generate them again. >> ++ var x [1]struct{} >> ++ _ = x[stateText-0] >> ++ _ = x[stateTag-1] >> ++ _ = x[stateAttrName-2] >> ++ _ = x[stateAfterName-3] >> ++ _ = x[stateBeforeValue-4] >> ++ _ = x[stateHTMLCmt-5] >> ++ _ = x[stateRCDATA-6] >> ++ _ = x[stateAttr-7] >> ++ _ = x[stateURL-8] >> ++ _ = x[stateSrcset-9] >> ++ _ = x[stateJS-10] >> ++ _ = x[stateJSDqStr-11] >> ++ _ = x[stateJSSqStr-12] >> ++ _ = x[stateJSBqStr-13] >> ++ _ = x[stateJSRegexp-14] >> ++ _ = x[stateJSBlockCmt-15] >> ++ _ = x[stateJSLineCmt-16] >> ++ _ = x[stateCSS-17] >> ++ _ = x[stateCSSDqStr-18] >> ++ _ = x[stateCSSSqStr-19] >> ++ _ = x[stateCSSDqURL-20] >> ++ _ = x[stateCSSSqURL-21] >> ++ _ = x[stateCSSURL-22] >> ++ _ = x[stateCSSBlockCmt-23] >> ++ _ = x[stateCSSLineCmt-24] >> ++ _ = x[stateError-25] >> ++ _ = x[stateDead-26] >> ++} >> ++ >> ++const _state_name = >> "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead" >> + >> +-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} >> ++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} >> + >> + func (i state) String() string { >> + if i >= state(len(_state_index)-1) { >> diff --git a/src/html/template/transition.go >> b/src/html/template/transition.go >> index 06df679..92eb351 100644 >> --- 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 <sdo...@mvista.com> >> src/html/template/context.go | 6 ++- >> src/html/template/escape.go | 5 +- >> src/html/template/escape_test.go | 10 ++++ >> - src/html/template/state_string.go | 4 +- >> + src/html/template/state_string.go | 26 +++++----- >> src/html/template/transition.go | 80 ++++++++++++++++++++----------- >> - 5 files changed, 72 insertions(+), 33 deletions(-) >> + 5 files changed, 84 insertions(+), 43 deletions(-) >> >> diff --git a/src/html/template/context.go b/src/html/template/context.go >> index 0b65313..4eb7891 100644 >> @@ -105,14 +105,38 @@ diff --git a/src/html/template/state_string.go >> b/src/html/template/state_string. >> index 05104be..b5cfe70 100644 >> --- a/src/html/template/state_string.go >> +++ b/src/html/template/state_string.go >> -@@ -4,9 +4,9 @@ package template >> - >> - import "strconv" >> +@@ -25,21 +25,23 @@ func _() { >> + _ = x[stateJSRegexp-14] >> + _ = x[stateJSBlockCmt-15] >> + _ = x[stateJSLineCmt-16] >> +- _ = x[stateCSS-17] >> +- _ = x[stateCSSDqStr-18] >> +- _ = x[stateCSSSqStr-19] >> +- _ = x[stateCSSDqURL-20] >> +- _ = x[stateCSSSqURL-21] >> +- _ = x[stateCSSURL-22] >> +- _ = x[stateCSSBlockCmt-23] >> +- _ = x[stateCSSLineCmt-24] >> +- _ = x[stateError-25] >> +- _ = x[stateDead-26] >> ++ _ = x[stateJSHTMLOpenCmt-17] >> ++ _ = x[stateJSHTMLCloseCmt-18] >> ++ _ = x[stateCSS-19] >> ++ _ = x[stateCSSDqStr-20] >> ++ _ = x[stateCSSSqStr-21] >> ++ _ = x[stateCSSDqURL-22] >> ++ _ = x[stateCSSSqURL-23] >> ++ _ = x[stateCSSURL-24] >> ++ _ = x[stateCSSBlockCmt-25] >> ++ _ = x[stateCSSLineCmt-26] >> ++ _ = x[stateError-27] >> ++ _ = x[stateDead-28] >> + } >> >> --const _state_name = >> "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateError" >> +-const _state_name = >> "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead" >> +const _state_name = >> "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead" >> >> --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} >> +-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} >> +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} >> >> func (i state) String() string { >> -- >> 2.42.0 >>
-=-=-=-=-=-=-=-=-=-=-=- Links: You receive all messages sent to this group. View/Reply Online (#188414): https://lists.openembedded.org/g/openembedded-core/message/188414 Mute This Topic: https://lists.openembedded.org/mt/101664364/21656 Group Owner: openembedded-core+ow...@lists.openembedded.org Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-