Sorry, this patch doesn't apply: Applying: go: Update fix for CVE-2023-24538 & CVE-2023-39318 error: corrupt patch at line 478 error: could not build fake ancestor Patch failed at 0001 go: Update fix for CVE-2023-24538 & CVE-2023-39318
Steve On Fri, Sep 29, 2023 at 9:21 AM Shubham Kulkarni via lists.openembedded.org <skulkarni=mvista....@lists.openembedded.org> 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 (#188453): https://lists.openembedded.org/g/openembedded-core/message/188453 Mute This Topic: https://lists.openembedded.org/mt/101664679/21656 Group Owner: openembedded-core+ow...@lists.openembedded.org Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-