On Tue, Oct 3, 2023 at 3:49 AM Shubham Kulkarni <skulka...@mvista.com> wrote:
>
> Hi Steve,
>
> I have recreated the patch from scratch for dunfell and sent it as v4 - 
> https://lists.openembedded.org/g/openembedded-core/message/188639
> The issue in v3 might be due to whitespaces. But v4 should be good.

Sorry, it still fails:

Applying: go: Update fix for CVE-2023-24538 & CVE-2023-39318
error: corrupt patch at line 1074
error: could not build fake ancestor

To debug, try downloading your patch from the list and then applying
it to the dunfell HEAD.

Alternatively you could download from patchworks:
https://patchwork.yoctoproject.org/project/oe-core/patch/20231003134246.24630-1-skulka...@mvista.com/

Steve

> On Sat, Sep 30, 2023 at 9:11 PM Shubham Kulkarni via lists.openembedded.org 
> <skulkarni=mvista....@lists.openembedded.org> wrote:
>>
>> Apologies Steve,
>>
>> I will look into the issue and send a new patch for Dunfell. It worked for 
>> me on my machine. Maybe something I missed.
>>
>> Thanks,
>> Shubham Kulkarni
>>
>> On Sat, Sep 30, 2023 at 8:02 AM Steve Sakoman <st...@sakoman.com> wrote:
>>>
>>> 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> &amp;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> &amp;tc!`,
>>> > +                               ` dir=&#34;ltr&#34;`,
>>> > +                               `c &amp;&amp; alert(&#34;Hello, 
>>> > World!&#34;);`,
>>> > +-                              `Hello, World &amp; O&#39;Reilly\x21`,
>>> > ++                              `Hello, World &amp; O&#39;Reilly\u0021`,
>>> > +                               `greeting=H%69,&amp;addressee=(World)`,
>>> > +                               `greeting=H%69,&amp;addressee=(World) 2x, 
>>> > https://golang.org/favicon.ico 500.5w`,
>>> > +                               `,foo/,`,
>>> > +@@ -100,7 +100,7 @@ func TestTypedContent(t *testing.T) {
>>> > +                               `Hello,&#32;World&#32;&amp;tc!`,
>>> > +                               `&#32;dir&#61;&#34;ltr&#34;`,
>>> > +                               
>>> > `c&#32;&amp;&amp;&#32;alert(&#34;Hello,&#32;World!&#34;);`,
>>> > +-                              
>>> > `Hello,&#32;World&#32;&amp;&#32;O&#39;Reilly\x21`,
>>> > ++                              
>>> > `Hello,&#32;World&#32;&amp;&#32;O&#39;Reilly\u0021`,
>>> > +                               
>>> > `greeting&#61;H%69,&amp;addressee&#61;(World)`,
>>> > +                               
>>> > `greeting&#61;H%69,&amp;addressee&#61;(World)&#32;2x,&#32;https://golang.org/favicon.ico&#32;500.5w`,
>>> > +                               `,foo/,`,
>>> > +@@ -115,7 +115,7 @@ func TestTypedContent(t *testing.T) {
>>> > +                               `Hello, World &amp;tc!`,
>>> > +                               ` dir=&#34;ltr&#34;`,
>>> > +                               `c &amp;&amp; alert(&#34;Hello, 
>>> > World!&#34;);`,
>>> > +-                              `Hello, World &amp; O&#39;Reilly\x21`,
>>> > ++                              `Hello, World &amp; O&#39;Reilly\u0021`,
>>> > +                               `greeting=H%69,&amp;addressee=(World)`,
>>> > +                               `greeting=H%69,&amp;addressee=(World) 2x, 
>>> > https://golang.org/favicon.ico 500.5w`,
>>> > +                               `,foo/,`,
>>> > +@@ -130,7 +130,7 @@ func TestTypedContent(t *testing.T) {
>>> > +                               `Hello, &lt;b&gt;World&lt;/b&gt; 
>>> > &amp;tc!`,
>>> > +                               ` dir=&#34;ltr&#34;`,
>>> > +                               `c &amp;&amp; alert(&#34;Hello, 
>>> > World!&#34;);`,
>>> > +-                              `Hello, World &amp; O&#39;Reilly\x21`,
>>> > ++                              `Hello, World &amp; O&#39;Reilly\u0021`,
>>> > +                               `greeting=H%69,&amp;addressee=(World)`,
>>> > +                               `greeting=H%69,&amp;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 &amp;&amp; alert(&#34;Hello, 
>>> > World!&#34;);`,
>>> > +                               // Escape sequence not over-escaped.
>>> > +-                              `&#34;Hello, World &amp; 
>>> > O&#39;Reilly\x21&#34;`,
>>> > ++                              `&#34;Hello, World &amp; 
>>> > O&#39;Reilly\u0021&#34;`,
>>> > +                               
>>> > `&#34;greeting=H%69,\u0026addressee=(World)&#34;`,
>>> > +                               
>>> > `&#34;greeting=H%69,\u0026addressee=(World) 2x, 
>>> > https://golang.org/favicon.ico 500.5w&#34;`,
>>> > +                               `&#34;,foo/,&#34;`,
>>> > +@@ -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> &amp;tc!`,
>>> > +                               ` dir=&#34;ltr&#34;`,
>>> > +                               `c &amp;&amp; alert(&#34;Hello, 
>>> > World!&#34;);`,
>>> > +-                              `Hello, World &amp; O&#39;Reilly\x21`,
>>> > ++                              `Hello, World &amp; O&#39;Reilly\u0021`,
>>> > +                               `greeting=H%69,&amp;addressee=(World)`,
>>> > +                               `greeting=H%69,&amp;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,&amp;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(&quot;{{.H}}&quot;)'>",
>>> > +-                      `<button 
>>> > onclick='alert(&quot;\x3cHello\x3e&quot;)'>`,
>>> > ++                      `<button 
>>> > onclick='alert(&quot;\u003cHello\u003e&quot;)'>`,
>>> > +               },
>>> > +               {
>>> > +                       "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 &lt;100&gt;</button>`,
>>> > ++                      `<button onclick="title='11 of \u003c100\u003e'; 
>>> > ...">11 of &lt;100&gt;</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() {
>>> > +       // &#34;Fran &amp; Freddie&#39;s Diner&#34; 
>>> > &lt;ta...@example.com&gt;
>>> > +       // &#34;Fran &amp; Freddie&#39;s Diner&#34; 
>>> > &lt;ta...@example.com&gt;
>>> > +       // &#34;Fran &amp; Freddie&#39;s 
>>> > Diner&#34;32&lt;ta...@example.com&gt;
>>> > +-      // \"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.
>>> > +-              {`&amp;`, `\x26amp;`},
>>> > ++              {`&amp;`, `\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.
>>> > +-              {`&amp;`, `\x26amp;`},
>>> > ++              {`&amp;`, `\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`},
>>> > +-              {`&#x27; does not become HTML entity`, `\x26#x27; does 
>>> > not become HTML entity`},
>>> > ++              {`<html>`, `\u003Chtml\u003E`},
>>> > ++              {`no = in attributes`, `no \u003D in attributes`},
>>> > ++              {`&#x27; 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 (#188644): 
https://lists.openembedded.org/g/openembedded-core/message/188644
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]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to