summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/go')
-rw-r--r--meta/recipes-devtools/go/go-1.14.inc109
-rw-r--r--meta/recipes-devtools/go/go-1.14/0001-CVE-2022-32190.patch74
-rw-r--r--meta/recipes-devtools/go/go-1.14/0002-CVE-2022-32190.patch48
-rw-r--r--meta/recipes-devtools/go/go-1.14/0003-CVE-2022-32190.patch36
-rw-r--r--meta/recipes-devtools/go/go-1.14/0004-CVE-2022-32190.patch82
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2020-29510.patch65
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-27918.patch191
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-31525.patch38
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-33195.patch373
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-33196.patch124
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-33197.patch152
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-33198.patch113
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-34558.patch51
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch101
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-38297.patch97
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-39293.patch79
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-41771.patch86
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-44716.patch93
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2021-44717.patch83
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-1962.patch357
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-23772.patch50
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-23806.patch142
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch271
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch198
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-27664.patch68
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-28131.patch104
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-28327.patch36
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-2879.patch111
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch164
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-30629.patch47
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-30631.patch116
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-30632.patch71
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-30633.patch131
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-30635.patch120
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-32148.patch49
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-32189.patch113
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-41715.patch271
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-41717.patch75
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-41722-1.patch53
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-41722-2.patch104
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-41723.patch156
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre1.patch85
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre2.patch97
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre3.patch98
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2022-41725.patch660
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24534.patch200
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24536_1.patch134
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24536_2.patch184
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24536_3.patch349
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24537.patch76
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch125
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch635
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24538_3.patch393
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24538_4.patch497
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24538_5.patch585
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch371
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24539.patch60
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24540.patch90
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-29400.patch94
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-29402.patch201
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-29404.patch84
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-29405-1.patch112
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-29405-2.patch38
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-29406-1.patch212
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-29406-2.patch114
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-29409.patch175
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-39318.patch262
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch230
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-39326.patch181
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre1.patch393
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre2.patch401
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre3.patch86
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-45287.patch1697
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-45289.patch121
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch271
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2024-24784.patch205
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2024-24785.patch197
-rw-r--r--meta/recipes-devtools/go/go-crosssdk.inc2
-rw-r--r--meta/recipes-devtools/go/go-dep_0.5.4.bb2
-rw-r--r--meta/recipes-devtools/go/go_1.14.bb10
80 files changed, 14521 insertions, 8 deletions
diff --git a/meta/recipes-devtools/go/go-1.14.inc b/meta/recipes-devtools/go/go-1.14.inc
index c52593db6b..9c7ceda891 100644
--- a/meta/recipes-devtools/go/go-1.14.inc
+++ b/meta/recipes-devtools/go/go-1.14.inc
@@ -1,7 +1,7 @@
require go-common.inc
GO_BASEVERSION = "1.14"
-GO_MINOR = ".1"
+GO_MINOR = ".15"
PV .= "${GO_MINOR}"
FILESEXTRAPATHS_prepend := "${FILE_DIRNAME}/go-${GO_BASEVERSION}:"
@@ -16,7 +16,112 @@ SRC_URI += "\
file://0006-cmd-dist-separate-host-and-target-builds.patch \
file://0007-cmd-go-make-GOROOT-precious-by-default.patch \
file://0008-use-GOBUILDMODE-to-set-buildmode.patch \
+ file://CVE-2021-34558.patch \
+ file://CVE-2021-33196.patch \
+ file://CVE-2021-33197.patch \
+ file://CVE-2021-38297.patch \
+ file://CVE-2022-23806.patch \
+ file://CVE-2022-23772.patch \
+ file://CVE-2021-44717.patch \
+ file://CVE-2022-24675.patch \
+ file://CVE-2021-31525.patch \
+ file://CVE-2022-30629.patch \
+ file://CVE-2022-30631.patch \
+ file://CVE-2022-30632.patch \
+ file://CVE-2022-30633.patch \
+ file://CVE-2022-30635.patch \
+ file://CVE-2022-32148.patch \
+ file://CVE-2022-32189.patch \
+ file://CVE-2021-27918.patch \
+ file://CVE-2021-36221.patch \
+ file://CVE-2021-39293.patch \
+ file://CVE-2021-41771.patch \
+ file://CVE-2022-27664.patch \
+ file://0001-CVE-2022-32190.patch \
+ file://0002-CVE-2022-32190.patch \
+ file://0003-CVE-2022-32190.patch \
+ file://0004-CVE-2022-32190.patch \
+ file://CVE-2022-2880.patch \
+ file://CVE-2022-2879.patch \
+ file://CVE-2021-33195.patch \
+ file://CVE-2021-33198.patch \
+ file://CVE-2021-44716.patch \
+ file://CVE-2022-24921.patch \
+ file://CVE-2022-28131.patch \
+ file://CVE-2022-28327.patch \
+ file://CVE-2022-41715.patch \
+ file://CVE-2022-41717.patch \
+ file://CVE-2022-1962.patch \
+ file://CVE-2022-41723.patch \
+ file://CVE-2022-41722-1.patch \
+ file://CVE-2022-41722-2.patch \
+ file://CVE-2020-29510.patch \
+ file://CVE-2023-24537.patch \
+ 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_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 \
+ file://CVE-2023-29405-2.patch \
+ file://CVE-2023-29402.patch \
+ file://CVE-2023-29404.patch \
+ file://CVE-2023-29400.patch \
+ file://CVE-2023-29406-1.patch \
+ file://CVE-2023-29406-2.patch \
+ file://CVE-2023-29409.patch \
+ file://CVE-2022-41725-pre1.patch \
+ file://CVE-2022-41725-pre2.patch \
+ file://CVE-2022-41725-pre3.patch \
+ file://CVE-2022-41725.patch \
+ file://CVE-2023-24536_1.patch \
+ file://CVE-2023-24536_2.patch \
+ file://CVE-2023-24536_3.patch \
+ file://CVE-2023-39318.patch \
+ file://CVE-2023-39319.patch \
+ file://CVE-2023-39326.patch \
+ file://CVE-2023-45287-pre1.patch \
+ file://CVE-2023-45287-pre2.patch \
+ file://CVE-2023-45287-pre3.patch \
+ file://CVE-2023-45287.patch \
+ file://CVE-2023-45289.patch \
+ file://CVE-2023-45290.patch \
+ file://CVE-2024-24785.patch \
+ file://CVE-2024-24784.patch \
"
+
SRC_URI_append_libc-musl = " file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch"
+SRC_URI[main.sha256sum] = "7ed13b2209e54a451835997f78035530b331c5b6943cdcd68a3d815fdc009149"
+
+# Upstream don't believe it is a signifiant real world issue and will only
+# fix in 1.17 onwards where we can drop this.
+# https://github.com/golang/go/issues/30999#issuecomment-910470358
+CVE_CHECK_WHITELIST += "CVE-2021-29923"
+
+# this issue affected go1.15 onwards
+# https://security-tracker.debian.org/tracker/CVE-2022-29526
+CVE_CHECK_WHITELIST += "CVE-2022-29526"
+
+# Issue only on windows
+CVE_CHECK_WHITELIST += "CVE-2022-29804"
+CVE_CHECK_WHITELIST += "CVE-2022-30580"
+CVE_CHECK_WHITELIST += "CVE-2022-30634"
+
+# Issue is in golang.org/x/net/html/parse.go, not used in go compiler
+CVE_CHECK_WHITELIST += "CVE-2021-33194"
+
+# Issue introduced in go1.16, does not exist in 1.14
+CVE_CHECK_WHITELIST += "CVE-2021-41772"
+
+# Fixes code that was added in go1.16, does not exist in 1.14
+CVE_CHECK_WHITELIST += "CVE-2022-30630"
+
+# This is specific to Microsoft Windows
+CVE_CHECK_WHITELIST += "CVE-2022-41716"
-SRC_URI[main.sha256sum] = "2ad2572115b0d1b4cb4c138e6b3a31cee6294cb48af75ee86bec3dca04507676"
+# Issue introduced in go1.15beta1, does not exist in 1.14
+CVE_CHECK_WHITELIST += "CVE-2022-1705"
diff --git a/meta/recipes-devtools/go/go-1.14/0001-CVE-2022-32190.patch b/meta/recipes-devtools/go/go-1.14/0001-CVE-2022-32190.patch
new file mode 100644
index 0000000000..ad263b8023
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/0001-CVE-2022-32190.patch
@@ -0,0 +1,74 @@
+From 755f2dc35a19e6806de3ecbf836fa06ad875c67a Mon Sep 17 00:00:00 2001
+From: Carl Johnson <me@carlmjohnson.net>
+Date: Fri, 4 Mar 2022 14:49:52 +0000
+Subject: [PATCH 1/4] net/url: add JoinPath, URL.JoinPath
+
+Builds on CL 332209.
+
+Fixes #47005
+
+Change-Id: I82708dede05d79a196ca63f5a4e7cb5ac9a041ea
+GitHub-Last-Rev: 51b735066eef74f5e67c3e8899c58f44c0383c61
+GitHub-Pull-Request: golang/go#50383
+Reviewed-on: https://go-review.googlesource.com/c/go/+/374654
+Reviewed-by: Russ Cox <rsc@golang.org>
+Auto-Submit: Russ Cox <rsc@golang.org>
+Trust: Ian Lance Taylor <iant@golang.org>
+Reviewed-by: Damien Neil <dneil@google.com>
+Run-TryBot: Ian Lance Taylor <iant@golang.org>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/604140d93111f89911e17cb147dcf6a02d2700d0]
+CVE: CVE-2022-32190
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/net/url/url.go | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/src/net/url/url.go b/src/net/url/url.go
+index 2880e82..dea8bfe 100644
+--- a/src/net/url/url.go
++++ b/src/net/url/url.go
+@@ -13,6 +13,7 @@ package url
+ import (
+ "errors"
+ "fmt"
++ "path"
+ "sort"
+ "strconv"
+ "strings"
+@@ -1104,6 +1105,17 @@ func (u *URL) UnmarshalBinary(text []byte) error {
+ return nil
+ }
+
++// JoinPath returns a new URL with the provided path elements joined to
++// any existing path and the resulting path cleaned of any ./ or ../ elements.
++func (u *URL) JoinPath(elem ...string) *URL {
++ url := *u
++ if len(elem) > 0 {
++ elem = append([]string{u.Path}, elem...)
++ url.setPath(path.Join(elem...))
++ }
++ return &url
++}
++
+ // validUserinfo reports whether s is a valid userinfo string per RFC 3986
+ // Section 3.2.1:
+ // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+@@ -1144,3 +1156,14 @@ func stringContainsCTLByte(s string) bool {
+ }
+ return false
+ }
++
++// JoinPath returns a URL string with the provided path elements joined to
++// the existing path of base and the resulting path cleaned of any ./ or ../ elements.
++func JoinPath(base string, elem ...string) (result string, err error) {
++ url, err := Parse(base)
++ if err != nil {
++ return
++ }
++ result = url.JoinPath(elem...).String()
++ return
++}
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/0002-CVE-2022-32190.patch b/meta/recipes-devtools/go/go-1.14/0002-CVE-2022-32190.patch
new file mode 100644
index 0000000000..1a11cc72bc
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/0002-CVE-2022-32190.patch
@@ -0,0 +1,48 @@
+From 985108de87e7d2ecb2b28cb53b323d530387b884 Mon Sep 17 00:00:00 2001
+From: Ian Lance Taylor <iant@golang.org>
+Date: Thu, 31 Mar 2022 13:21:39 -0700
+Subject: [PATCH 2/4] net/url: preserve a trailing slash in JoinPath
+
+Fixes #52074
+
+Change-Id: I30897f32e70a6ca0c4e11aaf07088c27336efaba
+Reviewed-on: https://go-review.googlesource.com/c/go/+/397256
+Trust: Ian Lance Taylor <iant@golang.org>
+Run-TryBot: Ian Lance Taylor <iant@golang.org>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Matt Layher <mdlayher@gmail.com>
+Trust: Matt Layher <mdlayher@gmail.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/dbb52cc9f3e83a3040f46c2ae7650c15ab342179]
+CVE: CVE-2022-32190
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/net/url/url.go | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/src/net/url/url.go b/src/net/url/url.go
+index dea8bfe..3436707 100644
+--- a/src/net/url/url.go
++++ b/src/net/url/url.go
+@@ -1107,11 +1107,18 @@ func (u *URL) UnmarshalBinary(text []byte) error {
+
+ // JoinPath returns a new URL with the provided path elements joined to
+ // any existing path and the resulting path cleaned of any ./ or ../ elements.
++// Any sequences of multiple / characters will be reduced to a single /.
+ func (u *URL) JoinPath(elem ...string) *URL {
+ url := *u
+ if len(elem) > 0 {
+ elem = append([]string{u.Path}, elem...)
+- url.setPath(path.Join(elem...))
++ p := path.Join(elem...)
++ // path.Join will remove any trailing slashes.
++ // Preserve at least one.
++ if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
++ p += "/"
++ }
++ url.setPath(p)
+ }
+ return &url
+ }
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/0003-CVE-2022-32190.patch b/meta/recipes-devtools/go/go-1.14/0003-CVE-2022-32190.patch
new file mode 100644
index 0000000000..816d914983
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/0003-CVE-2022-32190.patch
@@ -0,0 +1,36 @@
+From 2c632b883b0f11084cc247c8b50ad6c71fa7b447 Mon Sep 17 00:00:00 2001
+From: Sean Liao <sean@liao.dev>
+Date: Sat, 9 Jul 2022 18:38:45 +0100
+Subject: [PATCH 3/4] net/url: use EscapedPath for url.JoinPath
+
+Fixes #53763
+
+Change-Id: I08b53f159ebdce7907e8cc17316fd0c982363239
+Reviewed-on: https://go-review.googlesource.com/c/go/+/416774
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-by: Bryan Mills <bcmills@google.com>
+Run-TryBot: Ian Lance Taylor <iant@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/bf5898ef53d1693aa572da0da746c05e9a6f15c5]
+CVE: CVE-2022-32190
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/net/url/url.go | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/net/url/url.go b/src/net/url/url.go
+index 3436707..73079a5 100644
+--- a/src/net/url/url.go
++++ b/src/net/url/url.go
+@@ -1111,7 +1111,7 @@ func (u *URL) UnmarshalBinary(text []byte) error {
+ func (u *URL) JoinPath(elem ...string) *URL {
+ url := *u
+ if len(elem) > 0 {
+- elem = append([]string{u.Path}, elem...)
++ elem = append([]string{u.EscapedPath()}, elem...)
+ p := path.Join(elem...)
+ // path.Join will remove any trailing slashes.
+ // Preserve at least one.
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/0004-CVE-2022-32190.patch b/meta/recipes-devtools/go/go-1.14/0004-CVE-2022-32190.patch
new file mode 100644
index 0000000000..4bdff3aed4
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/0004-CVE-2022-32190.patch
@@ -0,0 +1,82 @@
+From f61e428699cbb52bab31fe2c124f49d085a209fe Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Fri, 12 Aug 2022 16:21:09 -0700
+Subject: [PATCH 4/4] net/url: consistently remove ../ elements in JoinPath
+
+JoinPath would fail to remove relative elements from the start of
+the path when the first path element is "".
+
+In addition, JoinPath would return the original path unmodified
+when provided with no elements to join, violating the documented
+behavior of always cleaning the resulting path.
+
+Correct both these cases.
+
+ JoinPath("http://go.dev", "../go")
+ // before: http://go.dev/../go
+ // after: http://go.dev/go
+
+ JoinPath("http://go.dev/../go")
+ // before: http://go.dev/../go
+ // after: http://go.dev/go
+
+For #54385.
+Fixes #54635.
+Fixes CVE-2022-32190.
+
+Change-Id: I6d22cd160d097c50703dd96e4f453c6c118fd5d9
+Reviewed-on: https://go-review.googlesource.com/c/go/+/423514
+Reviewed-by: David Chase <drchase@google.com>
+Reviewed-by: Alan Donovan <adonovan@google.com>
+(cherry picked from commit 0765da5884adcc8b744979303a36a27092d8fc51)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/425357
+Run-TryBot: Damien Neil <dneil@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/28335508913a46e05ef0c04a18e8a1a6beb775ec]
+CVE: CVE-2022-32190
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/net/url/url.go | 26 ++++++++++++++++----------
+ 1 file changed, 16 insertions(+), 10 deletions(-)
+
+diff --git a/src/net/url/url.go b/src/net/url/url.go
+index 73079a5..1e8baf9 100644
+--- a/src/net/url/url.go
++++ b/src/net/url/url.go
+@@ -1109,17 +1109,23 @@ func (u *URL) UnmarshalBinary(text []byte) error {
+ // any existing path and the resulting path cleaned of any ./ or ../ elements.
+ // Any sequences of multiple / characters will be reduced to a single /.
+ func (u *URL) JoinPath(elem ...string) *URL {
+- url := *u
+- if len(elem) > 0 {
+- elem = append([]string{u.EscapedPath()}, elem...)
+- p := path.Join(elem...)
+- // path.Join will remove any trailing slashes.
+- // Preserve at least one.
+- if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
+- p += "/"
+- }
+- url.setPath(p)
++ elem = append([]string{u.EscapedPath()}, elem...)
++ var p string
++ if !strings.HasPrefix(elem[0], "/") {
++ // Return a relative path if u is relative,
++ // but ensure that it contains no ../ elements.
++ elem[0] = "/" + elem[0]
++ p = path.Join(elem...)[1:]
++ } else {
++ p = path.Join(elem...)
+ }
++ // path.Join will remove any trailing slashes.
++ // Preserve at least one.
++ if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
++ p += "/"
++ }
++ url := *u
++ url.setPath(p)
+ return &url
+ }
+
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2020-29510.patch b/meta/recipes-devtools/go/go-1.14/CVE-2020-29510.patch
new file mode 100644
index 0000000000..e1c9e0bdb9
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2020-29510.patch
@@ -0,0 +1,65 @@
+From a0bf4d38dc2057d28396594264bbdd43d412de22 Mon Sep 17 00:00:00 2001
+From: Filippo Valsorda <filippo@golang.org>
+Date: Tue, 27 Oct 2020 00:21:30 +0100
+Subject: [PATCH] encoding/xml: replace comments inside directives with a space
+
+A Directive (like <!ENTITY xxx []>) can't have other nodes nested inside
+it (in our data structure representation), so there is no way to
+preserve comments. The previous behavior was to just elide them, which
+however might change the semantic meaning of the surrounding markup.
+Instead, replace them with a space which hopefully has the same semantic
+effect of the comment.
+
+Directives are not actually a node type in the XML spec, which instead
+specifies each of them separately (<!ENTITY, <!DOCTYPE, etc.), each with
+its own grammar. The rules for where and when the comments are allowed
+are not straightforward, and can't be implemented without implementing
+custom logic for each of the directives.
+
+Simply preserving the comments in the body of the directive would be
+problematic, as there can be unmatched quotes inside the comment.
+Whether those quotes are considered meaningful semantically or not,
+other parsers might disagree and interpret the output differently.
+
+This issue was reported by Juho Nurminen of Mattermost as it leads to
+round-trip mismatches. See #43168. It's not being fixed in a security
+release because round-trip stability is not a currently supported
+security property of encoding/xml, and we don't believe these fixes
+would be sufficient to reliably guarantee it in the future.
+
+Fixes CVE-2020-29510
+Updates #43168
+
+Change-Id: Icd86c75beff3e1e0689543efebdad10ed5178ce3
+Reviewed-on: https://go-review.googlesource.com/c/go/+/277893
+Run-TryBot: Filippo Valsorda <filippo@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Trust: Filippo Valsorda <filippo@golang.org>
+Reviewed-by: Katie Hockman <katie@golang.org>
+
+Upstream-Status: Backport from https://github.com/golang/go/commit/a9cfd55e2b09735a25976d1b008a0a3c767494f8
+CVE: CVE-2020-29510
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/encoding/xml/xml.go | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go
+index 01a1460..98647b2 100644
+--- a/src/encoding/xml/xml.go
++++ b/src/encoding/xml/xml.go
+@@ -768,6 +768,12 @@ func (d *Decoder) rawToken() (Token, error) {
+ }
+ b0, b1 = b1, b
+ }
++
++ // Replace the comment with a space in the returned Directive
++ // body, so that markup parts that were separated by the comment
++ // (like a "<" and a "!") don't get joined when re-encoding the
++ // Directive, taking new semantic meaning.
++ d.buf.WriteByte(' ')
+ }
+ }
+ return Directive(d.buf.Bytes()), nil
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-27918.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-27918.patch
new file mode 100644
index 0000000000..faa3f7f641
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-27918.patch
@@ -0,0 +1,191 @@
+From d0b79e3513a29628f3599dc8860666b6eed75372 Mon Sep 17 00:00:00 2001
+From: Katie Hockman <katie@golang.org>
+Date: Mon, 1 Mar 2021 09:54:00 -0500
+Subject: [PATCH] encoding/xml: prevent infinite loop while decoding
+
+This change properly handles a TokenReader which
+returns an EOF in the middle of an open XML
+element.
+
+Thanks to Sam Whited for reporting this.
+
+Fixes CVE-2021-27918
+Fixes #44913
+
+Change-Id: Id02a3f3def4a1b415fa2d9a8e3b373eb6cb0f433
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1004594
+Reviewed-by: Russ Cox <rsc@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Filippo Valsorda <valsorda@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/300391
+Trust: Katie Hockman <katie@golang.org>
+Run-TryBot: Katie Hockman <katie@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Alexander Rakoczy <alex@golang.org>
+Reviewed-by: Filippo Valsorda <filippo@golang.org>
+
+https://github.com/golang/go/commit/d0b79e3513a29628f3599dc8860666b6eed75372
+CVE: CVE-2021-27918
+Upstream-Status: Backport
+Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
+---
+ src/encoding/xml/xml.go | 19 ++++---
+ src/encoding/xml/xml_test.go | 104 +++++++++++++++++++++++++++--------
+ 2 files changed, 92 insertions(+), 31 deletions(-)
+
+diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go
+index adaf4daf198b9..6f9594d7ba7a3 100644
+--- a/src/encoding/xml/xml.go
++++ b/src/encoding/xml/xml.go
+@@ -271,7 +271,7 @@ func NewTokenDecoder(t TokenReader) *Decoder {
+ // it will return an error.
+ //
+ // Token implements XML name spaces as described by
+-// https://www.w3.org/TR/REC-xml-names/. Each of the
++// https://www.w3.org/TR/REC-xml-names/. Each of the
+ // Name structures contained in the Token has the Space
+ // set to the URL identifying its name space when known.
+ // If Token encounters an unrecognized name space prefix,
+@@ -285,16 +285,17 @@ func (d *Decoder) Token() (Token, error) {
+ if d.nextToken != nil {
+ t = d.nextToken
+ d.nextToken = nil
+- } else if t, err = d.rawToken(); err != nil {
+- switch {
+- case err == io.EOF && d.t != nil:
+- err = nil
+- case err == io.EOF && d.stk != nil && d.stk.kind != stkEOF:
+- err = d.syntaxError("unexpected EOF")
++ } else {
++ if t, err = d.rawToken(); t == nil && err != nil {
++ if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF {
++ err = d.syntaxError("unexpected EOF")
++ }
++ return nil, err
+ }
+- return t, err
++ // We still have a token to process, so clear any
++ // errors (e.g. EOF) and proceed.
++ err = nil
+ }
+-
+ if !d.Strict {
+ if t1, ok := d.autoClose(t); ok {
+ d.nextToken = t
+diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go
+index efddca43e9102..5672ebb375f0d 100644
+--- a/src/encoding/xml/xml_test.go
++++ b/src/encoding/xml/xml_test.go
+@@ -33,30 +33,90 @@ func (t *toks) Token() (Token, error) {
+
+ func TestDecodeEOF(t *testing.T) {
+ start := StartElement{Name: Name{Local: "test"}}
+- t.Run("EarlyEOF", func(t *testing.T) {
+- d := NewTokenDecoder(&toks{earlyEOF: true, t: []Token{
+- start,
+- start.End(),
+- }})
+- err := d.Decode(&struct {
+- XMLName Name `xml:"test"`
+- }{})
+- if err != nil {
+- t.Error(err)
++ tests := []struct {
++ name string
++ tokens []Token
++ ok bool
++ }{
++ {
++ name: "OK",
++ tokens: []Token{
++ start,
++ start.End(),
++ },
++ ok: true,
++ },
++ {
++ name: "Malformed",
++ tokens: []Token{
++ start,
++ StartElement{Name: Name{Local: "bad"}},
++ start.End(),
++ },
++ ok: false,
++ },
++ }
++ for _, tc := range tests {
++ for _, eof := range []bool{true, false} {
++ name := fmt.Sprintf("%s/earlyEOF=%v", tc.name, eof)
++ t.Run(name, func(t *testing.T) {
++ d := NewTokenDecoder(&toks{
++ earlyEOF: eof,
++ t: tc.tokens,
++ })
++ err := d.Decode(&struct {
++ XMLName Name `xml:"test"`
++ }{})
++ if tc.ok && err != nil {
++ t.Fatalf("d.Decode: expected nil error, got %v", err)
++ }
++ if _, ok := err.(*SyntaxError); !tc.ok && !ok {
++ t.Errorf("d.Decode: expected syntax error, got %v", err)
++ }
++ })
+ }
+- })
+- t.Run("LateEOF", func(t *testing.T) {
+- d := NewTokenDecoder(&toks{t: []Token{
+- start,
+- start.End(),
+- }})
+- err := d.Decode(&struct {
+- XMLName Name `xml:"test"`
+- }{})
+- if err != nil {
+- t.Error(err)
++ }
++}
++
++type toksNil struct {
++ returnEOF bool
++ t []Token
++}
++
++func (t *toksNil) Token() (Token, error) {
++ if len(t.t) == 0 {
++ if !t.returnEOF {
++ // Return nil, nil before returning an EOF. It's legal, but
++ // discouraged.
++ t.returnEOF = true
++ return nil, nil
+ }
+- })
++ return nil, io.EOF
++ }
++ var tok Token
++ tok, t.t = t.t[0], t.t[1:]
++ return tok, nil
++}
++
++func TestDecodeNilToken(t *testing.T) {
++ for _, strict := range []bool{true, false} {
++ name := fmt.Sprintf("Strict=%v", strict)
++ t.Run(name, func(t *testing.T) {
++ start := StartElement{Name: Name{Local: "test"}}
++ bad := StartElement{Name: Name{Local: "bad"}}
++ d := NewTokenDecoder(&toksNil{
++ // Malformed
++ t: []Token{start, bad, start.End()},
++ })
++ d.Strict = strict
++ err := d.Decode(&struct {
++ XMLName Name `xml:"test"`
++ }{})
++ if _, ok := err.(*SyntaxError); !ok {
++ t.Errorf("d.Decode: expected syntax error, got %v", err)
++ }
++ })
++ }
+ }
+
+ const testInput = `
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-31525.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-31525.patch
new file mode 100644
index 0000000000..afe4b0d2b8
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-31525.patch
@@ -0,0 +1,38 @@
+From efb465ada003d23353a91ef930be408eb575dba6 Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Thu, 16 Jun 2022 17:40:12 +0530
+Subject: [PATCH] CVE-2021-31525
+
+Upstream-Status: Backport [https://github.com/argoheyard/lang-net/commit/701957006ef151feb43f86aa99c8a1f474f69282]
+CVE: CVE-2021-31525
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+
+---
+ src/vendor/golang.org/x/net/http/httpguts/httplex.go | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/src/vendor/golang.org/x/net/http/httpguts/httplex.go b/src/vendor/golang.org/x/net/http/httpguts/httplex.go
+index e7de24e..c79aa73 100644
+--- a/src/vendor/golang.org/x/net/http/httpguts/httplex.go
++++ b/src/vendor/golang.org/x/net/http/httpguts/httplex.go
+@@ -137,11 +137,13 @@ func trimOWS(x string) string {
+ // contains token amongst its comma-separated tokens, ASCII
+ // case-insensitively.
+ func headerValueContainsToken(v string, token string) bool {
+- v = trimOWS(v)
+- if comma := strings.IndexByte(v, ','); comma != -1 {
+- return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
++ for comma := strings.IndexByte(v, ','); comma != -1; comma = strings.IndexByte(v, ',') {
++ if tokenEqual(trimOWS(v[:comma]), token) {
++ return true
++ }
++ v = v[comma+1:]
+ }
+- return tokenEqual(v, token)
++ return tokenEqual(trimOWS(v), token)
+ }
+
+ // lowerASCII returns the ASCII lowercase version of b.
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-33195.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-33195.patch
new file mode 100644
index 0000000000..3d9de888ff
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-33195.patch
@@ -0,0 +1,373 @@
+From 9324d7e53151e9dfa4b25af994a28c2e0b11f729 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <roland@golang.org>
+Date: Thu, 27 May 2021 10:40:06 -0700
+Subject: [PATCH] net: verify results from Lookup* are valid domain names
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/31d60cda1f58b7558fc5725d2b9e4531655d980e]
+CVE: CVE-2021-33195
+Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
+
+
+For the methods LookupCNAME, LookupSRV, LookupMX, LookupNS, and
+LookupAddr check that the returned domain names are in fact valid DNS
+names using the existing isDomainName function.
+
+Thanks to Philipp Jeitner and Haya Shulman from Fraunhofer SIT for
+reporting this issue.
+
+Updates #46241
+Fixes #46356
+Fixes CVE-2021-33195
+
+Change-Id: I47a4f58c031cb752f732e88bbdae7f819f0af4f3
+Reviewed-on: https://go-review.googlesource.com/c/go/+/323131
+Trust: Roland Shoemaker <roland@golang.org>
+Run-TryBot: Roland Shoemaker <roland@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Filippo Valsorda <filippo@golang.org>
+Reviewed-by: Katie Hockman <katie@golang.org>
+(cherry picked from commit cdcd02842da7c004efd023881e3719105209c908)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/323269
+---
+ src/net/dnsclient_unix_test.go | 157 +++++++++++++++++++++++++++++++++
+ src/net/lookup.go | 111 ++++++++++++++++++++---
+ 2 files changed, 255 insertions(+), 13 deletions(-)
+
+diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
+index 2ad40df..b8617d9 100644
+--- a/src/net/dnsclient_unix_test.go
++++ b/src/net/dnsclient_unix_test.go
+@@ -1800,3 +1800,160 @@ func TestPTRandNonPTR(t *testing.T) {
+ t.Errorf("names = %q; want %q", names, want)
+ }
+ }
++
++func TestCVE202133195(t *testing.T) {
++ fake := fakeDNSServer{
++ rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
++ r := dnsmessage.Message{
++ Header: dnsmessage.Header{
++ ID: q.Header.ID,
++ Response: true,
++ RCode: dnsmessage.RCodeSuccess,
++ RecursionAvailable: true,
++ },
++ Questions: q.Questions,
++ }
++ switch q.Questions[0].Type {
++ case dnsmessage.TypeCNAME:
++ r.Answers = []dnsmessage.Resource{}
++ case dnsmessage.TypeA: // CNAME lookup uses a A/AAAA as a proxy
++ r.Answers = append(r.Answers,
++ dnsmessage.Resource{
++ Header: dnsmessage.ResourceHeader{
++ Name: dnsmessage.MustNewName("<html>.golang.org."),
++ Type: dnsmessage.TypeA,
++ Class: dnsmessage.ClassINET,
++ Length: 4,
++ },
++ Body: &dnsmessage.AResource{
++ A: TestAddr,
++ },
++ },
++ )
++ case dnsmessage.TypeSRV:
++ n := q.Questions[0].Name
++ if n.String() == "_hdr._tcp.golang.org." {
++ n = dnsmessage.MustNewName("<html>.golang.org.")
++ }
++ r.Answers = append(r.Answers,
++ dnsmessage.Resource{
++ Header: dnsmessage.ResourceHeader{
++ Name: n,
++ Type: dnsmessage.TypeSRV,
++ Class: dnsmessage.ClassINET,
++ Length: 4,
++ },
++ Body: &dnsmessage.SRVResource{
++ Target: dnsmessage.MustNewName("<html>.golang.org."),
++ },
++ },
++ )
++ case dnsmessage.TypeMX:
++ r.Answers = append(r.Answers,
++ dnsmessage.Resource{
++ Header: dnsmessage.ResourceHeader{
++ Name: dnsmessage.MustNewName("<html>.golang.org."),
++ Type: dnsmessage.TypeMX,
++ Class: dnsmessage.ClassINET,
++ Length: 4,
++ },
++ Body: &dnsmessage.MXResource{
++ MX: dnsmessage.MustNewName("<html>.golang.org."),
++ },
++ },
++ )
++ case dnsmessage.TypeNS:
++ r.Answers = append(r.Answers,
++ dnsmessage.Resource{
++ Header: dnsmessage.ResourceHeader{
++ Name: dnsmessage.MustNewName("<html>.golang.org."),
++ Type: dnsmessage.TypeNS,
++ Class: dnsmessage.ClassINET,
++ Length: 4,
++ },
++ Body: &dnsmessage.NSResource{
++ NS: dnsmessage.MustNewName("<html>.golang.org."),
++ },
++ },
++ )
++ case dnsmessage.TypePTR:
++ r.Answers = append(r.Answers,
++ dnsmessage.Resource{
++ Header: dnsmessage.ResourceHeader{
++ Name: dnsmessage.MustNewName("<html>.golang.org."),
++ Type: dnsmessage.TypePTR,
++ Class: dnsmessage.ClassINET,
++ Length: 4,
++ },
++ Body: &dnsmessage.PTRResource{
++ PTR: dnsmessage.MustNewName("<html>.golang.org."),
++ },
++ },
++ )
++ }
++ return r, nil
++ },
++ }
++
++ r := Resolver{PreferGo: true, Dial: fake.DialContext}
++ // Change the default resolver to match our manipulated resolver
++ originalDefault := DefaultResolver
++ DefaultResolver = &r
++ defer func() {
++ DefaultResolver = originalDefault
++ }()
++
++ _, err := r.LookupCNAME(context.Background(), "golang.org")
++ if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("Resolver.LookupCNAME returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++ _, err = LookupCNAME("golang.org")
++ if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("LookupCNAME returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++
++ _, _, err = r.LookupSRV(context.Background(), "target", "tcp", "golang.org")
++ if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++ _, _, err = LookupSRV("target", "tcp", "golang.org")
++ if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++
++ _, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org")
++ if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++ _, _, err = LookupSRV("hdr", "tcp", "golang.org")
++ if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++
++ _, err = r.LookupMX(context.Background(), "golang.org")
++ if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("Resolver.LookupMX returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++ _, err = LookupMX("golang.org")
++ if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("LookupMX returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++
++ _, err = r.LookupNS(context.Background(), "golang.org")
++ if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("Resolver.LookupNS returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++ _, err = LookupNS("golang.org")
++ if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("LookupNS returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++
++ _, err = r.LookupAddr(context.Background(), "1.2.3.4")
++ if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("Resolver.LookupAddr returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++ _, err = LookupAddr("1.2.3.4")
++ if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected {
++ t.Errorf("LookupAddr returned unexpected error, got %q, want %q", err.Error(), expected)
++ }
++}
+diff --git a/src/net/lookup.go b/src/net/lookup.go
+index 9cebd10..05e88e4 100644
+--- a/src/net/lookup.go
++++ b/src/net/lookup.go
+@@ -364,8 +364,11 @@ func (r *Resolver) LookupPort(ctx context.Context, network, service string) (por
+ // LookupCNAME does not return an error if host does not
+ // contain DNS "CNAME" records, as long as host resolves to
+ // address records.
++//
++// The returned canonical name is validated to be a properly
++// formatted presentation-format domain name.
+ func LookupCNAME(host string) (cname string, err error) {
+- return DefaultResolver.lookupCNAME(context.Background(), host)
++ return DefaultResolver.LookupCNAME(context.Background(), host)
+ }
+
+ // LookupCNAME returns the canonical name for the given host.
+@@ -378,8 +381,18 @@ func LookupCNAME(host string) (cname string, err error) {
+ // LookupCNAME does not return an error if host does not
+ // contain DNS "CNAME" records, as long as host resolves to
+ // address records.
+-func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string, err error) {
+- return r.lookupCNAME(ctx, host)
++//
++// The returned canonical name is validated to be a properly
++// formatted presentation-format domain name.
++func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) {
++ cname, err := r.lookupCNAME(ctx, host)
++ if err != nil {
++ return "", err
++ }
++ if !isDomainName(cname) {
++ return "", &DNSError{Err: "CNAME target is invalid", Name: host}
++ }
++ return cname, nil
+ }
+
+ // LookupSRV tries to resolve an SRV query of the given service,
+@@ -391,8 +404,11 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string,
+ // That is, it looks up _service._proto.name. To accommodate services
+ // publishing SRV records under non-standard names, if both service
+ // and proto are empty strings, LookupSRV looks up name directly.
++//
++// The returned service names are validated to be properly
++// formatted presentation-format domain names.
+ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
+- return DefaultResolver.lookupSRV(context.Background(), service, proto, name)
++ return DefaultResolver.LookupSRV(context.Background(), service, proto, name)
+ }
+
+ // LookupSRV tries to resolve an SRV query of the given service,
+@@ -404,28 +420,82 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
+ // That is, it looks up _service._proto.name. To accommodate services
+ // publishing SRV records under non-standard names, if both service
+ // and proto are empty strings, LookupSRV looks up name directly.
+-func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
+- return r.lookupSRV(ctx, service, proto, name)
++//
++// The returned service names are validated to be properly
++// formatted presentation-format domain names.
++func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
++ cname, addrs, err := r.lookupSRV(ctx, service, proto, name)
++ if err != nil {
++ return "", nil, err
++ }
++ if cname != "" && !isDomainName(cname) {
++ return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name}
++ }
++ for _, addr := range addrs {
++ if addr == nil {
++ continue
++ }
++ if !isDomainName(addr.Target) {
++ return "", nil, &DNSError{Err: "SRV target is invalid", Name: name}
++ }
++ }
++ return cname, addrs, nil
+ }
+
+ // LookupMX returns the DNS MX records for the given domain name sorted by preference.
++//
++// The returned mail server names are validated to be properly
++// formatted presentation-format domain names.
+ func LookupMX(name string) ([]*MX, error) {
+- return DefaultResolver.lookupMX(context.Background(), name)
++ return DefaultResolver.LookupMX(context.Background(), name)
+ }
+
+ // LookupMX returns the DNS MX records for the given domain name sorted by preference.
++//
++// The returned mail server names are validated to be properly
++// formatted presentation-format domain names.
+ func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
+- return r.lookupMX(ctx, name)
++ records, err := r.lookupMX(ctx, name)
++ if err != nil {
++ return nil, err
++ }
++ for _, mx := range records {
++ if mx == nil {
++ continue
++ }
++ if !isDomainName(mx.Host) {
++ return nil, &DNSError{Err: "MX target is invalid", Name: name}
++ }
++ }
++ return records, nil
+ }
+
+ // LookupNS returns the DNS NS records for the given domain name.
++//
++// The returned name server names are validated to be properly
++// formatted presentation-format domain names.
+ func LookupNS(name string) ([]*NS, error) {
+- return DefaultResolver.lookupNS(context.Background(), name)
++ return DefaultResolver.LookupNS(context.Background(), name)
+ }
+
+ // LookupNS returns the DNS NS records for the given domain name.
++//
++// The returned name server names are validated to be properly
++// formatted presentation-format domain names.
+ func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
+- return r.lookupNS(ctx, name)
++ records, err := r.lookupNS(ctx, name)
++ if err != nil {
++ return nil, err
++ }
++ for _, ns := range records {
++ if ns == nil {
++ continue
++ }
++ if !isDomainName(ns.Host) {
++ return nil, &DNSError{Err: "NS target is invalid", Name: name}
++ }
++ }
++ return records, nil
+ }
+
+ // LookupTXT returns the DNS TXT records for the given domain name.
+@@ -441,14 +511,29 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error)
+ // LookupAddr performs a reverse lookup for the given address, returning a list
+ // of names mapping to that address.
+ //
++// The returned names are validated to be properly formatted presentation-format
++// domain names.
++//
+ // When using the host C library resolver, at most one result will be
+ // returned. To bypass the host resolver, use a custom Resolver.
+ func LookupAddr(addr string) (names []string, err error) {
+- return DefaultResolver.lookupAddr(context.Background(), addr)
++ return DefaultResolver.LookupAddr(context.Background(), addr)
+ }
+
+ // LookupAddr performs a reverse lookup for the given address, returning a list
+ // of names mapping to that address.
+-func (r *Resolver) LookupAddr(ctx context.Context, addr string) (names []string, err error) {
+- return r.lookupAddr(ctx, addr)
++//
++// The returned names are validated to be properly formatted presentation-format
++// domain names.
++func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
++ names, err := r.lookupAddr(ctx, addr)
++ if err != nil {
++ return nil, err
++ }
++ for _, name := range names {
++ if !isDomainName(name) {
++ return nil, &DNSError{Err: "PTR target is invalid", Name: addr}
++ }
++ }
++ return names, nil
+ }
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-33196.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-33196.patch
new file mode 100644
index 0000000000..2e2dc62c49
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-33196.patch
@@ -0,0 +1,124 @@
+From 74242baa4136c7a9132a8ccd9881354442788c8c Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <roland@golang.org>
+Date: Tue, 11 May 2021 11:31:31 -0700
+Subject: [PATCH] archive/zip: only preallocate File slice if reasonably sized
+
+Since the number of files in the EOCD record isn't validated, it isn't
+safe to preallocate Reader.Files using that field. A malformed archive
+can indicate it contains up to 1 << 128 - 1 files. We can still safely
+preallocate the slice by checking if the specified number of files in
+the archive is reasonable, given the size of the archive.
+
+Thanks to the OSS-Fuzz project for discovering this issue and to
+Emmanuel Odeke for reporting it.
+
+Fixes #46242
+Fixes CVE-2021-33196
+
+Change-Id: I3c76d8eec178468b380d87fdb4a3f2cb06f0ee76
+Reviewed-on: https://go-review.googlesource.com/c/go/+/318909
+Trust: Roland Shoemaker <roland@golang.org>
+Trust: Katie Hockman <katie@golang.org>
+Trust: Joe Tsai <thebrokentoaster@gmail.com>
+Run-TryBot: Roland Shoemaker <roland@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Katie Hockman <katie@golang.org>
+Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
+
+Upstream-Status: Backport
+CVE: CVE-2021-33196
+Signed-off-by: Armin Kuster <akuster@mvista.com>
+
+---
+ src/archive/zip/reader.go | 10 +++++-
+ src/archive/zip/reader_test.go | 59 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 68 insertions(+), 1 deletion(-)
+
+Index: go/src/archive/zip/reader.go
+===================================================================
+--- go.orig/src/archive/zip/reader.go
++++ go/src/archive/zip/reader.go
+@@ -84,7 +84,15 @@ func (z *Reader) init(r io.ReaderAt, siz
+ return err
+ }
+ z.r = r
+- z.File = make([]*File, 0, end.directoryRecords)
++ // Since the number of directory records is not validated, it is not
++ // safe to preallocate z.File without first checking that the specified
++ // number of files is reasonable, since a malformed archive may
++ // indicate it contains up to 1 << 128 - 1 files. Since each file has a
++ // header which will be _at least_ 30 bytes we can safely preallocate
++ // if (data size / 30) >= end.directoryRecords.
++ if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
++ z.File = make([]*File, 0, end.directoryRecords)
++ }
+ z.Comment = end.comment
+ rs := io.NewSectionReader(r, 0, size)
+ if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {
+Index: go/src/archive/zip/reader_test.go
+===================================================================
+--- go.orig/src/archive/zip/reader_test.go
++++ go/src/archive/zip/reader_test.go
+@@ -1070,3 +1070,62 @@ func TestIssue12449(t *testing.T) {
+ t.Errorf("Error reading the archive: %v", err)
+ }
+ }
++
++func TestCVE202133196(t *testing.T) {
++ // Archive that indicates it has 1 << 128 -1 files,
++ // this would previously cause a panic due to attempting
++ // to allocate a slice with 1 << 128 -1 elements.
++ data := []byte{
++ 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08,
++ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02,
++ 0x03, 0x62, 0x61, 0x65, 0x03, 0x04, 0x00, 0x00,
++ 0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0xbe, 0x20,
++ 0x5c, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00,
++ 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00,
++ 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xbe, 0x20, 0x5c, 0x6c, 0x09, 0x00,
++ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x01, 0x02, 0x03, 0x50, 0x4b, 0x06, 0x06, 0x2c,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
++ 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x50, 0x4b, 0x06, 0x07, 0x00,
++ 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50,
++ 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0x00, 0x00,
++ }
++ _, err := NewReader(bytes.NewReader(data), int64(len(data)))
++ if err != ErrFormat {
++ t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
++ }
++
++ // Also check that an archive containing a handful of empty
++ // files doesn't cause an issue
++ b := bytes.NewBuffer(nil)
++ w := NewWriter(b)
++ for i := 0; i < 5; i++ {
++ _, err := w.Create("")
++ if err != nil {
++ t.Fatalf("Writer.Create failed: %s", err)
++ }
++ }
++ if err := w.Close(); err != nil {
++ t.Fatalf("Writer.Close failed: %s", err)
++ }
++ r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
++ if err != nil {
++ t.Fatalf("NewReader failed: %s", err)
++ }
++ if len(r.File) != 5 {
++ t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
++ }
++}
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-33197.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-33197.patch
new file mode 100644
index 0000000000..2052b1d3db
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-33197.patch
@@ -0,0 +1,152 @@
+From cbd1ca84453fecf3825a6bb9f985823e8bc32b76 Mon Sep 17 00:00:00 2001
+From: Filippo Valsorda <filippo@golang.org>
+Date: Fri, 21 May 2021 14:02:30 -0400
+Subject: [PATCH] [release-branch.go1.15] net/http/httputil: always remove
+ hop-by-hop headers
+
+Previously, we'd fail to remove the Connection header from a request
+like this:
+
+ Connection:
+ Connection: x-header
+
+Updates #46313
+Fixes #46314
+Fixes CVE-2021-33197
+
+Change-Id: Ie3009e926ceecfa86dfa6bcc6fe14ff01086be7d
+Reviewed-on: https://go-review.googlesource.com/c/go/+/321929
+Run-TryBot: Filippo Valsorda <filippo@golang.org>
+Reviewed-by: Katie Hockman <katie@golang.org>
+Trust: Katie Hockman <katie@golang.org>
+Trust: Filippo Valsorda <filippo@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/323091
+Run-TryBot: Katie Hockman <katie@golang.org>
+
+Upstream-Status: Backport
+CVE: CVE-2021-33197
+Signed-off-by: Armin Kuster <akuster@mvista.com>
+
+---
+ src/net/http/httputil/reverseproxy.go | 22 ++++----
+ src/net/http/httputil/reverseproxy_test.go | 63 +++++++++++++++++++++-
+ 2 files changed, 70 insertions(+), 15 deletions(-)
+
+Index: go/src/net/http/httputil/reverseproxy.go
+===================================================================
+--- go.orig/src/net/http/httputil/reverseproxy.go
++++ go/src/net/http/httputil/reverseproxy.go
+@@ -221,22 +221,18 @@ func (p *ReverseProxy) ServeHTTP(rw http
+ // important is "Connection" because we want a persistent
+ // connection, regardless of what the client sent to us.
+ for _, h := range hopHeaders {
+- hv := outreq.Header.Get(h)
+- if hv == "" {
+- continue
+- }
+- if h == "Te" && hv == "trailers" {
+- // Issue 21096: tell backend applications that
+- // care about trailer support that we support
+- // trailers. (We do, but we don't go out of
+- // our way to advertise that unless the
+- // incoming client request thought it was
+- // worth mentioning)
+- continue
+- }
+ outreq.Header.Del(h)
+ }
+
++ // Issue 21096: tell backend applications that care about trailer support
++ // that we support trailers. (We do, but we don't go out of our way to
++ // advertise that unless the incoming client request thought it was worth
++ // mentioning.) Note that we look at req.Header, not outreq.Header, since
++ // the latter has passed through removeConnectionHeaders.
++ if httpguts.HeaderValuesContainsToken(req.Header["Te"], "trailers") {
++ outreq.Header.Set("Te", "trailers")
++ }
++
+ // After stripping all the hop-by-hop connection headers above, add back any
+ // necessary for protocol upgrades, such as for websockets.
+ if reqUpType != "" {
+Index: go/src/net/http/httputil/reverseproxy_test.go
+===================================================================
+--- go.orig/src/net/http/httputil/reverseproxy_test.go
++++ go/src/net/http/httputil/reverseproxy_test.go
+@@ -91,8 +91,9 @@ func TestReverseProxy(t *testing.T) {
+
+ getReq, _ := http.NewRequest("GET", frontend.URL, nil)
+ getReq.Host = "some-name"
+- getReq.Header.Set("Connection", "close")
+- getReq.Header.Set("Te", "trailers")
++ getReq.Header.Set("Connection", "close, TE")
++ getReq.Header.Add("Te", "foo")
++ getReq.Header.Add("Te", "bar, trailers")
+ getReq.Header.Set("Proxy-Connection", "should be deleted")
+ getReq.Header.Set("Upgrade", "foo")
+ getReq.Close = true
+@@ -236,6 +237,64 @@ func TestReverseProxyStripHeadersPresent
+ }
+ }
+
++func TestReverseProxyStripEmptyConnection(t *testing.T) {
++ // See Issue 46313.
++ const backendResponse = "I am the backend"
++
++ // someConnHeader is some arbitrary header to be declared as a hop-by-hop header
++ // in the Request's Connection header.
++ const someConnHeader = "X-Some-Conn-Header"
++
++ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
++ if c := r.Header.Values("Connection"); len(c) != 0 {
++ t.Errorf("handler got header %q = %v; want empty", "Connection", c)
++ }
++ if c := r.Header.Get(someConnHeader); c != "" {
++ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
++ }
++ w.Header().Add("Connection", "")
++ w.Header().Add("Connection", someConnHeader)
++ w.Header().Set(someConnHeader, "should be deleted")
++ io.WriteString(w, backendResponse)
++ }))
++ defer backend.Close()
++ backendURL, err := url.Parse(backend.URL)
++ if err != nil {
++ t.Fatal(err)
++ }
++ proxyHandler := NewSingleHostReverseProxy(backendURL)
++ frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
++ proxyHandler.ServeHTTP(w, r)
++ if c := r.Header.Get(someConnHeader); c != "should be deleted" {
++ t.Errorf("handler modified header %q = %q; want %q", someConnHeader, c, "should be deleted")
++ }
++ }))
++ defer frontend.Close()
++
++ getReq, _ := http.NewRequest("GET", frontend.URL, nil)
++ getReq.Header.Add("Connection", "")
++ getReq.Header.Add("Connection", someConnHeader)
++ getReq.Header.Set(someConnHeader, "should be deleted")
++ res, err := frontend.Client().Do(getReq)
++ if err != nil {
++ t.Fatalf("Get: %v", err)
++ }
++ defer res.Body.Close()
++ bodyBytes, err := ioutil.ReadAll(res.Body)
++ if err != nil {
++ t.Fatalf("reading body: %v", err)
++ }
++ if got, want := string(bodyBytes), backendResponse; got != want {
++ t.Errorf("got body %q; want %q", got, want)
++ }
++ if c := res.Header.Get("Connection"); c != "" {
++ t.Errorf("handler got header %q = %q; want empty", "Connection", c)
++ }
++ if c := res.Header.Get(someConnHeader); c != "" {
++ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
++ }
++}
++
+ func TestXForwardedFor(t *testing.T) {
+ const prevForwardedFor = "client ip"
+ const backendResponse = "I am the backend"
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-33198.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-33198.patch
new file mode 100644
index 0000000000..241c08dad7
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-33198.patch
@@ -0,0 +1,113 @@
+From c8866491ac424cdf39aedb325e6dec9e54418cfb Mon Sep 17 00:00:00 2001
+From: Robert Griesemer <gri@golang.org>
+Date: Sun, 2 May 2021 11:27:03 -0700
+Subject: [PATCH] math/big: check for excessive exponents in Rat.SetString
+
+CVE-2021-33198
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/df9ce19db6df32d94eae8760927bdfbc595433c3]
+CVE: CVE-2021-33198
+Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
+
+
+Found by OSS-Fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=33284
+
+Thanks to Emmanuel Odeke for reporting this issue.
+
+Updates #45910
+Fixes #46305
+Fixes CVE-2021-33198
+
+Change-Id: I61e7b04dbd80343420b57eede439e361c0f7b79c
+Reviewed-on: https://go-review.googlesource.com/c/go/+/316149
+Trust: Robert Griesemer <gri@golang.org>
+Trust: Katie Hockman <katie@golang.org>
+Run-TryBot: Robert Griesemer <gri@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Katie Hockman <katie@golang.org>
+Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
+(cherry picked from commit 6c591f79b0b5327549bd4e94970f7a279efb4ab0)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/321831
+Run-TryBot: Katie Hockman <katie@golang.org>
+Reviewed-by: Roland Shoemaker <roland@golang.org>
+---
+ src/math/big/ratconv.go | 15 ++++++++-------
+ src/math/big/ratconv_test.go | 25 +++++++++++++++++++++++++
+ 2 files changed, 33 insertions(+), 7 deletions(-)
+
+diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go
+index e8cbdbe..90053a9 100644
+--- a/src/math/big/ratconv.go
++++ b/src/math/big/ratconv.go
+@@ -51,7 +51,8 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
+ // An optional base-10 ``e'' or base-2 ``p'' (or their upper-case variants)
+ // exponent may be provided as well, except for hexadecimal floats which
+ // only accept an (optional) ``p'' exponent (because an ``e'' or ``E'' cannot
+-// be distinguished from a mantissa digit).
++// be distinguished from a mantissa digit). If the exponent's absolute value
++// is too large, the operation may fail.
+ // The entire string, not just a prefix, must be valid for success. If the
+ // operation failed, the value of z is undefined but the returned value is nil.
+ func (z *Rat) SetString(s string) (*Rat, bool) {
+@@ -174,6 +175,9 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
+ return nil, false
+ }
+ }
++ if n > 1e6 {
++ return nil, false // avoid excessively large exponents
++ }
+ pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil) // use underlying array of z.b.abs
+ if exp5 > 0 {
+ z.a.abs = z.a.abs.mul(z.a.abs, pow5)
+@@ -186,15 +190,12 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
+ }
+
+ // apply exp2 contributions
++ if exp2 < -1e7 || exp2 > 1e7 {
++ return nil, false // avoid excessively large exponents
++ }
+ if exp2 > 0 {
+- if int64(uint(exp2)) != exp2 {
+- panic("exponent too large")
+- }
+ z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2))
+ } else if exp2 < 0 {
+- if int64(uint(-exp2)) != -exp2 {
+- panic("exponent too large")
+- }
+ z.b.abs = z.b.abs.shl(z.b.abs, uint(-exp2))
+ }
+
+diff --git a/src/math/big/ratconv_test.go b/src/math/big/ratconv_test.go
+index b820df4..e55e655 100644
+--- a/src/math/big/ratconv_test.go
++++ b/src/math/big/ratconv_test.go
+@@ -590,3 +590,28 @@ func TestIssue31184(t *testing.T) {
+ }
+ }
+ }
++
++func TestIssue45910(t *testing.T) {
++ var x Rat
++ for _, test := range []struct {
++ input string
++ want bool
++ }{
++ {"1e-1000001", false},
++ {"1e-1000000", true},
++ {"1e+1000000", true},
++ {"1e+1000001", false},
++
++ {"0p1000000000000", true},
++ {"1p-10000001", false},
++ {"1p-10000000", true},
++ {"1p+10000000", true},
++ {"1p+10000001", false},
++ {"1.770p02041010010011001001", false}, // test case from issue
++ } {
++ _, got := x.SetString(test.input)
++ if got != test.want {
++ t.Errorf("SetString(%s) got ok = %v; want %v", test.input, got, test.want)
++ }
++ }
++}
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-34558.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-34558.patch
new file mode 100644
index 0000000000..8fb346d622
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-34558.patch
@@ -0,0 +1,51 @@
+From a98589711da5e9d935e8d690cfca92892e86d557 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <roland@golang.org>
+Date: Wed, 9 Jun 2021 11:31:27 -0700
+Subject: [PATCH] crypto/tls: test key type when casting
+
+When casting the certificate public key in generateClientKeyExchange,
+check the type is appropriate. This prevents a panic when a server
+agrees to a RSA based key exchange, but then sends an ECDSA (or
+other) certificate.
+
+Fixes #47143
+Fixes CVE-2021-34558
+
+Thanks to Imre Rad for reporting this issue.
+
+Change-Id: Iabccacca6052769a605cccefa1216a9f7b7f6aea
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1116723
+Reviewed-by: Filippo Valsorda <valsorda@google.com>
+Reviewed-by: Katie Hockman <katiehockman@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/334031
+Trust: Filippo Valsorda <filippo@golang.org>
+Run-TryBot: Filippo Valsorda <filippo@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
+
+Upstream-Status: Backport
+https://github.com/golang/go/commit/a98589711da5e9d935e8d690cfca92892e86d557
+CVE: CVE-2021-34558
+Signed-off-by: Armin Kuster <akuster@mvista.com>
+
+---
+ src/crypto/tls/key_agreement.go | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+Index: go/src/crypto/tls/key_agreement.go
+===================================================================
+--- go.orig/src/crypto/tls/key_agreement.go
++++ go/src/crypto/tls/key_agreement.go
+@@ -67,7 +67,11 @@ func (ka rsaKeyAgreement) generateClient
+ return nil, nil, err
+ }
+
+- encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
++ rsaKey, ok := cert.PublicKey.(*rsa.PublicKey)
++ if !ok {
++ return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite")
++ }
++ encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret)
+ if err != nil {
+ return nil, nil, err
+ }
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch
new file mode 100644
index 0000000000..9c00d4ebb2
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-36221.patch
@@ -0,0 +1,101 @@
+From b7a85e0003cedb1b48a1fd3ae5b746ec6330102e Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Wed, 7 Jul 2021 16:34:34 -0700
+Subject: [PATCH] net/http/httputil: close incoming ReverseProxy request body
+
+Reading from an incoming request body after the request handler aborts
+with a panic can cause a panic, becuse http.Server does not (contrary
+to its documentation) close the request body in this case.
+
+Always close the incoming request body in ReverseProxy.ServeHTTP to
+ensure that any in-flight outgoing requests using the body do not
+read from it.
+
+Updates #46866
+Fixes CVE-2021-36221
+
+Change-Id: I310df269200ad8732c5d9f1a2b00de68725831df
+Reviewed-on: https://go-review.googlesource.com/c/go/+/333191
+Trust: Damien Neil <dneil@google.com>
+Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
+Reviewed-by: Filippo Valsorda <filippo@golang.org>
+
+https://github.com/golang/go/commit/b7a85e0003cedb1b48a1fd3ae5b746ec6330102e
+CVE: CVE-2021-36221
+Upstream-Status: Backport
+Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
+---
+ src/net/http/httputil/reverseproxy.go | 9 +++++
+ src/net/http/httputil/reverseproxy_test.go | 39 ++++++++++++++++++++++
+ 2 files changed, 48 insertions(+)
+
+diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
+index 5d39955d62d15..8b63368386f43 100644
+--- a/src/net/http/httputil/reverseproxy.go
++++ b/src/net/http/httputil/reverseproxy.go
+@@ -235,6 +235,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+ if req.ContentLength == 0 {
+ outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
+ }
++ if outreq.Body != nil {
++ // Reading from the request body after returning from a handler is not
++ // allowed, and the RoundTrip goroutine that reads the Body can outlive
++ // this handler. This can lead to a crash if the handler panics (see
++ // Issue 46866). Although calling Close doesn't guarantee there isn't
++ // any Read in flight after the handle returns, in practice it's safe to
++ // read after closing it.
++ defer outreq.Body.Close()
++ }
+ if outreq.Header == nil {
+ outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
+ }
+diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
+index 1898ed8b8afde..4b6ad77a29466 100644
+--- a/src/net/http/httputil/reverseproxy_test.go
++++ b/src/net/http/httputil/reverseproxy_test.go
+@@ -1122,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) {
+ rproxy.ServeHTTP(httptest.NewRecorder(), req)
+ }
+
++// Issue #46866: panic without closing incoming request body causes a panic
++func TestReverseProxy_PanicClosesIncomingBody(t *testing.T) {
++ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
++ out := "this call was relayed by the reverse proxy"
++ // Coerce a wrong content length to induce io.ErrUnexpectedEOF
++ w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2))
++ fmt.Fprintln(w, out)
++ }))
++ defer backend.Close()
++ backendURL, err := url.Parse(backend.URL)
++ if err != nil {
++ t.Fatal(err)
++ }
++ proxyHandler := NewSingleHostReverseProxy(backendURL)
++ proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
++ frontend := httptest.NewServer(proxyHandler)
++ defer frontend.Close()
++ frontendClient := frontend.Client()
++
++ var wg sync.WaitGroup
++ for i := 0; i < 2; i++ {
++ wg.Add(1)
++ go func() {
++ defer wg.Done()
++ for j := 0; j < 10; j++ {
++ const reqLen = 6 * 1024 * 1024
++ req, _ := http.NewRequest("POST", frontend.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen})
++ req.ContentLength = reqLen
++ resp, _ := frontendClient.Transport.RoundTrip(req)
++ if resp != nil {
++ io.Copy(io.Discard, resp.Body)
++ resp.Body.Close()
++ }
++ }
++ }()
++ }
++ wg.Wait()
++}
++
+ func TestSelectFlushInterval(t *testing.T) {
+ tests := []struct {
+ name string
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-38297.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-38297.patch
new file mode 100644
index 0000000000..24ceabf808
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-38297.patch
@@ -0,0 +1,97 @@
+From 4548fcc8dfd933c237f29bba6f90040a85922564 Mon Sep 17 00:00:00 2001
+From: Michael Knyszek <mknyszek@google.com>
+Date: Thu, 2 Sep 2021 16:51:59 -0400
+Subject: [PATCH] [release-branch.go1.16] misc/wasm, cmd/link: do not let
+ command line args overwrite global data
+
+On Wasm, wasm_exec.js puts command line arguments at the beginning
+of the linear memory (following the "zero page"). Currently there
+is no limit for this, and a very long command line can overwrite
+the program's data section. Prevent this by limiting the command
+line to 4096 bytes, and in the linker ensuring the data section
+starts at a high enough address (8192).
+
+(Arguably our address assignment on Wasm is a bit confusing. This
+is the minimum fix I can come up with.)
+
+Thanks to Ben Lubar for reporting this issue.
+
+Change by Cherry Mui <cherryyz@google.com>.
+
+For #48797
+Fixes #48799
+Fixes CVE-2021-38297
+
+Change-Id: I0f50fbb2a5b6d0d047e3c134a88988d9133e4ab3
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1205933
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Than McIntosh <thanm@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/354591
+Trust: Michael Knyszek <mknyszek@google.com>
+Reviewed-by: Heschi Kreinick <heschi@google.com>
+
+CVE: CVE-2021-38297
+
+Upstream-Status: Backport:
+https://github.com/golang/go/commit/4548fcc8dfd933c237f29bba6f90040a85922564
+
+Inline of ctxt.isWAsm followin this implemetation:
+https://github.com/golang/go/blob/4548fcc8dfd933c237f29bba6f90040a85922564/src/cmd/link/internal/ld/target.go#L127
+
+Signed-off-by: Davide Gardenal <davide.gardenal@huawei.com>
+---
+ misc/wasm/wasm_exec.js | 7 +++++++
+ src/cmd/link/internal/ld/data.go | 11 ++++++++++-
+ 2 files changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js
+index 82041e6bb901..a0a264278b1b 100644
+--- a/misc/wasm/wasm_exec.js
++++ b/misc/wasm/wasm_exec.js
+@@ -564,6 +564,13 @@
+ offset += 8;
+ });
+
++ // The linker guarantees global data starts from at least wasmMinDataAddr.
++ // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
++ const wasmMinDataAddr = 4096 + 4096;
++ if (offset >= wasmMinDataAddr) {
++ throw new Error("command line too long");
++ }
++
+ this._inst.exports.run(argc, argv);
+ if (this.exited) {
+ this._resolveExitPromise();
+diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
+index 52035e96301c..54a1d188cdb9 100644
+--- a/src/cmd/link/internal/ld/data.go
++++ b/src/cmd/link/internal/ld/data.go
+@@ -2330,6 +2330,11 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64
+ return sect, n, va
+ }
+
++// On Wasm, we reserve 4096 bytes for zero page, then 4096 bytes for wasm_exec.js
++// to store command line args. Data sections starts from at least address 8192.
++// Keep in sync with wasm_exec.js.
++const wasmMinDataAddr = 4096 + 4096
++
+ // address assigns virtual addresses to all segments and sections and
+ // returns all segments in file order.
+ func (ctxt *Link) address() []*sym.Segment {
+@@ -2339,10 +2344,14 @@ func (ctxt *Link) address() []*sym.Segment {
+ order = append(order, &Segtext)
+ Segtext.Rwx = 05
+ Segtext.Vaddr = va
+- for _, s := range Segtext.Sections {
++ for i, s := range Segtext.Sections {
+ va = uint64(Rnd(int64(va), int64(s.Align)))
+ s.Vaddr = va
+ va += s.Length
++
++ if ctxt.Arch.Family == sys.Wasm && i == 0 && va < wasmMinDataAddr {
++ va = wasmMinDataAddr
++ }
+ }
+
+ Segtext.Length = va - uint64(*FlagTextAddr)
+ \ No newline at end of file
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-39293.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-39293.patch
new file mode 100644
index 0000000000..88fca9cad9
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-39293.patch
@@ -0,0 +1,79 @@
+From 6c480017ae600b2c90a264a922e041df04dfa785 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <roland@golang.org>
+Date: Wed, 18 Aug 2021 11:49:29 -0700
+Subject: [PATCH] [release-branch.go1.16] archive/zip: prevent preallocation
+ check from overflowing
+
+If the indicated directory size in the archive header is so large that
+subtracting it from the archive size overflows a uint64, the check that
+the indicated number of files in the archive can be effectively
+bypassed. Prevent this from happening by checking that the indicated
+directory size is less than the size of the archive.
+
+Thanks to the OSS-Fuzz project for discovering this issue and to
+Emmanuel Odeke for reporting it.
+
+Fixes #47985
+Updates #47801
+Fixes CVE-2021-39293
+
+Change-Id: Ifade26b98a40f3b37398ca86bd5252d12394dd24
+Reviewed-on: https://go-review.googlesource.com/c/go/+/343434
+Trust: Roland Shoemaker <roland@golang.org>
+Run-TryBot: Roland Shoemaker <roland@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Russ Cox <rsc@golang.org>
+(cherry picked from commit bacbc33439b124ffd7392c91a5f5d96eca8c0c0b)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/345409
+Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
+Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
+Trust: Cherry Mui <cherryyz@google.com>
+
+https://github.com/golang/go/commit/6c480017ae600b2c90a264a922e041df04dfa785
+CVE: CVE-2021-39293
+Upstream-Status: Backport
+Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
+---
+ src/archive/zip/reader.go | 2 +-
+ src/archive/zip/reader_test.go | 18 ++++++++++++++++++
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go
+index ddef2b7b5a517..801d1313b6c32 100644
+--- a/src/archive/zip/reader.go
++++ b/src/archive/zip/reader.go
+@@ -105,7 +105,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
+ // indicate it contains up to 1 << 128 - 1 files. Since each file has a
+ // header which will be _at least_ 30 bytes we can safely preallocate
+ // if (data size / 30) >= end.directoryRecords.
+- if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
++ if end.directorySize < uint64(size) && (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
+ z.File = make([]*File, 0, end.directoryRecords)
+ }
+ z.Comment = end.comment
+diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go
+index 471be27bb1004..99f13345d8d06 100644
+--- a/src/archive/zip/reader_test.go
++++ b/src/archive/zip/reader_test.go
+@@ -1225,3 +1225,21 @@ func TestCVE202133196(t *testing.T) {
+ t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
+ }
+ }
++
++func TestCVE202139293(t *testing.T) {
++ // directory size is so large, that the check in Reader.init
++ // overflows when subtracting from the archive size, causing
++ // the pre-allocation check to be bypassed.
++ data := []byte{
++ 0x50, 0x4b, 0x06, 0x06, 0x05, 0x06, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
++ 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
++ 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
++ 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
++ 0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
++ 0xff, 0x50, 0xfe, 0x00, 0xff, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xff,
++ }
++ _, err := NewReader(bytes.NewReader(data), int64(len(data)))
++ if err != ErrFormat {
++ t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
++ }
++}
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-41771.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-41771.patch
new file mode 100644
index 0000000000..526796dbcb
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-41771.patch
@@ -0,0 +1,86 @@
+From d19c5bdb24e093a2d5097b7623284eb02726cede Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <roland@golang.org>
+Date: Thu, 14 Oct 2021 13:02:01 -0700
+Subject: [PATCH] [release-branch.go1.16] debug/macho: fail on invalid dynamic
+ symbol table command
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Fail out when loading a file that contains a dynamic symbol table
+command that indicates a larger number of symbols than exist in the
+loaded symbol table.
+
+Thanks to Burak Çarıkçı - Yunus Yıldırım (CT-Zer0 Crypttech) for
+reporting this issue.
+
+Updates #48990
+Fixes #48991
+Fixes CVE-2021-41771
+
+Change-Id: Ic3d6e6529241afcc959544b326b21b663262bad5
+Reviewed-on: https://go-review.googlesource.com/c/go/+/355990
+Reviewed-by: Julie Qiu <julie@golang.org>
+Reviewed-by: Katie Hockman <katie@golang.org>
+Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
+Run-TryBot: Roland Shoemaker <roland@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Trust: Katie Hockman <katie@golang.org>
+(cherry picked from commit 61536ec03063b4951163bd09609c86d82631fa27)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/359454
+Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
+
+https://github.com/golang/go/commit/d19c5bdb24e093a2d5097b7623284eb02726cede
+CVE: CVE-2021-41771
+Upstream-Status: Backport
+Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
+---
+ src/debug/macho/file.go | 9 +++++++++
+ src/debug/macho/file_test.go | 7 +++++++
+ .../testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64 | 1 +
+ 3 files changed, 17 insertions(+)
+ create mode 100644 src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64
+
+diff --git a/src/debug/macho/file.go b/src/debug/macho/file.go
+index 085b0c8219bad..73cfce3c7606e 100644
+--- a/src/debug/macho/file.go
++++ b/src/debug/macho/file.go
+@@ -345,6 +345,15 @@ func NewFile(r io.ReaderAt) (*File, error) {
+ if err := binary.Read(b, bo, &hdr); err != nil {
+ return nil, err
+ }
++ if hdr.Iundefsym > uint32(len(f.Symtab.Syms)) {
++ return nil, &FormatError{offset, fmt.Sprintf(
++ "undefined symbols index in dynamic symbol table command is greater than symbol table length (%d > %d)",
++ hdr.Iundefsym, len(f.Symtab.Syms)), nil}
++ } else if hdr.Iundefsym+hdr.Nundefsym > uint32(len(f.Symtab.Syms)) {
++ return nil, &FormatError{offset, fmt.Sprintf(
++ "number of undefined symbols after index in dynamic symbol table command is greater than symbol table length (%d > %d)",
++ hdr.Iundefsym+hdr.Nundefsym, len(f.Symtab.Syms)), nil}
++ }
+ dat := make([]byte, hdr.Nindirectsyms*4)
+ if _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil {
+ return nil, err
+diff --git a/src/debug/macho/file_test.go b/src/debug/macho/file_test.go
+index 03915c86e23d9..9beeb80dd27c1 100644
+--- a/src/debug/macho/file_test.go
++++ b/src/debug/macho/file_test.go
+@@ -416,3 +416,10 @@ func TestTypeString(t *testing.T) {
+ t.Errorf("got %v, want %v", TypeExec.GoString(), "macho.Exec")
+ }
+ }
++
++func TestOpenBadDysymCmd(t *testing.T) {
++ _, err := openObscured("testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64")
++ if err == nil {
++ t.Fatal("openObscured did not fail when opening a file with an invalid dynamic symbol table command")
++ }
++}
+diff --git a/src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64 b/src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64
+new file mode 100644
+index 0000000000000..8e0436639c109
+--- /dev/null
++++ b/src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64
+@@ -0,0 +1 @@
++z/rt/gcAAAEDAACAAgAAAAsAAABoBQAAhQAAAAAAAAAZAAAASAAAAF9fUEFHRVpFUk8AAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAA2AEAAF9fVEVYVAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAcAAAAFAAAABQAAAAAAAABfX3RleHQAAAAAAAAAAAAAX19URVhUAAAAAAAAAAAAABQPAAABAAAAbQAAAAAAAAAUDwAAAgAAAAAAAAAAAAAAAAQAgAAAAAAAAAAAAAAAAF9fc3ltYm9sX3N0dWIxAABfX1RFWFQAAAAAAAAAAAAAgQ8AAAEAAAAMAAAAAAAAAIEPAAAAAAAAAAAAAAAAAAAIBACAAAAAAAYAAAAAAAAAX19zdHViX2hlbHBlcgAAAF9fVEVYVAAAAAAAAAAAAACQDwAAAQAAABgAAAAAAAAAkA8AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfX2NzdHJpbmcAAAAAAAAAX19URVhUAAAAAAAAAAAAAKgPAAABAAAADQAAAAAAAACoDwAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAF9fZWhfZnJhbWUAAAAAAABfX1RFWFQAAAAAAAAAAAAAuA8AAAEAAABIAAAAAAAAALgPAAADAAAAAAAAAAAAAAALAABgAAAAAAAAAAAAAAAAGQAAADgBAABfX0RBVEEAAAAAAAAAAAAAABAAAAEAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAHAAAAAwAAAAMAAAAAAAAAX19kYXRhAAAAAAAAAAAAAF9fREFUQQAAAAAAAAAAAAAAEAAAAQAAABwAAAAAAAAAABAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfX2R5bGQAAAAAAAAAAAAAX19EQVRBAAAAAAAAAAAAACAQAAABAAAAOAAAAAAAAAAgEAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF9fbGFfc3ltYm9sX3B0cgBfX0RBVEEAAAAAAAAAAAAAWBAAAAEAAAAQAAAAAAAAAFgQAAACAAAAAAAAAAAAAAAHAAAAAgAAAAAAAAAAAAAAGQAAAEgAAABfX0xJTktFRElUAAAAAAAAACAAAAEAAAAAEAAAAAAAAAAgAAAAAAAAQAEAAAAAAAAHAAAAAQAAAAAAAAAAAAAAAgAAABgAAAAAIAAACwAAAMAgAACAAAAACwAAAFAAAAAAAAAAAgAAAAIAAAAHAAAACQAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwIAAABAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAIAAAAAwAAAAvdXNyL2xpYi9keWxkAAAAAAAAABsAAAAYAAAAOyS4cg5FdtQoqu6JsMEhXQUAAAC4AAAABAAAACoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQPAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAOAAAABgAAAACAAAAAAABAAAAAQAvdXNyL2xpYi9saWJnY2Nfcy4xLmR5bGliAAAAAAAAAAwAAAA4AAAAGAAAAAIAAAAEAW8AAAABAC91c3IvbGliL2xpYlN5c3RlbS5CLmR5bGliAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqAEiJ5UiD5PBIi30ISI11EIn6g8IBweIDSAHySInR6wRIg8EISIM5AHX2SIPBCOgiAAAAicfoMgAAAPRBU0yNHafw//9BU/8lvwAAAA8fAP8lvgAAAFVIieVIjT0zAAAA6A0AAAC4AAAAAMnD/yXRAAAA/yXTAAAAAAAATI0dwQAAAOm0////TI0dvQAAAOmo////aGVsbG8sIHdvcmxkAAAAABQAAAAAAAAAAXpSAAF4EAEQDAcIkAEAACwAAAAcAAAAkv////////8XAAAAAAAAAAAEAQAAAA4QhgIEAwAAAA0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDAX/9/AAAIEMBf/38AAAAAAAABAAAAGBAAAAEAAAAQEAAAAQAAAAgQAAABAAAAABAAAAEAAACQDwAAAQAAAJwPAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAHgEAAFAPAAABAAAAGwAAAB4BAABkDwAAAQAAAC4AAAAPBgAAGBAAAAEAAAA2AAAADwYAABAQAAABAAAAPgAAAA8GAAAAEAAAAQAAAEoAAAADABAAAAAAAAEAAABeAAAADwYAAAgQAAABAAAAZwAAAA8BAABqDwAAAQAAAG0AAAAPAQAAFA8AAAEAAABzAAAAAQABAgAAAAAAAAAAeQAAAAEAAQIAAAAAAAAAAAkAAAAKAAAACQAAAAoAAAAgAGR5bGRfc3R1Yl9iaW5kaW5nX2hlbHBlcgBfX2R5bGRfZnVuY19sb29rdXAAX05YQXJnYwBfTlhBcmd2AF9fX3Byb2duYW1lAF9fbWhfZXhlY3V0ZV9oZWFkZXIAX2Vudmlyb24AX21haW4Ac3RhcnQAX2V4aXQAX3B1dHMAAA==
+\ No newline at end of file
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-44716.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-44716.patch
new file mode 100644
index 0000000000..9c4fee2db4
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-44716.patch
@@ -0,0 +1,93 @@
+From 9f1860075990e7bf908ca7cc329d1d3ef91741c8 Mon Sep 17 00:00:00 2001
+From: Filippo Valsorda <filippo@golang.org>
+Date: Thu, 9 Dec 2021 06:13:31 -0500
+Subject: [PATCH] net/http: update bundled golang.org/x/net/http2
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/d0aebe3e74fe14799f97ddd3f01129697c6a290a]
+CVE: CVE-2021-44716
+Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
+
+
+Pull in security fix
+
+ a5309b3 http2: cap the size of the server's canonical header cache
+
+Updates #50058
+Fixes CVE-2021-44716
+
+Change-Id: Ifdd13f97fce168de5fb4b2e74ef2060d059800b9
+Reviewed-on: https://go-review.googlesource.com/c/go/+/370575
+Trust: Filippo Valsorda <filippo@golang.org>
+Run-TryBot: Filippo Valsorda <filippo@golang.org>
+Reviewed-by: Alex Rakoczy <alex@golang.org>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+(cherry picked from commit d0aebe3e74fe14799f97ddd3f01129697c6a290a)
+---
+ src/go.mod | 2 +-
+ src/go.sum | 4 ++--
+ src/net/http/h2_bundle.go | 10 +++++++++-
+ src/vendor/modules.txt | 2 +-
+ 4 files changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/src/go.mod b/src/go.mod
+index ec6bd98..56f2fbb 100644
+--- a/src/go.mod
++++ b/src/go.mod
+@@ -4,7 +4,7 @@ go 1.14
+
+ require (
+ golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d
+- golang.org/x/net v0.0.0-20210129194117-4acb7895a057
++ golang.org/x/net v0.0.0-20211209100217-a5309b321dca
+ golang.org/x/sys v0.0.0-20200201011859-915c9c3d4ccf // indirect
+ golang.org/x/text v0.3.3-0.20191031172631-4b67af870c6f // indirect
+ )
+diff --git a/src/go.sum b/src/go.sum
+index 171e083..1ceba05 100644
+--- a/src/go.sum
++++ b/src/go.sum
+@@ -2,8 +2,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
+ golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U=
+ golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+-golang.org/x/net v0.0.0-20210129194117-4acb7895a057 h1:HThQeV5c0Ab/Puir+q6mC97b7+3dfZdsLWMLoBrzo68=
+-golang.org/x/net v0.0.0-20210129194117-4acb7895a057/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
++golang.org/x/net v0.0.0-20211209100217-a5309b321dca h1:UmeWAm8AwB6NA/e4FSaGlK1EKTLXKX3utx4Si+6kfPg=
++golang.org/x/net v0.0.0-20211209100217-a5309b321dca/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+ golang.org/x/sys v0.0.0-20200201011859-915c9c3d4ccf h1:+4j7oujXP478CVb/AFvHJmVX5+Pczx2NGts5yirA0oY=
+diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
+index 702fd5a..83f2a72 100644
+--- a/src/net/http/h2_bundle.go
++++ b/src/net/http/h2_bundle.go
+@@ -4293,7 +4293,15 @@ func (sc *http2serverConn) canonicalHeader(v string) string {
+ sc.canonHeader = make(map[string]string)
+ }
+ cv = CanonicalHeaderKey(v)
+- sc.canonHeader[v] = cv
++ // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
++ // entries in the canonHeader cache. This should be larger than the number
++ // of unique, uncommon header keys likely to be sent by the peer, while not
++ // so high as to permit unreaasonable memory usage if the peer sends an unbounded
++ // number of unique header keys.
++ const maxCachedCanonicalHeaders = 32
++ if len(sc.canonHeader) < maxCachedCanonicalHeaders {
++ sc.canonHeader[v] = cv
++ }
+ return cv
+ }
+
+diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt
+index 669bd9b..1d67183 100644
+--- a/src/vendor/modules.txt
++++ b/src/vendor/modules.txt
+@@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519
+ golang.org/x/crypto/hkdf
+ golang.org/x/crypto/internal/subtle
+ golang.org/x/crypto/poly1305
+-# golang.org/x/net v0.0.0-20210129194117-4acb7895a057
++# golang.org/x/net v0.0.0-20211209100217-a5309b321dca
+ ## explicit
+ golang.org/x/net/dns/dnsmessage
+ golang.org/x/net/http/httpguts
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2021-44717.patch b/meta/recipes-devtools/go/go-1.14/CVE-2021-44717.patch
new file mode 100644
index 0000000000..17cac7a5ba
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2021-44717.patch
@@ -0,0 +1,83 @@
+From 9171c664e7af479aa26bc72f2e7cf4e69d8e0a6f Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Fri, 17 Jun 2022 10:22:47 +0530
+Subject: [PATCH] CVE-2021-44717
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/44a3fb49]
+CVE: CVE-2021-44717
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+
+syscall: fix ForkLock spurious close(0) on pipe failure
+Pipe (and therefore forkLockPipe) does not make any guarantees
+about the state of p after a failed Pipe(p). Avoid that assumption
+and the too-clever goto, so that we don't accidentally Close a real fd
+if the failed pipe leaves p[0] or p[1] set >= 0.
+
+Updates #50057
+Fixes CVE-2021-44717
+
+Change-Id: Iff8e19a6efbba0c73cc8b13ecfae381c87600bb4
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1291270
+Reviewed-by: Ian Lance Taylor <iant@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/370514
+Trust: Filippo Valsorda <filippo@golang.org>
+Run-TryBot: Filippo Valsorda <filippo@golang.org>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Alex Rakoczy <alex@golang.org>
+---
+ src/syscall/exec_unix.go | 20 ++++++--------------
+ 1 file changed, 6 insertions(+), 14 deletions(-)
+
+diff --git a/src/syscall/exec_unix.go b/src/syscall/exec_unix.go
+index b3798b6..b73782c 100644
+--- a/src/syscall/exec_unix.go
++++ b/src/syscall/exec_unix.go
+@@ -151,9 +151,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
+ sys = &zeroSysProcAttr
+ }
+
+- p[0] = -1
+- p[1] = -1
+-
+ // Convert args to C form.
+ argv0p, err := BytePtrFromString(argv0)
+ if err != nil {
+@@ -194,14 +191,17 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
+
+ // Allocate child status pipe close on exec.
+ if err = forkExecPipe(p[:]); err != nil {
+- goto error
++ ForkLock.Unlock()
++ return 0, err
+ }
+
+ // Kick off child.
+ pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
+ if err1 != 0 {
+- err = Errno(err1)
+- goto error
++ Close(p[0])
++ Close(p[1])
++ ForkLock.Unlock()
++ return 0, Errno(err1)
+ }
+ ForkLock.Unlock()
+
+@@ -228,14 +228,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
+
+ // Read got EOF, so pipe closed on exec, so exec succeeded.
+ return pid, nil
+-
+-error:
+- if p[0] >= 0 {
+- Close(p[0])
+- Close(p[1])
+- }
+- ForkLock.Unlock()
+- return 0, err
+ }
+
+ // Combination of fork and exec, careful to be thread safe.
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-1962.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-1962.patch
new file mode 100644
index 0000000000..b2ab5d0669
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-1962.patch
@@ -0,0 +1,357 @@
+From ba8788ebcead55e99e631c6a1157ad7b35535d11 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Wed, 15 Jun 2022 10:43:05 -0700
+Subject: [PATCH] [release-branch.go1.17] go/parser: limit recursion depth
+
+Limit nested parsing to 100,000, which prevents stack exhaustion when
+parsing deeply nested statements, types, and expressions. Also limit
+the scope depth to 1,000 during object resolution.
+
+Thanks to Juho Nurminen of Mattermost for reporting this issue.
+
+Fixes #53707
+Updates #53616
+Fixes CVE-2022-1962
+
+Change-Id: I4d7b86c1d75d0bf3c7af1fdea91582aa74272c64
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1491025
+Reviewed-by: Russ Cox <rsc@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+(cherry picked from commit 6a856f08d58e4b6705c0c337d461c540c1235c83)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/417070
+Reviewed-by: Heschi Kreinick <heschi@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Run-TryBot: Michael Knyszek <mknyszek@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/ba8788ebcead55e99e631c6a1157ad7b35535d11]
+CVE: CVE-2022-1962
+Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
+---
+ src/go/parser/interface.go | 10 ++-
+ src/go/parser/parser.go | 48 ++++++++--
+ src/go/parser/parser_test.go | 169 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 220 insertions(+), 7 deletions(-)
+
+diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go
+index 54f9d7b..537b327 100644
+--- a/src/go/parser/interface.go
++++ b/src/go/parser/interface.go
+@@ -92,8 +92,11 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode)
+ defer func() {
+ if e := recover(); e != nil {
+ // resume same panic if it's not a bailout
+- if _, ok := e.(bailout); !ok {
++ bail, ok := e.(bailout)
++ if !ok {
+ panic(e)
++ } else if bail.msg != "" {
++ p.errors.Add(p.file.Position(bail.pos), bail.msg)
+ }
+ }
+
+@@ -188,8 +191,11 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M
+ defer func() {
+ if e := recover(); e != nil {
+ // resume same panic if it's not a bailout
+- if _, ok := e.(bailout); !ok {
++ bail, ok := e.(bailout)
++ if !ok {
+ panic(e)
++ } else if bail.msg != "" {
++ p.errors.Add(p.file.Position(bail.pos), bail.msg)
+ }
+ }
+ p.errors.Sort()
+diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go
+index 31a7398..586fe90 100644
+--- a/src/go/parser/parser.go
++++ b/src/go/parser/parser.go
+@@ -64,6 +64,10 @@ type parser struct {
+ unresolved []*ast.Ident // unresolved identifiers
+ imports []*ast.ImportSpec // list of imports
+
++ // nestLev is used to track and limit the recursion depth
++ // during parsing.
++ nestLev int
++
+ // Label scopes
+ // (maintained by open/close LabelScope)
+ labelScope *ast.Scope // label scope for current function
+@@ -236,6 +240,24 @@ func un(p *parser) {
+ p.printTrace(")")
+ }
+
++// maxNestLev is the deepest we're willing to recurse during parsing
++const maxNestLev int = 1e5
++
++func incNestLev(p *parser) *parser {
++ p.nestLev++
++ if p.nestLev > maxNestLev {
++ p.error(p.pos, "exceeded max nesting depth")
++ panic(bailout{})
++ }
++ return p
++}
++
++// decNestLev is used to track nesting depth during parsing to prevent stack exhaustion.
++// It is used along with incNestLev in a similar fashion to how un and trace are used.
++func decNestLev(p *parser) {
++ p.nestLev--
++}
++
+ // Advance to the next token.
+ func (p *parser) next0() {
+ // Because of one-token look-ahead, print the previous token
+@@ -348,8 +370,12 @@ func (p *parser) next() {
+ }
+ }
+
+-// A bailout panic is raised to indicate early termination.
+-type bailout struct{}
++// A bailout panic is raised to indicate early termination. pos and msg are
++// only populated when bailing out of object resolution.
++type bailout struct {
++ pos token.Pos
++ msg string
++}
+
+ func (p *parser) error(pos token.Pos, msg string) {
+ epos := p.file.Position(pos)
+@@ -1030,6 +1056,8 @@ func (p *parser) parseChanType() *ast.ChanType {
+
+ // If the result is an identifier, it is not resolved.
+ func (p *parser) tryIdentOrType() ast.Expr {
++ defer decNestLev(incNestLev(p))
++
+ switch p.tok {
+ case token.IDENT:
+ return p.parseTypeName()
+@@ -1609,7 +1637,13 @@ func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
+ }
+
+ x := p.parseUnaryExpr(lhs)
+- for {
++ // We track the nesting here rather than at the entry for the function,
++ // since it can iteratively produce a nested output, and we want to
++ // limit how deep a structure we generate.
++ var n int
++ defer func() { p.nestLev -= n }()
++ for n = 1; ; n++ {
++ incNestLev(p)
+ op, oprec := p.tokPrec()
+ if oprec < prec1 {
+ return x
+@@ -1628,7 +1662,7 @@ func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
+ // The result may be a type or even a raw type ([...]int). Callers must
+ // check the result (using checkExpr or checkExprOrType), depending on
+ // context.
+-func (p *parser) parseExpr(lhs bool) ast.Expr {
++func (p *parser) parseExpr(lhs bool) ast.Expr {
+ if p.trace {
+ defer un(trace(p, "Expression"))
+ }
+@@ -1899,6 +1933,8 @@ func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) {
+ }
+
+ func (p *parser) parseIfStmt() *ast.IfStmt {
++ defer decNestLev(incNestLev(p))
++
+ if p.trace {
+ defer un(trace(p, "IfStmt"))
+ }
+@@ -2214,6 +2250,8 @@ func (p *parser) parseForStmt() ast.Stmt {
+ }
+
+ func (p *parser) parseStmt() (s ast.Stmt) {
++ defer decNestLev(incNestLev(p))
++
+ if p.trace {
+ defer un(trace(p, "Statement"))
+ }
+diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go
+index 25a374e..37a6a2b 100644
+--- a/src/go/parser/parser_test.go
++++ b/src/go/parser/parser_test.go
+@@ -10,6 +10,7 @@ import (
+ "go/ast"
+ "go/token"
+ "os"
++ "runtime"
+ "strings"
+ "testing"
+ )
+@@ -569,3 +570,171 @@ type x int // comment
+ t.Errorf("got %q, want %q", comment, "// comment")
+ }
+ }
++
++var parseDepthTests = []struct {
++ name string
++ format string
++ // multipler is used when a single statement may result in more than one
++ // change in the depth level, for instance "1+(..." produces a BinaryExpr
++ // followed by a UnaryExpr, which increments the depth twice. The test
++ // case comment explains which nodes are triggering the multiple depth
++ // changes.
++ parseMultiplier int
++ // scope is true if we should also test the statement for the resolver scope
++ // depth limit.
++ scope bool
++ // scopeMultiplier does the same as parseMultiplier, but for the scope
++ // depths.
++ scopeMultiplier int
++}{
++ // The format expands the part inside « » many times.
++ // A second set of brackets nested inside the first stops the repetition,
++ // so that for example «(«1»)» expands to (((...((((1))))...))).
++ {name: "array", format: "package main; var x «[1]»int"},
++ {name: "slice", format: "package main; var x «[]»int"},
++ {name: "struct", format: "package main; var x «struct { X «int» }»", scope: true},
++ {name: "pointer", format: "package main; var x «*»int"},
++ {name: "func", format: "package main; var x «func()»int", scope: true},
++ {name: "chan", format: "package main; var x «chan »int"},
++ {name: "chan2", format: "package main; var x «<-chan »int"},
++ {name: "interface", format: "package main; var x «interface { M() «int» }»", scope: true, scopeMultiplier: 2}, // Scopes: InterfaceType, FuncType
++ {name: "map", format: "package main; var x «map[int]»int"},
++ {name: "slicelit", format: "package main; var x = «[]any{«»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
++ {name: "arraylit", format: "package main; var x = «[1]any{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
++ {name: "structlit", format: "package main; var x = «struct{x any}{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
++ {name: "maplit", format: "package main; var x = «map[int]any{1:«nil»}»", parseMultiplier: 2}, // Parser nodes: CompositeLit, KeyValueExpr
++ {name: "dot", format: "package main; var x = «x.»x"},
++ {name: "index", format: "package main; var x = x«[1]»"},
++ {name: "slice", format: "package main; var x = x«[1:2]»"},
++ {name: "slice3", format: "package main; var x = x«[1:2:3]»"},
++ {name: "dottype", format: "package main; var x = x«.(any)»"},
++ {name: "callseq", format: "package main; var x = x«()»"},
++ {name: "methseq", format: "package main; var x = x«.m()»", parseMultiplier: 2}, // Parser nodes: SelectorExpr, CallExpr
++ {name: "binary", format: "package main; var x = «1+»1"},
++ {name: "binaryparen", format: "package main; var x = «1+(«1»)»", parseMultiplier: 2}, // Parser nodes: BinaryExpr, ParenExpr
++ {name: "unary", format: "package main; var x = «^»1"},
++ {name: "addr", format: "package main; var x = «& »x"},
++ {name: "star", format: "package main; var x = «*»x"},
++ {name: "recv", format: "package main; var x = «<-»x"},
++ {name: "call", format: "package main; var x = «f(«1»)»", parseMultiplier: 2}, // Parser nodes: Ident, CallExpr
++ {name: "conv", format: "package main; var x = «(*T)(«1»)»", parseMultiplier: 2}, // Parser nodes: ParenExpr, CallExpr
++ {name: "label", format: "package main; func main() { «Label:» }"},
++ {name: "if", format: "package main; func main() { «if true { «» }»}", parseMultiplier: 2, scope: true, scopeMultiplier: 2}, // Parser nodes: IfStmt, BlockStmt. Scopes: IfStmt, BlockStmt
++ {name: "ifelse", format: "package main; func main() { «if true {} else » {} }", scope: true},
++ {name: "switch", format: "package main; func main() { «switch { default: «» }»}", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause
++ {name: "typeswitch", format: "package main; func main() { «switch x.(type) { default: «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause
++ {name: "for0", format: "package main; func main() { «for { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt
++ {name: "for1", format: "package main; func main() { «for x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt
++ {name: "for3", format: "package main; func main() { «for f(); g(); h() { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt
++ {name: "forrange0", format: "package main; func main() { «for range x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt
++ {name: "forrange1", format: "package main; func main() { «for x = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt
++ {name: "forrange2", format: "package main; func main() { «for x, y = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt
++ {name: "go", format: "package main; func main() { «go func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: GoStmt, FuncLit
++ {name: "defer", format: "package main; func main() { «defer func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: DeferStmt, FuncLit
++ {name: "select", format: "package main; func main() { «select { default: «» }» }", scope: true},
++}
++
++// split splits pre«mid»post into pre, mid, post.
++// If the string does not have that form, split returns x, "", "".
++func split(x string) (pre, mid, post string) {
++ start, end := strings.Index(x, "«"), strings.LastIndex(x, "»")
++ if start < 0 || end < 0 {
++ return x, "", ""
++ }
++ return x[:start], x[start+len("«") : end], x[end+len("»"):]
++}
++
++func TestParseDepthLimit(t *testing.T) {
++ if runtime.GOARCH == "wasm" {
++ t.Skip("causes call stack exhaustion on js/wasm")
++ }
++ for _, tt := range parseDepthTests {
++ for _, size := range []string{"small", "big"} {
++ t.Run(tt.name+"/"+size, func(t *testing.T) {
++ n := maxNestLev + 1
++ if tt.parseMultiplier > 0 {
++ n /= tt.parseMultiplier
++ }
++ if size == "small" {
++ // Decrease the number of statements by 10, in order to check
++ // that we do not fail when under the limit. 10 is used to
++ // provide some wiggle room for cases where the surrounding
++ // scaffolding syntax adds some noise to the depth that changes
++ // on a per testcase basis.
++ n -= 10
++ }
++
++ pre, mid, post := split(tt.format)
++ if strings.Contains(mid, "«") {
++ left, base, right := split(mid)
++ mid = strings.Repeat(left, n) + base + strings.Repeat(right, n)
++ } else {
++ mid = strings.Repeat(mid, n)
++ }
++ input := pre + mid + post
++
++ fset := token.NewFileSet()
++ _, err := ParseFile(fset, "", input, ParseComments|SkipObjectResolution)
++ if size == "small" {
++ if err != nil {
++ t.Errorf("ParseFile(...): %v (want success)", err)
++ }
++ } else {
++ expected := "exceeded max nesting depth"
++ if err == nil || !strings.HasSuffix(err.Error(), expected) {
++ t.Errorf("ParseFile(...) = _, %v, want %q", err, expected)
++ }
++ }
++ })
++ }
++ }
++}
++
++func TestScopeDepthLimit(t *testing.T) {
++ if runtime.GOARCH == "wasm" {
++ t.Skip("causes call stack exhaustion on js/wasm")
++ }
++ for _, tt := range parseDepthTests {
++ if !tt.scope {
++ continue
++ }
++ for _, size := range []string{"small", "big"} {
++ t.Run(tt.name+"/"+size, func(t *testing.T) {
++ n := maxScopeDepth + 1
++ if tt.scopeMultiplier > 0 {
++ n /= tt.scopeMultiplier
++ }
++ if size == "small" {
++ // Decrease the number of statements by 10, in order to check
++ // that we do not fail when under the limit. 10 is used to
++ // provide some wiggle room for cases where the surrounding
++ // scaffolding syntax adds some noise to the depth that changes
++ // on a per testcase basis.
++ n -= 10
++ }
++
++ pre, mid, post := split(tt.format)
++ if strings.Contains(mid, "«") {
++ left, base, right := split(mid)
++ mid = strings.Repeat(left, n) + base + strings.Repeat(right, n)
++ } else {
++ mid = strings.Repeat(mid, n)
++ }
++ input := pre + mid + post
++
++ fset := token.NewFileSet()
++ _, err := ParseFile(fset, "", input, DeclarationErrors)
++ if size == "small" {
++ if err != nil {
++ t.Errorf("ParseFile(...): %v (want success)", err)
++ }
++ } else {
++ expected := "exceeded max scope depth during object resolution"
++ if err == nil || !strings.HasSuffix(err.Error(), expected) {
++ t.Errorf("ParseFile(...) = _, %v, want %q", err, expected)
++ }
++ }
++ })
++ }
++ }
++}
+--
+2.30.2
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-23772.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-23772.patch
new file mode 100644
index 0000000000..f0daee3624
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-23772.patch
@@ -0,0 +1,50 @@
+From 70882eedccac803ddcf1c3215e0ae8fd59847e39 Mon Sep 17 00:00:00 2001
+From: Katie Hockman <katie@golang.org>
+Date: Sat, 26 Feb 2022 20:03:38 +0000
+Subject: [PATCH] [release-branch.go1.16] math/big: prevent overflow in
+ (*Rat).SetString
+
+Credit to rsc@ for the original patch.
+
+Thanks to the OSS-Fuzz project for discovering this
+issue and to Emmanuel Odeke (@odeke_et) for reporting it.
+
+Updates #50699
+Fixes #50700
+Fixes CVE-2022-23772
+---
+ src/math/big/ratconv.go | 5 +++++
+ src/math/big/ratconv_test.go | 1 +
+ 2 files changed, 6 insertions(+)
+
+diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go
+index 941139e..e8cbdbe 100644
+--- a/src/math/big/ratconv.go
++++ b/src/math/big/ratconv.go
+@@ -168,6 +168,11 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
+ n := exp5
+ if n < 0 {
+ n = -n
++ if n < 0 {
++ // This can occur if -n overflows. -(-1 << 63) would become
++ // -1 << 63, which is still negative.
++ return nil, false
++ }
+ }
+ pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil) // use underlying array of z.b.abs
+ if exp5 > 0 {
+diff --git a/src/math/big/ratconv_test.go b/src/math/big/ratconv_test.go
+index ba0d1ba..b820df4 100644
+--- a/src/math/big/ratconv_test.go
++++ b/src/math/big/ratconv_test.go
+@@ -104,6 +104,7 @@ var setStringTests = []StringTest{
+ {in: "4/3/"},
+ {in: "4/3."},
+ {in: "4/"},
++ {in: "13e-9223372036854775808"}, // CVE-2022-23772
+
+ // valid
+ {"0", "0", true},
+--
+2.17.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-23806.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-23806.patch
new file mode 100644
index 0000000000..772acdcbf6
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-23806.patch
@@ -0,0 +1,142 @@
+From 5b376a209d1c61e10847e062d78c4b1aa90dff0c Mon Sep 17 00:00:00 2001
+From: Filippo Valsorda <filippo@golang.org>
+Date: Sat, 26 Feb 2022 10:40:57 +0000
+Subject: [PATCH] crypto/elliptic: make IsOnCurve return false for invalid
+
+ field elements
+
+Updates #50974
+Fixes #50977
+Fixes CVE-2022-23806
+
+Signed-off-by: Minjae Kim <flowergom@gmail.com>
+
+---
+ src/crypto/elliptic/elliptic.go | 6 +++
+ src/crypto/elliptic/elliptic_test.go | 81 ++++++++++++++++++++++++++++
+ src/crypto/elliptic/p224.go | 6 +++
+ 3 files changed, 93 insertions(+)
+
+diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go
+index e2f71cd..bd574a4 100644
+--- a/src/crypto/elliptic/elliptic.go
++++ b/src/crypto/elliptic/elliptic.go
+@@ -53,6 +53,12 @@ func (curve *CurveParams) Params() *CurveParams {
+ }
+
+ func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
++
++ if x.Sign() < 0 || x.Cmp(curve.P) >= 0 ||
++ y.Sign() < 0 || y.Cmp(curve.P) >= 0 {
++ return false
++ }
++
+ // y² = x³ - 3x + b
+ y2 := new(big.Int).Mul(y, y)
+ y2.Mod(y2, curve.P)
+diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go
+index 09c5483..b13a620 100644
+--- a/src/crypto/elliptic/elliptic_test.go
++++ b/src/crypto/elliptic/elliptic_test.go
+@@ -628,3 +628,84 @@ func TestUnmarshalToLargeCoordinates(t *testing.T) {
+ t.Errorf("Unmarshal accepts invalid Y coordinate")
+ }
+ }
++
++func testAllCurves(t *testing.T, f func(*testing.T, Curve)) {
++ tests := []struct {
++ name string
++ curve Curve
++ }{
++ {"P256", P256()},
++ {"P256/Params", P256().Params()},
++ {"P224", P224()},
++ {"P224/Params", P224().Params()},
++ {"P384", P384()},
++ {"P384/Params", P384().Params()},
++ {"P521", P521()},
++ {"P521/Params", P521().Params()},
++ }
++ if testing.Short() {
++ tests = tests[:1]
++ }
++ for _, test := range tests {
++ curve := test.curve
++ t.Run(test.name, func(t *testing.T) {
++ t.Parallel()
++ f(t, curve)
++ })
++ }
++}
++
++// TestInvalidCoordinates tests big.Int values that are not valid field elements
++// (negative or bigger than P). They are expected to return false from
++// IsOnCurve, all other behavior is undefined.
++func TestInvalidCoordinates(t *testing.T) {
++ testAllCurves(t, testInvalidCoordinates)
++}
++
++func testInvalidCoordinates(t *testing.T, curve Curve) {
++ checkIsOnCurveFalse := func(name string, x, y *big.Int) {
++ if curve.IsOnCurve(x, y) {
++ t.Errorf("IsOnCurve(%s) unexpectedly returned true", name)
++ }
++ }
++
++ p := curve.Params().P
++ _, x, y, _ := GenerateKey(curve, rand.Reader)
++ xx, yy := new(big.Int), new(big.Int)
++
++ // Check if the sign is getting dropped.
++ xx.Neg(x)
++ checkIsOnCurveFalse("-x, y", xx, y)
++ yy.Neg(y)
++ checkIsOnCurveFalse("x, -y", x, yy)
++
++ // Check if negative values are reduced modulo P.
++ xx.Sub(x, p)
++ checkIsOnCurveFalse("x-P, y", xx, y)
++ yy.Sub(y, p)
++ checkIsOnCurveFalse("x, y-P", x, yy)
++
++ // Check if positive values are reduced modulo P.
++ xx.Add(x, p)
++ checkIsOnCurveFalse("x+P, y", xx, y)
++ yy.Add(y, p)
++ checkIsOnCurveFalse("x, y+P", x, yy)
++
++ // Check if the overflow is dropped.
++ xx.Add(x, new(big.Int).Lsh(big.NewInt(1), 535))
++ checkIsOnCurveFalse("x+2⁵³⁵, y", xx, y)
++ yy.Add(y, new(big.Int).Lsh(big.NewInt(1), 535))
++ checkIsOnCurveFalse("x, y+2⁵³⁵", x, yy)
++
++ // Check if P is treated like zero (if possible).
++ // y^2 = x^3 - 3x + B
++ // y = mod_sqrt(x^3 - 3x + B)
++ // y = mod_sqrt(B) if x = 0
++ // If there is no modsqrt, there is no point with x = 0, can't test x = P.
++ if yy := new(big.Int).ModSqrt(curve.Params().B, p); yy != nil {
++ if !curve.IsOnCurve(big.NewInt(0), yy) {
++ t.Fatal("(0, mod_sqrt(B)) is not on the curve?")
++ }
++ checkIsOnCurveFalse("P, y", p, yy)
++ }
++}
+diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go
+index 8c76021..f1bfd7e 100644
+--- a/src/crypto/elliptic/p224.go
++++ b/src/crypto/elliptic/p224.go
+@@ -48,6 +48,12 @@ func (curve p224Curve) Params() *CurveParams {
+ }
+
+ func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool {
++
++ if bigX.Sign() < 0 || bigX.Cmp(curve.P) >= 0 ||
++ bigY.Sign() < 0 || bigY.Cmp(curve.P) >= 0 {
++ return false
++ }
++
+ var x, y p224FieldElement
+ p224FromBig(&x, bigX)
+ p224FromBig(&y, bigY)
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch
new file mode 100644
index 0000000000..4bc012be21
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-24675.patch
@@ -0,0 +1,271 @@
+From 1eb931d60a24501a9668e5cb4647593e19115507 Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Fri, 17 Jun 2022 12:22:53 +0530
+Subject: [PATCH] CVE-2022-24675
+
+Upstream-Status: Backport [https://go-review.googlesource.com/c/go/+/399816/]
+CVE: CVE-2022-24675
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/encoding/pem/pem.go | 174 +++++++++++++++--------------------
+ src/encoding/pem/pem_test.go | 28 +++++-
+ 2 files changed, 101 insertions(+), 101 deletions(-)
+
+diff --git a/src/encoding/pem/pem.go b/src/encoding/pem/pem.go
+index a7272da..1bee1c1 100644
+--- a/src/encoding/pem/pem.go
++++ b/src/encoding/pem/pem.go
+@@ -87,123 +87,97 @@ func Decode(data []byte) (p *Block, rest []byte) {
+ // pemStart begins with a newline. However, at the very beginning of
+ // the byte array, we'll accept the start string without it.
+ rest = data
+- if bytes.HasPrefix(data, pemStart[1:]) {
+- rest = rest[len(pemStart)-1 : len(data)]
+- } else if i := bytes.Index(data, pemStart); i >= 0 {
+- rest = rest[i+len(pemStart) : len(data)]
+- } else {
+- return nil, data
+- }
+-
+- typeLine, rest := getLine(rest)
+- if !bytes.HasSuffix(typeLine, pemEndOfLine) {
+- return decodeError(data, rest)
+- }
+- typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)]
+-
+- p = &Block{
+- Headers: make(map[string]string),
+- Type: string(typeLine),
+- }
+-
+ for {
+- // This loop terminates because getLine's second result is
+- // always smaller than its argument.
+- if len(rest) == 0 {
++ if bytes.HasPrefix(rest, pemStart[1:]) {
++ rest = rest[len(pemStart)-1:]
++ } else if i := bytes.Index(rest, pemStart); i >= 0 {
++ rest = rest[i+len(pemStart) : len(rest)]
++ } else {
+ return nil, data
+ }
+- line, next := getLine(rest)
+
+- i := bytes.IndexByte(line, ':')
+- if i == -1 {
+- break
++ var typeLine []byte
++ typeLine, rest = getLine(rest)
++ if !bytes.HasSuffix(typeLine, pemEndOfLine) {
++ continue
+ }
++ typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)]
+
+- // TODO(agl): need to cope with values that spread across lines.
+- key, val := line[:i], line[i+1:]
+- key = bytes.TrimSpace(key)
+- val = bytes.TrimSpace(val)
+- p.Headers[string(key)] = string(val)
+- rest = next
+- }
++ p = &Block{
++ Headers: make(map[string]string),
++ Type: string(typeLine),
++ }
+
+- var endIndex, endTrailerIndex int
++ for {
++ // This loop terminates because getLine's second result is
++ // always smaller than its argument.
++ if len(rest) == 0 {
++ return nil, data
++ }
++ line, next := getLine(rest)
+
+- // If there were no headers, the END line might occur
+- // immediately, without a leading newline.
+- if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) {
+- endIndex = 0
+- endTrailerIndex = len(pemEnd) - 1
+- } else {
+- endIndex = bytes.Index(rest, pemEnd)
+- endTrailerIndex = endIndex + len(pemEnd)
+- }
++ i := bytes.IndexByte(line, ':')
++ if i == -1 {
++ break
++ }
+
+- if endIndex < 0 {
+- return decodeError(data, rest)
+- }
++ // TODO(agl): need to cope with values that spread across lines.
++ key, val := line[:i], line[i+1:]
++ key = bytes.TrimSpace(key)
++ val = bytes.TrimSpace(val)
++ p.Headers[string(key)] = string(val)
++ rest = next
++ }
+
+- // After the "-----" of the ending line, there should be the same type
+- // and then a final five dashes.
+- endTrailer := rest[endTrailerIndex:]
+- endTrailerLen := len(typeLine) + len(pemEndOfLine)
+- if len(endTrailer) < endTrailerLen {
+- return decodeError(data, rest)
+- }
++ var endIndex, endTrailerIndex int
+
+- restOfEndLine := endTrailer[endTrailerLen:]
+- endTrailer = endTrailer[:endTrailerLen]
+- if !bytes.HasPrefix(endTrailer, typeLine) ||
+- !bytes.HasSuffix(endTrailer, pemEndOfLine) {
+- return decodeError(data, rest)
+- }
++ // If there were no headers, the END line might occur
++ // immediately, without a leading newline.
++ if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) {
++ endIndex = 0
++ endTrailerIndex = len(pemEnd) - 1
++ } else {
++ endIndex = bytes.Index(rest, pemEnd)
++ endTrailerIndex = endIndex + len(pemEnd)
++ }
+
+- // The line must end with only whitespace.
+- if s, _ := getLine(restOfEndLine); len(s) != 0 {
+- return decodeError(data, rest)
+- }
++ if endIndex < 0 {
++ continue
++ }
+
+- base64Data := removeSpacesAndTabs(rest[:endIndex])
+- p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
+- n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
+- if err != nil {
+- return decodeError(data, rest)
+- }
+- p.Bytes = p.Bytes[:n]
++ // After the "-----" of the ending line, there should be the same type
++ // and then a final five dashes.
++ endTrailer := rest[endTrailerIndex:]
++ endTrailerLen := len(typeLine) + len(pemEndOfLine)
++ if len(endTrailer) < endTrailerLen {
++ continue
++ }
++
++ restOfEndLine := endTrailer[endTrailerLen:]
++ endTrailer = endTrailer[:endTrailerLen]
++ if !bytes.HasPrefix(endTrailer, typeLine) ||
++ !bytes.HasSuffix(endTrailer, pemEndOfLine) {
++ continue
++ }
+
+- // the -1 is because we might have only matched pemEnd without the
+- // leading newline if the PEM block was empty.
+- _, rest = getLine(rest[endIndex+len(pemEnd)-1:])
++ // The line must end with only whitespace.
++ if s, _ := getLine(restOfEndLine); len(s) != 0 {
++ continue
++ }
+
+- return
+-}
++ base64Data := removeSpacesAndTabs(rest[:endIndex])
++ p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
++ n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
++ if err != nil {
++ continue
++ }
++ p.Bytes = p.Bytes[:n]
+
+-func decodeError(data, rest []byte) (*Block, []byte) {
+- // If we get here then we have rejected a likely looking, but
+- // ultimately invalid PEM block. We need to start over from a new
+- // position. We have consumed the preamble line and will have consumed
+- // any lines which could be header lines. However, a valid preamble
+- // line is not a valid header line, therefore we cannot have consumed
+- // the preamble line for the any subsequent block. Thus, we will always
+- // find any valid block, no matter what bytes precede it.
+- //
+- // For example, if the input is
+- //
+- // -----BEGIN MALFORMED BLOCK-----
+- // junk that may look like header lines
+- // or data lines, but no END line
+- //
+- // -----BEGIN ACTUAL BLOCK-----
+- // realdata
+- // -----END ACTUAL BLOCK-----
+- //
+- // we've failed to parse using the first BEGIN line
+- // and now will try again, using the second BEGIN line.
+- p, rest := Decode(rest)
+- if p == nil {
+- rest = data
++ // the -1 is because we might have only matched pemEnd without the
++ // leading newline if the PEM block was empty.
++ _, rest = getLine(rest[endIndex+len(pemEnd)-1:])
++ return p, rest
+ }
+- return p, rest
+ }
+
+ const pemLineLength = 64
+diff --git a/src/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go
+index 8515b46..4485581 100644
+--- a/src/encoding/pem/pem_test.go
++++ b/src/encoding/pem/pem_test.go
+@@ -107,6 +107,12 @@ const pemMissingEndingSpace = `
+ dGVzdA==
+ -----ENDBAR-----`
+
++const pemMissingEndLine = `
++-----BEGIN FOO-----
++Header: 1`
++
++var pemRepeatingBegin = strings.Repeat("-----BEGIN \n", 10)
++
+ var badPEMTests = []struct {
+ name string
+ input string
+@@ -131,14 +137,34 @@ var badPEMTests = []struct {
+ "missing ending space",
+ pemMissingEndingSpace,
+ },
++ {
++ "repeating begin",
++ pemRepeatingBegin,
++ },
++ {
++ "missing end line",
++ pemMissingEndLine,
++ },
+ }
+
+ func TestBadDecode(t *testing.T) {
+ for _, test := range badPEMTests {
+- result, _ := Decode([]byte(test.input))
++ result, rest := Decode([]byte(test.input))
+ if result != nil {
+ t.Errorf("unexpected success while parsing %q", test.name)
+ }
++ if string(rest) != test.input {
++ t.Errorf("unexpected rest: %q; want = %q", rest, test.input)
++ }
++ }
++}
++
++func TestCVE202224675(t *testing.T) {
++ // Prior to CVE-2022-24675, this input would cause a stack overflow.
++ input := []byte(strings.Repeat("-----BEGIN \n", 10000000))
++ result, rest := Decode(input)
++ if result != nil || !reflect.DeepEqual(rest, input) {
++ t.Errorf("Encode of %#v decoded as %#v", input, rest)
+ }
+ }
+
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch
new file mode 100644
index 0000000000..e4270d8a75
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-24921.patch
@@ -0,0 +1,198 @@
+From ba99f699d26483ea1045f47c760e9be30799e311 Mon Sep 17 00:00:00 2001
+From: Russ Cox <rsc@golang.org>
+Date: Wed, 2 Feb 2022 16:41:32 -0500
+Subject: [PATCH] regexp/syntax: reject very deeply nested regexps in Parse
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/2b65cde5868d8245ef8a0b8eba1e361440252d3b]
+CVE: CVE-2022-24921
+Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org
+
+
+The regexp code assumes it can recurse over the structure of
+a regexp safely. Go's growable stacks make that reasonable
+for all plausible regexps, but implausible ones can reach the
+“infinite recursion?” stack limit.
+
+This CL limits the depth of any parsed regexp to 1000.
+That is, the depth of the parse tree is required to be ≤ 1000.
+Regexps that require deeper parse trees will return ErrInternalError.
+A future CL will change the error to ErrInvalidDepth,
+but using ErrInternalError for now avoids introducing new API
+in point releases when this is backported.
+
+Fixes #51112.
+Fixes #51117.
+
+Change-Id: I97d2cd82195946eb43a4ea8561f5b95f91fb14c5
+Reviewed-on: https://go-review.googlesource.com/c/go/+/384616
+Trust: Russ Cox <rsc@golang.org>
+Run-TryBot: Russ Cox <rsc@golang.org>
+Reviewed-by: Ian Lance Taylor <iant@golang.org>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/384855
+---
+ src/regexp/syntax/parse.go | 72 ++++++++++++++++++++++++++++++++-
+ src/regexp/syntax/parse_test.go | 7 ++++
+ 2 files changed, 77 insertions(+), 2 deletions(-)
+
+diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go
+index 8c6d43a..55bd20d 100644
+--- a/src/regexp/syntax/parse.go
++++ b/src/regexp/syntax/parse.go
+@@ -76,13 +76,29 @@ const (
+ opVerticalBar
+ )
+
++// maxHeight is the maximum height of a regexp parse tree.
++// It is somewhat arbitrarily chosen, but the idea is to be large enough
++// that no one will actually hit in real use but at the same time small enough
++// that recursion on the Regexp tree will not hit the 1GB Go stack limit.
++// The maximum amount of stack for a single recursive frame is probably
++// closer to 1kB, so this could potentially be raised, but it seems unlikely
++// that people have regexps nested even this deeply.
++// We ran a test on Google's C++ code base and turned up only
++// a single use case with depth > 100; it had depth 128.
++// Using depth 1000 should be plenty of margin.
++// As an optimization, we don't even bother calculating heights
++// until we've allocated at least maxHeight Regexp structures.
++const maxHeight = 1000
++
+ type parser struct {
+ flags Flags // parse mode flags
+ stack []*Regexp // stack of parsed expressions
+ free *Regexp
+ numCap int // number of capturing groups seen
+ wholeRegexp string
+- tmpClass []rune // temporary char class work space
++ tmpClass []rune // temporary char class work space
++ numRegexp int // number of regexps allocated
++ height map[*Regexp]int // regexp height for height limit check
+ }
+
+ func (p *parser) newRegexp(op Op) *Regexp {
+@@ -92,16 +108,52 @@ func (p *parser) newRegexp(op Op) *Regexp {
+ *re = Regexp{}
+ } else {
+ re = new(Regexp)
++ p.numRegexp++
+ }
+ re.Op = op
+ return re
+ }
+
+ func (p *parser) reuse(re *Regexp) {
++ if p.height != nil {
++ delete(p.height, re)
++ }
+ re.Sub0[0] = p.free
+ p.free = re
+ }
+
++func (p *parser) checkHeight(re *Regexp) {
++ if p.numRegexp < maxHeight {
++ return
++ }
++ if p.height == nil {
++ p.height = make(map[*Regexp]int)
++ for _, re := range p.stack {
++ p.checkHeight(re)
++ }
++ }
++ if p.calcHeight(re, true) > maxHeight {
++ panic(ErrInternalError)
++ }
++}
++
++func (p *parser) calcHeight(re *Regexp, force bool) int {
++ if !force {
++ if h, ok := p.height[re]; ok {
++ return h
++ }
++ }
++ h := 1
++ for _, sub := range re.Sub {
++ hsub := p.calcHeight(sub, false)
++ if h < 1+hsub {
++ h = 1 + hsub
++ }
++ }
++ p.height[re] = h
++ return h
++}
++
+ // Parse stack manipulation.
+
+ // push pushes the regexp re onto the parse stack and returns the regexp.
+@@ -137,6 +189,7 @@ func (p *parser) push(re *Regexp) *Regexp {
+ }
+
+ p.stack = append(p.stack, re)
++ p.checkHeight(re)
+ return re
+ }
+
+@@ -252,6 +305,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (
+ re.Sub = re.Sub0[:1]
+ re.Sub[0] = sub
+ p.stack[n-1] = re
++ p.checkHeight(re)
+
+ if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
+ return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
+@@ -699,6 +753,21 @@ func literalRegexp(s string, flags Flags) *Regexp {
+ // Flags, and returns a regular expression parse tree. The syntax is
+ // described in the top-level comment.
+ func Parse(s string, flags Flags) (*Regexp, error) {
++ return parse(s, flags)
++}
++
++func parse(s string, flags Flags) (_ *Regexp, err error) {
++ defer func() {
++ switch r := recover(); r {
++ default:
++ panic(r)
++ case nil:
++ // ok
++ case ErrInternalError:
++ err = &Error{Code: ErrInternalError, Expr: s}
++ }
++ }()
++
+ if flags&Literal != 0 {
+ // Trivial parser for literal string.
+ if err := checkUTF8(s); err != nil {
+@@ -710,7 +779,6 @@ func Parse(s string, flags Flags) (*Regexp, error) {
+ // Otherwise, must do real work.
+ var (
+ p parser
+- err error
+ c rune
+ op Op
+ lastRepeat string
+diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go
+index 5581ba1..1ef6d8a 100644
+--- a/src/regexp/syntax/parse_test.go
++++ b/src/regexp/syntax/parse_test.go
+@@ -207,6 +207,11 @@ var parseTests = []parseTest{
+ // Valid repetitions.
+ {`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``},
+ {`((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})`, ``},
++
++ // Valid nesting.
++ {strings.Repeat("(", 999) + strings.Repeat(")", 999), ``},
++ {strings.Repeat("(?:", 999) + strings.Repeat(")*", 999), ``},
++ {"(" + strings.Repeat("|", 12345) + ")", ``}, // not nested at all
+ }
+
+ const testFlags = MatchNL | PerlX | UnicodeGroups
+@@ -482,6 +487,8 @@ var invalidRegexps = []string{
+ `a{100000}`,
+ `a{100000,}`,
+ "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
++ strings.Repeat("(", 1000) + strings.Repeat(")", 1000),
++ strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000),
+ `\Q\E*`,
+ }
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-27664.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-27664.patch
new file mode 100644
index 0000000000..238c3eac5b
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-27664.patch
@@ -0,0 +1,68 @@
+From 48c9076dcfc2dc894842ff758c8cfae7957c9565 Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Thu, 29 Sep 2022 17:06:18 +0530
+Subject: [PATCH] CVE-2022-27664
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/5bc9106458fc07851ac324a4157132a91b1f3479]
+CVE: CVE-2022-27664
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/net/http/h2_bundle.go | 21 +++++++++++++--------
+ 1 file changed, 13 insertions(+), 8 deletions(-)
+
+diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
+index 65d851d..83f2a72 100644
+--- a/src/net/http/h2_bundle.go
++++ b/src/net/http/h2_bundle.go
+@@ -3254,10 +3254,11 @@ var (
+ // name (key). See httpguts.ValidHeaderName for the base rules.
+ //
+ // Further, http2 says:
+-// "Just as in HTTP/1.x, header field names are strings of ASCII
+-// characters that are compared in a case-insensitive
+-// fashion. However, header field names MUST be converted to
+-// lowercase prior to their encoding in HTTP/2. "
++//
++// "Just as in HTTP/1.x, header field names are strings of ASCII
++// characters that are compared in a case-insensitive
++// fashion. However, header field names MUST be converted to
++// lowercase prior to their encoding in HTTP/2. "
+ func http2validWireHeaderFieldName(v string) bool {
+ if len(v) == 0 {
+ return false
+@@ -3446,8 +3447,8 @@ func (s *http2sorter) SortStrings(ss []string) {
+ // validPseudoPath reports whether v is a valid :path pseudo-header
+ // value. It must be either:
+ //
+-// *) a non-empty string starting with '/'
+-// *) the string '*', for OPTIONS requests.
++// *) a non-empty string starting with '/'
++// *) the string '*', for OPTIONS requests.
+ //
+ // For now this is only used a quick check for deciding when to clean
+ // up Opaque URLs before sending requests from the Transport.
+@@ -4897,6 +4898,9 @@ func (sc *http2serverConn) startGracefulShutdownInternal() {
+ func (sc *http2serverConn) goAway(code http2ErrCode) {
+ sc.serveG.check()
+ if sc.inGoAway {
++ if sc.goAwayCode == http2ErrCodeNo {
++ sc.goAwayCode = code
++ }
+ return
+ }
+ sc.inGoAway = true
+@@ -6091,8 +6095,9 @@ func (rws *http2responseWriterState) writeChunk(p []byte) (n int, err error) {
+ // prior to the headers being written. If the set of trailers is fixed
+ // or known before the header is written, the normal Go trailers mechanism
+ // is preferred:
+-// https://golang.org/pkg/net/http/#ResponseWriter
+-// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
++//
++// https://golang.org/pkg/net/http/#ResponseWriter
++// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
+ const http2TrailerPrefix = "Trailer:"
+
+ // promoteUndeclaredTrailers permits http.Handlers to set trailers
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-28131.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-28131.patch
new file mode 100644
index 0000000000..8afa292144
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-28131.patch
@@ -0,0 +1,104 @@
+From 8136eb2e5c316a51d0da710fbd0504cbbefee526 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <roland@golang.org>
+Date: Mon, 28 Mar 2022 18:41:26 -0700
+Subject: [PATCH] encoding/xml: use iterative Skip, rather than recursive
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/58facfbe7db2fbb9afed794b281a70bdb12a60ae]
+CVE: CVE-2022-28131
+Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
+
+
+Prevents exhausting the stack limit in _incredibly_ deeply nested
+structures.
+
+Fixes #53711
+Updates #53614
+Fixes CVE-2022-28131
+
+Change-Id: I47db4595ce10cecc29fbd06afce7b299868599e6
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1419912
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+(cherry picked from commit 9278cb78443d2b4deb24cbb5b61c9ba5ac688d49)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/417068
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Heschi Kreinick <heschi@google.com>
+Run-TryBot: Michael Knyszek <mknyszek@google.com>
+---
+ src/encoding/xml/read.go | 15 ++++++++-------
+ src/encoding/xml/read_test.go | 18 ++++++++++++++++++
+ 2 files changed, 26 insertions(+), 7 deletions(-)
+
+diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go
+index 4ffed80..3fac859 100644
+--- a/src/encoding/xml/read.go
++++ b/src/encoding/xml/read.go
+@@ -743,12 +743,12 @@ Loop:
+ }
+
+ // Skip reads tokens until it has consumed the end element
+-// matching the most recent start element already consumed.
+-// It recurs if it encounters a start element, so it can be used to
+-// skip nested structures.
++// matching the most recent start element already consumed,
++// skipping nested structures.
+ // It returns nil if it finds an end element matching the start
+ // element; otherwise it returns an error describing the problem.
+ func (d *Decoder) Skip() error {
++ var depth int64
+ for {
+ tok, err := d.Token()
+ if err != nil {
+@@ -756,11 +756,12 @@ func (d *Decoder) Skip() error {
+ }
+ switch tok.(type) {
+ case StartElement:
+- if err := d.Skip(); err != nil {
+- return err
+- }
++ depth++
+ case EndElement:
+- return nil
++ if depth == 0 {
++ return nil
++ }
++ depth--
+ }
+ }
+ }
+diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go
+index 6a20b1a..7a621a5 100644
+--- a/src/encoding/xml/read_test.go
++++ b/src/encoding/xml/read_test.go
+@@ -5,9 +5,11 @@
+ package xml
+
+ import (
++ "bytes"
+ "errors"
+ "io"
+ "reflect"
++ "runtime"
+ "strings"
+ "testing"
+ "time"
+@@ -1093,3 +1095,19 @@ func TestCVE202228131(t *testing.T) {
+ t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth)
+ }
+ }
++
++func TestCVE202230633(t *testing.T) {
++ if runtime.GOARCH == "wasm" {
++ t.Skip("causes memory exhaustion on js/wasm")
++ }
++ defer func() {
++ p := recover()
++ if p != nil {
++ t.Fatal("Unmarshal panicked")
++ }
++ }()
++ var example struct {
++ Things []string
++ }
++ Unmarshal(bytes.Repeat([]byte("<a>"), 17_000_000), &example)
++}
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-28327.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-28327.patch
new file mode 100644
index 0000000000..6361deec7d
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-28327.patch
@@ -0,0 +1,36 @@
+From 34d9ab78568d63d8097911237897b188bdaba9c2 Mon Sep 17 00:00:00 2001
+From: Filippo Valsorda <filippo@golang.org>
+Date: Thu, 31 Mar 2022 12:31:58 -0400
+Subject: [PATCH] crypto/elliptic: tolerate zero-padded scalars in generic
+ P-256
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/7139e8b024604ab168b51b99c6e8168257a5bf58]
+CVE: CVE-2022-28327
+Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
+
+
+Updates #52075
+Fixes #52076
+Fixes CVE-2022-28327
+
+Change-Id: I595a7514c9a0aa1b9c76aedfc2307e1124271f27
+Reviewed-on: https://go-review.googlesource.com/c/go/+/397136
+Trust: Filippo Valsorda <filippo@golang.org>
+Reviewed-by: Julie Qiu <julie@golang.org>
+---
+ src/crypto/elliptic/p256.go | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go
+index c23e414..787e3e7 100644
+--- a/src/crypto/elliptic/p256.go
++++ b/src/crypto/elliptic/p256.go
+@@ -51,7 +51,7 @@ func p256GetScalar(out *[32]byte, in []byte) {
+ n := new(big.Int).SetBytes(in)
+ var scalarBytes []byte
+
+- if n.Cmp(p256Params.N) >= 0 {
++ if n.Cmp(p256Params.N) >= 0 || len(in) > len(out) {
+ n.Mod(n, p256Params.N)
+ scalarBytes = n.Bytes()
+ } else {
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-2879.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-2879.patch
new file mode 100644
index 0000000000..ea04a82d16
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-2879.patch
@@ -0,0 +1,111 @@
+From 9d339f1d0f53c4116a7cb4acfa895f31a07212ee Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Fri, 2 Sep 2022 20:45:18 -0700
+Subject: [PATCH] archive/tar: limit size of headers
+
+Set a 1MiB limit on special file blocks (PAX headers, GNU long names,
+GNU link names), to avoid reading arbitrarily large amounts of data
+into memory.
+
+Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting
+this issue.
+
+Fixes CVE-2022-2879
+Updates #54853
+Fixes #55926
+
+Change-Id: I85136d6ff1e0af101a112190e027987ab4335680
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1565555
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+(cherry picked from commit 6ee768cef6b82adf7a90dcf367a1699ef694f3b2)
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1591053
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/438498
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+Reviewed-by: Carlos Amedee <carlos@golang.org>
+Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
+Run-TryBot: Carlos Amedee <carlos@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/0a723816cd2]
+CVE: CVE-2022-2879
+Signed-off-by: Sunil Kumar <sukumar@mvista.com>
+---
+ src/archive/tar/format.go | 4 ++++
+ src/archive/tar/reader.go | 14 ++++++++++++--
+ src/archive/tar/writer.go | 3 +++
+ 3 files changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/src/archive/tar/format.go b/src/archive/tar/format.go
+index cfe24a5..6642364 100644
+--- a/src/archive/tar/format.go
++++ b/src/archive/tar/format.go
+@@ -143,6 +143,10 @@ const (
+ blockSize = 512 // Size of each block in a tar stream
+ nameSize = 100 // Max length of the name field in USTAR format
+ prefixSize = 155 // Max length of the prefix field in USTAR format
++
++ // Max length of a special file (PAX header, GNU long name or link).
++ // This matches the limit used by libarchive.
++ maxSpecialFileSize = 1 << 20
+ )
+
+ // blockPadding computes the number of bytes needed to pad offset up to the
+diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go
+index 4f9135b..e996595 100644
+--- a/src/archive/tar/reader.go
++++ b/src/archive/tar/reader.go
+@@ -104,7 +104,7 @@ func (tr *Reader) next() (*Header, error) {
+ continue // This is a meta header affecting the next header
+ case TypeGNULongName, TypeGNULongLink:
+ format.mayOnlyBe(FormatGNU)
+- realname, err := ioutil.ReadAll(tr)
++ realname, err := readSpecialFile(tr)
+ if err != nil {
+ return nil, err
+ }
+@@ -294,7 +294,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) {
+ // parsePAX parses PAX headers.
+ // If an extended header (type 'x') is invalid, ErrHeader is returned
+ func parsePAX(r io.Reader) (map[string]string, error) {
+- buf, err := ioutil.ReadAll(r)
++ buf, err := readSpecialFile(r)
+ if err != nil {
+ return nil, err
+ }
+@@ -827,6 +827,16 @@ func tryReadFull(r io.Reader, b []byte) (n int, err error) {
+ return n, err
+ }
+
++// readSpecialFile is like ioutil.ReadAll except it returns
++// ErrFieldTooLong if more than maxSpecialFileSize is read.
++func readSpecialFile(r io.Reader) ([]byte, error) {
++ buf, err := ioutil.ReadAll(io.LimitReader(r, maxSpecialFileSize+1))
++ if len(buf) > maxSpecialFileSize {
++ return nil, ErrFieldTooLong
++ }
++ return buf, err
++}
++
+ // discard skips n bytes in r, reporting an error if unable to do so.
+ func discard(r io.Reader, n int64) error {
+ // If possible, Seek to the last byte before the end of the data section.
+diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go
+index e80498d..893eac0 100644
+--- a/src/archive/tar/writer.go
++++ b/src/archive/tar/writer.go
+@@ -199,6 +199,9 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error {
+ flag = TypeXHeader
+ }
+ data := buf.String()
++ if len(data) > maxSpecialFileSize {
++ return ErrFieldTooLong
++ }
+ if err := tw.writeRawFile(name, data, flag, FormatPAX); err != nil || isGlobal {
+ return err // Global headers return here
+ }
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch
new file mode 100644
index 0000000000..8376dc45ba
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-2880.patch
@@ -0,0 +1,164 @@
+From 753e3f8da191c2ac400407d83c70f46900769417 Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Thu, 27 Oct 2022 12:22:41 +0530
+Subject: [PATCH] CVE-2022-2880
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/9d2c73a9fd69e45876509bb3bdb2af99bf77da1e]
+CVE: CVE-2022-2880
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+
+net/http/httputil: avoid query parameter
+
+Query parameter smuggling occurs when a proxy's interpretation
+of query parameters differs from that of a downstream server.
+Change ReverseProxy to avoid forwarding ignored query parameters.
+
+Remove unparsable query parameters from the outbound request
+
+ * if req.Form != nil after calling ReverseProxy.Director; and
+ * before calling ReverseProxy.Rewrite.
+
+This change preserves the existing behavior of forwarding the
+raw query untouched if a Director hook does not parse the query
+by calling Request.ParseForm (possibly indirectly).
+---
+ src/net/http/httputil/reverseproxy.go | 36 +++++++++++
+ src/net/http/httputil/reverseproxy_test.go | 74 ++++++++++++++++++++++
+ 2 files changed, 110 insertions(+)
+
+diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
+index 2072a5f..c6fb873 100644
+--- a/src/net/http/httputil/reverseproxy.go
++++ b/src/net/http/httputil/reverseproxy.go
+@@ -212,6 +212,9 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+ }
+
+ p.Director(outreq)
++ if outreq.Form != nil {
++ outreq.URL.RawQuery = cleanQueryParams(outreq.URL.RawQuery)
++ }
+ outreq.Close = false
+
+ reqUpType := upgradeType(outreq.Header)
+@@ -561,3 +564,36 @@ func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
+ _, err := io.Copy(c.backend, c.user)
+ errc <- err
+ }
++
++func cleanQueryParams(s string) string {
++ reencode := func(s string) string {
++ v, _ := url.ParseQuery(s)
++ return v.Encode()
++ }
++ for i := 0; i < len(s); {
++ switch s[i] {
++ case ';':
++ return reencode(s)
++ case '%':
++ if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
++ return reencode(s)
++ }
++ i += 3
++ default:
++ i++
++ }
++ }
++ return s
++}
++
++func ishex(c byte) bool {
++ switch {
++ case '0' <= c && c <= '9':
++ return true
++ case 'a' <= c && c <= 'f':
++ return true
++ case 'A' <= c && c <= 'F':
++ return true
++ }
++ return false
++}
+diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
+index 9a7223a..bc87a3b 100644
+--- a/src/net/http/httputil/reverseproxy_test.go
++++ b/src/net/http/httputil/reverseproxy_test.go
+@@ -1269,3 +1269,77 @@ func TestSingleJoinSlash(t *testing.T) {
+ }
+ }
+ }
++
++const (
++ testWantsCleanQuery = true
++ testWantsRawQuery = false
++)
++
++func TestReverseProxyQueryParameterSmugglingDirectorDoesNotParseForm(t *testing.T) {
++ testReverseProxyQueryParameterSmuggling(t, testWantsRawQuery, func(u *url.URL) *ReverseProxy {
++ proxyHandler := NewSingleHostReverseProxy(u)
++ oldDirector := proxyHandler.Director
++ proxyHandler.Director = func(r *http.Request) {
++ oldDirector(r)
++ }
++ return proxyHandler
++ })
++}
++
++func TestReverseProxyQueryParameterSmugglingDirectorParsesForm(t *testing.T) {
++ testReverseProxyQueryParameterSmuggling(t, testWantsCleanQuery, func(u *url.URL) *ReverseProxy {
++ proxyHandler := NewSingleHostReverseProxy(u)
++ oldDirector := proxyHandler.Director
++ proxyHandler.Director = func(r *http.Request) {
++ // Parsing the form causes ReverseProxy to remove unparsable
++ // query parameters before forwarding.
++ r.FormValue("a")
++ oldDirector(r)
++ }
++ return proxyHandler
++ })
++}
++
++func testReverseProxyQueryParameterSmuggling(t *testing.T, wantCleanQuery bool, newProxy func(*url.URL) *ReverseProxy) {
++ const content = "response_content"
++ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
++ w.Write([]byte(r.URL.RawQuery))
++ }))
++ defer backend.Close()
++ backendURL, err := url.Parse(backend.URL)
++ if err != nil {
++ t.Fatal(err)
++ }
++ proxyHandler := newProxy(backendURL)
++ frontend := httptest.NewServer(proxyHandler)
++ defer frontend.Close()
++
++ // Don't spam output with logs of queries containing semicolons.
++ backend.Config.ErrorLog = log.New(io.Discard, "", 0)
++ frontend.Config.ErrorLog = log.New(io.Discard, "", 0)
++
++ for _, test := range []struct {
++ rawQuery string
++ cleanQuery string
++ }{{
++ rawQuery: "a=1&a=2;b=3",
++ cleanQuery: "a=1",
++ }, {
++ rawQuery: "a=1&a=%zz&b=3",
++ cleanQuery: "a=1&b=3",
++ }} {
++ res, err := frontend.Client().Get(frontend.URL + "?" + test.rawQuery)
++ if err != nil {
++ t.Fatalf("Get: %v", err)
++ }
++ defer res.Body.Close()
++ body, _ := io.ReadAll(res.Body)
++ wantQuery := test.rawQuery
++ if wantCleanQuery {
++ wantQuery = test.cleanQuery
++ }
++ if got, want := string(body), wantQuery; got != want {
++ t.Errorf("proxy forwarded raw query %q as %q, want %q", test.rawQuery, got, want)
++ }
++ }
++}
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-30629.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-30629.patch
new file mode 100644
index 0000000000..47313a547f
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-30629.patch
@@ -0,0 +1,47 @@
+From 8d0bbb5a6280c2cf951241ec7f6579c90d38df57 Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Thu, 25 Aug 2022 10:55:08 +0530
+Subject: [PATCH] CVE-2022-30629
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/c15a8e2dbb5ac376a6ed890735341b812d6b965c]
+CVE: CVE-2022-30629
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/crypto/tls/handshake_server_tls13.go | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go
+index 5432145..d91797e 100644
+--- a/src/crypto/tls/handshake_server_tls13.go
++++ b/src/crypto/tls/handshake_server_tls13.go
+@@ -9,6 +9,7 @@ import (
+ "crypto"
+ "crypto/hmac"
+ "crypto/rsa"
++ "encoding/binary"
+ "errors"
+ "hash"
+ "io"
+@@ -742,6 +743,19 @@ func (hs *serverHandshakeStateTLS13) sendSessionTickets() error {
+ }
+ m.lifetime = uint32(maxSessionTicketLifetime / time.Second)
+
++ // ticket_age_add is a random 32-bit value. See RFC 8446, section 4.6.1
++ // The value is not stored anywhere; we never need to check the ticket age
++ // because 0-RTT is not supported.
++ ageAdd := make([]byte, 4)
++ _, err = hs.c.config.rand().Read(ageAdd)
++ if err != nil {
++ return err
++ }
++ m.ageAdd = binary.LittleEndian.Uint32(ageAdd)
++
++ // ticket_nonce, which must be unique per connection, is always left at
++ // zero because we only ever send one ticket per connection.
++
+ if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
+ return err
+ }
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-30631.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-30631.patch
new file mode 100644
index 0000000000..5dcfd27f16
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-30631.patch
@@ -0,0 +1,116 @@
+From d10fc3a84e3344f2421c1dd3046faa50709ab4d5 Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Thu, 25 Aug 2022 11:01:21 +0530
+Subject: [PATCH] CVE-2022-30631
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/0117dee7dccbbd7803d88f65a2ce8bd686219ad3]
+CVE: CVE-2022-30631
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/compress/gzip/gunzip.go | 60 +++++++++++++++-----------------
+ src/compress/gzip/gunzip_test.go | 16 +++++++++
+ 2 files changed, 45 insertions(+), 31 deletions(-)
+
+diff --git a/src/compress/gzip/gunzip.go b/src/compress/gzip/gunzip.go
+index 924bce1..237b2b9 100644
+--- a/src/compress/gzip/gunzip.go
++++ b/src/compress/gzip/gunzip.go
+@@ -248,42 +248,40 @@ func (z *Reader) Read(p []byte) (n int, err error) {
+ return 0, z.err
+ }
+
+- n, z.err = z.decompressor.Read(p)
+- z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n])
+- z.size += uint32(n)
+- if z.err != io.EOF {
+- // In the normal case we return here.
+- return n, z.err
+- }
++ for n == 0 {
++ n, z.err = z.decompressor.Read(p)
++ z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n])
++ z.size += uint32(n)
++ if z.err != io.EOF {
++ // In the normal case we return here.
++ return n, z.err
++ }
+
+- // Finished file; check checksum and size.
+- if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil {
+- z.err = noEOF(err)
+- return n, z.err
+- }
+- digest := le.Uint32(z.buf[:4])
+- size := le.Uint32(z.buf[4:8])
+- if digest != z.digest || size != z.size {
+- z.err = ErrChecksum
+- return n, z.err
+- }
+- z.digest, z.size = 0, 0
++ // Finished file; check checksum and size.
++ if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil {
++ z.err = noEOF(err)
++ return n, z.err
++ }
++ digest := le.Uint32(z.buf[:4])
++ size := le.Uint32(z.buf[4:8])
++ if digest != z.digest || size != z.size {
++ z.err = ErrChecksum
++ return n, z.err
++ }
++ z.digest, z.size = 0, 0
+
+- // File is ok; check if there is another.
+- if !z.multistream {
+- return n, io.EOF
+- }
+- z.err = nil // Remove io.EOF
++ // File is ok; check if there is another.
++ if !z.multistream {
++ return n, io.EOF
++ }
++ z.err = nil // Remove io.EOF
+
+- if _, z.err = z.readHeader(); z.err != nil {
+- return n, z.err
++ if _, z.err = z.readHeader(); z.err != nil {
++ return n, z.err
++ }
+ }
+
+- // Read from next file, if necessary.
+- if n > 0 {
+- return n, nil
+- }
+- return z.Read(p)
++ return n, nil
+ }
+
+ // Close closes the Reader. It does not close the underlying io.Reader.
+diff --git a/src/compress/gzip/gunzip_test.go b/src/compress/gzip/gunzip_test.go
+index 1b01404..95220ae 100644
+--- a/src/compress/gzip/gunzip_test.go
++++ b/src/compress/gzip/gunzip_test.go
+@@ -516,3 +516,19 @@ func TestTruncatedStreams(t *testing.T) {
+ }
+ }
+ }
++
++func TestCVE202230631(t *testing.T) {
++ var empty = []byte{0x1f, 0x8b, 0x08, 0x00, 0xa7, 0x8f, 0x43, 0x62, 0x00,
++ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
++ r := bytes.NewReader(bytes.Repeat(empty, 4e6))
++ z, err := NewReader(r)
++ if err != nil {
++ t.Fatalf("NewReader: got %v, want nil", err)
++ }
++ // Prior to CVE-2022-30631 fix, this would cause an unrecoverable panic due
++ // to stack exhaustion.
++ _, err = z.Read(make([]byte, 10))
++ if err != io.EOF {
++ t.Errorf("Reader.Read: got %v, want %v", err, io.EOF)
++ }
++}
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-30632.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-30632.patch
new file mode 100644
index 0000000000..c54ef56a0e
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-30632.patch
@@ -0,0 +1,71 @@
+From 35d1dfe9746029aea9027b405c75555d41ffd2f8 Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Thu, 25 Aug 2022 13:12:40 +0530
+Subject: [PATCH] CVE-2022-30632
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/76f8b7304d1f7c25834e2a0cc9e88c55276c47df]
+CVE: CVE-2022-30632
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/path/filepath/match.go | 16 +++++++++++++++-
+ src/path/filepath/match_test.go | 10 ++++++++++
+ 2 files changed, 25 insertions(+), 1 deletion(-)
+
+diff --git a/src/path/filepath/match.go b/src/path/filepath/match.go
+index 46badb5..ba68daa 100644
+--- a/src/path/filepath/match.go
++++ b/src/path/filepath/match.go
+@@ -232,6 +232,20 @@ func getEsc(chunk string) (r rune, nchunk string, err error) {
+ // The only possible returned error is ErrBadPattern, when pattern
+ // is malformed.
+ func Glob(pattern string) (matches []string, err error) {
++ return globWithLimit(pattern, 0)
++}
++
++func globWithLimit(pattern string, depth int) (matches []string, err error) {
++ // This limit is used prevent stack exhaustion issues. See CVE-2022-30632.
++ const pathSeparatorsLimit = 10000
++ if depth == pathSeparatorsLimit {
++ return nil, ErrBadPattern
++ }
++
++ // Check pattern is well-formed.
++ if _, err := Match(pattern, ""); err != nil {
++ return nil, err
++ }
+ if !hasMeta(pattern) {
+ if _, err = os.Lstat(pattern); err != nil {
+ return nil, nil
+@@ -257,7 +271,7 @@ func Glob(pattern string) (matches []string, err error) {
+ }
+
+ var m []string
+- m, err = Glob(dir)
++ m, err = globWithLimit(dir, depth+1)
+ if err != nil {
+ return
+ }
+diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go
+index b865762..c37c812 100644
+--- a/src/path/filepath/match_test.go
++++ b/src/path/filepath/match_test.go
+@@ -154,6 +154,16 @@ func TestGlob(t *testing.T) {
+ }
+ }
+
++func TestCVE202230632(t *testing.T) {
++ // Prior to CVE-2022-30632, this would cause a stack exhaustion given a
++ // large number of separators (more than 4,000,000). There is now a limit
++ // of 10,000.
++ _, err := Glob("/*" + strings.Repeat("/", 10001))
++ if err != ErrBadPattern {
++ t.Fatalf("Glob returned err=%v, want ErrBadPattern", err)
++ }
++}
++
+ func TestGlobError(t *testing.T) {
+ _, err := Glob("[]")
+ if err == nil {
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-30633.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-30633.patch
new file mode 100644
index 0000000000..c16cb5f50c
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-30633.patch
@@ -0,0 +1,131 @@
+From ab6e2ffdcab0501bcc2de4b196c1c18ae2301d4b Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Thu, 25 Aug 2022 13:29:55 +0530
+Subject: [PATCH] CVE-2022-30633
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/2678d0c957193dceef336c969a9da74dd716a827]
+CVE: CVE-2022-30633
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/encoding/xml/read.go | 27 +++++++++++++++++++--------
+ src/encoding/xml/read_test.go | 14 ++++++++++++++
+ 2 files changed, 33 insertions(+), 8 deletions(-)
+
+diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go
+index 10a60ee..4ffed80 100644
+--- a/src/encoding/xml/read.go
++++ b/src/encoding/xml/read.go
+@@ -148,7 +148,7 @@ func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
+ if val.Kind() != reflect.Ptr {
+ return errors.New("non-pointer passed to Unmarshal")
+ }
+- return d.unmarshal(val.Elem(), start)
++ return d.unmarshal(val.Elem(), start, 0)
+ }
+
+ // An UnmarshalError represents an error in the unmarshaling process.
+@@ -304,8 +304,15 @@ var (
+ textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+ )
+
++const maxUnmarshalDepth = 10000
++
++var errExeceededMaxUnmarshalDepth = errors.New("exceeded max depth")
++
+ // Unmarshal a single XML element into val.
+-func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
++func (d *Decoder) unmarshal(val reflect.Value, start *StartElement, depth int) error {
++ if depth >= maxUnmarshalDepth {
++ return errExeceededMaxUnmarshalDepth
++ }
+ // Find start element if we need it.
+ if start == nil {
+ for {
+@@ -398,7 +405,7 @@ func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
+ v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem())))
+
+ // Recur to read element into slice.
+- if err := d.unmarshal(v.Index(n), start); err != nil {
++ if err := d.unmarshal(v.Index(n), start, depth+1); err != nil {
+ v.SetLen(n)
+ return err
+ }
+@@ -521,13 +528,15 @@ Loop:
+ case StartElement:
+ consumed := false
+ if sv.IsValid() {
+- consumed, err = d.unmarshalPath(tinfo, sv, nil, &t)
++ // unmarshalPath can call unmarshal, so we need to pass the depth through so that
++ // we can continue to enforce the maximum recusion limit.
++ consumed, err = d.unmarshalPath(tinfo, sv, nil, &t, depth)
+ if err != nil {
+ return err
+ }
+ if !consumed && saveAny.IsValid() {
+ consumed = true
+- if err := d.unmarshal(saveAny, &t); err != nil {
++ if err := d.unmarshal(saveAny, &t, depth+1); err != nil {
+ return err
+ }
+ }
+@@ -672,7 +681,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
+ // The consumed result tells whether XML elements have been consumed
+ // from the Decoder until start's matching end element, or if it's
+ // still untouched because start is uninteresting for sv's fields.
+-func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
++func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement, depth int) (consumed bool, err error) {
+ recurse := false
+ Loop:
+ for i := range tinfo.fields {
+@@ -687,7 +696,7 @@ Loop:
+ }
+ if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
+ // It's a perfect match, unmarshal the field.
+- return true, d.unmarshal(finfo.value(sv), start)
++ return true, d.unmarshal(finfo.value(sv), start, depth+1)
+ }
+ if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
+ // It's a prefix for the field. Break and recurse
+@@ -716,7 +725,9 @@ Loop:
+ }
+ switch t := tok.(type) {
+ case StartElement:
+- consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t)
++ // the recursion depth of unmarshalPath is limited to the path length specified
++ // by the struct field tag, so we don't increment the depth here.
++ consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t, depth)
+ if err != nil {
+ return true, err
+ }
+diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go
+index 8c2e70f..6a20b1a 100644
+--- a/src/encoding/xml/read_test.go
++++ b/src/encoding/xml/read_test.go
+@@ -5,6 +5,7 @@
+ package xml
+
+ import (
++ "errors"
+ "io"
+ "reflect"
+ "strings"
+@@ -1079,3 +1080,16 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) {
+ t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want)
+ }
+ }
++
++func TestCVE202228131(t *testing.T) {
++ type nested struct {
++ Parent *nested `xml:",any"`
++ }
++ var n nested
++ err := Unmarshal(bytes.Repeat([]byte("<a>"), maxUnmarshalDepth+1), &n)
++ if err == nil {
++ t.Fatal("Unmarshal did not fail")
++ } else if !errors.Is(err, errExeceededMaxUnmarshalDepth) {
++ t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth)
++ }
++}
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-30635.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-30635.patch
new file mode 100644
index 0000000000..73959f70fa
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-30635.patch
@@ -0,0 +1,120 @@
+From fdd4316737ed5681689a1f40802ffa0805e5b11c Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Fri, 26 Aug 2022 12:17:05 +0530
+Subject: [PATCH] CVE-2022-30635
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/cd54600b866db0ad068ab8df06c7f5f6cb55c9b3]
+CVE-2022-30635
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/encoding/gob/decode.go | 19 ++++++++++++-------
+ src/encoding/gob/gobencdec_test.go | 24 ++++++++++++++++++++++++
+ 2 files changed, 36 insertions(+), 7 deletions(-)
+
+diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go
+index d2f6c74..0e0ec75 100644
+--- a/src/encoding/gob/decode.go
++++ b/src/encoding/gob/decode.go
+@@ -871,8 +871,13 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
+ return &op
+ }
+
++var maxIgnoreNestingDepth = 10000
++
+ // decIgnoreOpFor returns the decoding op for a field that has no destination.
+-func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp {
++func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, depth int) *decOp {
++ if depth > maxIgnoreNestingDepth {
++ error_(errors.New("invalid nesting depth"))
++ }
+ // If this type is already in progress, it's a recursive type (e.g. map[string]*T).
+ // Return the pointer to the op we're already building.
+ if opPtr := inProgress[wireId]; opPtr != nil {
+@@ -896,7 +901,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp)
+ errorf("bad data: undefined type %s", wireId.string())
+ case wire.ArrayT != nil:
+ elemId := wire.ArrayT.Elem
+- elemOp := dec.decIgnoreOpFor(elemId, inProgress)
++ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len)
+ }
+@@ -904,15 +909,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp)
+ case wire.MapT != nil:
+ keyId := dec.wireType[wireId].MapT.Key
+ elemId := dec.wireType[wireId].MapT.Elem
+- keyOp := dec.decIgnoreOpFor(keyId, inProgress)
+- elemOp := dec.decIgnoreOpFor(elemId, inProgress)
++ keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1)
++ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.ignoreMap(state, *keyOp, *elemOp)
+ }
+
+ case wire.SliceT != nil:
+ elemId := wire.SliceT.Elem
+- elemOp := dec.decIgnoreOpFor(elemId, inProgress)
++ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
+ op = func(i *decInstr, state *decoderState, value reflect.Value) {
+ state.dec.ignoreSlice(state, *elemOp)
+ }
+@@ -1073,7 +1078,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de
+ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine {
+ engine := new(decEngine)
+ engine.instr = make([]decInstr, 1) // one item
+- op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp))
++ op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp), 0)
+ ovfl := overflow(dec.typeString(remoteId))
+ engine.instr[0] = decInstr{*op, 0, nil, ovfl}
+ engine.numInstr = 1
+@@ -1118,7 +1123,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
+ localField, present := srt.FieldByName(wireField.Name)
+ // TODO(r): anonymous names
+ if !present || !isExported(wireField.Name) {
+- op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp))
++ op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp), 0)
+ engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl}
+ continue
+ }
+diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go
+index 6d2c8db..1b52ecc 100644
+--- a/src/encoding/gob/gobencdec_test.go
++++ b/src/encoding/gob/gobencdec_test.go
+@@ -12,6 +12,7 @@ import (
+ "fmt"
+ "io"
+ "net"
++ "reflect"
+ "strings"
+ "testing"
+ "time"
+@@ -796,3 +797,26 @@ func TestNetIP(t *testing.T) {
+ t.Errorf("decoded to %v, want 1.2.3.4", ip.String())
+ }
+ }
++
++func TestIngoreDepthLimit(t *testing.T) {
++ // We don't test the actual depth limit because it requires building an
++ // extremely large message, which takes quite a while.
++ oldNestingDepth := maxIgnoreNestingDepth
++ maxIgnoreNestingDepth = 100
++ defer func() { maxIgnoreNestingDepth = oldNestingDepth }()
++ b := new(bytes.Buffer)
++ enc := NewEncoder(b)
++ typ := reflect.TypeOf(int(0))
++ nested := reflect.ArrayOf(1, typ)
++ for i := 0; i < 100; i++ {
++ nested = reflect.ArrayOf(1, nested)
++ }
++ badStruct := reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}}))
++ enc.Encode(badStruct.Interface())
++ dec := NewDecoder(b)
++ var output struct{ Hello int }
++ expectedErr := "invalid nesting depth"
++ if err := dec.Decode(&output); err == nil || err.Error() != expectedErr {
++ t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err)
++ }
++}
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-32148.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-32148.patch
new file mode 100644
index 0000000000..aab98e99fd
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-32148.patch
@@ -0,0 +1,49 @@
+From 0fe3adec199e8cd2c101933f75d8cd617de70350 Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Fri, 26 Aug 2022 12:48:13 +0530
+Subject: [PATCH] CVE-2022-32148
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/ed2f33e1a7e0d18f61bd56f7ee067331d612c27e]
+CVE: CVE-2022-32148
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/net/http/header.go | 6 ++++++
+ src/net/http/header_test.go | 5 +++++
+ 2 files changed, 11 insertions(+)
+
+diff --git a/src/net/http/header.go b/src/net/http/header.go
+index b9b5391..221f613 100644
+--- a/src/net/http/header.go
++++ b/src/net/http/header.go
+@@ -100,6 +100,12 @@ func (h Header) Clone() Header {
+ sv := make([]string, nv) // shared backing array for headers' values
+ h2 := make(Header, len(h))
+ for k, vv := range h {
++ if vv == nil {
++ // Preserve nil values. ReverseProxy distinguishes
++ // between nil and zero-length header values.
++ h2[k] = nil
++ continue
++ }
+ n := copy(sv, vv)
+ h2[k] = sv[:n:n]
+ sv = sv[n:]
+diff --git a/src/net/http/header_test.go b/src/net/http/header_test.go
+index 4789362..80c0035 100644
+--- a/src/net/http/header_test.go
++++ b/src/net/http/header_test.go
+@@ -235,6 +235,11 @@ func TestCloneOrMakeHeader(t *testing.T) {
+ in: Header{"foo": {"bar"}},
+ want: Header{"foo": {"bar"}},
+ },
++ {
++ name: "nil value",
++ in: Header{"foo": nil},
++ want: Header{"foo": nil},
++ },
+ }
+
+ for _, tt := range tests {
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-32189.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-32189.patch
new file mode 100644
index 0000000000..15fda7de1b
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-32189.patch
@@ -0,0 +1,113 @@
+From 027e7e1578d3d7614f7586eff3894b83d9709e14 Mon Sep 17 00:00:00 2001
+From: Hitendra Prajapati <hprajapati@mvista.com>
+Date: Mon, 29 Aug 2022 10:08:34 +0530
+Subject: [PATCH] CVE-2022-32189
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/703c8ab7e5ba75c95553d4e249309297abad7102]
+CVE: CVE-2022-32189
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/math/big/floatmarsh.go | 7 +++++++
+ src/math/big/floatmarsh_test.go | 12 ++++++++++++
+ src/math/big/ratmarsh.go | 6 ++++++
+ src/math/big/ratmarsh_test.go | 12 ++++++++++++
+ 4 files changed, 37 insertions(+)
+
+diff --git a/src/math/big/floatmarsh.go b/src/math/big/floatmarsh.go
+index d1c1dab..990e085 100644
+--- a/src/math/big/floatmarsh.go
++++ b/src/math/big/floatmarsh.go
+@@ -8,6 +8,7 @@ package big
+
+ import (
+ "encoding/binary"
++ "errors"
+ "fmt"
+ )
+
+@@ -67,6 +68,9 @@ func (z *Float) GobDecode(buf []byte) error {
+ *z = Float{}
+ return nil
+ }
++ if len(buf) < 6 {
++ return errors.New("Float.GobDecode: buffer too small")
++ }
+
+ if buf[0] != floatGobVersion {
+ return fmt.Errorf("Float.GobDecode: encoding version %d not supported", buf[0])
+@@ -83,6 +87,9 @@ func (z *Float) GobDecode(buf []byte) error {
+ z.prec = binary.BigEndian.Uint32(buf[2:])
+
+ if z.form == finite {
++ if len(buf) < 10 {
++ return errors.New("Float.GobDecode: buffer too small for finite form float")
++ }
+ z.exp = int32(binary.BigEndian.Uint32(buf[6:]))
+ z.mant = z.mant.setBytes(buf[10:])
+ }
+diff --git a/src/math/big/floatmarsh_test.go b/src/math/big/floatmarsh_test.go
+index c056d78..401f45a 100644
+--- a/src/math/big/floatmarsh_test.go
++++ b/src/math/big/floatmarsh_test.go
+@@ -137,3 +137,15 @@ func TestFloatJSONEncoding(t *testing.T) {
+ }
+ }
+ }
++
++func TestFloatGobDecodeShortBuffer(t *testing.T) {
++ for _, tc := range [][]byte{
++ []byte{0x1, 0x0, 0x0, 0x0},
++ []byte{0x1, 0xfa, 0x0, 0x0, 0x0, 0x0},
++ } {
++ err := NewFloat(0).GobDecode(tc)
++ if err == nil {
++ t.Error("expected GobDecode to return error for malformed input")
++ }
++ }
++}
+diff --git a/src/math/big/ratmarsh.go b/src/math/big/ratmarsh.go
+index fbc7b60..56102e8 100644
+--- a/src/math/big/ratmarsh.go
++++ b/src/math/big/ratmarsh.go
+@@ -45,12 +45,18 @@ func (z *Rat) GobDecode(buf []byte) error {
+ *z = Rat{}
+ return nil
+ }
++ if len(buf) < 5 {
++ return errors.New("Rat.GobDecode: buffer too small")
++ }
+ b := buf[0]
+ if b>>1 != ratGobVersion {
+ return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
+ }
+ const j = 1 + 4
+ i := j + binary.BigEndian.Uint32(buf[j-4:j])
++ if len(buf) < int(i) {
++ return errors.New("Rat.GobDecode: buffer too small")
++ }
+ z.a.neg = b&1 != 0
+ z.a.abs = z.a.abs.setBytes(buf[j:i])
+ z.b.abs = z.b.abs.setBytes(buf[i:])
+diff --git a/src/math/big/ratmarsh_test.go b/src/math/big/ratmarsh_test.go
+index 351d109..55a9878 100644
+--- a/src/math/big/ratmarsh_test.go
++++ b/src/math/big/ratmarsh_test.go
+@@ -123,3 +123,15 @@ func TestRatXMLEncoding(t *testing.T) {
+ }
+ }
+ }
++
++func TestRatGobDecodeShortBuffer(t *testing.T) {
++ for _, tc := range [][]byte{
++ []byte{0x2},
++ []byte{0x2, 0x0, 0x0, 0x0, 0xff},
++ } {
++ err := NewRat(1, 2).GobDecode(tc)
++ if err == nil {
++ t.Error("expected GobDecode to return error for malformed input")
++ }
++ }
++}
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-41715.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-41715.patch
new file mode 100644
index 0000000000..fac0ebe94c
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-41715.patch
@@ -0,0 +1,271 @@
+From e9017c2416ad0ef642f5e0c2eab2dbf3cba4d997 Mon Sep 17 00:00:00 2001
+From: Russ Cox <rsc@golang.org>
+Date: Wed, 28 Sep 2022 11:18:51 -0400
+Subject: [PATCH] [release-branch.go1.18] regexp: limit size of parsed regexps
+
+Set a 128 MB limit on the amount of space used by []syntax.Inst
+in the compiled form corresponding to a given regexp.
+
+Also set a 128 MB limit on the rune storage in the *syntax.Regexp
+tree itself.
+
+Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting this issue.
+
+Fixes CVE-2022-41715.
+Updates #55949.
+Fixes #55950.
+
+Change-Id: Ia656baed81564436368cf950e1c5409752f28e1b
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1592136
+TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/438501
+Run-TryBot: Carlos Amedee <carlos@golang.org>
+Reviewed-by: Carlos Amedee <carlos@golang.org>
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/e9017c2416ad0ef642f5e0c2eab2dbf3cba4d997]
+CVE: CVE-2022-41715
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+
+---
+ src/regexp/syntax/parse.go | 145 ++++++++++++++++++++++++++++++--
+ src/regexp/syntax/parse_test.go | 13 +--
+ 2 files changed, 148 insertions(+), 10 deletions(-)
+
+diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go
+index 55bd20d..60491d5 100644
+--- a/src/regexp/syntax/parse.go
++++ b/src/regexp/syntax/parse.go
+@@ -90,15 +90,49 @@ const (
+ // until we've allocated at least maxHeight Regexp structures.
+ const maxHeight = 1000
+
++// maxSize is the maximum size of a compiled regexp in Insts.
++// It too is somewhat arbitrarily chosen, but the idea is to be large enough
++// to allow significant regexps while at the same time small enough that
++// the compiled form will not take up too much memory.
++// 128 MB is enough for a 3.3 million Inst structures, which roughly
++// corresponds to a 3.3 MB regexp.
++const (
++ maxSize = 128 << 20 / instSize
++ instSize = 5 * 8 // byte, 2 uint32, slice is 5 64-bit words
++)
++
++// maxRunes is the maximum number of runes allowed in a regexp tree
++// counting the runes in all the nodes.
++// Ignoring character classes p.numRunes is always less than the length of the regexp.
++// Character classes can make it much larger: each \pL adds 1292 runes.
++// 128 MB is enough for 32M runes, which is over 26k \pL instances.
++// Note that repetitions do not make copies of the rune slices,
++// so \pL{1000} is only one rune slice, not 1000.
++// We could keep a cache of character classes we've seen,
++// so that all the \pL we see use the same rune list,
++// but that doesn't remove the problem entirely:
++// consider something like [\pL01234][\pL01235][\pL01236]...[\pL^&*()].
++// And because the Rune slice is exposed directly in the Regexp,
++// there is not an opportunity to change the representation to allow
++// partial sharing between different character classes.
++// So the limit is the best we can do.
++const (
++ maxRunes = 128 << 20 / runeSize
++ runeSize = 4 // rune is int32
++)
++
+ type parser struct {
+ flags Flags // parse mode flags
+ stack []*Regexp // stack of parsed expressions
+ free *Regexp
+ numCap int // number of capturing groups seen
+ wholeRegexp string
+- tmpClass []rune // temporary char class work space
+- numRegexp int // number of regexps allocated
+- height map[*Regexp]int // regexp height for height limit check
++ tmpClass []rune // temporary char class work space
++ numRegexp int // number of regexps allocated
++ numRunes int // number of runes in char classes
++ repeats int64 // product of all repetitions seen
++ height map[*Regexp]int // regexp height, for height limit check
++ size map[*Regexp]int64 // regexp compiled size, for size limit check
+ }
+
+ func (p *parser) newRegexp(op Op) *Regexp {
+@@ -122,6 +156,104 @@ func (p *parser) reuse(re *Regexp) {
+ p.free = re
+ }
+
++func (p *parser) checkLimits(re *Regexp) {
++ if p.numRunes > maxRunes {
++ panic(ErrInternalError)
++ }
++ p.checkSize(re)
++ p.checkHeight(re)
++}
++
++func (p *parser) checkSize(re *Regexp) {
++ if p.size == nil {
++ // We haven't started tracking size yet.
++ // Do a relatively cheap check to see if we need to start.
++ // Maintain the product of all the repeats we've seen
++ // and don't track if the total number of regexp nodes
++ // we've seen times the repeat product is in budget.
++ if p.repeats == 0 {
++ p.repeats = 1
++ }
++ if re.Op == OpRepeat {
++ n := re.Max
++ if n == -1 {
++ n = re.Min
++ }
++ if n <= 0 {
++ n = 1
++ }
++ if int64(n) > maxSize/p.repeats {
++ p.repeats = maxSize
++ } else {
++ p.repeats *= int64(n)
++ }
++ }
++ if int64(p.numRegexp) < maxSize/p.repeats {
++ return
++ }
++
++ // We need to start tracking size.
++ // Make the map and belatedly populate it
++ // with info about everything we've constructed so far.
++ p.size = make(map[*Regexp]int64)
++ for _, re := range p.stack {
++ p.checkSize(re)
++ }
++ }
++
++ if p.calcSize(re, true) > maxSize {
++ panic(ErrInternalError)
++ }
++}
++
++func (p *parser) calcSize(re *Regexp, force bool) int64 {
++ if !force {
++ if size, ok := p.size[re]; ok {
++ return size
++ }
++ }
++
++ var size int64
++ switch re.Op {
++ case OpLiteral:
++ size = int64(len(re.Rune))
++ case OpCapture, OpStar:
++ // star can be 1+ or 2+; assume 2 pessimistically
++ size = 2 + p.calcSize(re.Sub[0], false)
++ case OpPlus, OpQuest:
++ size = 1 + p.calcSize(re.Sub[0], false)
++ case OpConcat:
++ for _, sub := range re.Sub {
++ size += p.calcSize(sub, false)
++ }
++ case OpAlternate:
++ for _, sub := range re.Sub {
++ size += p.calcSize(sub, false)
++ }
++ if len(re.Sub) > 1 {
++ size += int64(len(re.Sub)) - 1
++ }
++ case OpRepeat:
++ sub := p.calcSize(re.Sub[0], false)
++ if re.Max == -1 {
++ if re.Min == 0 {
++ size = 2 + sub // x*
++ } else {
++ size = 1 + int64(re.Min)*sub // xxx+
++ }
++ break
++ }
++ // x{2,5} = xx(x(x(x)?)?)?
++ size = int64(re.Max)*sub + int64(re.Max-re.Min)
++ }
++
++ if size < 1 {
++ size = 1
++ }
++ p.size[re] = size
++ return size
++}
++
+ func (p *parser) checkHeight(re *Regexp) {
+ if p.numRegexp < maxHeight {
+ return
+@@ -158,6 +290,7 @@ func (p *parser) calcHeight(re *Regexp, force bool) int {
+
+ // push pushes the regexp re onto the parse stack and returns the regexp.
+ func (p *parser) push(re *Regexp) *Regexp {
++ p.numRunes += len(re.Rune)
+ if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] {
+ // Single rune.
+ if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) {
+@@ -189,7 +322,7 @@ func (p *parser) push(re *Regexp) *Regexp {
+ }
+
+ p.stack = append(p.stack, re)
+- p.checkHeight(re)
++ p.checkLimits(re)
+ return re
+ }
+
+@@ -305,7 +438,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (
+ re.Sub = re.Sub0[:1]
+ re.Sub[0] = sub
+ p.stack[n-1] = re
+- p.checkHeight(re)
++ p.checkLimits(re)
+
+ if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
+ return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
+@@ -509,6 +642,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp {
+
+ for j := start; j < i; j++ {
+ sub[j] = p.removeLeadingString(sub[j], len(str))
++ p.checkLimits(sub[j])
+ }
+ suffix := p.collapse(sub[start:i], OpAlternate) // recurse
+
+@@ -566,6 +700,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp {
+ for j := start; j < i; j++ {
+ reuse := j != start // prefix came from sub[start]
+ sub[j] = p.removeLeadingRegexp(sub[j], reuse)
++ p.checkLimits(sub[j])
+ }
+ suffix := p.collapse(sub[start:i], OpAlternate) // recurse
+
+diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go
+index 1ef6d8a..67e3c56 100644
+--- a/src/regexp/syntax/parse_test.go
++++ b/src/regexp/syntax/parse_test.go
+@@ -484,12 +484,15 @@ var invalidRegexps = []string{
+ `(?P<>a)`,
+ `[a-Z]`,
+ `(?i)[a-Z]`,
+- `a{100000}`,
+- `a{100000,}`,
+- "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
+- strings.Repeat("(", 1000) + strings.Repeat(")", 1000),
+- strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000),
+ `\Q\E*`,
++ `a{100000}`, // too much repetition
++ `a{100000,}`, // too much repetition
++ "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", // too much repetition
++ strings.Repeat("(", 1000) + strings.Repeat(")", 1000), // too deep
++ strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000), // too deep
++ "(" + strings.Repeat("(xx?)", 1000) + "){1000}", // too long
++ strings.Repeat("(xx?){1000}", 1000), // too long
++ strings.Repeat(`\pL`, 27000), // too many runes
+ }
+
+ var onlyPerl = []string{
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-41717.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-41717.patch
new file mode 100644
index 0000000000..8bf22ee4d4
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-41717.patch
@@ -0,0 +1,75 @@
+From 618120c165669c00a1606505defea6ca755cdc27 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Wed, 30 Nov 2022 16:46:33 -0500
+Subject: [PATCH] [release-branch.go1.19] net/http: update bundled
+ golang.org/x/net/http2
+
+Disable cmd/internal/moddeps test, since this update includes PRIVATE
+track fixes.
+
+For #56350.
+For #57009.
+Fixes CVE-2022-41717.
+
+Change-Id: I5c6ce546add81f361dcf0d5123fa4eaaf8f0a03b
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1663835
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/455363
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Run-TryBot: Jenny Rakoczy <jenny@golang.org>
+Reviewed-by: Michael Pratt <mpratt@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/618120c165669c00a1606505defea6ca755cdc27]
+CVE-2022-41717
+Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
+---
+ src/net/http/h2_bundle.go | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
+index 83f2a72..cc03a62 100644
+--- a/src/net/http/h2_bundle.go
++++ b/src/net/http/h2_bundle.go
+@@ -4096,6 +4096,7 @@ type http2serverConn struct {
+ headerTableSize uint32
+ peerMaxHeaderListSize uint32 // zero means unknown (default)
+ canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
++ canonHeaderKeysSize int // canonHeader keys size in bytes
+ writingFrame bool // started writing a frame (on serve goroutine or separate)
+ writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
+ needsFrameFlush bool // last frame write wasn't a flush
+@@ -4278,6 +4279,13 @@ func (sc *http2serverConn) condlogf(err error, format string, args ...interface{
+ }
+ }
+
++// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size
++// of the entries in the canonHeader cache.
++// This should be larger than the size of unique, uncommon header keys likely to
++// be sent by the peer, while not so high as to permit unreasonable memory usage
++// if the peer sends an unbounded number of unique header keys.
++const http2maxCachedCanonicalHeadersKeysSize = 2048
++
+ func (sc *http2serverConn) canonicalHeader(v string) string {
+ sc.serveG.check()
+ http2buildCommonHeaderMapsOnce()
+@@ -4293,14 +4301,10 @@ func (sc *http2serverConn) canonicalHeader(v string) string {
+ sc.canonHeader = make(map[string]string)
+ }
+ cv = CanonicalHeaderKey(v)
+- // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
+- // entries in the canonHeader cache. This should be larger than the number
+- // of unique, uncommon header keys likely to be sent by the peer, while not
+- // so high as to permit unreaasonable memory usage if the peer sends an unbounded
+- // number of unique header keys.
+- const maxCachedCanonicalHeaders = 32
+- if len(sc.canonHeader) < maxCachedCanonicalHeaders {
++ size := 100 + len(v)*2 // 100 bytes of map overhead + key + value
++ if sc.canonHeaderKeysSize+size <= http2maxCachedCanonicalHeadersKeysSize {
+ sc.canonHeader[v] = cv
++ sc.canonHeaderKeysSize += size
+ }
+ return cv
+ }
+--
+2.30.2
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-41722-1.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-41722-1.patch
new file mode 100644
index 0000000000..f5bffd7a0b
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-41722-1.patch
@@ -0,0 +1,53 @@
+From 94e0c36694fb044e81381d112fef3692de7cdf52 Mon Sep 17 00:00:00 2001
+From: Yasuhiro Matsumoto <mattn.jp@gmail.com>
+Date: Fri, 22 Apr 2022 10:07:51 +0900
+Subject: [PATCH 1/2] path/filepath: do not remove prefix "." when following
+ path contains ":".
+
+Fixes #52476
+
+Change-Id: I9eb72ac7dbccd6322d060291f31831dc389eb9bb
+Reviewed-on: https://go-review.googlesource.com/c/go/+/401595
+Auto-Submit: Ian Lance Taylor <iant@google.com>
+Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
+Run-TryBot: Ian Lance Taylor <iant@google.com>
+Reviewed-by: Ian Lance Taylor <iant@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+
+Upstream-Status: Backport from https://github.com/golang/go/commit/9cd1818a7d019c02fa4898b3e45a323e35033290
+CVE: CVE-2022-41722
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/path/filepath/path.go | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go
+index 26f1833..92dc090 100644
+--- a/src/path/filepath/path.go
++++ b/src/path/filepath/path.go
+@@ -116,9 +116,21 @@ func Clean(path string) string {
+ case os.IsPathSeparator(path[r]):
+ // empty path element
+ r++
+- case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
++ case path[r] == '.' && r+1 == n:
+ // . element
+ r++
++ case path[r] == '.' && os.IsPathSeparator(path[r+1]):
++ // ./ element
++ r++
++
++ for r < len(path) && os.IsPathSeparator(path[r]) {
++ r++
++ }
++ if out.w == 0 && volumeNameLen(path[r:]) > 0 {
++ // When joining prefix "." and an absolute path on Windows,
++ // the prefix should not be removed.
++ out.append('.')
++ }
+ case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
+ // .. element: remove to last separator
+ r += 2
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-41722-2.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-41722-2.patch
new file mode 100644
index 0000000000..e1f7a55581
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-41722-2.patch
@@ -0,0 +1,104 @@
+From b8803cb711ae163b8e67897deb6cf8c49702227c Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Mon, 12 Dec 2022 16:43:37 -0800
+Subject: [PATCH 2/2] path/filepath: do not Clean("a/../c:/b") into c:\b on
+ Windows
+
+Do not permit Clean to convert a relative path into one starting
+with a drive reference. This change causes Clean to insert a .
+path element at the start of a path when the original path does not
+start with a volume name, and the first path element would contain
+a colon.
+
+This may introduce a spurious but harmless . path element under
+some circumstances. For example, Clean("a/../b:/../c") becomes `.\c`.
+
+This reverts CL 401595, since the change here supersedes the one
+in that CL.
+
+Thanks to RyotaK (https://twitter.com/ryotkak) for reporting this issue.
+
+Updates #57274
+Fixes #57276
+Fixes CVE-2022-41722
+
+Change-Id: I837446285a03aa74c79d7642720e01f354c2ca17
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1675249
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Run-TryBot: Damien Neil <dneil@google.com>
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
+(cherry picked from commit 8ca37f4813ef2f64600c92b83f17c9f3ca6c03a5)
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1728944
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/468119
+Reviewed-by: Than McIntosh <thanm@google.com>
+Run-TryBot: Michael Pratt <mpratt@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Auto-Submit: Michael Pratt <mpratt@google.com>
+
+Upstream-Status: Backport from https://github.com/golang/go/commit/bdf07c2e168baf736e4c057279ca12a4d674f18c
+CVE: CVE-2022-41722
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/path/filepath/path.go | 27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go
+index 92dc090..f0f095e 100644
+--- a/src/path/filepath/path.go
++++ b/src/path/filepath/path.go
+@@ -14,6 +14,7 @@ package filepath
+ import (
+ "errors"
+ "os"
++ "runtime"
+ "sort"
+ "strings"
+ )
+@@ -116,21 +117,9 @@ func Clean(path string) string {
+ case os.IsPathSeparator(path[r]):
+ // empty path element
+ r++
+- case path[r] == '.' && r+1 == n:
++ case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
+ // . element
+ r++
+- case path[r] == '.' && os.IsPathSeparator(path[r+1]):
+- // ./ element
+- r++
+-
+- for r < len(path) && os.IsPathSeparator(path[r]) {
+- r++
+- }
+- if out.w == 0 && volumeNameLen(path[r:]) > 0 {
+- // When joining prefix "." and an absolute path on Windows,
+- // the prefix should not be removed.
+- out.append('.')
+- }
+ case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
+ // .. element: remove to last separator
+ r += 2
+@@ -156,6 +145,18 @@ func Clean(path string) string {
+ if rooted && out.w != 1 || !rooted && out.w != 0 {
+ out.append(Separator)
+ }
++ // If a ':' appears in the path element at the start of a Windows path,
++ // insert a .\ at the beginning to avoid converting relative paths
++ // like a/../c: into c:.
++ if runtime.GOOS == "windows" && out.w == 0 && out.volLen == 0 && r != 0 {
++ for i := r; i < n && !os.IsPathSeparator(path[i]); i++ {
++ if path[i] == ':' {
++ out.append('.')
++ out.append(Separator)
++ break
++ }
++ }
++ }
+ // copy element
+ for ; r < n && !os.IsPathSeparator(path[r]); r++ {
+ out.append(path[r])
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-41723.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-41723.patch
new file mode 100644
index 0000000000..a93fa31dcd
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-41723.patch
@@ -0,0 +1,156 @@
+From 451766789f646617157c725e20c955d4a9a70d4e Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Mon, 6 Feb 2023 10:03:44 -0800
+Subject: [PATCH] net/http: update bundled golang.org/x/net/http2
+
+Disable cmd/internal/moddeps test, since this update includes PRIVATE
+track fixes.
+
+Fixes CVE-2022-41723
+Fixes #58355
+Updates #57855
+
+Change-Id: Ie870562a6f6e44e4e8f57db6a0dde1a41a2b090c
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1728939
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/468118
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Run-TryBot: Michael Pratt <mpratt@google.com>
+Auto-Submit: Michael Pratt <mpratt@google.com>
+Reviewed-by: Than McIntosh <thanm@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/5c3e11bd0b5c0a86e5beffcd4339b86a902b21c3]
+CVE: CVE-2022-41723
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/vendor/golang.org/x/net/http2/hpack/hpack.go | 79 +++++++++++++++---------
+ 1 file changed, 49 insertions(+), 30 deletions(-)
+
+diff --git a/src/vendor/golang.org/x/net/http2/hpack/hpack.go b/src/vendor/golang.org/x/net/http2/hpack/hpack.go
+index 85f18a2..02e80e3 100644
+--- a/src/vendor/golang.org/x/net/http2/hpack/hpack.go
++++ b/src/vendor/golang.org/x/net/http2/hpack/hpack.go
+@@ -359,6 +359,7 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
+
+ var hf HeaderField
+ wantStr := d.emitEnabled || it.indexed()
++ var undecodedName undecodedString
+ if nameIdx > 0 {
+ ihf, ok := d.at(nameIdx)
+ if !ok {
+@@ -366,15 +367,27 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
+ }
+ hf.Name = ihf.Name
+ } else {
+- hf.Name, buf, err = d.readString(buf, wantStr)
++ undecodedName, buf, err = d.readString(buf)
+ if err != nil {
+ return err
+ }
+ }
+- hf.Value, buf, err = d.readString(buf, wantStr)
++ undecodedValue, buf, err := d.readString(buf)
+ if err != nil {
+ return err
+ }
++ if wantStr {
++ if nameIdx <= 0 {
++ hf.Name, err = d.decodeString(undecodedName)
++ if err != nil {
++ return err
++ }
++ }
++ hf.Value, err = d.decodeString(undecodedValue)
++ if err != nil {
++ return err
++ }
++ }
+ d.buf = buf
+ if it.indexed() {
+ d.dynTab.add(hf)
+@@ -459,46 +472,52 @@ func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
+ return 0, origP, errNeedMore
+ }
+
+-// readString decodes an hpack string from p.
++// readString reads an hpack string from p.
+ //
+-// wantStr is whether s will be used. If false, decompression and
+-// []byte->string garbage are skipped if s will be ignored
+-// anyway. This does mean that huffman decoding errors for non-indexed
+-// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
+-// is returning an error anyway, and because they're not indexed, the error
+-// won't affect the decoding state.
+-func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
++// It returns a reference to the encoded string data to permit deferring decode costs
++// until after the caller verifies all data is present.
++func (d *Decoder) readString(p []byte) (u undecodedString, remain []byte, err error) {
+ if len(p) == 0 {
+- return "", p, errNeedMore
++ return u, p, errNeedMore
+ }
+ isHuff := p[0]&128 != 0
+ strLen, p, err := readVarInt(7, p)
+ if err != nil {
+- return "", p, err
++ return u, p, err
+ }
+ if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
+- return "", nil, ErrStringLength
++ // Returning an error here means Huffman decoding errors
++ // for non-indexed strings past the maximum string length
++ // are ignored, but the server is returning an error anyway
++ // and because the string is not indexed the error will not
++ // affect the decoding state.
++ return u, nil, ErrStringLength
+ }
+ if uint64(len(p)) < strLen {
+- return "", p, errNeedMore
+- }
+- if !isHuff {
+- if wantStr {
+- s = string(p[:strLen])
+- }
+- return s, p[strLen:], nil
++ return u, p, errNeedMore
+ }
++ u.isHuff = isHuff
++ u.b = p[:strLen]
++ return u, p[strLen:], nil
++}
+
+- if wantStr {
+- buf := bufPool.Get().(*bytes.Buffer)
+- buf.Reset() // don't trust others
+- defer bufPool.Put(buf)
+- if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
+- buf.Reset()
+- return "", nil, err
+- }
++type undecodedString struct {
++ isHuff bool
++ b []byte
++}
++
++func (d *Decoder) decodeString(u undecodedString) (string, error) {
++ if !u.isHuff {
++ return string(u.b), nil
++ }
++ buf := bufPool.Get().(*bytes.Buffer)
++ buf.Reset() // don't trust others
++ var s string
++ err := huffmanDecode(buf, d.maxStrLen, u.b)
++ if err == nil {
+ s = buf.String()
+- buf.Reset() // be nice to GC
+ }
+- return s, p[strLen:], nil
++ buf.Reset() // be nice to GC
++ bufPool.Put(buf)
++ return s, err
+ }
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre1.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre1.patch
new file mode 100644
index 0000000000..37ebc41947
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre1.patch
@@ -0,0 +1,85 @@
+From 874b3132a84cf76da6a48978826c04c380a37a50 Mon Sep 17 00:00:00 2001
+From: avivklas <avivklas@gmail.com>
+Date: Fri, 7 Aug 2020 21:50:12 +0300
+Subject: [PATCH] mime/multipart: return overflow errors in Reader.ReadForm
+
+Updates Reader.ReadForm to check for overflow errors that may
+result from a leeway addition of 10MiB to the input argument
+maxMemory.
+
+Fixes #40430
+
+Change-Id: I510b8966c95c51d04695ba9d08fcfe005fd11a5d
+Reviewed-on: https://go-review.googlesource.com/c/go/+/247477
+Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
+Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
+Trust: Emmanuel Odeke <emm.odeke@gmail.com>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/874b3132a84cf76da6a48978826c04c380a37a50]
+CVE: CVE-2022-41725 #Dependency Patch1
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/mime/multipart/formdata.go | 4 ++++
+ src/mime/multipart/formdata_test.go | 18 ++++++++++++++++++
+ 2 files changed, 22 insertions(+)
+
+diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
+index 832d0ad693666..4eb31012941ac 100644
+--- a/src/mime/multipart/formdata.go
++++ b/src/mime/multipart/formdata.go
+@@ -7,6 +7,7 @@ package multipart
+ import (
+ "bytes"
+ "errors"
++ "fmt"
+ "io"
+ "io/ioutil"
+ "net/textproto"
+@@ -41,6 +42,9 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+
+ // Reserve an additional 10 MB for non-file parts.
+ maxValueBytes := maxMemory + int64(10<<20)
++ if maxValueBytes <= 0 {
++ return nil, fmt.Errorf("multipart: integer overflow from maxMemory(%d) + 10MiB for non-file parts", maxMemory)
++ }
+ for {
+ p, err := r.NextPart()
+ if err == io.EOF {
+diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
+index 7d756c8c244a0..7112e0d3727fe 100644
+--- a/src/mime/multipart/formdata_test.go
++++ b/src/mime/multipart/formdata_test.go
+@@ -7,6 +7,7 @@ package multipart
+ import (
+ "bytes"
+ "io"
++ "math"
+ "os"
+ "strings"
+ "testing"
+@@ -52,6 +53,23 @@ func TestReadFormWithNamelessFile(t *testing.T) {
+ }
+ }
+
++// Issue 40430: Ensure that we report integer overflows in additions of maxMemory,
++// instead of silently and subtly failing without indication.
++func TestReadFormMaxMemoryOverflow(t *testing.T) {
++ b := strings.NewReader(strings.ReplaceAll(messageWithTextContentType, "\n", "\r\n"))
++ r := NewReader(b, boundary)
++ f, err := r.ReadForm(math.MaxInt64)
++ if err == nil {
++ t.Fatal("Unexpected a non-nil error")
++ }
++ if f != nil {
++ t.Fatalf("Unexpected returned a non-nil form: %v\n", f)
++ }
++ if g, w := err.Error(), "integer overflow from maxMemory"; !strings.Contains(g, w) {
++ t.Errorf(`Error mismatch\n%q\ndid not contain\n%q`, g, w)
++ }
++}
++
+ func TestReadFormWithTextContentType(t *testing.T) {
+ // From https://github.com/golang/go/issues/24041
+ b := strings.NewReader(strings.ReplaceAll(messageWithTextContentType, "\n", "\r\n"))
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre2.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre2.patch
new file mode 100644
index 0000000000..b951ee893e
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre2.patch
@@ -0,0 +1,97 @@
+From 4e5a313524da62600eb59dbf98624cfe946456f8 Mon Sep 17 00:00:00 2001
+From: Emmanuel T Odeke <emmanuel@orijtech.com>
+Date: Tue, 20 Oct 2020 04:11:12 -0700
+Subject: [PATCH] net/http: test that ParseMultipartForm catches overflows
+
+Tests that if the combination of:
+* HTTP multipart file payload size
+* ParseMultipartForm's maxMemory parameter
+* the internal leeway buffer size of 10MiB
+
+overflows, then we'll report an overflow instead of silently
+passing.
+
+Reapplies and fixes CL 254977, which was reverted in CL 263658.
+
+The prior test lacked a res.Body.Close(), so fixed that and
+added a leaked Transport check to verify correctness.
+
+Updates 40430.
+
+Change-Id: I3c0f7ef43d621f6eb00f07755f04f9f36c51f98f
+Reviewed-on: https://go-review.googlesource.com/c/go/+/263817
+Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Bryan C. Mills <bcmills@google.com>
+Trust: Damien Neil <dneil@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/4e5a313524da62600eb59dbf98624cfe946456f8]
+CVE: CVE-2022-41725 #Dependency Patch2
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/net/http/request_test.go | 45 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 45 insertions(+)
+
+diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
+index b4ef472e71229..19526b9ad791a 100644
+--- a/src/net/http/request_test.go
++++ b/src/net/http/request_test.go
+@@ -13,6 +13,7 @@ import (
+ "fmt"
+ "io"
+ "io/ioutil"
++ "math"
+ "mime/multipart"
+ . "net/http"
+ "net/http/httptest"
+@@ -245,6 +246,50 @@ func TestParseMultipartForm(t *testing.T) {
+ }
+ }
+
++// Issue #40430: Test that if maxMemory for ParseMultipartForm when combined with
++// the payload size and the internal leeway buffer size of 10MiB overflows, that we
++// correctly return an error.
++func TestMaxInt64ForMultipartFormMaxMemoryOverflow(t *testing.T) {
++ defer afterTest(t)
++
++ payloadSize := 1 << 10
++ cst := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
++ // The combination of:
++ // MaxInt64 + payloadSize + (internal spare of 10MiB)
++ // triggers the overflow. See issue https://golang.org/issue/40430/
++ if err := req.ParseMultipartForm(math.MaxInt64); err != nil {
++ Error(rw, err.Error(), StatusBadRequest)
++ return
++ }
++ }))
++ defer cst.Close()
++ fBuf := new(bytes.Buffer)
++ mw := multipart.NewWriter(fBuf)
++ mf, err := mw.CreateFormFile("file", "myfile.txt")
++ if err != nil {
++ t.Fatal(err)
++ }
++ if _, err := mf.Write(bytes.Repeat([]byte("abc"), payloadSize)); err != nil {
++ t.Fatal(err)
++ }
++ if err := mw.Close(); err != nil {
++ t.Fatal(err)
++ }
++ req, err := NewRequest("POST", cst.URL, fBuf)
++ if err != nil {
++ t.Fatal(err)
++ }
++ req.Header.Set("Content-Type", mw.FormDataContentType())
++ res, err := cst.Client().Do(req)
++ if err != nil {
++ t.Fatal(err)
++ }
++ res.Body.Close()
++ if g, w := res.StatusCode, StatusBadRequest; g != w {
++ t.Fatalf("Status code mismatch: got %d, want %d", g, w)
++ }
++}
++
+ func TestRedirect_h1(t *testing.T) { testRedirect(t, h1Mode) }
+ func TestRedirect_h2(t *testing.T) { testRedirect(t, h2Mode) }
+ func testRedirect(t *testing.T, h2 bool) {
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre3.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre3.patch
new file mode 100644
index 0000000000..767225b888
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-41725-pre3.patch
@@ -0,0 +1,98 @@
+From 5246fa5e75b129a7dbd9722aa4de0cbaf7ceae43 Mon Sep 17 00:00:00 2001
+From: Russ Cox <rsc@golang.org>
+Date: Thu, 3 Dec 2020 09:45:07 -0500
+Subject: [PATCH] mime/multipart: handle ReadForm(math.MaxInt64) better
+
+Returning an error about integer overflow is needlessly pedantic.
+The meaning of ReadForm(MaxInt64) is easily understood
+(accept a lot of data) and can be implemented.
+
+Fixes #40430.
+
+Change-Id: I8a522033dd9a2f9ad31dd2ad82cf08d553736ab9
+Reviewed-on: https://go-review.googlesource.com/c/go/+/275112
+Trust: Russ Cox <rsc@golang.org>
+Run-TryBot: Russ Cox <rsc@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Ian Lance Taylor <iant@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/5246fa5e75b129a7dbd9722aa4de0cbaf7ceae43]
+CVE: CVE-2022-41725 #Dependency Patch3
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/mime/multipart/formdata.go | 8 ++++++--
+ src/mime/multipart/formdata_test.go | 14 +++++---------
+ src/net/http/request_test.go | 2 +-
+ 3 files changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
+index 4eb31012941ac..9c42ea8c023b5 100644
+--- a/src/mime/multipart/formdata.go
++++ b/src/mime/multipart/formdata.go
+@@ -7,9 +7,9 @@ package multipart
+ import (
+ "bytes"
+ "errors"
+- "fmt"
+ "io"
+ "io/ioutil"
++ "math"
+ "net/textproto"
+ "os"
+ )
+@@ -43,7 +43,11 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ // Reserve an additional 10 MB for non-file parts.
+ maxValueBytes := maxMemory + int64(10<<20)
+ if maxValueBytes <= 0 {
+- return nil, fmt.Errorf("multipart: integer overflow from maxMemory(%d) + 10MiB for non-file parts", maxMemory)
++ if maxMemory < 0 {
++ maxValueBytes = 0
++ } else {
++ maxValueBytes = math.MaxInt64
++ }
+ }
+ for {
+ p, err := r.NextPart()
+diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
+index 7112e0d3727fe..e3a3a3eae8e15 100644
+--- a/src/mime/multipart/formdata_test.go
++++ b/src/mime/multipart/formdata_test.go
+@@ -53,20 +53,16 @@ func TestReadFormWithNamelessFile(t *testing.T) {
+ }
+ }
+
+-// Issue 40430: Ensure that we report integer overflows in additions of maxMemory,
+-// instead of silently and subtly failing without indication.
++// Issue 40430: Handle ReadForm(math.MaxInt64)
+ func TestReadFormMaxMemoryOverflow(t *testing.T) {
+ b := strings.NewReader(strings.ReplaceAll(messageWithTextContentType, "\n", "\r\n"))
+ r := NewReader(b, boundary)
+ f, err := r.ReadForm(math.MaxInt64)
+- if err == nil {
+- t.Fatal("Unexpected a non-nil error")
+- }
+- if f != nil {
+- t.Fatalf("Unexpected returned a non-nil form: %v\n", f)
++ if err != nil {
++ t.Fatalf("ReadForm(MaxInt64): %v", err)
+ }
+- if g, w := err.Error(), "integer overflow from maxMemory"; !strings.Contains(g, w) {
+- t.Errorf(`Error mismatch\n%q\ndid not contain\n%q`, g, w)
++ if f == nil {
++ t.Fatal("ReadForm(MaxInt64): missing form")
+ }
+ }
+
+diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
+index 19526b9ad791a..689498e19d5dd 100644
+--- a/src/net/http/request_test.go
++++ b/src/net/http/request_test.go
+@@ -285,7 +285,7 @@ func TestMaxInt64ForMultipartFormMaxMemoryOverflow(t *testing.T) {
+ t.Fatal(err)
+ }
+ res.Body.Close()
+- if g, w := res.StatusCode, StatusBadRequest; g != w {
++ if g, w := res.StatusCode, StatusOK; g != w {
+ t.Fatalf("Status code mismatch: got %d, want %d", g, w)
+ }
+ }
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2022-41725.patch b/meta/recipes-devtools/go/go-1.14/CVE-2022-41725.patch
new file mode 100644
index 0000000000..5f80c62b0b
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2022-41725.patch
@@ -0,0 +1,660 @@
+From 5c55ac9bf1e5f779220294c843526536605f42ab Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Wed, 25 Jan 2023 09:27:01 -0800
+Subject: [PATCH] [release-branch.go1.19] mime/multipart: limit memory/inode consumption of ReadForm
+
+Reader.ReadForm is documented as storing "up to maxMemory bytes + 10MB"
+in memory. Parsed forms can consume substantially more memory than
+this limit, since ReadForm does not account for map entry overhead
+and MIME headers.
+
+In addition, while the amount of disk memory consumed by ReadForm can
+be constrained by limiting the size of the parsed input, ReadForm will
+create one temporary file per form part stored on disk, potentially
+consuming a large number of inodes.
+
+Update ReadForm's memory accounting to include part names,
+MIME headers, and map entry overhead.
+
+Update ReadForm to store all on-disk file parts in a single
+temporary file.
+
+Files returned by FileHeader.Open are documented as having a concrete
+type of *os.File when a file is stored on disk. The change to use a
+single temporary file for all parts means that this is no longer the
+case when a form contains more than a single file part stored on disk.
+
+The previous behavior of storing each file part in a separate disk
+file may be reenabled with GODEBUG=multipartfiles=distinct.
+
+Update Reader.NextPart and Reader.NextRawPart to set a 10MiB cap
+on the size of MIME headers.
+
+Thanks to Jakob Ackermann (@das7pad) for reporting this issue.
+
+Updates #58006
+Fixes #58362
+Fixes CVE-2022-41725
+
+Change-Id: Ibd780a6c4c83ac8bcfd3cbe344f042e9940f2eab
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1714276
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Run-TryBot: Damien Neil <dneil@google.com>
+(cherry picked from commit ed4664330edcd91b24914c9371c377c132dbce8c)
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1728949
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/468116
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Than McIntosh <thanm@google.com>
+Run-TryBot: Michael Pratt <mpratt@google.com>
+Auto-Submit: Michael Pratt <mpratt@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/5c55ac9bf1e5f779220294c843526536605f42ab]
+CVE: CVE-2022-41725
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/mime/multipart/formdata.go | 132 ++++++++++++++++++++-----
+ src/mime/multipart/formdata_test.go | 140 ++++++++++++++++++++++++++-
+ src/mime/multipart/multipart.go | 25 +++--
+ src/mime/multipart/readmimeheader.go | 14 +++
+ src/net/http/request_test.go | 2 +-
+ src/net/textproto/reader.go | 27 ++++++
+ 6 files changed, 303 insertions(+), 37 deletions(-)
+ create mode 100644 src/mime/multipart/readmimeheader.go
+
+diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
+index 9c42ea8..1eeb340 100644
+--- a/src/mime/multipart/formdata.go
++++ b/src/mime/multipart/formdata.go
+@@ -7,6 +7,7 @@ package multipart
+ import (
+ "bytes"
+ "errors"
++ "internal/godebug"
+ "io"
+ "io/ioutil"
+ "math"
+@@ -34,23 +35,58 @@ func (r *Reader) ReadForm(maxMemory int64) (*Form, error) {
+
+ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
++ var (
++ file *os.File
++ fileOff int64
++ )
++ numDiskFiles := 0
++ multipartFiles := godebug.Get("multipartfiles")
++ combineFiles := multipartFiles != "distinct"
+ defer func() {
++ if file != nil {
++ if cerr := file.Close(); err == nil {
++ err = cerr
++ }
++ }
++ if combineFiles && numDiskFiles > 1 {
++ for _, fhs := range form.File {
++ for _, fh := range fhs {
++ fh.tmpshared = true
++ }
++ }
++ }
+ if err != nil {
+ form.RemoveAll()
++ if file != nil {
++ os.Remove(file.Name())
++ }
+ }
+ }()
+
+- // Reserve an additional 10 MB for non-file parts.
+- maxValueBytes := maxMemory + int64(10<<20)
+- if maxValueBytes <= 0 {
++ // maxFileMemoryBytes is the maximum bytes of file data we will store in memory.
++ // Data past this limit is written to disk.
++ // This limit strictly applies to content, not metadata (filenames, MIME headers, etc.),
++ // since metadata is always stored in memory, not disk.
++ //
++ // maxMemoryBytes is the maximum bytes we will store in memory, including file content,
++ // non-file part values, metdata, and map entry overhead.
++ //
++ // We reserve an additional 10 MB in maxMemoryBytes for non-file data.
++ //
++ // The relationship between these parameters, as well as the overly-large and
++ // unconfigurable 10 MB added on to maxMemory, is unfortunate but difficult to change
++ // within the constraints of the API as documented.
++ maxFileMemoryBytes := maxMemory
++ maxMemoryBytes := maxMemory + int64(10<<20)
++ if maxMemoryBytes <= 0 {
+ if maxMemory < 0 {
+- maxValueBytes = 0
++ maxMemoryBytes = 0
+ } else {
+- maxValueBytes = math.MaxInt64
++ maxMemoryBytes = math.MaxInt64
+ }
+ }
+ for {
+- p, err := r.NextPart()
++ p, err := r.nextPart(false, maxMemoryBytes)
+ if err == io.EOF {
+ break
+ }
+@@ -64,16 +100,27 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ }
+ filename := p.FileName()
+
++ // Multiple values for the same key (one map entry, longer slice) are cheaper
++ // than the same number of values for different keys (many map entries), but
++ // using a consistent per-value cost for overhead is simpler.
++ maxMemoryBytes -= int64(len(name))
++ maxMemoryBytes -= 100 // map overhead
++ if maxMemoryBytes < 0 {
++ // We can't actually take this path, since nextPart would already have
++ // rejected the MIME headers for being too large. Check anyway.
++ return nil, ErrMessageTooLarge
++ }
++
+ var b bytes.Buffer
+
+ if filename == "" {
+ // value, store as string in memory
+- n, err := io.CopyN(&b, p, maxValueBytes+1)
++ n, err := io.CopyN(&b, p, maxMemoryBytes+1)
+ if err != nil && err != io.EOF {
+ return nil, err
+ }
+- maxValueBytes -= n
+- if maxValueBytes < 0 {
++ maxMemoryBytes -= n
++ if maxMemoryBytes < 0 {
+ return nil, ErrMessageTooLarge
+ }
+ form.Value[name] = append(form.Value[name], b.String())
+@@ -81,35 +128,45 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ }
+
+ // file, store in memory or on disk
++ maxMemoryBytes -= mimeHeaderSize(p.Header)
++ if maxMemoryBytes < 0 {
++ return nil, ErrMessageTooLarge
++ }
+ fh := &FileHeader{
+ Filename: filename,
+ Header: p.Header,
+ }
+- n, err := io.CopyN(&b, p, maxMemory+1)
++ n, err := io.CopyN(&b, p, maxFileMemoryBytes+1)
+ if err != nil && err != io.EOF {
+ return nil, err
+ }
+- if n > maxMemory {
+- // too big, write to disk and flush buffer
+- file, err := ioutil.TempFile("", "multipart-")
+- if err != nil {
+- return nil, err
++ if n > maxFileMemoryBytes {
++ if file == nil {
++ file, err = ioutil.TempFile(r.tempDir, "multipart-")
++ if err != nil {
++ return nil, err
++ }
+ }
++ numDiskFiles++
+ size, err := io.Copy(file, io.MultiReader(&b, p))
+- if cerr := file.Close(); err == nil {
+- err = cerr
+- }
+ if err != nil {
+- os.Remove(file.Name())
+ return nil, err
+ }
+ fh.tmpfile = file.Name()
+ fh.Size = size
++ fh.tmpoff = fileOff
++ fileOff += size
++ if !combineFiles {
++ if err := file.Close(); err != nil {
++ return nil, err
++ }
++ file = nil
++ }
+ } else {
+ fh.content = b.Bytes()
+ fh.Size = int64(len(fh.content))
+- maxMemory -= n
+- maxValueBytes -= n
++ maxFileMemoryBytes -= n
++ maxMemoryBytes -= n
+ }
+ form.File[name] = append(form.File[name], fh)
+ }
+@@ -117,6 +174,17 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ return form, nil
+ }
+
++func mimeHeaderSize(h textproto.MIMEHeader) (size int64) {
++ for k, vs := range h {
++ size += int64(len(k))
++ size += 100 // map entry overhead
++ for _, v := range vs {
++ size += int64(len(v))
++ }
++ }
++ return size
++}
++
+ // Form is a parsed multipart form.
+ // Its File parts are stored either in memory or on disk,
+ // and are accessible via the *FileHeader's Open method.
+@@ -134,7 +202,7 @@ func (f *Form) RemoveAll() error {
+ for _, fh := range fhs {
+ if fh.tmpfile != "" {
+ e := os.Remove(fh.tmpfile)
+- if e != nil && err == nil {
++ if e != nil && !errors.Is(e, os.ErrNotExist) && err == nil {
+ err = e
+ }
+ }
+@@ -149,15 +217,25 @@ type FileHeader struct {
+ Header textproto.MIMEHeader
+ Size int64
+
+- content []byte
+- tmpfile string
++ content []byte
++ tmpfile string
++ tmpoff int64
++ tmpshared bool
+ }
+
+ // Open opens and returns the FileHeader's associated File.
+ func (fh *FileHeader) Open() (File, error) {
+ if b := fh.content; b != nil {
+ r := io.NewSectionReader(bytes.NewReader(b), 0, int64(len(b)))
+- return sectionReadCloser{r}, nil
++ return sectionReadCloser{r, nil}, nil
++ }
++ if fh.tmpshared {
++ f, err := os.Open(fh.tmpfile)
++ if err != nil {
++ return nil, err
++ }
++ r := io.NewSectionReader(f, fh.tmpoff, fh.Size)
++ return sectionReadCloser{r, f}, nil
+ }
+ return os.Open(fh.tmpfile)
+ }
+@@ -176,8 +254,12 @@ type File interface {
+
+ type sectionReadCloser struct {
+ *io.SectionReader
++ io.Closer
+ }
+
+ func (rc sectionReadCloser) Close() error {
++ if rc.Closer != nil {
++ return rc.Closer.Close()
++ }
+ return nil
+ }
+diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
+index e3a3a3e..5cded71 100644
+--- a/src/mime/multipart/formdata_test.go
++++ b/src/mime/multipart/formdata_test.go
+@@ -6,8 +6,10 @@ package multipart
+
+ import (
+ "bytes"
++ "fmt"
+ "io"
+ "math"
++ "net/textproto"
+ "os"
+ "strings"
+ "testing"
+@@ -208,8 +210,8 @@ Content-Disposition: form-data; name="largetext"
+ maxMemory int64
+ err error
+ }{
+- {"smaller", 50, nil},
+- {"exact-fit", 25, nil},
++ {"smaller", 50 + int64(len("largetext")) + 100, nil},
++ {"exact-fit", 25 + int64(len("largetext")) + 100, nil},
+ {"too-large", 0, ErrMessageTooLarge},
+ }
+ for _, tc := range testCases {
+@@ -224,7 +226,7 @@ Content-Disposition: form-data; name="largetext"
+ defer f.RemoveAll()
+ }
+ if tc.err != err {
+- t.Fatalf("ReadForm error - got: %v; expected: %v", tc.err, err)
++ t.Fatalf("ReadForm error - got: %v; expected: %v", err, tc.err)
+ }
+ if err == nil {
+ if g := f.Value["largetext"][0]; g != largeTextValue {
+@@ -234,3 +236,135 @@ Content-Disposition: form-data; name="largetext"
+ })
+ }
+ }
++
++// TestReadForm_MetadataTooLarge verifies that we account for the size of field names,
++// MIME headers, and map entry overhead while limiting the memory consumption of parsed forms.
++func TestReadForm_MetadataTooLarge(t *testing.T) {
++ for _, test := range []struct {
++ name string
++ f func(*Writer)
++ }{{
++ name: "large name",
++ f: func(fw *Writer) {
++ name := strings.Repeat("a", 10<<20)
++ w, _ := fw.CreateFormField(name)
++ w.Write([]byte("value"))
++ },
++ }, {
++ name: "large MIME header",
++ f: func(fw *Writer) {
++ h := make(textproto.MIMEHeader)
++ h.Set("Content-Disposition", `form-data; name="a"`)
++ h.Set("X-Foo", strings.Repeat("a", 10<<20))
++ w, _ := fw.CreatePart(h)
++ w.Write([]byte("value"))
++ },
++ }, {
++ name: "many parts",
++ f: func(fw *Writer) {
++ for i := 0; i < 110000; i++ {
++ w, _ := fw.CreateFormField("f")
++ w.Write([]byte("v"))
++ }
++ },
++ }} {
++ t.Run(test.name, func(t *testing.T) {
++ var buf bytes.Buffer
++ fw := NewWriter(&buf)
++ test.f(fw)
++ if err := fw.Close(); err != nil {
++ t.Fatal(err)
++ }
++ fr := NewReader(&buf, fw.Boundary())
++ _, err := fr.ReadForm(0)
++ if err != ErrMessageTooLarge {
++ t.Errorf("fr.ReadForm() = %v, want ErrMessageTooLarge", err)
++ }
++ })
++ }
++}
++
++// TestReadForm_ManyFiles_Combined tests that a multipart form containing many files only
++// results in a single on-disk file.
++func TestReadForm_ManyFiles_Combined(t *testing.T) {
++ const distinct = false
++ testReadFormManyFiles(t, distinct)
++}
++
++// TestReadForm_ManyFiles_Distinct tests that setting GODEBUG=multipartfiles=distinct
++// results in every file in a multipart form being placed in a distinct on-disk file.
++func TestReadForm_ManyFiles_Distinct(t *testing.T) {
++ t.Setenv("GODEBUG", "multipartfiles=distinct")
++ const distinct = true
++ testReadFormManyFiles(t, distinct)
++}
++
++func testReadFormManyFiles(t *testing.T, distinct bool) {
++ var buf bytes.Buffer
++ fw := NewWriter(&buf)
++ const numFiles = 10
++ for i := 0; i < numFiles; i++ {
++ name := fmt.Sprint(i)
++ w, err := fw.CreateFormFile(name, name)
++ if err != nil {
++ t.Fatal(err)
++ }
++ w.Write([]byte(name))
++ }
++ if err := fw.Close(); err != nil {
++ t.Fatal(err)
++ }
++ fr := NewReader(&buf, fw.Boundary())
++ fr.tempDir = t.TempDir()
++ form, err := fr.ReadForm(0)
++ if err != nil {
++ t.Fatal(err)
++ }
++ for i := 0; i < numFiles; i++ {
++ name := fmt.Sprint(i)
++ if got := len(form.File[name]); got != 1 {
++ t.Fatalf("form.File[%q] has %v entries, want 1", name, got)
++ }
++ fh := form.File[name][0]
++ file, err := fh.Open()
++ if err != nil {
++ t.Fatalf("form.File[%q].Open() = %v", name, err)
++ }
++ if distinct {
++ if _, ok := file.(*os.File); !ok {
++ t.Fatalf("form.File[%q].Open: %T, want *os.File", name, file)
++ }
++ }
++ got, err := io.ReadAll(file)
++ file.Close()
++ if string(got) != name || err != nil {
++ t.Fatalf("read form.File[%q]: %q, %v; want %q, nil", name, string(got), err, name)
++ }
++ }
++ dir, err := os.Open(fr.tempDir)
++ if err != nil {
++ t.Fatal(err)
++ }
++ defer dir.Close()
++ names, err := dir.Readdirnames(0)
++ if err != nil {
++ t.Fatal(err)
++ }
++ wantNames := 1
++ if distinct {
++ wantNames = numFiles
++ }
++ if len(names) != wantNames {
++ t.Fatalf("temp dir contains %v files; want 1", len(names))
++ }
++ if err := form.RemoveAll(); err != nil {
++ t.Fatalf("form.RemoveAll() = %v", err)
++ }
++ names, err = dir.Readdirnames(0)
++ if err != nil {
++ t.Fatal(err)
++ }
++ if len(names) != 0 {
++ t.Fatalf("temp dir contains %v files; want 0", len(names))
++ }
++}
+diff --git a/src/mime/multipart/multipart.go b/src/mime/multipart/multipart.go
+index 1750300..958cef8 100644
+--- a/src/mime/multipart/multipart.go
++++ b/src/mime/multipart/multipart.go
+@@ -121,12 +121,12 @@ func (r *stickyErrorReader) Read(p []byte) (n int, _ error) {
+ return n, r.err
+ }
+
+-func newPart(mr *Reader, rawPart bool) (*Part, error) {
++func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
+ bp := &Part{
+ Header: make(map[string][]string),
+ mr: mr,
+ }
+- if err := bp.populateHeaders(); err != nil {
++ if err := bp.populateHeaders(maxMIMEHeaderSize); err != nil {
+ return nil, err
+ }
+ bp.r = partReader{bp}
+@@ -142,12 +142,16 @@ func newPart(mr *Reader, rawPart bool) (*Part, error) {
+ return bp, nil
+ }
+
+-func (bp *Part) populateHeaders() error {
++func (bp *Part) populateHeaders(maxMIMEHeaderSize int64) error {
+ r := textproto.NewReader(bp.mr.bufReader)
+- header, err := r.ReadMIMEHeader()
++ header, err := readMIMEHeader(r, maxMIMEHeaderSize)
+ if err == nil {
+ bp.Header = header
+ }
++ // TODO: Add a distinguishable error to net/textproto.
++ if err != nil && err.Error() == "message too large" {
++ err = ErrMessageTooLarge
++ }
+ return err
+ }
+
+@@ -287,6 +291,7 @@ func (p *Part) Close() error {
+ // isn't supported.
+ type Reader struct {
+ bufReader *bufio.Reader
++ tempDir string // used in tests
+
+ currentPart *Part
+ partsRead int
+@@ -297,6 +302,10 @@ type Reader struct {
+ dashBoundary []byte // "--boundary"
+ }
+
++// maxMIMEHeaderSize is the maximum size of a MIME header we will parse,
++// including header keys, values, and map overhead.
++const maxMIMEHeaderSize = 10 << 20
++
+ // NextPart returns the next part in the multipart or an error.
+ // When there are no more parts, the error io.EOF is returned.
+ //
+@@ -304,7 +313,7 @@ type Reader struct {
+ // has a value of "quoted-printable", that header is instead
+ // hidden and the body is transparently decoded during Read calls.
+ func (r *Reader) NextPart() (*Part, error) {
+- return r.nextPart(false)
++ return r.nextPart(false, maxMIMEHeaderSize)
+ }
+
+ // NextRawPart returns the next part in the multipart or an error.
+@@ -313,10 +322,10 @@ func (r *Reader) NextPart() (*Part, error) {
+ // Unlike NextPart, it does not have special handling for
+ // "Content-Transfer-Encoding: quoted-printable".
+ func (r *Reader) NextRawPart() (*Part, error) {
+- return r.nextPart(true)
++ return r.nextPart(true, maxMIMEHeaderSize)
+ }
+
+-func (r *Reader) nextPart(rawPart bool) (*Part, error) {
++func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
+ if r.currentPart != nil {
+ r.currentPart.Close()
+ }
+@@ -341,7 +350,7 @@ func (r *Reader) nextPart(rawPart bool) (*Part, error) {
+
+ if r.isBoundaryDelimiterLine(line) {
+ r.partsRead++
+- bp, err := newPart(r, rawPart)
++ bp, err := newPart(r, rawPart, maxMIMEHeaderSize)
+ if err != nil {
+ return nil, err
+ }
+diff --git a/src/mime/multipart/readmimeheader.go b/src/mime/multipart/readmimeheader.go
+new file mode 100644
+index 0000000..6836928
+--- /dev/null
++++ b/src/mime/multipart/readmimeheader.go
+@@ -0,0 +1,14 @@
++// Copyright 2023 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++package multipart
++
++import (
++ "net/textproto"
++ _ "unsafe" // for go:linkname
++)
++
++// readMIMEHeader is defined in package net/textproto.
++//
++//go:linkname readMIMEHeader net/textproto.readMIMEHeader
++func readMIMEHeader(r *textproto.Reader, lim int64) (textproto.MIMEHeader, error)
+diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
+index 94133ee..170d3f5 100644
+--- a/src/net/http/request_test.go
++++ b/src/net/http/request_test.go
+@@ -962,7 +962,7 @@ func testMissingFile(t *testing.T, req *Request) {
+ t.Errorf("FormFile file = %v, want nil", f)
+ }
+ if fh != nil {
+- t.Errorf("FormFile file header = %q, want nil", fh)
++ t.Errorf("FormFile file header = %v, want nil", fh)
+ }
+ if err != ErrMissingFile {
+ t.Errorf("FormFile err = %q, want ErrMissingFile", err)
+diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
+index f63f5ec..96553fb 100644
+--- a/src/net/textproto/reader.go
++++ b/src/net/textproto/reader.go
+@@ -7,9 +7,11 @@ package textproto
+ import (
+ "bufio"
+ "bytes"
++ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
++ "math"
+ "strconv"
+ "strings"
+ "sync"
+@@ -482,6 +484,12 @@ func (r *Reader) ReadDotLines() ([]string, error) {
+ // }
+ //
+ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
++ return readMIMEHeader(r, math.MaxInt64)
++}
++
++// readMIMEHeader is a version of ReadMIMEHeader which takes a limit on the header size.
++// It is called by the mime/multipart package.
++func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
+ // Avoid lots of small slice allocations later by allocating one
+ // large one ahead of time which we'll cut up into smaller
+ // slices. If this isn't big enough later, we allocate small ones.
+@@ -525,6 +533,15 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
+ continue
+ }
+
++ // backport 5c55ac9bf1e5f779220294c843526536605f42ab
++ //
++ // value is computed as
++ // value := string(bytes.TrimLeft(v, " \t"))
++ //
++ // in the original patch from 1.19. This relies on
++ // 'v' which does not exist in 1.14. We leave the
++ // 1.14 method unchanged.
++
+ // Skip initial spaces in value.
+ i++ // skip colon
+ for i < len(kv) && (kv[i] == ' ' || kv[i] == '\t') {
+@@ -533,6 +550,16 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
+ value := string(kv[i:])
+
+ vv := m[key]
++ if vv == nil {
++ lim -= int64(len(key))
++ lim -= 100 // map entry overhead
++ }
++ lim -= int64(len(value))
++ if lim < 0 {
++ // TODO: This should be a distinguishable error (ErrMessageTooLarge)
++ // to allow mime/multipart to detect it.
++ return m, errors.New("message too large")
++ }
+ if vv == nil && len(strs) > 0 {
+ // More than likely this will be a single-element key.
+ // Most headers aren't multi-valued.
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24534.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24534.patch
new file mode 100644
index 0000000000..d50db04bed
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24534.patch
@@ -0,0 +1,200 @@
+From d6759e7a059f4208f07aa781402841d7ddaaef96 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Fri, 10 Mar 2023 14:21:05 -0800
+Subject: [PATCH] [release-branch.go1.19] net/textproto: avoid overpredicting
+ the number of MIME header keys
+
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802452
+Run-TryBot: Damien Neil <dneil@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+(cherry picked from commit f739f080a72fd5b06d35c8e244165159645e2ed6)
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802393
+Reviewed-by: Damien Neil <dneil@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Change-Id: I675451438d619a9130360c56daf529559004903f
+Reviewed-on: https://go-review.googlesource.com/c/go/+/481982
+Run-TryBot: Michael Knyszek <mknyszek@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Matthew Dempsky <mdempsky@google.com>
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/d6759e7a059f4208f07aa781402841d7ddaaef96]
+CVE: CVE-2023-24534
+Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
+---
+ src/bytes/bytes.go | 13 +++++++
+ src/net/textproto/reader.go | 31 +++++++++++------
+ src/net/textproto/reader_test.go | 59 ++++++++++++++++++++++++++++++++
+ 3 files changed, 92 insertions(+), 11 deletions(-)
+
+diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go
+index e872cc2..1f0d760 100644
+--- a/src/bytes/bytes.go
++++ b/src/bytes/bytes.go
+@@ -1078,6 +1078,19 @@ func Index(s, sep []byte) int {
+ return -1
+ }
+
++// Cut slices s around the first instance of sep,
++// returning the text before and after sep.
++// The found result reports whether sep appears in s.
++// If sep does not appear in s, cut returns s, nil, false.
++//
++// Cut returns slices of the original slice s, not copies.
++func Cut(s, sep []byte) (before, after []byte, found bool) {
++ if i := Index(s, sep); i >= 0 {
++ return s[:i], s[i+len(sep):], true
++ }
++ return s, nil, false
++}
++
+ func indexRabinKarp(s, sep []byte) int {
+ // Rabin-Karp search
+ hashsep, pow := hashStr(sep)
+diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
+index a505da9..8d547fe 100644
+--- a/src/net/textproto/reader.go
++++ b/src/net/textproto/reader.go
+@@ -486,8 +487,11 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
+ // large one ahead of time which we'll cut up into smaller
+ // slices. If this isn't big enough later, we allocate small ones.
+ var strs []string
+- hint := r.upcomingHeaderNewlines()
++ hint := r.upcomingHeaderKeys()
+ if hint > 0 {
++ if hint > 1000 {
++ hint = 1000 // set a cap to avoid overallocation
++ }
+ strs = make([]string, hint)
+ }
+
+@@ -562,9 +566,11 @@ func mustHaveFieldNameColon(line []byte) error {
+ return nil
+ }
+
+-// upcomingHeaderNewlines returns an approximation of the number of newlines
++var nl = []byte("\n")
++
++// upcomingHeaderKeys returns an approximation of the number of keys
+ // that will be in this header. If it gets confused, it returns 0.
+-func (r *Reader) upcomingHeaderNewlines() (n int) {
++func (r *Reader) upcomingHeaderKeys() (n int) {
+ // Try to determine the 'hint' size.
+ r.R.Peek(1) // force a buffer load if empty
+ s := r.R.Buffered()
+@@ -572,17 +578,20 @@ func (r *Reader) upcomingHeaderNewlines() (n int) {
+ return
+ }
+ peek, _ := r.R.Peek(s)
+- for len(peek) > 0 {
+- i := bytes.IndexByte(peek, '\n')
+- if i < 3 {
+- // Not present (-1) or found within the next few bytes,
+- // implying we're at the end ("\r\n\r\n" or "\n\n")
+- return
++ for len(peek) > 0 && n < 1000 {
++ var line []byte
++ line, peek, _ = bytes.Cut(peek, nl)
++ if len(line) == 0 || (len(line) == 1 && line[0] == '\r') {
++ // Blank line separating headers from the body.
++ break
++ }
++ if line[0] == ' ' || line[0] == '\t' {
++ // Folded continuation of the previous line.
++ continue
+ }
+ n++
+- peek = peek[i+1:]
+ }
+- return
++ return n
+ }
+
+ // CanonicalMIMEHeaderKey returns the canonical format of the
+diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
+index 3124d43..3ae0de1 100644
+--- a/src/net/textproto/reader_test.go
++++ b/src/net/textproto/reader_test.go
+@@ -9,6 +9,7 @@ import (
+ "bytes"
+ "io"
+ "reflect"
++ "runtime"
+ "strings"
+ "testing"
+ )
+@@ -127,6 +128,42 @@ func TestReadMIMEHeaderSingle(t *testing.T) {
+ }
+ }
+
++// TestReaderUpcomingHeaderKeys is testing an internal function, but it's very
++// difficult to test well via the external API.
++func TestReaderUpcomingHeaderKeys(t *testing.T) {
++ for _, test := range []struct {
++ input string
++ want int
++ }{{
++ input: "",
++ want: 0,
++ }, {
++ input: "A: v",
++ want: 1,
++ }, {
++ input: "A: v\r\nB: v\r\n",
++ want: 2,
++ }, {
++ input: "A: v\nB: v\n",
++ want: 2,
++ }, {
++ input: "A: v\r\n continued\r\n still continued\r\nB: v\r\n\r\n",
++ want: 2,
++ }, {
++ input: "A: v\r\n\r\nB: v\r\nC: v\r\n",
++ want: 1,
++ }, {
++ input: "A: v" + strings.Repeat("\n", 1000),
++ want: 1,
++ }} {
++ r := reader(test.input)
++ got := r.upcomingHeaderKeys()
++ if test.want != got {
++ t.Fatalf("upcomingHeaderKeys(%q): %v; want %v", test.input, got, test.want)
++ }
++ }
++}
++
+ func TestReadMIMEHeaderNoKey(t *testing.T) {
+ r := reader(": bar\ntest-1: 1\n\n")
+ m, err := r.ReadMIMEHeader()
+@@ -223,6 +260,28 @@ func TestReadMIMEHeaderTrimContinued(t *testing.T) {
+ }
+ }
+
++// Test that reading a header doesn't overallocate. Issue 58975.
++func TestReadMIMEHeaderAllocations(t *testing.T) {
++ var totalAlloc uint64
++ const count = 200
++ for i := 0; i < count; i++ {
++ r := reader("A: b\r\n\r\n" + strings.Repeat("\n", 4096))
++ var m1, m2 runtime.MemStats
++ runtime.ReadMemStats(&m1)
++ _, err := r.ReadMIMEHeader()
++ if err != nil {
++ t.Fatalf("ReadMIMEHeader: %v", err)
++ }
++ runtime.ReadMemStats(&m2)
++ totalAlloc += m2.TotalAlloc - m1.TotalAlloc
++ }
++ // 32k is large and we actually allocate substantially less,
++ // but prior to the fix for #58975 we allocated ~400k in this case.
++ if got, want := totalAlloc/count, uint64(32768); got > want {
++ t.Fatalf("ReadMIMEHeader allocated %v bytes, want < %v", got, want)
++ }
++}
++
+ type readResponseTest struct {
+ in string
+ inCode int
+--
+2.25.1
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24536_1.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24536_1.patch
new file mode 100644
index 0000000000..39e1304fbd
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24536_1.patch
@@ -0,0 +1,134 @@
+From ef41a4e2face45e580c5836eaebd51629fc23f15 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Thu, 16 Mar 2023 14:18:04 -0700
+Subject: [PATCH] [release-branch.go1.19] mime/multipart: avoid excessive copy
+ buffer allocations in ReadForm
+
+When copying form data to disk with io.Copy,
+allocate only one copy buffer and reuse it rather than
+creating two buffers per file (one from io.multiReader.WriteTo,
+and a second one from os.File.ReadFrom).
+
+Thanks to Jakob Ackermann (@das7pad) for reporting this issue.
+
+For CVE-2023-24536
+For #59153
+For #59269
+
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802453
+Run-TryBot: Damien Neil <dneil@google.com>
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802395
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Change-Id: Ie405470c92abffed3356913b37d813e982c96c8b
+Reviewed-on: https://go-review.googlesource.com/c/go/+/481983
+Run-TryBot: Michael Knyszek <mknyszek@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+Reviewed-by: Matthew Dempsky <mdempsky@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/ef41a4e2face45e580c5836eaebd51629fc23f15]
+CVE: CVE-2023-24536
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/mime/multipart/formdata.go | 15 +++++++--
+ src/mime/multipart/formdata_test.go | 49 +++++++++++++++++++++++++++++
+ 2 files changed, 61 insertions(+), 3 deletions(-)
+
+diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
+index a7d4ca97f0484..975dcb6b26db4 100644
+--- a/src/mime/multipart/formdata.go
++++ b/src/mime/multipart/formdata.go
+@@ -84,6 +84,7 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ maxMemoryBytes = math.MaxInt64
+ }
+ }
++ var copyBuf []byte
+ for {
+ p, err := r.nextPart(false, maxMemoryBytes)
+ if err == io.EOF {
+@@ -147,14 +148,22 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ }
+ }
+ numDiskFiles++
+- size, err := io.Copy(file, io.MultiReader(&b, p))
++ if _, err := file.Write(b.Bytes()); err != nil {
++ return nil, err
++ }
++ if copyBuf == nil {
++ copyBuf = make([]byte, 32*1024) // same buffer size as io.Copy uses
++ }
++ // os.File.ReadFrom will allocate its own copy buffer if we let io.Copy use it.
++ type writerOnly struct{ io.Writer }
++ remainingSize, err := io.CopyBuffer(writerOnly{file}, p, copyBuf)
+ if err != nil {
+ return nil, err
+ }
+ fh.tmpfile = file.Name()
+- fh.Size = size
++ fh.Size = int64(b.Len()) + remainingSize
+ fh.tmpoff = fileOff
+- fileOff += size
++ fileOff += fh.Size
+ if !combineFiles {
+ if err := file.Close(); err != nil {
+ return nil, err
+diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
+index 5cded7170c6b8..f5b56083b2377 100644
+--- a/src/mime/multipart/formdata_test.go
++++ b/src/mime/multipart/formdata_test.go
+@@ -368,3 +368,52 @@ func testReadFormManyFiles(t *testing.T, distinct bool) {
+ t.Fatalf("temp dir contains %v files; want 0", len(names))
+ }
+ }
++
++func BenchmarkReadForm(b *testing.B) {
++ for _, test := range []struct {
++ name string
++ form func(fw *Writer, count int)
++ }{{
++ name: "fields",
++ form: func(fw *Writer, count int) {
++ for i := 0; i < count; i++ {
++ w, _ := fw.CreateFormField(fmt.Sprintf("field%v", i))
++ fmt.Fprintf(w, "value %v", i)
++ }
++ },
++ }, {
++ name: "files",
++ form: func(fw *Writer, count int) {
++ for i := 0; i < count; i++ {
++ w, _ := fw.CreateFormFile(fmt.Sprintf("field%v", i), fmt.Sprintf("file%v", i))
++ fmt.Fprintf(w, "value %v", i)
++ }
++ },
++ }} {
++ b.Run(test.name, func(b *testing.B) {
++ for _, maxMemory := range []int64{
++ 0,
++ 1 << 20,
++ } {
++ var buf bytes.Buffer
++ fw := NewWriter(&buf)
++ test.form(fw, 10)
++ if err := fw.Close(); err != nil {
++ b.Fatal(err)
++ }
++ b.Run(fmt.Sprintf("maxMemory=%v", maxMemory), func(b *testing.B) {
++ b.ReportAllocs()
++ for i := 0; i < b.N; i++ {
++ fr := NewReader(bytes.NewReader(buf.Bytes()), fw.Boundary())
++ form, err := fr.ReadForm(maxMemory)
++ if err != nil {
++ b.Fatal(err)
++ }
++ form.RemoveAll()
++ }
++
++ })
++ }
++ })
++ }
++}
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24536_2.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24536_2.patch
new file mode 100644
index 0000000000..9ba5114c82
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24536_2.patch
@@ -0,0 +1,184 @@
+From 7a359a651c7ebdb29e0a1c03102fce793e9f58f0 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Thu, 16 Mar 2023 16:56:12 -0700
+Subject: [PATCH] [release-branch.go1.19] net/textproto, mime/multipart:
+ improve accounting of non-file data
+
+For requests containing large numbers of small parts,
+memory consumption of a parsed form could be about 250%
+over the estimated size.
+
+When considering the size of parsed forms, account for the size of
+FileHeader structs and increase the estimate of memory consumed by
+map entries.
+
+Thanks to Jakob Ackermann (@das7pad) for reporting this issue.
+
+For CVE-2023-24536
+For #59153
+For #59269
+
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802454
+Run-TryBot: Damien Neil <dneil@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802396
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Change-Id: I31bc50e9346b4eee6fbe51a18c3c57230cc066db
+Reviewed-on: https://go-review.googlesource.com/c/go/+/481984
+Reviewed-by: Matthew Dempsky <mdempsky@google.com>
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Run-TryBot: Michael Knyszek <mknyszek@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/7a359a651c7ebdb29e0a1c03102fce793e9f58f0]
+CVE: CVE-2023-24536
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/mime/multipart/formdata.go | 9 +++--
+ src/mime/multipart/formdata_test.go | 55 ++++++++++++-----------------
+ src/net/textproto/reader.go | 8 ++++-
+ 3 files changed, 37 insertions(+), 35 deletions(-)
+
+diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
+index 975dcb6b26db4..3f6ff697ca608 100644
+--- a/src/mime/multipart/formdata.go
++++ b/src/mime/multipart/formdata.go
+@@ -103,8 +103,9 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ // Multiple values for the same key (one map entry, longer slice) are cheaper
+ // than the same number of values for different keys (many map entries), but
+ // using a consistent per-value cost for overhead is simpler.
++ const mapEntryOverhead = 200
+ maxMemoryBytes -= int64(len(name))
+- maxMemoryBytes -= 100 // map overhead
++ maxMemoryBytes -= mapEntryOverhead
+ if maxMemoryBytes < 0 {
+ // We can't actually take this path, since nextPart would already have
+ // rejected the MIME headers for being too large. Check anyway.
+@@ -128,7 +129,10 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ }
+
+ // file, store in memory or on disk
++ const fileHeaderSize = 100
+ maxMemoryBytes -= mimeHeaderSize(p.Header)
++ maxMemoryBytes -= mapEntryOverhead
++ maxMemoryBytes -= fileHeaderSize
+ if maxMemoryBytes < 0 {
+ return nil, ErrMessageTooLarge
+ }
+@@ -183,9 +187,10 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ }
+
+ func mimeHeaderSize(h textproto.MIMEHeader) (size int64) {
++ size = 400
+ for k, vs := range h {
+ size += int64(len(k))
+- size += 100 // map entry overhead
++ size += 200 // map entry overhead
+ for _, v := range vs {
+ size += int64(len(v))
+ }
+diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
+index f5b56083b2377..8ed26e0c34081 100644
+--- a/src/mime/multipart/formdata_test.go
++++ b/src/mime/multipart/formdata_test.go
+@@ -192,10 +192,10 @@ func (r *failOnReadAfterErrorReader) Read(p []byte) (n int, err error) {
+ // TestReadForm_NonFileMaxMemory asserts that the ReadForm maxMemory limit is applied
+ // while processing non-file form data as well as file form data.
+ func TestReadForm_NonFileMaxMemory(t *testing.T) {
+- n := 10<<20 + 25
+ if testing.Short() {
+- n = 10<<10 + 25
++ t.Skip("skipping in -short mode")
+ }
++ n := 10 << 20
+ largeTextValue := strings.Repeat("1", n)
+ message := `--MyBoundary
+ Content-Disposition: form-data; name="largetext"
+@@ -203,38 +203,29 @@ Content-Disposition: form-data; name="largetext"
+ ` + largeTextValue + `
+ --MyBoundary--
+ `
+-
+ testBody := strings.ReplaceAll(message, "\n", "\r\n")
+- testCases := []struct {
+- name string
+- maxMemory int64
+- err error
+- }{
+- {"smaller", 50 + int64(len("largetext")) + 100, nil},
+- {"exact-fit", 25 + int64(len("largetext")) + 100, nil},
+- {"too-large", 0, ErrMessageTooLarge},
+- }
+- for _, tc := range testCases {
+- t.Run(tc.name, func(t *testing.T) {
+- if tc.maxMemory == 0 && testing.Short() {
+- t.Skip("skipping in -short mode")
+- }
+- b := strings.NewReader(testBody)
+- r := NewReader(b, boundary)
+- f, err := r.ReadForm(tc.maxMemory)
+- if err == nil {
+- defer f.RemoveAll()
+- }
+- if tc.err != err {
+- t.Fatalf("ReadForm error - got: %v; expected: %v", err, tc.err)
+- }
+- if err == nil {
+- if g := f.Value["largetext"][0]; g != largeTextValue {
+- t.Errorf("largetext mismatch: got size: %v, expected size: %v", len(g), len(largeTextValue))
+- }
+- }
+- })
++ // Try parsing the form with increasing maxMemory values.
++ // Changes in how we account for non-file form data may cause the exact point
++ // where we change from rejecting the form as too large to accepting it to vary,
++ // but we should see both successes and failures.
++ const failWhenMaxMemoryLessThan = 128
++ for maxMemory := int64(0); maxMemory < failWhenMaxMemoryLessThan*2; maxMemory += 16 {
++ b := strings.NewReader(testBody)
++ r := NewReader(b, boundary)
++ f, err := r.ReadForm(maxMemory)
++ if err != nil {
++ continue
++ }
++ if g := f.Value["largetext"][0]; g != largeTextValue {
++ t.Errorf("largetext mismatch: got size: %v, expected size: %v", len(g), len(largeTextValue))
++ }
++ f.RemoveAll()
++ if maxMemory < failWhenMaxMemoryLessThan {
++ t.Errorf("ReadForm(%v): no error, expect to hit memory limit when maxMemory < %v", maxMemory, failWhenMaxMemoryLessThan)
++ }
++ return
+ }
++ t.Errorf("ReadForm(x) failed for x < 1024, expect success")
+ }
+
+ // TestReadForm_MetadataTooLarge verifies that we account for the size of field names,
+diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
+index 9a21777df8be0..c1284fde25eb7 100644
+--- a/src/net/textproto/reader.go
++++ b/src/net/textproto/reader.go
+@@ -503,6 +503,12 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
+
+ m := make(MIMEHeader, hint)
+
++ // Account for 400 bytes of overhead for the MIMEHeader, plus 200 bytes per entry.
++ // Benchmarking map creation as of go1.20, a one-entry MIMEHeader is 416 bytes and large
++ // MIMEHeaders average about 200 bytes per entry.
++ lim -= 400
++ const mapEntryOverhead = 200
++
+ // The first line cannot start with a leading space.
+ if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
+ line, err := r.readLineSlice()
+@@ -538,7 +544,7 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
+ vv := m[key]
+ if vv == nil {
+ lim -= int64(len(key))
+- lim -= 100 // map entry overhead
++ lim -= mapEntryOverhead
+ }
+ lim -= int64(len(value))
+ if lim < 0 {
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24536_3.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24536_3.patch
new file mode 100644
index 0000000000..58c0a484ee
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24536_3.patch
@@ -0,0 +1,349 @@
+From 7917b5f31204528ea72e0629f0b7d52b35b27538 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Mon, 20 Mar 2023 10:43:19 -0700
+Subject: [PATCH] [release-branch.go1.19] mime/multipart: limit parsed mime message sizes
+
+The parsed forms of MIME headers and multipart forms can consume
+substantially more memory than the size of the input data.
+A malicious input containing a very large number of headers or
+form parts can cause excessively large memory allocations.
+
+Set limits on the size of MIME data:
+
+Reader.NextPart and Reader.NextRawPart limit the the number
+of headers in a part to 10000.
+
+Reader.ReadForm limits the total number of headers in all
+FileHeaders to 10000.
+
+Both of these limits may be set with with
+GODEBUG=multipartmaxheaders=<values>.
+
+Reader.ReadForm limits the number of parts in a form to 1000.
+This limit may be set with GODEBUG=multipartmaxparts=<value>.
+
+Thanks for Jakob Ackermann (@das7pad) for reporting this issue.
+
+For CVE-2023-24536
+For #59153
+For #59269
+
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802455
+Run-TryBot: Damien Neil <dneil@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1801087
+Reviewed-by: Damien Neil <dneil@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Change-Id: If134890d75f0d95c681d67234daf191ba08e6424
+Reviewed-on: https://go-review.googlesource.com/c/go/+/481985
+Run-TryBot: Michael Knyszek <mknyszek@google.com>
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Matthew Dempsky <mdempsky@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/7917b5f31204528ea72e0629f0b7d52b35b27538]
+CVE: CVE-2023-24536
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/mime/multipart/formdata.go | 19 ++++++++-
+ src/mime/multipart/formdata_test.go | 61 ++++++++++++++++++++++++++++
+ src/mime/multipart/multipart.go | 31 ++++++++++----
+ src/mime/multipart/readmimeheader.go | 2 +-
+ src/net/textproto/reader.go | 19 +++++----
+ 5 files changed, 115 insertions(+), 17 deletions(-)
+
+diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
+index 216cccb..0b508ae 100644
+--- a/src/mime/multipart/formdata.go
++++ b/src/mime/multipart/formdata.go
+@@ -13,6 +13,7 @@ import (
+ "math"
+ "net/textproto"
+ "os"
++ "strconv"
+ )
+
+ // ErrMessageTooLarge is returned by ReadForm if the message form
+@@ -42,6 +43,15 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ numDiskFiles := 0
+ multipartFiles := godebug.Get("multipartfiles")
+ combineFiles := multipartFiles != "distinct"
++ maxParts := 1000
++ multipartMaxParts := godebug.Get("multipartmaxparts")
++ if multipartMaxParts != "" {
++ if v, err := strconv.Atoi(multipartMaxParts); err == nil && v >= 0 {
++ maxParts = v
++ }
++ }
++ maxHeaders := maxMIMEHeaders()
++
+ defer func() {
+ if file != nil {
+ if cerr := file.Close(); err == nil {
+@@ -87,13 +97,17 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ }
+ var copyBuf []byte
+ for {
+- p, err := r.nextPart(false, maxMemoryBytes)
++ p, err := r.nextPart(false, maxMemoryBytes, maxHeaders)
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
++ if maxParts <= 0 {
++ return nil, ErrMessageTooLarge
++ }
++ maxParts--
+
+ name := p.FormName()
+ if name == "" {
+@@ -137,6 +151,9 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
+ if maxMemoryBytes < 0 {
+ return nil, ErrMessageTooLarge
+ }
++ for _, v := range p.Header {
++ maxHeaders -= int64(len(v))
++ }
+ fh := &FileHeader{
+ Filename: filename,
+ Header: p.Header,
+diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
+index 8ed26e0..c78eeb7 100644
+--- a/src/mime/multipart/formdata_test.go
++++ b/src/mime/multipart/formdata_test.go
+@@ -360,6 +360,67 @@ func testReadFormManyFiles(t *testing.T, distinct bool) {
+ }
+ }
+
++func TestReadFormLimits(t *testing.T) {
++ for _, test := range []struct {
++ values int
++ files int
++ extraKeysPerFile int
++ wantErr error
++ godebug string
++ }{
++ {values: 1000},
++ {values: 1001, wantErr: ErrMessageTooLarge},
++ {values: 500, files: 500},
++ {values: 501, files: 500, wantErr: ErrMessageTooLarge},
++ {files: 1000},
++ {files: 1001, wantErr: ErrMessageTooLarge},
++ {files: 1, extraKeysPerFile: 9998}, // plus Content-Disposition and Content-Type
++ {files: 1, extraKeysPerFile: 10000, wantErr: ErrMessageTooLarge},
++ {godebug: "multipartmaxparts=100", values: 100},
++ {godebug: "multipartmaxparts=100", values: 101, wantErr: ErrMessageTooLarge},
++ {godebug: "multipartmaxheaders=100", files: 2, extraKeysPerFile: 48},
++ {godebug: "multipartmaxheaders=100", files: 2, extraKeysPerFile: 50, wantErr: ErrMessageTooLarge},
++ } {
++ name := fmt.Sprintf("values=%v/files=%v/extraKeysPerFile=%v", test.values, test.files, test.extraKeysPerFile)
++ if test.godebug != "" {
++ name += fmt.Sprintf("/godebug=%v", test.godebug)
++ }
++ t.Run(name, func(t *testing.T) {
++ if test.godebug != "" {
++ t.Setenv("GODEBUG", test.godebug)
++ }
++ var buf bytes.Buffer
++ fw := NewWriter(&buf)
++ for i := 0; i < test.values; i++ {
++ w, _ := fw.CreateFormField(fmt.Sprintf("field%v", i))
++ fmt.Fprintf(w, "value %v", i)
++ }
++ for i := 0; i < test.files; i++ {
++ h := make(textproto.MIMEHeader)
++ h.Set("Content-Disposition",
++ fmt.Sprintf(`form-data; name="file%v"; filename="file%v"`, i, i))
++ h.Set("Content-Type", "application/octet-stream")
++ for j := 0; j < test.extraKeysPerFile; j++ {
++ h.Set(fmt.Sprintf("k%v", j), "v")
++ }
++ w, _ := fw.CreatePart(h)
++ fmt.Fprintf(w, "value %v", i)
++ }
++ if err := fw.Close(); err != nil {
++ t.Fatal(err)
++ }
++ fr := NewReader(bytes.NewReader(buf.Bytes()), fw.Boundary())
++ form, err := fr.ReadForm(1 << 10)
++ if err == nil {
++ defer form.RemoveAll()
++ }
++ if err != test.wantErr {
++ t.Errorf("ReadForm = %v, want %v", err, test.wantErr)
++ }
++ })
++ }
++}
++
+ func BenchmarkReadForm(b *testing.B) {
+ for _, test := range []struct {
+ name string
+diff --git a/src/mime/multipart/multipart.go b/src/mime/multipart/multipart.go
+index 958cef8..94464a8 100644
+--- a/src/mime/multipart/multipart.go
++++ b/src/mime/multipart/multipart.go
+@@ -16,11 +16,13 @@ import (
+ "bufio"
+ "bytes"
+ "fmt"
++ "internal/godebug"
+ "io"
+ "io/ioutil"
+ "mime"
+ "mime/quotedprintable"
+ "net/textproto"
++ "strconv"
+ "strings"
+ )
+
+@@ -121,12 +123,12 @@ func (r *stickyErrorReader) Read(p []byte) (n int, _ error) {
+ return n, r.err
+ }
+
+-func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
++func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders int64) (*Part, error) {
+ bp := &Part{
+ Header: make(map[string][]string),
+ mr: mr,
+ }
+- if err := bp.populateHeaders(maxMIMEHeaderSize); err != nil {
++ if err := bp.populateHeaders(maxMIMEHeaderSize, maxMIMEHeaders); err != nil {
+ return nil, err
+ }
+ bp.r = partReader{bp}
+@@ -142,9 +144,9 @@ func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
+ return bp, nil
+ }
+
+-func (bp *Part) populateHeaders(maxMIMEHeaderSize int64) error {
++func (bp *Part) populateHeaders(maxMIMEHeaderSize, maxMIMEHeaders int64) error {
+ r := textproto.NewReader(bp.mr.bufReader)
+- header, err := readMIMEHeader(r, maxMIMEHeaderSize)
++ header, err := readMIMEHeader(r, maxMIMEHeaderSize, maxMIMEHeaders)
+ if err == nil {
+ bp.Header = header
+ }
+@@ -306,6 +308,19 @@ type Reader struct {
+ // including header keys, values, and map overhead.
+ const maxMIMEHeaderSize = 10 << 20
+
++func maxMIMEHeaders() int64 {
++ // multipartMaxHeaders is the maximum number of header entries NextPart will return,
++ // as well as the maximum combined total of header entries Reader.ReadForm will return
++ // in FileHeaders.
++ multipartMaxHeaders := godebug.Get("multipartmaxheaders")
++ if multipartMaxHeaders != "" {
++ if v, err := strconv.ParseInt(multipartMaxHeaders, 10, 64); err == nil && v >= 0 {
++ return v
++ }
++ }
++ return 10000
++}
++
+ // NextPart returns the next part in the multipart or an error.
+ // When there are no more parts, the error io.EOF is returned.
+ //
+@@ -313,7 +328,7 @@ const maxMIMEHeaderSize = 10 << 20
+ // has a value of "quoted-printable", that header is instead
+ // hidden and the body is transparently decoded during Read calls.
+ func (r *Reader) NextPart() (*Part, error) {
+- return r.nextPart(false, maxMIMEHeaderSize)
++ return r.nextPart(false, maxMIMEHeaderSize, maxMIMEHeaders())
+ }
+
+ // NextRawPart returns the next part in the multipart or an error.
+@@ -322,10 +337,10 @@ func (r *Reader) NextPart() (*Part, error) {
+ // Unlike NextPart, it does not have special handling for
+ // "Content-Transfer-Encoding: quoted-printable".
+ func (r *Reader) NextRawPart() (*Part, error) {
+- return r.nextPart(true, maxMIMEHeaderSize)
++ return r.nextPart(true, maxMIMEHeaderSize, maxMIMEHeaders())
+ }
+
+-func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
++func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders int64) (*Part, error) {
+ if r.currentPart != nil {
+ r.currentPart.Close()
+ }
+@@ -350,7 +365,7 @@ func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize int64) (*Part, error)
+
+ if r.isBoundaryDelimiterLine(line) {
+ r.partsRead++
+- bp, err := newPart(r, rawPart, maxMIMEHeaderSize)
++ bp, err := newPart(r, rawPart, maxMIMEHeaderSize, maxMIMEHeaders)
+ if err != nil {
+ return nil, err
+ }
+diff --git a/src/mime/multipart/readmimeheader.go b/src/mime/multipart/readmimeheader.go
+index 6836928..25aa6e2 100644
+--- a/src/mime/multipart/readmimeheader.go
++++ b/src/mime/multipart/readmimeheader.go
+@@ -11,4 +11,4 @@ import (
+ // readMIMEHeader is defined in package net/textproto.
+ //
+ //go:linkname readMIMEHeader net/textproto.readMIMEHeader
+-func readMIMEHeader(r *textproto.Reader, lim int64) (textproto.MIMEHeader, error)
++func readMIMEHeader(r *textproto.Reader, maxMemory, maxHeaders int64) (textproto.MIMEHeader, error)
+diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
+index 1c79f0a..ad2d777 100644
+--- a/src/net/textproto/reader.go
++++ b/src/net/textproto/reader.go
+@@ -484,12 +484,12 @@ func (r *Reader) ReadDotLines() ([]string, error) {
+ // }
+ //
+ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
+- return readMIMEHeader(r, math.MaxInt64)
++ return readMIMEHeader(r, math.MaxInt64, math.MaxInt64)
+ }
+
+ // readMIMEHeader is a version of ReadMIMEHeader which takes a limit on the header size.
+ // It is called by the mime/multipart package.
+-func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
++func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) {
+ // Avoid lots of small slice allocations later by allocating one
+ // large one ahead of time which we'll cut up into smaller
+ // slices. If this isn't big enough later, we allocate small ones.
+@@ -507,7 +507,7 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
+ // Account for 400 bytes of overhead for the MIMEHeader, plus 200 bytes per entry.
+ // Benchmarking map creation as of go1.20, a one-entry MIMEHeader is 416 bytes and large
+ // MIMEHeaders average about 200 bytes per entry.
+- lim -= 400
++ maxMemory -= 400
+ const mapEntryOverhead = 200
+
+ // The first line cannot start with a leading space.
+@@ -539,6 +539,11 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
+ continue
+ }
+
++ maxHeaders--
++ if maxHeaders < 0 {
++ return nil, errors.New("message too large")
++ }
++
+ // backport 5c55ac9bf1e5f779220294c843526536605f42ab
+ //
+ // value is computed as
+@@ -557,11 +562,11 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
+
+ vv := m[key]
+ if vv == nil {
+- lim -= int64(len(key))
+- lim -= mapEntryOverhead
++ maxMemory -= int64(len(key))
++ maxMemory -= mapEntryOverhead
+ }
+- lim -= int64(len(value))
+- if lim < 0 {
++ maxMemory -= int64(len(value))
++ if maxMemory < 0 {
+ // TODO: This should be a distinguishable error (ErrMessageTooLarge)
+ // to allow mime/multipart to detect it.
+ return m, errors.New("message too large")
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24537.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24537.patch
new file mode 100644
index 0000000000..e04b717fc1
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24537.patch
@@ -0,0 +1,76 @@
+From bf8c7c575c8a552d9d79deb29e80854dc88528d0 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Mon, 20 Mar 2023 10:43:19 -0700
+Subject: [PATCH] [release-branch.go1.20] mime/multipart: limit parsed mime
+ message sizes
+
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802456
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Run-TryBot: Damien Neil <dneil@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802611
+Reviewed-by: Damien Neil <dneil@google.com>
+Change-Id: Ifdfa192d54f722d781a4d8c5f35b5fb72d122168
+Reviewed-on: https://go-review.googlesource.com/c/go/+/481986
+Reviewed-by: Matthew Dempsky <mdempsky@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Run-TryBot: Michael Knyszek <mknyszek@google.com>
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/126a1d02da82f93ede7ce0bd8d3c51ef627f2104]
+CVE: CVE-2023-24537
+Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
+---
+ src/go/parser/parser_test.go | 16 ++++++++++++++++
+ src/go/scanner/scanner.go | 5 ++++-
+ 2 files changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go
+index 37a6a2b..714557c 100644
+--- a/src/go/parser/parser_test.go
++++ b/src/go/parser/parser_test.go
+@@ -738,3 +738,19 @@ func TestScopeDepthLimit(t *testing.T) {
+ }
+ }
+ }
++
++// TestIssue59180 tests that line number overflow doesn't cause an infinite loop.
++func TestIssue59180(t *testing.T) {
++ testcases := []string{
++ "package p\n//line :9223372036854775806\n\n//",
++ "package p\n//line :1:9223372036854775806\n\n//",
++ "package p\n//line file:9223372036854775806\n\n//",
++ }
++
++ for _, src := range testcases {
++ _, err := ParseFile(token.NewFileSet(), "", src, ParseComments)
++ if err == nil {
++ t.Errorf("ParseFile(%s) succeeded unexpectedly", src)
++ }
++ }
++}
+diff --git a/src/go/scanner/scanner.go b/src/go/scanner/scanner.go
+index 00fe2dc..3159d25 100644
+--- a/src/go/scanner/scanner.go
++++ b/src/go/scanner/scanner.go
+@@ -246,13 +246,16 @@ func (s *Scanner) updateLineInfo(next, offs int, text []byte) {
+ return
+ }
+
++ // Put a cap on the maximum size of line and column numbers.
++ // 30 bits allows for some additional space before wrapping an int32.
++ const maxLineCol = 1<<30 - 1
+ var line, col int
+ i2, n2, ok2 := trailingDigits(text[:i-1])
+ if ok2 {
+ //line filename:line:col
+ i, i2 = i2, i
+ line, col = n2, n
+- if col == 0 {
++ if col == 0 || col > maxLineCol {
+ s.error(offs+i2, "invalid column number: "+string(text[i2:]))
+ return
+ }
+--
+2.25.1
+
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
new file mode 100644
index 0000000000..23c5075e41
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-1.patch
@@ -0,0 +1,125 @@
+From 8acd01094d9ee17f6e763a61e49a8a808b3a9ddb Mon Sep 17 00:00:00 2001
+From: Brad Fitzpatrick <bradfitz@golang.org>
+Date: Mon, 2 Aug 2021 14:55:51 -0700
+Subject: [PATCH 1/6] net/netip: add new IP address package
+
+Co-authored-by: Alex Willmer <alex@moreati.org.uk> (GitHub @moreati)
+Co-authored-by: Alexander Yastrebov <yastrebov.alex@gmail.com>
+Co-authored-by: David Anderson <dave@natulte.net> (Tailscale CLA)
+Co-authored-by: David Crawshaw <crawshaw@tailscale.com> (Tailscale CLA)
+Co-authored-by: Dmytro Shynkevych <dmytro@tailscale.com> (Tailscale CLA)
+Co-authored-by: Elias Naur <mail@eliasnaur.com>
+Co-authored-by: Joe Tsai <joetsai@digital-static.net> (Tailscale CLA)
+Co-authored-by: Jonathan Yu <jawnsy@cpan.org> (GitHub @jawnsy)
+Co-authored-by: Josh Bleecher Snyder <josharian@gmail.com> (Tailscale CLA)
+Co-authored-by: Maisem Ali <maisem@tailscale.com> (Tailscale CLA)
+Co-authored-by: Manuel Mendez (Go AUTHORS mmendez534@...)
+Co-authored-by: Matt Layher <mdlayher@gmail.com>
+Co-authored-by: Noah Treuhaft <noah.treuhaft@gmail.com> (GitHub @nwt)
+Co-authored-by: Stefan Majer <stefan.majer@gmail.com>
+Co-authored-by: Terin Stock <terinjokes@gmail.com> (Cloudflare CLA)
+Co-authored-by: Tobias Klauser <tklauser@distanz.ch>
+
+Fixes #46518
+
+Change-Id: I0041f9e1115d61fa6e95fcf32b01d9faee708712
+Reviewed-on: https://go-review.googlesource.com/c/go/+/339309
+Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
+TryBot-Result: Go Bot <gobot@golang.org>
+Reviewed-by: Russ Cox <rsc@golang.org>
+Trust: Brad Fitzpatrick <bradfitz@golang.org>
+
+Dependency Patch #1
+
+Upstream-Status: Backport from https://github.com/golang/go/commit/a59e33224e42d60a97fa720a45e1b74eb6aaa3d0
+CVE: CVE-2023-24538
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/internal/godebug/godebug.go | 34 ++++++++++++++++++++++++++++++++++
+ src/internal/godebug/godebug_test.go | 34 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 68 insertions(+)
+ create mode 100644 src/internal/godebug/godebug.go
+ create mode 100644 src/internal/godebug/godebug_test.go
+
+diff --git a/src/internal/godebug/godebug.go b/src/internal/godebug/godebug.go
+new file mode 100644
+index 0000000..ac434e5
+--- /dev/null
++++ b/src/internal/godebug/godebug.go
+@@ -0,0 +1,34 @@
++// Copyright 2021 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Package godebug parses the GODEBUG environment variable.
++package godebug
++
++import "os"
++
++// Get returns the value for the provided GODEBUG key.
++func Get(key string) string {
++ return get(os.Getenv("GODEBUG"), key)
++}
++
++// get returns the value part of key=value in s (a GODEBUG value).
++func get(s, key string) string {
++ for i := 0; i < len(s)-len(key)-1; i++ {
++ if i > 0 && s[i-1] != ',' {
++ continue
++ }
++ afterKey := s[i+len(key):]
++ if afterKey[0] != '=' || s[i:i+len(key)] != key {
++ continue
++ }
++ val := afterKey[1:]
++ for i, b := range val {
++ if b == ',' {
++ return val[:i]
++ }
++ }
++ return val
++ }
++ return ""
++}
+diff --git a/src/internal/godebug/godebug_test.go b/src/internal/godebug/godebug_test.go
+new file mode 100644
+index 0000000..41b9117
+--- /dev/null
++++ b/src/internal/godebug/godebug_test.go
+@@ -0,0 +1,34 @@
++// Copyright 2021 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package godebug
++
++import "testing"
++
++func TestGet(t *testing.T) {
++ tests := []struct {
++ godebug string
++ key string
++ want string
++ }{
++ {"", "", ""},
++ {"", "foo", ""},
++ {"foo=bar", "foo", "bar"},
++ {"foo=bar,after=x", "foo", "bar"},
++ {"before=x,foo=bar,after=x", "foo", "bar"},
++ {"before=x,foo=bar", "foo", "bar"},
++ {",,,foo=bar,,,", "foo", "bar"},
++ {"foodecoy=wrong,foo=bar", "foo", "bar"},
++ {"foo=", "foo", ""},
++ {"foo", "foo", ""},
++ {",foo", "foo", ""},
++ {"foo=bar,baz", "loooooooong", ""},
++ }
++ for _, tt := range tests {
++ got := get(tt.godebug, tt.key)
++ if got != tt.want {
++ t.Errorf("get(%q, %q) = %q; want %q", tt.godebug, tt.key, got, tt.want)
++ }
++ }
++}
+--
+2.7.4
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
new file mode 100644
index 0000000000..f200c41e16
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538-2.patch
@@ -0,0 +1,635 @@
+From 6fc21505614f36178df0dad7034b6b8e3f7588d5 Mon Sep 17 00:00:00 2001
+From: empijei <robclap8@gmail.com>
+Date: Fri, 27 Mar 2020 19:27:55 +0100
+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
+Content-Transfer-Encoding: 8bit
+
+The existing implementation is not compatible with JSON
+escape as it uses hex escaping.
+Unicode escape, instead, is valid for both JSON and JS.
+This fix avoids creating a separate escaping context for
+scripts of type "application/ld+json" and it is more
+future-proof in case more JSON+JS contexts get added
+to the platform (e.g. import maps).
+
+Fixes #33671
+Fixes #37634
+
+Change-Id: Id6f6524b4abc52e81d9d744d46bbe5bf2e081543
+Reviewed-on: https://go-review.googlesource.com/c/go/+/226097
+Reviewed-by: Carl Johnson <me@carlmjohnson.net>
+Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
+Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
+TryBot-Result: Gobot Gobot <gobot@golang.org>
+
+Dependency Patch #2
+
+Upstream-Status: Backport from https://github.com/golang/go/commit/d4d298040d072ddacea0e0d6b55fb148fff18070
+CVE: CVE-2023-24538
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ 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;tasty@example.com&gt;
+ // &#34;Fran &amp; Freddie&#39;s Diner&#34; &lt;tasty@example.com&gt;
+ // &#34;Fran &amp; Freddie&#39;s Diner&#34;32&lt;tasty@example.com&gt;
+- // \"Fran \x26 Freddie\'s Diner\" \x3Ctasty@example.com\x3E
+- // \"Fran \x26 Freddie\'s Diner\" \x3Ctasty@example.com\x3E
+- // \"Fran \x26 Freddie\'s Diner\"32\x3Ctasty@example.com\x3E
++ // \"Fran \u0026 Freddie\'s Diner\" \u003Ctasty@example.com\u003E
++ // \"Fran \u0026 Freddie\'s Diner\" \u003Ctasty@example.com\u003E
++ // \"Fran \u0026 Freddie\'s Diner\"32\u003Ctasty@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
++++ b/src/html/template/js.go
+@@ -163,7 +163,6 @@ func jsValEscaper(args ...interface{}) string {
+ }
+ // TODO: detect cycles before calling Marshal which loops infinitely on
+ // cyclic data. This may be an unacceptable DoS risk.
+-
+ b, err := json.Marshal(a)
+ if err != nil {
+ // Put a space before comment so that if it is flush against
+@@ -178,8 +177,8 @@ func jsValEscaper(args ...interface{}) string {
+ // TODO: maybe post-process output to prevent it from containing
+ // "<!--", "-->", "<![CDATA[", "]]>", or "</script"
+ // in case custom marshalers produce output containing those.
+-
+- // TODO: Maybe abbreviate \u00ab to \xab to produce more compact output.
++ // Note: Do not use \x escaping to save bytes because it is not JSON compatible and this escaper
++ // supports ld+json content-type.
+ if len(b) == 0 {
+ // In, `x=y/{{.}}*z` a json.Marshaler that produces "" should
+ // not cause the output `x=y/*z`.
+@@ -260,6 +259,8 @@ func replace(s string, replacementTable []string) string {
+ r, w = utf8.DecodeRuneInString(s[i:])
+ var repl string
+ switch {
++ case int(r) < len(lowUnicodeReplacementTable):
++ repl = lowUnicodeReplacementTable[r]
+ case int(r) < len(replacementTable) && replacementTable[r] != "":
+ repl = replacementTable[r]
+ case r == '\u2028':
+@@ -283,67 +284,80 @@ func replace(s string, replacementTable []string) string {
+ return b.String()
+ }
+
++var lowUnicodeReplacementTable = []string{
++ 0: `\u0000`, 1: `\u0001`, 2: `\u0002`, 3: `\u0003`, 4: `\u0004`, 5: `\u0005`, 6: `\u0006`,
++ '\a': `\u0007`,
++ '\b': `\u0008`,
++ '\t': `\t`,
++ '\n': `\n`,
++ '\v': `\u000b`, // "\v" == "v" on IE 6.
++ '\f': `\f`,
++ '\r': `\r`,
++ 0xe: `\u000e`, 0xf: `\u000f`, 0x10: `\u0010`, 0x11: `\u0011`, 0x12: `\u0012`, 0x13: `\u0013`,
++ 0x14: `\u0014`, 0x15: `\u0015`, 0x16: `\u0016`, 0x17: `\u0017`, 0x18: `\u0018`, 0x19: `\u0019`,
++ 0x1a: `\u001a`, 0x1b: `\u001b`, 0x1c: `\u001c`, 0x1d: `\u001d`, 0x1e: `\u001e`, 0x1f: `\u001f`,
++}
++
+ var jsStrReplacementTable = []string{
+- 0: `\0`,
++ 0: `\u0000`,
+ '\t': `\t`,
+ '\n': `\n`,
+- '\v': `\x0b`, // "\v" == "v" on IE 6.
++ '\v': `\u000b`, // "\v" == "v" on IE 6.
+ '\f': `\f`,
+ '\r': `\r`,
+ // Encode HTML specials as hex so the output can be embedded
+ // in HTML attributes without further encoding.
+- '"': `\x22`,
+- '&': `\x26`,
+- '\'': `\x27`,
+- '+': `\x2b`,
++ '"': `\u0022`,
++ '&': `\u0026`,
++ '\'': `\u0027`,
++ '+': `\u002b`,
+ '/': `\/`,
+- '<': `\x3c`,
+- '>': `\x3e`,
++ '<': `\u003c`,
++ '>': `\u003e`,
+ '\\': `\\`,
+ }
+
+ // jsStrNormReplacementTable is like jsStrReplacementTable but does not
+ // overencode existing escapes since this table has no entry for `\`.
+ var jsStrNormReplacementTable = []string{
+- 0: `\0`,
++ 0: `\u0000`,
+ '\t': `\t`,
+ '\n': `\n`,
+- '\v': `\x0b`, // "\v" == "v" on IE 6.
++ '\v': `\u000b`, // "\v" == "v" on IE 6.
+ '\f': `\f`,
+ '\r': `\r`,
+ // Encode HTML specials as hex so the output can be embedded
+ // in HTML attributes without further encoding.
+- '"': `\x22`,
+- '&': `\x26`,
+- '\'': `\x27`,
+- '+': `\x2b`,
++ '"': `\u0022`,
++ '&': `\u0026`,
++ '\'': `\u0027`,
++ '+': `\u002b`,
+ '/': `\/`,
+- '<': `\x3c`,
+- '>': `\x3e`,
++ '<': `\u003c`,
++ '>': `\u003e`,
+ }
+-
+ var jsRegexpReplacementTable = []string{
+- 0: `\0`,
++ 0: `\u0000`,
+ '\t': `\t`,
+ '\n': `\n`,
+- '\v': `\x0b`, // "\v" == "v" on IE 6.
++ '\v': `\u000b`, // "\v" == "v" on IE 6.
+ '\f': `\f`,
+ '\r': `\r`,
+ // Encode HTML specials as hex so the output can be embedded
+ // in HTML attributes without further encoding.
+- '"': `\x22`,
++ '"': `\u0022`,
+ '$': `\$`,
+- '&': `\x26`,
+- '\'': `\x27`,
++ '&': `\u0026`,
++ '\'': `\u0027`,
+ '(': `\(`,
+ ')': `\)`,
+ '*': `\*`,
+- '+': `\x2b`,
++ '+': `\u002b`,
+ '-': `\-`,
+ '.': `\.`,
+ '/': `\/`,
+- '<': `\x3c`,
+- '>': `\x3e`,
++ '<': `\u003c`,
++ '>': `\u003e`,
+ '?': `\?`,
+ '[': `\[`,
+ '\\': `\\`,
+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", "P"},
++ }
++ 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
++++ b/src/text/template/funcs.go
+@@ -640,10 +640,10 @@ var (
+ jsBackslash = []byte(`\\`)
+ jsApos = []byte(`\'`)
+ jsQuot = []byte(`\"`)
+- jsLt = []byte(`\x3C`)
+- jsGt = []byte(`\x3E`)
+- jsAmp = []byte(`\x26`)
+- jsEq = []byte(`\x3D`)
++ jsLt = []byte(`\u003C`)
++ jsGt = []byte(`\u003E`)
++ jsAmp = []byte(`\u0026`)
++ jsEq = []byte(`\u003D`)
+ )
+
+ // JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
+--
+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_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 <ariel@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í <mvdan@mvdan.cc>
+Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
+TryBot-Result: Gobot Gobot <gobot@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 <skulkarni@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 <rsc@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 <rsc@golang.org>
+Run-TryBot: Russ Cox <rsc@golang.org>
+TryBot-Result: Go Bot <gobot@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 <skulkarni@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 <rsc@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 <rsc@golang.org>
+Run-TryBot: Russ Cox <rsc@golang.org>
+TryBot-Result: Go Bot <gobot@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 <skulkarni@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_6.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch
new file mode 100644
index 0000000000..baf400b891
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch
@@ -0,0 +1,371 @@
+From 16f4882984569f179d73967c9eee679bb9b098c5 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Mon, 20 Mar 2023 11:01:13 -0700
+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
+delimiters for other string literals. Additionally template literals can
+contain special syntax for string interpolation.
+
+There is no clear way to allow safe insertion of actions within JS
+template literals, as handling (JS) string interpolation inside of these
+literals is rather complex. As such we've chosen to simply disallow
+template actions within these template literals.
+
+A new error code is added for this parsing failure case, errJsTmplLit,
+but it is unexported as it is not backwards compatible with other minor
+release versions to introduce an API change in a minor release. We will
+export this code in the next major release.
+
+The previous behavior (with the cavet that backticks are now escaped
+properly) can be re-enabled with GODEBUG=jstmpllitinterp=1.
+
+This change subsumes CL471455.
+
+Thanks to Sohom Datta, Manipal Institute of Technology, for reporting
+this issue.
+
+Fixes CVE-2023-24538
+For #59234
+Fixes #59271
+
+[0] https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-template-literals
+[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
+
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802457
+Reviewed-by: Damien Neil <dneil@google.com>
+Run-TryBot: Damien Neil <dneil@google.com>
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802612
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Change-Id: Ic7f10595615f2b2740d9c85ad7ef40dc0e78c04c
+Reviewed-on: https://go-review.googlesource.com/c/go/+/481987
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Run-TryBot: Michael Knyszek <mknyszek@google.com>
+Reviewed-by: Matthew Dempsky <mdempsky@google.com>
+
+Upstream-Status: Backport from https://github.com/golang/go/commit/b1e3ecfa06b67014429a197ec5e134ce4303ad9b
+CVE: CVE-2023-24538
+Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
+---
+ src/html/template/context.go | 2 ++
+ 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/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
+--- a/src/html/template/context.go
++++ b/src/html/template/context.go
+@@ -116,6 +116,8 @@ const (
+ stateJSDqStr
+ // stateJSSqStr occurs inside a JavaScript single quoted string.
+ stateJSSqStr
++ // stateJSBqStr occurs inside a JavaScript back quoted string.
++ stateJSBqStr
+ // stateJSRegexp occurs inside a JavaScript regexp literal.
+ stateJSRegexp
+ // stateJSBlockCmt occurs inside a JavaScript /* block comment */.
+diff --git a/src/html/template/error.go b/src/html/template/error.go
+index 0e52706..fd26b64 100644
+--- a/src/html/template/error.go
++++ b/src/html/template/error.go
+@@ -211,6 +211,19 @@ const (
+ // pipeline occurs in an unquoted attribute value context, "html" is
+ // disallowed. Avoid using "html" and "urlquery" entirely in new templates.
+ ErrPredefinedEscaper
++
++ // errJSTmplLit: "... appears in a JS template literal"
++ // Example:
++ // <script>var tmpl = `{{.Interp}`</script>
++ // Discussion:
++ // Package html/template does not support actions inside of JS template
++ // literals.
++ //
++ // TODO(rolandshoemaker): we cannot add this as an exported error in a minor
++ // release, since it is backwards incompatible with the other minor
++ // releases. As such we need to leave it unexported, and then we'll add it
++ // in the next major release.
++ errJSTmplLit
+ )
+
+ func (e *Error) Error() string {
+diff --git a/src/html/template/escape.go b/src/html/template/escape.go
+index f12dafa..29ca5b3 100644
+--- a/src/html/template/escape.go
++++ b/src/html/template/escape.go
+@@ -8,6 +8,7 @@ import (
+ "bytes"
+ "fmt"
+ "html"
++ "internal/godebug"
+ "io"
+ "text/template"
+ "text/template/parse"
+@@ -203,6 +204,16 @@ func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
+ c.jsCtx = jsCtxDivOp
+ case stateJSDqStr, stateJSSqStr:
+ s = append(s, "_html_template_jsstrescaper")
++ case stateJSBqStr:
++ debugAllowActionJSTmpl := godebug.Get("jstmpllitinterp")
++ if debugAllowActionJSTmpl == "1" {
++ s = append(s, "_html_template_jsstrescaper")
++ } else {
++ return context{
++ state: stateError,
++ err: errorf(errJSTmplLit, n, n.Line, "%s appears in a JS template literal", n),
++ }
++ }
+ 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
++++ b/src/html/template/js.go
+@@ -308,6 +308,7 @@ var jsStrReplacementTable = []string{
+ // Encode HTML specials as hex so the output can be embedded
+ // in HTML attributes without further encoding.
+ '"': `\u0022`,
++ '`': `\u0060`,
+ '&': `\u0026`,
+ '\'': `\u0027`,
+ '+': `\u002b`,
+@@ -331,6 +332,7 @@ var jsStrNormReplacementTable = []string{
+ '"': `\u0022`,
+ '&': `\u0026`,
+ '\'': `\u0027`,
++ '`': `\u0060`,
+ '+': `\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
++++ b/src/html/template/jsctx_string.go
+@@ -4,6 +4,15 @@ package template
+
+ import "strconv"
+
++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[jsCtxRegexp-0]
++ _ = x[jsCtxDivOp-1]
++ _ = x[jsCtxUnknown-2]
++}
++
+ 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
++++ b/src/html/template/transition.go
+@@ -27,6 +27,7 @@ var transitionFunc = [...]func(context, []byte) (context, int){
+ stateJS: tJS,
+ stateJSDqStr: tJSDelimited,
+ stateJSSqStr: tJSDelimited,
++ stateJSBqStr: tJSDelimited,
+ stateJSRegexp: tJSDelimited,
+ stateJSBlockCmt: tBlockCmt,
+ stateJSLineCmt: tLineCmt,
+@@ -262,7 +263,7 @@ func tURL(c context, s []byte) (context, int) {
+
+ // tJS is the context transition function for the JS state.
+ func tJS(c context, s []byte) (context, int) {
+- i := bytes.IndexAny(s, `"'/`)
++ i := bytes.IndexAny(s, "\"`'/")
+ if i == -1 {
+ // Entire input is non string, comment, regexp tokens.
+ c.jsCtx = nextJSCtx(s, c.jsCtx)
+@@ -274,6 +275,8 @@ func tJS(c context, s []byte) (context, int) {
+ c.state, c.jsCtx = stateJSDqStr, jsCtxRegexp
+ case '\'':
+ c.state, c.jsCtx = stateJSSqStr, jsCtxRegexp
++ case '`':
++ c.state, c.jsCtx = stateJSBqStr, jsCtxRegexp
+ case '/':
+ switch {
+ case i+1 < len(s) && s[i+1] == '/':
+@@ -303,6 +306,8 @@ func tJSDelimited(c context, s []byte) (context, int) {
+ switch c.state {
+ case stateJSSqStr:
+ specials = `\'`
++ case stateJSBqStr:
++ specials = "`\\"
+ case stateJSRegexp:
+ specials = `\/[]`
+ }
+--
+2.7.4
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24539.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24539.patch
new file mode 100644
index 0000000000..281b6486a8
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24539.patch
@@ -0,0 +1,60 @@
+From 8673ca81e5340b87709db2d9749c92a3bf925df1 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Thu, 13 Apr 2023 15:40:44 -0700
+Subject: [PATCH] html/template: disallow angle brackets in CSS values
+
+Angle brackets should not appear in CSS contexts, as they may affect
+token boundaries (such as closing a <style> tag, resulting in
+injection). Instead emit filterFailsafe, matching the behavior for other
+dangerous characters.
+
+Thanks to Juho Nurminen of Mattermost for reporting this issue.
+
+Fixes #59720
+Fixes CVE-2023-24539
+
+Change-Id: Iccc659c9a18415992b0c05c178792228e3a7bae4
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1826636
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/491615
+Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+Run-TryBot: Carlos Amedee <carlos@golang.org>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+
+Upstream-Status: Backport from [https://github.com/golang/go/commit/8673ca81e5340b87709db2d9749c92a3bf925df1]
+CVE: CVE-2023-24539
+Signed-off-by: Ashish Sharma <asharma@mvista.com>
+---
+ src/html/template/css.go | 2 +-
+ src/html/template/css_test.go | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/html/template/css.go b/src/html/template/css.go
+index 890a0c6b227fe..f650d8b3e843a 100644
+--- a/src/html/template/css.go
++++ b/src/html/template/css.go
+@@ -238,7 +238,7 @@ func cssValueFilter(args ...any) string {
+ // inside a string that might embed JavaScript source.
+ for i, c := range b {
+ switch c {
+- case 0, '"', '\'', '(', ')', '/', ';', '@', '[', '\\', ']', '`', '{', '}':
++ case 0, '"', '\'', '(', ')', '/', ';', '@', '[', '\\', ']', '`', '{', '}', '<', '>':
+ return filterFailsafe
+ case '-':
+ // Disallow <!-- or -->.
+diff --git a/src/html/template/css_test.go b/src/html/template/css_test.go
+index a735638b0314f..2b76256a766e9 100644
+--- a/src/html/template/css_test.go
++++ b/src/html/template/css_test.go
+@@ -231,6 +231,8 @@ func TestCSSValueFilter(t *testing.T) {
+ {`-exp\000052 ession(alert(1337))`, "ZgotmplZ"},
+ {`-expre\0000073sion`, "-expre\x073sion"},
+ {`@import url evil.css`, "ZgotmplZ"},
++ {"<", "ZgotmplZ"},
++ {">", "ZgotmplZ"},
+ }
+ for _, test := range tests {
+ got := cssValueFilter(test.css)
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24540.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24540.patch
new file mode 100644
index 0000000000..799a0dfcda
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24540.patch
@@ -0,0 +1,90 @@
+From ce7bd33345416e6d8cac901792060591cafc2797 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Tue, 11 Apr 2023 16:27:43 +0100
+Subject: [PATCH] [release-branch.go1.19] html/template: handle all JS
+ whitespace characters
+
+Rather than just a small set. Character class as defined by \s [0].
+
+Thanks to Juho Nurminen of Mattermost for reporting this.
+
+For #59721
+Fixes #59813
+Fixes CVE-2023-24540
+
+[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
+
+Change-Id: I56d4fa1ef08125b417106ee7dbfb5b0923b901ba
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1821459
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1851497
+Run-TryBot: Damien Neil <dneil@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/491355
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+Reviewed-by: Carlos Amedee <carlos@golang.org>
+TryBot-Bypass: Carlos Amedee <carlos@golang.org>
+Run-TryBot: Carlos Amedee <carlos@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/ce7bd33345416e6d8cac901792060591cafc2797]
+CVE: CVE-2023-24540
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/html/template/js.go | 8 +++++++-
+ src/html/template/js_test.go | 11 +++++++----
+ 2 files changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/src/html/template/js.go b/src/html/template/js.go
+index fe7054efe5cd8..4e05c1455723f 100644
+--- a/src/html/template/js.go
++++ b/src/html/template/js.go
+@@ -13,6 +13,11 @@ import (
+ "unicode/utf8"
+ )
+
++// jsWhitespace contains all of the JS whitespace characters, as defined
++// by the \s character class.
++// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Character_classes.
++const jsWhitespace = "\f\n\r\t\v\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff"
++
+ // nextJSCtx returns the context that determines whether a slash after the
+ // given run of tokens starts a regular expression instead of a division
+ // operator: / or /=.
+@@ -26,7 +31,8 @@ import (
+ // JavaScript 2.0 lexical grammar and requires one token of lookbehind:
+ // https://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html
+ func nextJSCtx(s []byte, preceding jsCtx) jsCtx {
+- s = bytes.TrimRight(s, "\t\n\f\r \u2028\u2029")
++ // Trim all JS whitespace characters
++ s = bytes.TrimRight(s, jsWhitespace)
+ if len(s) == 0 {
+ return preceding
+ }
+diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go
+index e07c695f7a77d..e52180cc113b5 100644
+--- a/src/html/template/js_test.go
++++ b/src/html/template/js_test.go
+@@ -81,14 +81,17 @@ func TestNextJsCtx(t *testing.T) {
+ {jsCtxDivOp, "0"},
+ // Dots that are part of a number are div preceders.
+ {jsCtxDivOp, "0."},
++ // Some JS interpreters treat NBSP as a normal space, so
++ // we must too in order to properly escape things.
++ {jsCtxRegexp, "=\u00A0"},
+ }
+
+ for _, test := range tests {
+- if nextJSCtx([]byte(test.s), jsCtxRegexp) != test.jsCtx {
+- t.Errorf("want %s got %q", test.jsCtx, test.s)
++ if ctx := nextJSCtx([]byte(test.s), jsCtxRegexp); ctx != test.jsCtx {
++ t.Errorf("%q: want %s got %s", test.s, test.jsCtx, ctx)
+ }
+- if nextJSCtx([]byte(test.s), jsCtxDivOp) != test.jsCtx {
+- t.Errorf("want %s got %q", test.jsCtx, test.s)
++ if ctx := nextJSCtx([]byte(test.s), jsCtxDivOp); ctx != test.jsCtx {
++ t.Errorf("%q: want %s got %s", test.s, test.jsCtx, ctx)
+ }
+ }
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-29400.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-29400.patch
new file mode 100644
index 0000000000..092c7aa0ff
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-29400.patch
@@ -0,0 +1,94 @@
+From 0d347544cbca0f42b160424f6bc2458ebcc7b3fc Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Thu, 13 Apr 2023 14:01:50 -0700
+Subject: [PATCH] html/template: emit filterFailsafe for empty unquoted attr
+ value
+
+An unquoted action used as an attribute value can result in unsafe
+behavior if it is empty, as HTML normalization will result in unexpected
+attributes, and may allow attribute injection. If executing a template
+results in a empty unquoted attribute value, emit filterFailsafe
+instead.
+
+Thanks to Juho Nurminen of Mattermost for reporting this issue.
+
+Fixes #59722
+Fixes CVE-2023-29400
+
+Change-Id: Ia38d1b536ae2b4af5323a6c6d861e3c057c2570a
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1826631
+Reviewed-by: Julie Qiu <julieqiu@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/491617
+Run-TryBot: Carlos Amedee <carlos@golang.org>
+Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+
+Upstream-Status: Backport from [https://github.com/golang/go/commit/0d347544cbca0f42b160424f6bc2458ebcc7b3fc]
+CVE: CVE-2023-29400
+Signed-off-by: Ashish Sharma <asharma@mvista.com>
+---
+ src/html/template/escape.go | 5 ++---
+ src/html/template/escape_test.go | 15 +++++++++++++++
+ src/html/template/html.go | 3 +++
+ 3 files changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/src/html/template/escape.go b/src/html/template/escape.go
+index 4ba1d6b31897e..a62ef159f0dcd 100644
+--- a/src/html/template/escape.go
++++ b/src/html/template/escape.go
+@@ -382,9 +382,8 @@ func normalizeEscFn(e string) string {
+ // for all x.
+ var redundantFuncs = map[string]map[string]bool{
+ "_html_template_commentescaper": {
+- "_html_template_attrescaper": true,
+- "_html_template_nospaceescaper": true,
+- "_html_template_htmlescaper": true,
++ "_html_template_attrescaper": true,
++ "_html_template_htmlescaper": true,
+ },
+ "_html_template_cssescaper": {
+ "_html_template_attrescaper": true,
+diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
+index 3dd212bac9406..f8b2b448f2dfa 100644
+--- a/src/html/template/escape_test.go
++++ b/src/html/template/escape_test.go
+@@ -678,6 +678,21 @@ func TestEscape(t *testing.T) {
+ `<img srcset={{",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"}}>`,
+ `<img srcset=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>`,
+ },
++ {
++ "unquoted empty attribute value (plaintext)",
++ "<p name={{.U}}>",
++ "<p name=ZgotmplZ>",
++ },
++ {
++ "unquoted empty attribute value (url)",
++ "<p href={{.U}}>",
++ "<p href=ZgotmplZ>",
++ },
++ {
++ "quoted empty attribute value",
++ "<p name=\"{{.U}}\">",
++ "<p name=\"\">",
++ },
+ }
+
+ for _, test := range tests {
+diff --git a/src/html/template/html.go b/src/html/template/html.go
+index bcca0b51a0ef9..a181699a5bda8 100644
+--- a/src/html/template/html.go
++++ b/src/html/template/html.go
+@@ -14,6 +14,9 @@ import (
+ // htmlNospaceEscaper escapes for inclusion in unquoted attribute values.
+ func htmlNospaceEscaper(args ...interface{}) string {
+ s, t := stringify(args...)
++ if s == "" {
++ return filterFailsafe
++ }
+ if t == contentTypeHTML {
+ return htmlReplacer(stripTags(s), htmlNospaceNormReplacementTable, false)
+ }
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-29402.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-29402.patch
new file mode 100644
index 0000000000..01eed9fe1b
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-29402.patch
@@ -0,0 +1,201 @@
+rom c160b49b6d328c86bd76ca2fff9009a71347333f Mon Sep 17 00:00:00 2001
+From: "Bryan C. Mills" <bcmills@google.com>
+Date: Fri, 12 May 2023 14:15:16 -0400
+Subject: [PATCH] [release-branch.go1.19] cmd/go: disallow package directories
+ containing newlines
+
+Directory or file paths containing newlines may cause tools (such as
+cmd/cgo) that emit "//line" or "#line" -directives to write part of
+the path into non-comment lines in generated source code. If those
+lines contain valid Go code, it may be injected into the resulting
+binary.
+
+(Note that Go import paths and file paths within module zip files
+already could not contain newlines.)
+
+Thanks to Juho Nurminen of Mattermost for reporting this issue.
+
+Updates #60167.
+Fixes #60515.
+Fixes CVE-2023-29402.
+
+Change-Id: If55d0400c02beb7a5da5eceac60f1abeac99f064
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1882606
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Russ Cox <rsc@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+(cherry picked from commit 41f9046495564fc728d6f98384ab7276450ac7e2)
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1902229
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1904343
+Reviewed-by: Michael Knyszek <mknyszek@google.com>
+Reviewed-by: Bryan Mills <bcmills@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/501218
+Run-TryBot: David Chase <drchase@google.com>
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/c160b49b6d328c86bd76ca2fff9009a71347333f]
+CVE: CVE-2023-29402
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/cmd/go/internal/load/pkg.go | 4 +
+ src/cmd/go/internal/work/exec.go | 6 ++
+ src/cmd/go/script_test.go | 1 +
+ .../go/testdata/script/build_cwd_newline.txt | 100 ++++++++++++++++++
+ 4 files changed, 111 insertions(+)
+ create mode 100644 src/cmd/go/testdata/script/build_cwd_newline.txt
+
+diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
+index 369a79b..d2b63b0 100644
+--- a/src/cmd/go/internal/load/pkg.go
++++ b/src/cmd/go/internal/load/pkg.go
+@@ -1697,6 +1697,10 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
+ setError(ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath))
+ return
+ }
++ if strings.ContainsAny(p.Dir, "\r\n") {
++ setError(fmt.Errorf("invalid package directory %q", p.Dir))
++ return
++ }
+
+ // Build list of imported packages and full dependency list.
+ imports := make([]*Package, 0, len(p.Imports))
+diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
+index 9a9650b..050b785 100644
+--- a/src/cmd/go/internal/work/exec.go
++++ b/src/cmd/go/internal/work/exec.go
+@@ -458,6 +458,12 @@ func (b *Builder) build(a *Action) (err error) {
+ b.Print(a.Package.ImportPath + "\n")
+ }
+
++ if p.Error != nil {
++ // Don't try to build anything for packages with errors. There may be a
++ // problem with the inputs that makes the package unsafe to build.
++ return p.Error
++ }
++
+ if a.Package.BinaryOnly {
+ p.Stale = true
+ p.StaleReason = "binary-only packages are no longer supported"
+diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go
+index ec498bb..a1398ad 100644
+--- a/src/cmd/go/script_test.go
++++ b/src/cmd/go/script_test.go
+@@ -123,6 +123,7 @@ func (ts *testScript) setup() {
+ "devnull=" + os.DevNull,
+ "goversion=" + goVersion(ts),
+ ":=" + string(os.PathListSeparator),
++ "newline=\n",
+ }
+
+ if runtime.GOOS == "plan9" {
+diff --git a/src/cmd/go/testdata/script/build_cwd_newline.txt b/src/cmd/go/testdata/script/build_cwd_newline.txt
+new file mode 100644
+index 0000000..61c6966
+--- /dev/null
++++ b/src/cmd/go/testdata/script/build_cwd_newline.txt
+@@ -0,0 +1,100 @@
++[windows] skip 'filesystem normalizes / to \'
++[plan9] skip 'filesystem disallows \n in paths'
++
++# If the directory path containing a package to be built includes a newline,
++# the go command should refuse to even try to build the package.
++
++env DIR=$WORK${/}${newline}'package main'${newline}'func main() { panic("uh-oh")'${newline}'/*'
++
++mkdir $DIR
++cd $DIR
++exec pwd
++cp $WORK/go.mod ./go.mod
++cp $WORK/main.go ./main.go
++cp $WORK/main_test.go ./main_test.go
++
++! go build -o $devnull .
++stderr 'package example: invalid package directory .*uh-oh'
++
++! go build -o $devnull main.go
++stderr 'package command-line-arguments: invalid package directory .*uh-oh'
++
++! go run .
++stderr 'package example: invalid package directory .*uh-oh'
++
++! go run main.go
++stderr 'package command-line-arguments: invalid package directory .*uh-oh'
++
++! go test .
++stderr 'package example: invalid package directory .*uh-oh'
++
++! go test -v main.go main_test.go
++stderr 'package command-line-arguments: invalid package directory .*uh-oh'
++
++
++# Since we do preserve $PWD (or set it appropriately) for commands, and we do
++# not resolve symlinks unnecessarily, referring to the contents of the unsafe
++# directory via a safe symlink should be ok, and should not inject the data from
++# the symlink target path.
++
++[!symlink] stop 'remainder of test checks symlink behavior'
++[short] stop 'links and runs binaries'
++
++symlink $WORK${/}link -> $DIR
++
++go run $WORK${/}link${/}main.go
++! stdout panic
++! stderr panic
++stderr '^ok$'
++
++go test -v $WORK${/}link${/}main.go $WORK${/}link${/}main_test.go
++! stdout panic
++! stderr panic
++stdout '^ok$' # 'go test' combines the test's stdout into stderr
++
++cd $WORK/link
++
++! go run $DIR${/}main.go
++stderr 'package command-line-arguments: invalid package directory .*uh-oh'
++
++go run .
++! stdout panic
++! stderr panic
++stderr '^ok$'
++
++go run main.go
++! stdout panic
++! stderr panic
++stderr '^ok$'
++
++go test -v
++! stdout panic
++! stderr panic
++stdout '^ok$' # 'go test' combines the test's stdout into stderr
++
++go test -v .
++! stdout panic
++! stderr panic
++stdout '^ok$' # 'go test' combines the test's stdout into stderr
++
++
++-- $WORK/go.mod --
++module example
++go 1.19
++-- $WORK/main.go --
++package main
++
++import "C"
++
++func main() {
++ /* nothing here */
++ println("ok")
++}
++-- $WORK/main_test.go --
++package main
++
++import "testing"
++
++func TestMain(*testing.M) {
++ main()
++}
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-29404.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-29404.patch
new file mode 100644
index 0000000000..61336ee9ee
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-29404.patch
@@ -0,0 +1,84 @@
+From bf3c8ce03e175e870763901a3850bca01381a828 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Fri, 5 May 2023 13:10:34 -0700
+Subject: [PATCH] [release-branch.go1.19] cmd/go: enforce flags with
+ non-optional arguments
+
+Enforce that linker flags which expect arguments get them, otherwise it
+may be possible to smuggle unexpected flags through as the linker can
+consume what looks like a flag as an argument to a preceding flag (i.e.
+"-Wl,-O -Wl,-R,-bad-flag" is interpreted as "-O=-R -bad-flag"). Also be
+somewhat more restrictive in the general format of some flags.
+
+Thanks to Juho Nurminen of Mattermost for reporting this issue.
+
+Updates #60305
+Fixes #60511
+Fixes CVE-2023-29404
+
+Change-Id: Icdffef2c0f644da50261cace6f43742783931cff
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1876275
+Reviewed-by: Ian Lance Taylor <iant@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+(cherry picked from commit 896779503cf754cbdac24b61d4cc953b50fe2dde)
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1902225
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1904342
+Reviewed-by: Michael Knyszek <mknyszek@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/501217
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+Run-TryBot: David Chase <drchase@google.com>
+TryBot-Bypass: Michael Knyszek <mknyszek@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/bf3c8ce03e175e870763901a3850bca01381a828]
+CVE: CVE-2023-29404
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/cmd/go/internal/work/security.go | 6 +++---
+ src/cmd/go/internal/work/security_test.go | 5 +++++
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go
+index a823b20..8acb6dc 100644
+--- a/src/cmd/go/internal/work/security.go
++++ b/src/cmd/go/internal/work/security.go
+@@ -177,17 +177,17 @@ var validLinkerFlags = []*lazyregexp.Regexp{
+ re(`-Wl,-Bdynamic`),
+ re(`-Wl,-berok`),
+ re(`-Wl,-Bstatic`),
+- re(`-WL,-O([^@,\-][^,]*)?`),
++ re(`-Wl,-O[0-9]+`),
+ re(`-Wl,-d[ny]`),
+ re(`-Wl,--disable-new-dtags`),
+- re(`-Wl,-e[=,][a-zA-Z0-9]*`),
++ re(`-Wl,-e[=,][a-zA-Z0-9]+`),
+ re(`-Wl,--enable-new-dtags`),
+ re(`-Wl,--end-group`),
+ re(`-Wl,--(no-)?export-dynamic`),
+ re(`-Wl,-framework,[^,@\-][^,]+`),
+ re(`-Wl,-headerpad_max_install_names`),
+ re(`-Wl,--no-undefined`),
+- re(`-Wl,-R([^@\-][^,@]*$)`),
++ re(`-Wl,-R,?([^@\-,][^,@]*$)`),
+ re(`-Wl,--just-symbols[=,]([^,@\-][^,@]+)`),
+ re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]+)`),
+ re(`-Wl,-s`),
+diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go
+index bd707ff..7b0b7d3 100644
+--- a/src/cmd/go/internal/work/security_test.go
++++ b/src/cmd/go/internal/work/security_test.go
+@@ -220,6 +220,11 @@ var badLinkerFlags = [][]string{
+ {"-Wl,-R,@foo"},
+ {"-Wl,--just-symbols,@foo"},
+ {"../x.o"},
++ {"-Wl,-R,"},
++ {"-Wl,-O"},
++ {"-Wl,-e="},
++ {"-Wl,-e,"},
++ {"-Wl,-R,-flag"},
+ }
+
+ func TestCheckLinkerFlags(t *testing.T) {
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-29405-1.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-29405-1.patch
new file mode 100644
index 0000000000..70d50cc08a
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-29405-1.patch
@@ -0,0 +1,112 @@
+From fa60c381ed06c12f9c27a7b50ca44c5f84f7f0f4 Mon Sep 17 00:00:00 2001
+From: Ian Lance Taylor <iant@golang.org>
+Date: Thu, 4 May 2023 14:06:39 -0700
+Subject: [PATCH] [release-branch.go1.20] cmd/go,cmd/cgo: in _cgo_flags use one
+ line per flag
+
+The flags that we recorded in _cgo_flags did not use any quoting,
+so a flag containing embedded spaces was mishandled.
+Change the _cgo_flags format to put each flag on a separate line.
+That is a simple format that does not require any quoting.
+
+As far as I can tell only cmd/go uses _cgo_flags, and it is only
+used for gccgo. If this patch doesn't cause any trouble, then
+in the next release we can change to only using _cgo_flags for gccgo.
+
+Thanks to Juho Nurminen of Mattermost for reporting this issue.
+
+Updates #60306
+Fixes #60514
+Fixes CVE-2023-29405
+
+Change-Id: I36b6e188a44c80d7b9573efa577c386770bd2ba3
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1875094
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+(cherry picked from commit bcdfcadd5612212089d958bc352a6f6c90742dcc)
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1902228
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1904345
+Reviewed-by: Michael Knyszek <mknyszek@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/501220
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Run-TryBot: David Chase <drchase@google.com>
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+---
+Upstream-Status: Backport [https://github.com/golang/go/commit/fa60c381ed06c12f9c27a7b50ca44c5f84f7f0f4]
+CVE: CVE-2023-29405
+Signed-off-by: Ashish Sharma <asharma@mvista.com>
+
+ src/cmd/cgo/out.go | 4 +++-
+ src/cmd/go/internal/work/gccgo.go | 14 ++++++-------
+ .../go/testdata/script/gccgo_link_ldflags.txt | 20 +++++++++++++++++++
+ 3 files changed, 29 insertions(+), 9 deletions(-)
+ create mode 100644 src/cmd/go/testdata/script/gccgo_link_ldflags.txt
+
+diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
+index d26f9e76a374a..d0c6fe3d4c2c2 100644
+--- a/src/cmd/cgo/out.go
++++ b/src/cmd/cgo/out.go
+@@ -47,7 +47,9 @@ func (p *Package) writeDefs() {
+
+ fflg := creat(*objDir + "_cgo_flags")
+ for k, v := range p.CgoFlags {
+- fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
++ for _, arg := range v {
++ fmt.Fprintf(fflg, "_CGO_%s=%s\n", arg)
++ }
+ if k == "LDFLAGS" && !*gccgo {
+ for _, arg := range v {
+ fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
+diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go
+index 08a4c2d8166c7..a048b7f4eecef 100644
+--- a/src/cmd/go/internal/work/gccgo.go
++++ b/src/cmd/go/internal/work/gccgo.go
+@@ -280,14 +280,12 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
+ const ldflagsPrefix = "_CGO_LDFLAGS="
+ for _, line := range strings.Split(string(flags), "\n") {
+ if strings.HasPrefix(line, ldflagsPrefix) {
+- newFlags := strings.Fields(line[len(ldflagsPrefix):])
+- for _, flag := range newFlags {
+- // Every _cgo_flags file has -g and -O2 in _CGO_LDFLAGS
+- // but they don't mean anything to the linker so filter
+- // them out.
+- if flag != "-g" && !strings.HasPrefix(flag, "-O") {
+- cgoldflags = append(cgoldflags, flag)
+- }
++ flag := line[len(ldflagsPrefix):]
++ // Every _cgo_flags file has -g and -O2 in _CGO_LDFLAGS
++ // but they don't mean anything to the linker so filter
++ // them out.
++ if flag != "-g" && !strings.HasPrefix(flag, "-O") {
++ cgoldflags = append(cgoldflags, flag)
+ }
+ }
+ }
+diff --git a/src/cmd/go/testdata/script/gccgo_link_ldflags.txt b/src/cmd/go/testdata/script/gccgo_link_ldflags.txt
+new file mode 100644
+index 0000000000000..4e91ae56505b6
+--- /dev/null
++++ b/src/cmd/go/testdata/script/gccgo_link_ldflags.txt
+@@ -0,0 +1,20 @@
++# Test that #cgo LDFLAGS are properly quoted.
++# The #cgo LDFLAGS below should pass a string with spaces to -L,
++# as though searching a directory with a space in its name.
++# It should not pass --nosuchoption to the external linker.
++
++[!cgo] skip
++
++go build
++
++[!exec:gccgo] skip
++
++go build -compiler gccgo
++
++-- go.mod --
++module m
++-- cgo.go --
++package main
++// #cgo LDFLAGS: -L "./ -Wl,--nosuchoption"
++import "C"
++func main() {}
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-29405-2.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-29405-2.patch
new file mode 100644
index 0000000000..369eca581e
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-29405-2.patch
@@ -0,0 +1,38 @@
+From 1008486a9ff979dbd21c7466eeb6abf378f9c637 Mon Sep 17 00:00:00 2001
+From: Ian Lance Taylor <iant@golang.org>
+Date: Tue, 6 Jun 2023 12:51:17 -0700
+Subject: [PATCH] [release-branch.go1.20] cmd/cgo: correct _cgo_flags output
+
+For #60306
+For #60514
+
+Change-Id: I3f5d14aee7d7195030e8872e42b1d97aa11d3582
+Reviewed-on: https://go-review.googlesource.com/c/go/+/501298
+Run-TryBot: Ian Lance Taylor <iant@golang.org>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+Reviewed-by: David Chase <drchase@google.com>
+Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
+---
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/1008486a9ff979dbd21c7466eeb6abf378f9c637]
+CVE: CVE-2023-29405
+Signed-off-by: Ashish Sharma <asharma@mvista.com>
+
+
+ src/cmd/cgo/out.go | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
+index d0c6fe3d4c2c2..a48f52105628a 100644
+--- a/src/cmd/cgo/out.go
++++ b/src/cmd/cgo/out.go
+@@ -48,7 +48,7 @@ func (p *Package) writeDefs() {
+ fflg := creat(*objDir + "_cgo_flags")
+ for k, v := range p.CgoFlags {
+ for _, arg := range v {
+- fmt.Fprintf(fflg, "_CGO_%s=%s\n", arg)
++ fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, arg)
+ }
+ if k == "LDFLAGS" && !*gccgo {
+ for _, arg := range v {
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-29406-1.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-29406-1.patch
new file mode 100644
index 0000000000..080def4682
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-29406-1.patch
@@ -0,0 +1,212 @@
+From 5fa6923b1ea891400153d04ddf1545e23b40041b Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Wed, 28 Jun 2023 13:20:08 -0700
+Subject: [PATCH] [release-branch.go1.19] net/http: validate Host header before
+ sending
+
+Verify that the Host header we send is valid.
+Avoids surprising behavior such as a Host of "go.dev\r\nX-Evil:oops"
+adding an X-Evil header to HTTP/1 requests.
+
+Add a test, skip the test for HTTP/2. HTTP/2 is not vulnerable to
+header injection in the way HTTP/1 is, but x/net/http2 doesn't validate
+the header and will go into a retry loop when the server rejects it.
+CL 506995 adds the necessary validation to x/net/http2.
+
+Updates #60374
+Fixes #61075
+For CVE-2023-29406
+
+Change-Id: I05cb6866a9bead043101954dfded199258c6dd04
+Reviewed-on: https://go-review.googlesource.com/c/go/+/506996
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Run-TryBot: Damien Neil <dneil@google.com>
+(cherry picked from commit 499458f7ca04087958987a33c2703c3ef03e27e2)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/507358
+Run-TryBot: Tatiana Bradley <tatianabradley@google.com>
+Reviewed-by: Roland Shoemaker <roland@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/5fa6923b1ea891400153d04ddf1545e23b40041b]
+CVE: CVE-2023-29406
+Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
+---
+ src/net/http/http_test.go | 29 ---------------------
+ src/net/http/request.go | 47 ++++++++--------------------------
+ src/net/http/request_test.go | 11 ++------
+ src/net/http/transport_test.go | 18 +++++++++++++
+ 4 files changed, 31 insertions(+), 74 deletions(-)
+
+diff --git a/src/net/http/http_test.go b/src/net/http/http_test.go
+index f4ea52d..ea38cb4 100644
+--- a/src/net/http/http_test.go
++++ b/src/net/http/http_test.go
+@@ -49,35 +49,6 @@ func TestForeachHeaderElement(t *testing.T) {
+ }
+ }
+
+-func TestCleanHost(t *testing.T) {
+- tests := []struct {
+- in, want string
+- }{
+- {"www.google.com", "www.google.com"},
+- {"www.google.com foo", "www.google.com"},
+- {"www.google.com/foo", "www.google.com"},
+- {" first character is a space", ""},
+- {"[1::6]:8080", "[1::6]:8080"},
+-
+- // Punycode:
+- {"гофер.рф/foo", "xn--c1ae0ajs.xn--p1ai"},
+- {"bücher.de", "xn--bcher-kva.de"},
+- {"bücher.de:8080", "xn--bcher-kva.de:8080"},
+- // Verify we convert to lowercase before punycode:
+- {"BÜCHER.de", "xn--bcher-kva.de"},
+- {"BÜCHER.de:8080", "xn--bcher-kva.de:8080"},
+- // Verify we normalize to NFC before punycode:
+- {"gophér.nfc", "xn--gophr-esa.nfc"}, // NFC input; no work needed
+- {"goph\u0065\u0301r.nfd", "xn--gophr-esa.nfd"}, // NFD input
+- }
+- for _, tt := range tests {
+- got := cleanHost(tt.in)
+- if tt.want != got {
+- t.Errorf("cleanHost(%q) = %q, want %q", tt.in, got, tt.want)
+- }
+- }
+-}
+-
+ // Test that cmd/go doesn't link in the HTTP server.
+ //
+ // This catches accidental dependencies between the HTTP transport and
+diff --git a/src/net/http/request.go b/src/net/http/request.go
+index cb2edd2..2706300 100644
+--- a/src/net/http/request.go
++++ b/src/net/http/request.go
+@@ -18,7 +18,6 @@ import (
+ "io/ioutil"
+ "mime"
+ "mime/multipart"
+- "net"
+ "net/http/httptrace"
+ "net/textproto"
+ "net/url"
+@@ -26,7 +25,8 @@ import (
+ "strconv"
+ "strings"
+ "sync"
+-
++
++ "golang.org/x/net/http/httpguts"
+ "golang.org/x/net/idna"
+ )
+
+@@ -557,12 +557,19 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
+ // is not given, use the host from the request URL.
+ //
+ // Clean the host, in case it arrives with unexpected stuff in it.
+- host := cleanHost(r.Host)
++ host := r.Host
+ if host == "" {
+ if r.URL == nil {
+ return errMissingHost
+ }
+- host = cleanHost(r.URL.Host)
++ host = r.URL.Host
++ }
++ host, err = httpguts.PunycodeHostPort(host)
++ if err != nil {
++ return err
++ }
++ if !httpguts.ValidHostHeader(host) {
++ return errors.New("http: invalid Host header")
+ }
+
+ // According to RFC 6874, an HTTP client, proxy, or other
+@@ -717,38 +724,6 @@ func idnaASCII(v string) (string, error) {
+ return idna.Lookup.ToASCII(v)
+ }
+
+-// cleanHost cleans up the host sent in request's Host header.
+-//
+-// It both strips anything after '/' or ' ', and puts the value
+-// into Punycode form, if necessary.
+-//
+-// Ideally we'd clean the Host header according to the spec:
+-// https://tools.ietf.org/html/rfc7230#section-5.4 (Host = uri-host [ ":" port ]")
+-// https://tools.ietf.org/html/rfc7230#section-2.7 (uri-host -> rfc3986's host)
+-// https://tools.ietf.org/html/rfc3986#section-3.2.2 (definition of host)
+-// But practically, what we are trying to avoid is the situation in
+-// issue 11206, where a malformed Host header used in the proxy context
+-// would create a bad request. So it is enough to just truncate at the
+-// first offending character.
+-func cleanHost(in string) string {
+- if i := strings.IndexAny(in, " /"); i != -1 {
+- in = in[:i]
+- }
+- host, port, err := net.SplitHostPort(in)
+- if err != nil { // input was just a host
+- a, err := idnaASCII(in)
+- if err != nil {
+- return in // garbage in, garbage out
+- }
+- return a
+- }
+- a, err := idnaASCII(host)
+- if err != nil {
+- return in // garbage in, garbage out
+- }
+- return net.JoinHostPort(a, port)
+-}
+-
+ // removeZone removes IPv6 zone identifier from host.
+ // E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"
+ func removeZone(host string) string {
+diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
+index 461d66e..0d417ff 100644
+--- a/src/net/http/request_test.go
++++ b/src/net/http/request_test.go
+@@ -676,15 +676,8 @@ func TestRequestBadHost(t *testing.T) {
+ }
+ req.Host = "foo.com with spaces"
+ req.URL.Host = "foo.com with spaces"
+- req.Write(logWrites{t, &got})
+- want := []string{
+- "GET /after HTTP/1.1\r\n",
+- "Host: foo.com\r\n",
+- "User-Agent: " + DefaultUserAgent + "\r\n",
+- "\r\n",
+- }
+- if !reflect.DeepEqual(got, want) {
+- t.Errorf("Writes = %q\n Want = %q", got, want)
++ if err := req.Write(logWrites{t, &got}); err == nil {
++ t.Errorf("Writing request with invalid Host: succeded, want error")
+ }
+ }
+
+diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
+index fa0c370..0afb6b9 100644
+--- a/src/net/http/transport_test.go
++++ b/src/net/http/transport_test.go
+@@ -6249,3 +6249,21 @@ func TestIssue32441(t *testing.T) {
+ t.Error(err)
+ }
+ }
++
++func TestRequestSanitization(t *testing.T) {
++ setParallel(t)
++ defer afterTest(t)
++
++ ts := newClientServerTest(t, h1Mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
++ if h, ok := req.Header["X-Evil"]; ok {
++ t.Errorf("request has X-Evil header: %q", h)
++ }
++ })).ts
++ defer ts.Close()
++ req, _ := NewRequest("GET", ts.URL, nil)
++ req.Host = "go.dev\r\nX-Evil:evil"
++ resp, _ := ts.Client().Do(req)
++ if resp != nil {
++ resp.Body.Close()
++ }
++}
+--
+2.25.1
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-29406-2.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-29406-2.patch
new file mode 100644
index 0000000000..637f46a537
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-29406-2.patch
@@ -0,0 +1,114 @@
+From c08a5fa413a34111c9a37fd9e545de27ab0978b1 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Wed, 19 Jul 2023 10:30:46 -0700
+Subject: [PATCH] [release-branch.go1.19] net/http: permit requests with
+ invalid Host headers
+
+Historically, the Transport has silently truncated invalid
+Host headers at the first '/' or ' ' character. CL 506996 changed
+this behavior to reject invalid Host headers entirely.
+Unfortunately, Docker appears to rely on the previous behavior.
+
+When sending a HTTP/1 request with an invalid Host, send an empty
+Host header. This is safer than truncation: If you care about the
+Host, then you should get the one you set; if you don't care,
+then an empty Host should be fine.
+
+Continue to fully validate Host headers sent to a proxy,
+since proxies generally can't productively forward requests
+without a Host.
+
+For #60374
+Fixes #61431
+Fixes #61825
+
+Change-Id: If170c7dd860aa20eb58fe32990fc93af832742b6
+Reviewed-on: https://go-review.googlesource.com/c/go/+/511155
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Roland Shoemaker <roland@golang.org>
+Run-TryBot: Damien Neil <dneil@google.com>
+(cherry picked from commit b9153f6ef338baee5fe02a867c8fbc83a8b29dd1)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/518855
+Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
+Run-TryBot: Roland Shoemaker <roland@golang.org>
+Reviewed-by: Russ Cox <rsc@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/c08a5fa413a34111c9a37fd9e545de27ab0978b1]
+CVE: CVE-2023-29406
+Signed-off-by: Ming Liu <liu.ming50@gmail.com>
+---
+ src/net/http/request.go | 23 ++++++++++++++++++++++-
+ src/net/http/request_test.go | 17 ++++++++++++-----
+ 2 files changed, 34 insertions(+), 6 deletions(-)
+
+diff --git a/src/net/http/request.go b/src/net/http/request.go
+index 3100037386..91cb8a66b9 100644
+--- a/src/net/http/request.go
++++ b/src/net/http/request.go
+@@ -582,8 +582,29 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
+ if err != nil {
+ return err
+ }
++ // Validate that the Host header is a valid header in general,
++ // but don't validate the host itself. This is sufficient to avoid
++ // header or request smuggling via the Host field.
++ // The server can (and will, if it's a net/http server) reject
++ // the request if it doesn't consider the host valid.
+ if !httpguts.ValidHostHeader(host) {
+- return errors.New("http: invalid Host header")
++ // Historically, we would truncate the Host header after '/' or ' '.
++ // Some users have relied on this truncation to convert a network
++ // address such as Unix domain socket path into a valid, ignored
++ // Host header (see https://go.dev/issue/61431).
++ //
++ // We don't preserve the truncation, because sending an altered
++ // header field opens a smuggling vector. Instead, zero out the
++ // Host header entirely if it isn't valid. (An empty Host is valid;
++ // see RFC 9112 Section 3.2.)
++ //
++ // Return an error if we're sending to a proxy, since the proxy
++ // probably can't do anything useful with an empty Host header.
++ if !usingProxy {
++ host = ""
++ } else {
++ return errors.New("http: invalid Host header")
++ }
+ }
+
+ // According to RFC 6874, an HTTP client, proxy, or other
+diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
+index fddc85d6a9..dd1e2dc2a1 100644
+--- a/src/net/http/request_test.go
++++ b/src/net/http/request_test.go
+@@ -770,16 +770,23 @@ func TestRequestWriteBufferedWriter(t *testing.T) {
+ }
+ }
+
+-func TestRequestBadHost(t *testing.T) {
++func TestRequestBadHostHeader(t *testing.T) {
+ got := []string{}
+ req, err := NewRequest("GET", "http://foo/after", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+- req.Host = "foo.com with spaces"
+- req.URL.Host = "foo.com with spaces"
+- if err := req.Write(logWrites{t, &got}); err == nil {
+- t.Errorf("Writing request with invalid Host: succeded, want error")
++ req.Host = "foo.com\nnewline"
++ req.URL.Host = "foo.com\nnewline"
++ req.Write(logWrites{t, &got})
++ want := []string{
++ "GET /after HTTP/1.1\r\n",
++ "Host: \r\n",
++ "User-Agent: " + DefaultUserAgent + "\r\n",
++ "\r\n",
++ }
++ if !reflect.DeepEqual(got, want) {
++ t.Errorf("Writes = %q\n Want = %q", got, want)
+ }
+ }
+
+--
+2.34.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-29409.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-29409.patch
new file mode 100644
index 0000000000..00685cc180
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-29409.patch
@@ -0,0 +1,175 @@
+From 2300f7ef07718f6be4d8aa8486c7de99836e233f Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Wed, 7 Jun 2023 15:27:13 -0700
+Subject: [PATCH] [release-branch.go1.19] crypto/tls: restrict RSA keys in
+ certificates to <= 8192 bits
+
+Extremely large RSA keys in certificate chains can cause a client/server
+to expend significant CPU time verifying signatures. Limit this by
+restricting the size of RSA keys transmitted during handshakes to <=
+8192 bits.
+
+Based on a survey of publicly trusted RSA keys, there are currently only
+three certificates in circulation with keys larger than this, and all
+three appear to be test certificates that are not actively deployed. It
+is possible there are larger keys in use in private PKIs, but we target
+the web PKI, so causing breakage here in the interests of increasing the
+default safety of users of crypto/tls seems reasonable.
+
+Thanks to Mateusz Poliwczak for reporting this issue.
+
+Updates #61460
+Fixes #61579
+Fixes CVE-2023-29409
+
+Change-Id: Ie35038515a649199a36a12fc2c5df3af855dca6c
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1912161
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+(cherry picked from commit d865c715d92887361e4bd5596e19e513f27781b7)
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1965487
+Reviewed-on: https://go-review.googlesource.com/c/go/+/514915
+Run-TryBot: David Chase <drchase@google.com>
+Reviewed-by: Matthew Dempsky <mdempsky@google.com>
+TryBot-Bypass: David Chase <drchase@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/2300f7ef07718f6be4d8aa8486c7de99836e233f]
+CVE: CVE-2023-29409
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/crypto/tls/handshake_client.go | 8 +++
+ src/crypto/tls/handshake_client_test.go | 78 +++++++++++++++++++++++++
+ src/crypto/tls/handshake_server.go | 4 ++
+ 3 files changed, 90 insertions(+)
+
+diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
+index 4fb528c..ba33ea1 100644
+--- a/src/crypto/tls/handshake_client.go
++++ b/src/crypto/tls/handshake_client.go
+@@ -788,6 +788,10 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error {
+ return nil
+ }
+
++// maxRSAKeySize is the maximum RSA key size in bits that we are willing
++// to verify the signatures of during a TLS handshake.
++const maxRSAKeySize = 8192
++
+ // verifyServerCertificate parses and verifies the provided chain, setting
+ // c.verifiedChains and c.peerCertificates or sending the appropriate alert.
+ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
+@@ -798,6 +802,10 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
+ c.sendAlert(alertBadCertificate)
+ return errors.New("tls: failed to parse certificate from server: " + err.Error())
+ }
++ if cert.PublicKeyAlgorithm == x509.RSA && cert.PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
++ c.sendAlert(alertBadCertificate)
++ return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
++ }
+ certs[i] = cert
+ }
+
+diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go
+index 6bd3c37..8d20b2b 100644
+--- a/src/crypto/tls/handshake_client_test.go
++++ b/src/crypto/tls/handshake_client_test.go
+@@ -1984,3 +1984,81 @@ func TestCloseClientConnectionOnIdleServer(t *testing.T) {
+ t.Errorf("Error expected, but no error returned")
+ }
+ }
++
++// discardConn wraps a net.Conn but discards all writes, but reports that they happened.
++type discardConn struct {
++ net.Conn
++}
++
++func (dc *discardConn) Write(data []byte) (int, error) {
++ return len(data), nil
++}
++
++// largeRSAKeyCertPEM contains a 8193 bit RSA key
++const largeRSAKeyCertPEM = `-----BEGIN CERTIFICATE-----
++MIIInjCCBIWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0
++aW5nMB4XDTIzMDYwNzIxMjMzNloXDTIzMDYwNzIzMjMzNlowEjEQMA4GA1UEAxMH
++dGVzdGluZzCCBCIwDQYJKoZIhvcNAQEBBQADggQPADCCBAoCggQBAWdHsf6Rh2Ca
++n2SQwn4t4OQrOjbLLdGE1pM6TBKKrHUFy62uEL8atNjlcfXIsa4aEu3xNGiqxqur
++ZectlkZbm0FkaaQ1Wr9oikDY3KfjuaXdPdO/XC/h8AKNxlDOylyXwUSK/CuYb+1j
++gy8yF5QFvVfwW/xwTlHmhUeSkVSQPosfQ6yXNNsmMzkd+ZPWLrfq4R+wiNtwYGu0
++WSBcI/M9o8/vrNLnIppoiBJJ13j9CR1ToEAzOFh9wwRWLY10oZhoh1ONN1KQURx4
++qedzvvP2DSjZbUccdvl2rBGvZpzfOiFdm1FCnxB0c72Cqx+GTHXBFf8bsa7KHky9
++sNO1GUanbq17WoDNgwbY6H51bfShqv0CErxatwWox3we4EcAmFHPVTCYL1oWVMGo
++a3Eth91NZj+b/nGhF9lhHKGzXSv9brmLLkfvM1jA6XhNhA7BQ5Vz67lj2j3XfXdh
++t/BU5pBXbL4Ut4mIhT1YnKXAjX2/LF5RHQTE8Vwkx5JAEKZyUEGOReD/B+7GOrLp
++HduMT9vZAc5aR2k9I8qq1zBAzsL69lyQNAPaDYd1BIAjUety9gAYaSQffCgAgpRO
++Gt+DYvxS+7AT/yEd5h74MU2AH7KrAkbXOtlwupiGwhMVTstncDJWXMJqbBhyHPF8
++3UmZH0hbL4PYmzSj9LDWQQXI2tv6vrCpfts3Cqhqxz9vRpgY7t1Wu6l/r+KxYYz3
++1pcGpPvRmPh0DJm7cPTiXqPnZcPt+ulSaSdlxmd19OnvG5awp0fXhxryZVwuiT8G
++VDkhyARrxYrdjlINsZJZbQjO0t8ketXAELJOnbFXXzeCOosyOHkLwsqOO96AVJA8
++45ZVL5m95ClGy0RSrjVIkXsxTAMVG6SPAqKwk6vmTdRGuSPS4rhgckPVDHmccmuq
++dfnT2YkX+wB2/M3oCgU+s30fAHGkbGZ0pCdNbFYFZLiH0iiMbTDl/0L/z7IdK0nH
++GLHVE7apPraKC6xl6rPWsD2iSfrmtIPQa0+rqbIVvKP5JdfJ8J4alI+OxFw/znQe
++V0/Rez0j22Fe119LZFFSXhRv+ZSvcq20xDwh00mzcumPWpYuCVPozA18yIhC9tNn
++ALHndz0tDseIdy9vC71jQWy9iwri3ueN0DekMMF8JGzI1Z6BAFzgyAx3DkHtwHg7
++B7qD0jPG5hJ5+yt323fYgJsuEAYoZ8/jzZ01pkX8bt+UsVN0DGnSGsI2ktnIIk3J
++l+8krjmUy6EaW79nITwoOqaeHOIp8m3UkjEcoKOYrzHRKqRy+A09rY+m/cAQaafW
++4xp0Zv7qZPLwnu0jsqB4jD8Ll9yPB02ndsoV6U5PeHzTkVhPml19jKUAwFfs7TJg
++kXy+/xFhYVUCAwEAATANBgkqhkiG9w0BAQsFAAOCBAIAAQnZY77pMNeypfpba2WK
++aDasT7dk2JqP0eukJCVPTN24Zca+xJNPdzuBATm/8SdZK9lddIbjSnWRsKvTnO2r
++/rYdlPf3jM5uuJtb8+Uwwe1s+gszelGS9G/lzzq+ehWicRIq2PFcs8o3iQMfENiv
++qILJ+xjcrvms5ZPDNahWkfRx3KCg8Q+/at2n5p7XYjMPYiLKHnDC+RE2b1qT20IZ
++FhuK/fTWLmKbfYFNNga6GC4qcaZJ7x0pbm4SDTYp0tkhzcHzwKhidfNB5J2vNz6l
++Ur6wiYwamFTLqcOwWo7rdvI+sSn05WQBv0QZlzFX+OAu0l7WQ7yU+noOxBhjvHds
++14+r9qcQZg2q9kG+evopYZqYXRUNNlZKo9MRBXhfrISulFAc5lRFQIXMXnglvAu+
++Ipz2gomEAOcOPNNVldhKAU94GAMJd/KfN0ZP7gX3YvPzuYU6XDhag5RTohXLm18w
++5AF+ES3DOQ6ixu3DTf0D+6qrDuK+prdX8ivcdTQVNOQ+MIZeGSc6NWWOTaMGJ3lg
++aZIxJUGdo6E7GBGiC1YTjgFKFbHzek1LRTh/LX3vbSudxwaG0HQxwsU9T4DWiMqa
++Fkf2KteLEUA6HrR+0XlAZrhwoqAmrJ+8lCFX3V0gE9lpENfVHlFXDGyx10DpTB28
++DdjnY3F7EPWNzwf9P3oNT69CKW3Bk6VVr3ROOJtDxVu1ioWo3TaXltQ0VOnap2Pu
++sa5wfrpfwBDuAS9JCDg4ttNp2nW3F7tgXC6xPqw5pvGwUppEw9XNrqV8TZrxduuv
++rQ3NyZ7KSzIpmFlD3UwV/fGfz3UQmHS6Ng1evrUID9DjfYNfRqSGIGjDfxGtYD+j
++Z1gLJZuhjJpNtwBkKRtlNtrCWCJK2hidK/foxwD7kwAPo2I9FjpltxCRywZUs07X
++KwXTfBR9v6ij1LV6K58hFS+8ezZyZ05CeVBFkMQdclTOSfuPxlMkQOtjp8QWDj+F
++j/MYziT5KBkHvcbrjdRtUJIAi4N7zCsPZtjik918AK1WBNRVqPbrgq/XSEXMfuvs
++6JbfK0B76vdBDRtJFC1JsvnIrGbUztxXzyQwFLaR/AjVJqpVlysLWzPKWVX6/+SJ
++u1NQOl2E8P6ycyBsuGnO89p0S4F8cMRcI2X1XQsZ7/q0NBrOMaEp5T3SrWo9GiQ3
++o2SBdbs3Y6MBPBtTu977Z/0RO63J3M5i2tjUiDfrFy7+VRLKr7qQ7JibohyB8QaR
++9tedgjn2f+of7PnP/PEl1cCphUZeHM7QKUMPT8dbqwmKtlYY43EHXcvNOT5IBk3X
++9lwJoZk/B2i+ZMRNSP34ztAwtxmasPt6RAWGQpWCn9qmttAHAnMfDqe7F7jVR6rS
++u58=
++-----END CERTIFICATE-----`
++
++func TestHandshakeRSATooBig(t *testing.T) {
++ testCert, _ := pem.Decode([]byte(largeRSAKeyCertPEM))
++
++ c := &Conn{conn: &discardConn{}, config: testConfig.Clone()}
++
++ expectedErr := "tls: server sent certificate containing RSA key larger than 8192 bits"
++ err := c.verifyServerCertificate([][]byte{testCert.Bytes})
++ if err == nil || err.Error() != expectedErr {
++ t.Errorf("Conn.verifyServerCertificate unexpected error: want %q, got %q", expectedErr, err)
++ }
++
++ expectedErr = "tls: client sent certificate containing RSA key larger than 8192 bits"
++ err = c.processCertsFromClient(Certificate{Certificate: [][]byte{testCert.Bytes}})
++ if err == nil || err.Error() != expectedErr {
++ t.Errorf("Conn.processCertsFromClient unexpected error: want %q, got %q", expectedErr, err)
++ }
++}
+diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
+index b16415a..2e36840 100644
+--- a/src/crypto/tls/handshake_server.go
++++ b/src/crypto/tls/handshake_server.go
+@@ -738,6 +738,10 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
+ c.sendAlert(alertBadCertificate)
+ return errors.New("tls: failed to parse client certificate: " + err.Error())
+ }
++ if certs[i].PublicKeyAlgorithm == x509.RSA && certs[i].PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
++ c.sendAlert(alertBadCertificate)
++ return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
++ }
+ }
+
+ if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) {
+--
+2.25.1
+
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
new file mode 100644
index 0000000000..00def8fcda
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-39318.patch
@@ -0,0 +1,262 @@
+From 023b542edf38e2a1f87fcefb9f75ff2f99401b4c Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Thu, 3 Aug 2023 12:24:13 -0700
+Subject: [PATCH] [release-branch.go1.20] html/template: support HTML-like
+ comments in script contexts
+
+Per Appendix B.1.1 of the ECMAScript specification, support HTML-like
+comments in script contexts. Also per section 12.5, support hashbang
+comments. This brings our parsing in-line with how browsers treat these
+comment types.
+
+Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
+reporting this issue.
+
+Fixes #62196
+Fixes #62395
+Fixes CVE-2023-39318
+
+Change-Id: Id512702c5de3ae46cf648e268cb10e1eb392a181
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976593
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014620
+Reviewed-on: https://go-review.googlesource.com/c/go/+/526098
+Run-TryBot: Cherry Mui <cherryyz@google.com>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+
+Upstream-Status: Backport from [https://github.com/golang/go/commit/023b542edf38e2a1f87fcefb9f75ff2f99401b4c]
+CVE: CVE-2023-39318
+Signed-off-by: Siddharth Doshi <sdoshi@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 | 26 +++++-----
+ src/html/template/transition.go | 80 ++++++++++++++++++++-----------
+ 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
+--- a/src/html/template/context.go
++++ b/src/html/template/context.go
+@@ -124,6 +124,10 @@ const (
+ stateJSBlockCmt
+ // stateJSLineCmt occurs inside a JavaScript // line comment.
+ stateJSLineCmt
++ // stateJSHTMLOpenCmt occurs inside a JavaScript <!-- HTML-like comment.
++ stateJSHTMLOpenCmt
++ // stateJSHTMLCloseCmt occurs inside a JavaScript --> HTML-like comment.
++ stateJSHTMLCloseCmt
+ // stateCSS occurs inside a <style> element or style attribute.
+ stateCSS
+ // stateCSSDqStr occurs inside a CSS double quoted string.
+@@ -149,7 +153,7 @@ const (
+ // authors & maintainers, not for end-users or machines.
+ func isComment(s state) bool {
+ switch s {
+- case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateCSSBlockCmt, stateCSSLineCmt:
++ case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt, stateCSSBlockCmt, stateCSSLineCmt:
+ return true
+ }
+ return false
+diff --git a/src/html/template/escape.go b/src/html/template/escape.go
+index 435f912..ad2ec69 100644
+--- a/src/html/template/escape.go
++++ b/src/html/template/escape.go
+@@ -698,9 +698,12 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
+ if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
+ // Preserve the portion between written and the comment start.
+ cs := i1 - 2
+- if c1.state == stateHTMLCmt {
++ if c1.state == stateHTMLCmt || c1.state == stateJSHTMLOpenCmt {
+ // "<!--" instead of "/*" or "//"
+ cs -= 2
++ } else if c1.state == stateJSHTMLCloseCmt {
++ // "-->" instead of "/*" or "//"
++ cs -= 1
+ }
+ b.Write(s[written:cs])
+ written = i1
+diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
+index f550691..5f41e52 100644
+--- a/src/html/template/escape_test.go
++++ b/src/html/template/escape_test.go
+@@ -503,6 +503,16 @@ func TestEscape(t *testing.T) {
+ "<script>var a/*b*///c\nd</script>",
+ "<script>var a \nd</script>",
+ },
++ {
++ "JS HTML-like comments",
++ "<script>before <!-- beep\nbetween\nbefore-->boop\n</script>",
++ "<script>before \nbetween\nbefore\n</script>",
++ },
++ {
++ "JS hashbang comment",
++ "<script>#! beep\n</script>",
++ "<script>\n</script>",
++ },
+ {
+ "CSS comments",
+ "<style>p// paragraph\n" +
+diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go
+index 05104be..b5cfe70 100644
+--- a/src/html/template/state_string.go
++++ b/src/html/template/state_string.go
+@@ -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 = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
++const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
+
+-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 {
+ if i >= state(len(_state_index)-1) {
+diff --git a/src/html/template/transition.go b/src/html/template/transition.go
+index 92eb351..12aa4c4 100644
+--- a/src/html/template/transition.go
++++ b/src/html/template/transition.go
+@@ -14,32 +14,34 @@ import (
+ // the updated context and the number of bytes consumed from the front of the
+ // input.
+ var transitionFunc = [...]func(context, []byte) (context, int){
+- stateText: tText,
+- stateTag: tTag,
+- stateAttrName: tAttrName,
+- stateAfterName: tAfterName,
+- stateBeforeValue: tBeforeValue,
+- stateHTMLCmt: tHTMLCmt,
+- stateRCDATA: tSpecialTagEnd,
+- stateAttr: tAttr,
+- stateURL: tURL,
+- stateSrcset: tURL,
+- stateJS: tJS,
+- stateJSDqStr: tJSDelimited,
+- stateJSSqStr: tJSDelimited,
+- stateJSBqStr: tJSDelimited,
+- stateJSRegexp: tJSDelimited,
+- stateJSBlockCmt: tBlockCmt,
+- stateJSLineCmt: tLineCmt,
+- stateCSS: tCSS,
+- stateCSSDqStr: tCSSStr,
+- stateCSSSqStr: tCSSStr,
+- stateCSSDqURL: tCSSStr,
+- stateCSSSqURL: tCSSStr,
+- stateCSSURL: tCSSStr,
+- stateCSSBlockCmt: tBlockCmt,
+- stateCSSLineCmt: tLineCmt,
+- stateError: tError,
++ stateText: tText,
++ stateTag: tTag,
++ stateAttrName: tAttrName,
++ stateAfterName: tAfterName,
++ stateBeforeValue: tBeforeValue,
++ stateHTMLCmt: tHTMLCmt,
++ stateRCDATA: tSpecialTagEnd,
++ stateAttr: tAttr,
++ stateURL: tURL,
++ stateSrcset: tURL,
++ stateJS: tJS,
++ stateJSDqStr: tJSDelimited,
++ stateJSSqStr: tJSDelimited,
++ stateJSBqStr: tJSDelimited,
++ stateJSRegexp: tJSDelimited,
++ stateJSBlockCmt: tBlockCmt,
++ stateJSLineCmt: tLineCmt,
++ stateJSHTMLOpenCmt: tLineCmt,
++ stateJSHTMLCloseCmt: tLineCmt,
++ stateCSS: tCSS,
++ stateCSSDqStr: tCSSStr,
++ stateCSSSqStr: tCSSStr,
++ stateCSSDqURL: tCSSStr,
++ stateCSSSqURL: tCSSStr,
++ stateCSSURL: tCSSStr,
++ stateCSSBlockCmt: tBlockCmt,
++ stateCSSLineCmt: tLineCmt,
++ stateError: tError,
+ }
+
+ var commentStart = []byte("<!--")
+@@ -263,7 +265,7 @@ func tURL(c context, s []byte) (context, int) {
+
+ // tJS is the context transition function for the JS state.
+ func tJS(c context, s []byte) (context, int) {
+- i := bytes.IndexAny(s, "\"`'/")
++ i := bytes.IndexAny(s, "\"`'/<-#")
+ if i == -1 {
+ // Entire input is non string, comment, regexp tokens.
+ c.jsCtx = nextJSCtx(s, c.jsCtx)
+@@ -293,6 +295,26 @@ func tJS(c context, s []byte) (context, int) {
+ err: errorf(ErrSlashAmbig, nil, 0, "'/' could start a division or regexp: %.32q", s[i:]),
+ }, len(s)
+ }
++ // ECMAScript supports HTML style comments for legacy reasons, see Appendix
++ // B.1.1 "HTML-like Comments". The handling of these comments is somewhat
++ // confusing. Multi-line comments are not supported, i.e. anything on lines
++ // between the opening and closing tokens is not considered a comment, but
++ // anything following the opening or closing token, on the same line, is
++ // ignored. As such we simply treat any line prefixed with "<!--" or "-->"
++ // as if it were actually prefixed with "//" and move on.
++ case '<':
++ if i+3 < len(s) && bytes.Equal(commentStart, s[i:i+4]) {
++ c.state, i = stateJSHTMLOpenCmt, i+3
++ }
++ case '-':
++ if i+2 < len(s) && bytes.Equal(commentEnd, s[i:i+3]) {
++ c.state, i = stateJSHTMLCloseCmt, i+2
++ }
++ // ECMAScript also supports "hashbang" comment lines, see Section 12.5.
++ case '#':
++ if i+1 < len(s) && s[i+1] == '!' {
++ c.state, i = stateJSLineCmt, i+1
++ }
+ default:
+ panic("unreachable")
+ }
+@@ -372,12 +394,12 @@ func tBlockCmt(c context, s []byte) (context, int) {
+ return c, i + 2
+ }
+
+-// tLineCmt is the context transition function for //comment states.
++// tLineCmt is the context transition function for //comment states, and the JS HTML-like comment state.
+ func tLineCmt(c context, s []byte) (context, int) {
+ var lineTerminators string
+ var endState state
+ switch c.state {
+- case stateJSLineCmt:
++ case stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt:
+ lineTerminators, endState = "\n\r\u2028\u2029", stateJS
+ case stateCSSLineCmt:
+ lineTerminators, endState = "\n\f\r", stateCSS
+--
+2.24.4
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch
new file mode 100644
index 0000000000..69106e3e05
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch
@@ -0,0 +1,230 @@
+From 2070531d2f53df88e312edace6c8dfc9686ab2f5 Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Thu, 3 Aug 2023 12:28:28 -0700
+Subject: [PATCH] [release-branch.go1.20] html/template: properly handle
+ special tags within the script context
+
+The HTML specification has incredibly complex rules for how to handle
+"<!--", "<script", and "</script" when they appear within literals in
+the script context. Rather than attempting to apply these restrictions
+(which require a significantly more complex state machine) we apply
+the workaround suggested in section 4.12.1.3 of the HTML specification [1].
+
+More precisely, when "<!--", "<script", and "</script" appear within
+literals (strings and regular expressions, ignoring comments since we
+already elide their content) we replace the "<" with "\x3C". This avoids
+the unintuitive behavior that using these tags within literals can cause,
+by simply preventing the rendered content from triggering it. This may
+break some correct usages of these tags, but on balance is more likely
+to prevent XSS attacks where users are unknowingly either closing or not
+closing the script blocks where they think they are.
+
+Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
+reporting this issue.
+
+Fixes #62197
+Fixes #62397
+Fixes CVE-2023-39319
+
+[1] https://html.spec.whatwg.org/#restrictions-for-contents-of-script-elements
+
+Change-Id: Iab57b0532694827e3eddf57a7497ba1fab1746dc
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976594
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014621
+TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/526099
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Run-TryBot: Cherry Mui <cherryyz@google.com>
+
+Upstream-Status: Backport from [https://github.com/golang/go/commit/2070531d2f53df88e312edace6c8dfc9686ab2f5]
+CVE: CVE-2023-39319
+Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
+---
+ src/html/template/context.go | 14 ++++++++++
+ src/html/template/escape.go | 26 ++++++++++++++++++
+ src/html/template/escape_test.go | 47 +++++++++++++++++++++++++++++++-
+ src/html/template/transition.go | 15 ++++++++++
+ 4 files changed, 101 insertions(+), 1 deletion(-)
+
+diff --git a/src/html/template/context.go b/src/html/template/context.go
+index 4eb7891..feb6517 100644
+--- a/src/html/template/context.go
++++ b/src/html/template/context.go
+@@ -168,6 +168,20 @@ func isInTag(s state) bool {
+ return false
+ }
+
++// isInScriptLiteral returns true if s is one of the literal states within a
++// <script> tag, and as such occurances of "<!--", "<script", and "</script"
++// need to be treated specially.
++func isInScriptLiteral(s state) bool {
++ // Ignore the comment states (stateJSBlockCmt, stateJSLineCmt,
++ // stateJSHTMLOpenCmt, stateJSHTMLCloseCmt) because their content is already
++ // omitted from the output.
++ switch s {
++ case stateJSDqStr, stateJSSqStr, stateJSBqStr, stateJSRegexp:
++ return true
++ }
++ return false
++}
++
+ // delim is the delimiter that will end the current HTML attribute.
+ type delim uint8
+
+diff --git a/src/html/template/escape.go b/src/html/template/escape.go
+index ad2ec69..de8cf6f 100644
+--- a/src/html/template/escape.go
++++ b/src/html/template/escape.go
+@@ -10,6 +10,7 @@ import (
+ "html"
+ "internal/godebug"
+ "io"
++ "regexp"
+ "text/template"
+ "text/template/parse"
+ )
+@@ -650,6 +651,26 @@ var delimEnds = [...]string{
+ delimSpaceOrTagEnd: " \t\n\f\r>",
+ }
+
++var (
++ // Per WHATWG HTML specification, section 4.12.1.3, there are extremely
++ // complicated rules for how to handle the set of opening tags <!--,
++ // <script, and </script when they appear in JS literals (i.e. strings,
++ // regexs, and comments). The specification suggests a simple solution,
++ // rather than implementing the arcane ABNF, which involves simply escaping
++ // the opening bracket with \x3C. We use the below regex for this, since it
++ // makes doing the case-insensitive find-replace much simpler.
++ specialScriptTagRE = regexp.MustCompile("(?i)<(script|/script|!--)")
++ specialScriptTagReplacement = []byte("\\x3C$1")
++)
++
++func containsSpecialScriptTag(s []byte) bool {
++ return specialScriptTagRE.Match(s)
++}
++
++func escapeSpecialScriptTags(s []byte) []byte {
++ return specialScriptTagRE.ReplaceAll(s, specialScriptTagReplacement)
++}
++
+ var doctypeBytes = []byte("<!DOCTYPE")
+
+ // escapeText escapes a text template node.
+@@ -708,6 +729,11 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
+ b.Write(s[written:cs])
+ written = i1
+ }
++ if isInScriptLiteral(c.state) && containsSpecialScriptTag(s[i:i1]) {
++ b.Write(s[written:i])
++ b.Write(escapeSpecialScriptTags(s[i:i1]))
++ written = i1
++ }
+ if i == i1 && c.state == c1.state {
+ panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
+ }
+diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
+index 5f41e52..0cacb20 100644
+--- a/src/html/template/escape_test.go
++++ b/src/html/template/escape_test.go
+@@ -513,6 +513,21 @@ func TestEscape(t *testing.T) {
+ "<script>#! beep\n</script>",
+ "<script>\n</script>",
+ },
++ {
++ "Special tags in <script> string literals",
++ `<script>var a = "asd < 123 <!-- 456 < fgh <script jkl < 789 </script"</script>`,
++ `<script>var a = "asd < 123 \x3C!-- 456 < fgh \x3Cscript jkl < 789 \x3C/script"</script>`,
++ },
++ {
++ "Special tags in <script> string literals (mixed case)",
++ `<script>var a = "<!-- <ScripT </ScripT"</script>`,
++ `<script>var a = "\x3C!-- \x3CScripT \x3C/ScripT"</script>`,
++ },
++ {
++ "Special tags in <script> regex literals (mixed case)",
++ `<script>var a = /<!-- <ScripT </ScripT/</script>`,
++ `<script>var a = /\x3C!-- \x3CScripT \x3C/ScripT/</script>`,
++ },
+ {
+ "CSS comments",
+ "<style>p// paragraph\n" +
+@@ -1501,8 +1516,38 @@ func TestEscapeText(t *testing.T) {
+ context{state: stateJS, element: elementScript},
+ },
+ {
++ // <script and </script tags are escaped, so </script> should not
++ // cause us to exit the JS state.
+ `<script>document.write("<script>alert(1)</script>");`,
+- context{state: stateText},
++ context{state: stateJS, element: elementScript},
++ },
++ {
++ `<script>document.write("<script>`,
++ context{state: stateJSDqStr, element: elementScript},
++ },
++ {
++ `<script>document.write("<script>alert(1)</script>`,
++ context{state: stateJSDqStr, element: elementScript},
++ },
++ {
++ `<script>document.write("<script>alert(1)<!--`,
++ context{state: stateJSDqStr, element: elementScript},
++ },
++ {
++ `<script>document.write("<script>alert(1)</Script>");`,
++ context{state: stateJS, element: elementScript},
++ },
++ {
++ `<script>document.write("<!--");`,
++ context{state: stateJS, element: elementScript},
++ },
++ {
++ `<script>let a = /</script`,
++ context{state: stateJSRegexp, element: elementScript},
++ },
++ {
++ `<script>let a = /</script/`,
++ context{state: stateJS, element: elementScript, jsCtx: jsCtxDivOp},
+ },
+ {
+ `<script type="text/template">`,
+diff --git a/src/html/template/transition.go b/src/html/template/transition.go
+index 12aa4c4..3d2a37c 100644
+--- a/src/html/template/transition.go
++++ b/src/html/template/transition.go
+@@ -214,6 +214,11 @@ var (
+ // element states.
+ func tSpecialTagEnd(c context, s []byte) (context, int) {
+ if c.element != elementNone {
++ // script end tags ("</script") within script literals are ignored, so that
++ // we can properly escape them.
++ if c.element == elementScript && (isInScriptLiteral(c.state) || isComment(c.state)) {
++ return c, len(s)
++ }
+ if i := indexTagEnd(s, specialTagEndMarkers[c.element]); i != -1 {
+ return context{}, i
+ }
+@@ -353,6 +358,16 @@ func tJSDelimited(c context, s []byte) (context, int) {
+ inCharset = true
+ case ']':
+ inCharset = false
++ case '/':
++ // If "</script" appears in a regex literal, the '/' should not
++ // close the regex literal, and it will later be escaped to
++ // "\x3C/script" in escapeText.
++ if i > 0 && i+7 <= len(s) && bytes.Compare(bytes.ToLower(s[i-1:i+7]), []byte("</script")) == 0 {
++ i++
++ } else if !inCharset {
++ c.state, c.jsCtx = stateJS, jsCtxDivOp
++ return c, i + 1
++ }
+ default:
+ // end delimiter
+ if !inCharset {
+--
+2.24.4
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-39326.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-39326.patch
new file mode 100644
index 0000000000..998af361e8
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-39326.patch
@@ -0,0 +1,181 @@
+From 6446af942e2e2b161c4ec1b60d9703a2b55dc4dd Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Tue, 7 Nov 2023 10:47:56 -0800
+Subject: [PATCH] [release-branch.go1.20] net/http: limit chunked data overhead
+
+The chunked transfer encoding adds some overhead to
+the content transferred. When writing one byte per
+chunk, for example, there are five bytes of overhead
+per byte of data transferred: "1\r\nX\r\n" to send "X".
+
+Chunks may include "chunk extensions",
+which we skip over and do not use.
+For example: "1;chunk extension here\r\nX\r\n".
+
+A malicious sender can use chunk extensions to add
+about 4k of overhead per byte of data.
+(The maximum chunk header line size we will accept.)
+
+Track the amount of overhead read in chunked data,
+and produce an error if it seems excessive.
+
+Updates #64433
+Fixes #64434
+Fixes CVE-2023-39326
+
+Change-Id: I40f8d70eb6f9575fb43f506eb19132ccedafcf39
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2076135
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+(cherry picked from commit 3473ae72ee66c60744665a24b2fde143e8964d4f)
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2095407
+Run-TryBot: Roland Shoemaker <bracewell@google.com>
+TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/547355
+Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
+LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/6446af942e2e2b161c4ec1b60d9703a2b55dc4dd]
+CVE: CVE-2023-39326
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/net/http/internal/chunked.go | 36 +++++++++++++---
+ src/net/http/internal/chunked_test.go | 59 +++++++++++++++++++++++++++
+ 2 files changed, 89 insertions(+), 6 deletions(-)
+
+diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go
+index f06e572..ddbaacb 100644
+--- a/src/net/http/internal/chunked.go
++++ b/src/net/http/internal/chunked.go
+@@ -39,7 +39,8 @@ type chunkedReader struct {
+ n uint64 // unread bytes in chunk
+ err error
+ buf [2]byte
+- checkEnd bool // whether need to check for \r\n chunk footer
++ checkEnd bool // whether need to check for \r\n chunk footer
++ excess int64 // "excessive" chunk overhead, for malicious sender detection
+ }
+
+ func (cr *chunkedReader) beginChunk() {
+@@ -49,10 +50,38 @@ func (cr *chunkedReader) beginChunk() {
+ if cr.err != nil {
+ return
+ }
++ cr.excess += int64(len(line)) + 2 // header, plus \r\n after the chunk data
++ line = trimTrailingWhitespace(line)
++ line, cr.err = removeChunkExtension(line)
++ if cr.err != nil {
++ return
++ }
+ cr.n, cr.err = parseHexUint(line)
+ if cr.err != nil {
+ return
+ }
++ // A sender who sends one byte per chunk will send 5 bytes of overhead
++ // for every byte of data. ("1\r\nX\r\n" to send "X".)
++ // We want to allow this, since streaming a byte at a time can be legitimate.
++ //
++ // A sender can use chunk extensions to add arbitrary amounts of additional
++ // data per byte read. ("1;very long extension\r\nX\r\n" to send "X".)
++ // We don't want to disallow extensions (although we discard them),
++ // but we also don't want to allow a sender to reduce the signal/noise ratio
++ // arbitrarily.
++ //
++ // We track the amount of excess overhead read,
++ // and produce an error if it grows too large.
++ //
++ // Currently, we say that we're willing to accept 16 bytes of overhead per chunk,
++ // plus twice the amount of real data in the chunk.
++ cr.excess -= 16 + (2 * int64(cr.n))
++ if cr.excess < 0 {
++ cr.excess = 0
++ }
++ if cr.excess > 16*1024 {
++ cr.err = errors.New("chunked encoding contains too much non-data")
++ }
+ if cr.n == 0 {
+ cr.err = io.EOF
+ }
+@@ -133,11 +162,6 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) {
+ if len(p) >= maxLineLength {
+ return nil, ErrLineTooLong
+ }
+- p = trimTrailingWhitespace(p)
+- p, err = removeChunkExtension(p)
+- if err != nil {
+- return nil, err
+- }
+ return p, nil
+ }
+
+diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go
+index d067165..b20747d 100644
+--- a/src/net/http/internal/chunked_test.go
++++ b/src/net/http/internal/chunked_test.go
+@@ -212,3 +212,62 @@ func TestChunkReadPartial(t *testing.T) {
+ }
+
+ }
++
++func TestChunkReaderTooMuchOverhead(t *testing.T) {
++ // If the sender is sending 100x as many chunk header bytes as chunk data,
++ // we should reject the stream at some point.
++ chunk := []byte("1;")
++ for i := 0; i < 100; i++ {
++ chunk = append(chunk, 'a') // chunk extension
++ }
++ chunk = append(chunk, "\r\nX\r\n"...)
++ const bodylen = 1 << 20
++ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) {
++ if i < bodylen {
++ return chunk, nil
++ }
++ return []byte("0\r\n"), nil
++ }})
++ _, err := io.ReadAll(r)
++ if err == nil {
++ t.Fatalf("successfully read body with excessive overhead; want error")
++ }
++}
++
++func TestChunkReaderByteAtATime(t *testing.T) {
++ // Sending one byte per chunk should not trip the excess-overhead detection.
++ const bodylen = 1 << 20
++ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) {
++ if i < bodylen {
++ return []byte("1\r\nX\r\n"), nil
++ }
++ return []byte("0\r\n"), nil
++ }})
++ got, err := io.ReadAll(r)
++ if err != nil {
++ t.Errorf("unexpected error: %v", err)
++ }
++ if len(got) != bodylen {
++ t.Errorf("read %v bytes, want %v", len(got), bodylen)
++ }
++}
++
++type funcReader struct {
++ f func(iteration int) ([]byte, error)
++ i int
++ b []byte
++ err error
++}
++
++func (r *funcReader) Read(p []byte) (n int, err error) {
++ if len(r.b) == 0 && r.err == nil {
++ r.b, r.err = r.f(r.i)
++ r.i++
++ }
++ n = copy(p, r.b)
++ r.b = r.b[n:]
++ if len(r.b) > 0 {
++ return n, nil
++ }
++ return n, r.err
++}
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre1.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre1.patch
new file mode 100644
index 0000000000..4d65180253
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre1.patch
@@ -0,0 +1,393 @@
+From 9baafabac9a84813a336f068862207d2bb06d255 Mon Sep 17 00:00:00 2001
+From: Filippo Valsorda <filippo@golang.org>
+Date: Wed, 1 Apr 2020 17:25:40 -0400
+Subject: [PATCH] crypto/rsa: refactor RSA-PSS signing and verification
+
+Cleaned up for readability and consistency.
+
+There is one tiny behavioral change: when PSSSaltLengthEqualsHash is
+used and both hash and opts.Hash were set, hash.Size() was used for the
+salt length instead of opts.Hash.Size(). That's clearly wrong because
+opts.Hash is documented to override hash.
+
+Change-Id: I3e25dad933961eac827c6d2e3bbfe45fc5a6fb0e
+Reviewed-on: https://go-review.googlesource.com/c/go/+/226937
+Run-TryBot: Filippo Valsorda <filippo@golang.org>
+TryBot-Result: Gobot Gobot <gobot@golang.org>
+Reviewed-by: Katie Hockman <katie@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/9baafabac9a84813a336f068862207d2bb06d255]
+CVE: CVE-2023-45287 #Dependency Patch1
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/crypto/rsa/pss.go | 173 ++++++++++++++++++++++--------------------
+ src/crypto/rsa/rsa.go | 9 ++-
+ 2 files changed, 96 insertions(+), 86 deletions(-)
+
+diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
+index 3ff0c2f4d0076..f9844d87329a8 100644
+--- a/src/crypto/rsa/pss.go
++++ b/src/crypto/rsa/pss.go
+@@ -4,9 +4,7 @@
+
+ package rsa
+
+-// This file implements the PSS signature scheme [1].
+-//
+-// [1] https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf
++// This file implements the RSASSA-PSS signature scheme according to RFC 8017.
+
+ import (
+ "bytes"
+@@ -17,8 +15,22 @@ import (
+ "math/big"
+ )
+
++// Per RFC 8017, Section 9.1
++//
++// EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc
++//
++// where
++//
++// DB = PS || 0x01 || salt
++//
++// and PS can be empty so
++//
++// emLen = dbLen + hLen + 1 = psLen + sLen + hLen + 2
++//
++
+ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
+- // See [1], section 9.1.1
++ // See RFC 8017, Section 9.1.1.
++
+ hLen := hash.Size()
+ sLen := len(salt)
+ emLen := (emBits + 7) / 8
+@@ -30,7 +42,7 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
+ // 2. Let mHash = Hash(M), an octet string of length hLen.
+
+ if len(mHash) != hLen {
+- return nil, errors.New("crypto/rsa: input must be hashed message")
++ return nil, errors.New("crypto/rsa: input must be hashed with given hash")
+ }
+
+ // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop.
+@@ -40,8 +52,9 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
+ }
+
+ em := make([]byte, emLen)
+- db := em[:emLen-sLen-hLen-2+1+sLen]
+- h := em[emLen-sLen-hLen-2+1+sLen : emLen-1]
++ psLen := emLen - sLen - hLen - 2
++ db := em[:psLen+1+sLen]
++ h := em[psLen+1+sLen : emLen-1]
+
+ // 4. Generate a random octet string salt of length sLen; if sLen = 0,
+ // then salt is the empty string.
+@@ -69,8 +82,8 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
+ // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length
+ // emLen - hLen - 1.
+
+- db[emLen-sLen-hLen-2] = 0x01
+- copy(db[emLen-sLen-hLen-1:], salt)
++ db[psLen] = 0x01
++ copy(db[psLen+1:], salt)
+
+ // 9. Let dbMask = MGF(H, emLen - hLen - 1).
+ //
+@@ -81,47 +94,57 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
+ // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in
+ // maskedDB to zero.
+
+- db[0] &= (0xFF >> uint(8*emLen-emBits))
++ db[0] &= 0xff >> (8*emLen - emBits)
+
+ // 12. Let EM = maskedDB || H || 0xbc.
+- em[emLen-1] = 0xBC
++ em[emLen-1] = 0xbc
+
+ // 13. Output EM.
+ return em, nil
+ }
+
+ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
++ // See RFC 8017, Section 9.1.2.
++
++ hLen := hash.Size()
++ if sLen == PSSSaltLengthEqualsHash {
++ sLen = hLen
++ }
++ emLen := (emBits + 7) / 8
++ if emLen != len(em) {
++ return errors.New("rsa: internal error: inconsistent length")
++ }
++
+ // 1. If the length of M is greater than the input limitation for the
+ // hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
+ // and stop.
+ //
+ // 2. Let mHash = Hash(M), an octet string of length hLen.
+- hLen := hash.Size()
+ if hLen != len(mHash) {
+ return ErrVerification
+ }
+
+ // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop.
+- emLen := (emBits + 7) / 8
+ if emLen < hLen+sLen+2 {
+ return ErrVerification
+ }
+
+ // 4. If the rightmost octet of EM does not have hexadecimal value
+ // 0xbc, output "inconsistent" and stop.
+- if em[len(em)-1] != 0xBC {
++ if em[emLen-1] != 0xbc {
+ return ErrVerification
+ }
+
+ // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
+ // let H be the next hLen octets.
+ db := em[:emLen-hLen-1]
+- h := em[emLen-hLen-1 : len(em)-1]
++ h := em[emLen-hLen-1 : emLen-1]
+
+ // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in
+ // maskedDB are not all equal to zero, output "inconsistent" and
+ // stop.
+- if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 {
++ var bitMask byte = 0xff >> (8*emLen - emBits)
++ if em[0] & ^bitMask != 0 {
+ return ErrVerification
+ }
+
+@@ -132,37 +155,30 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
+
+ // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
+ // to zero.
+- db[0] &= (0xFF >> uint(8*emLen-emBits))
++ db[0] &= bitMask
+
++ // If we don't know the salt length, look for the 0x01 delimiter.
+ if sLen == PSSSaltLengthAuto {
+- FindSaltLength:
+- for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- {
+- switch db[emLen-hLen-sLen-2] {
+- case 1:
+- break FindSaltLength
+- case 0:
+- continue
+- default:
+- return ErrVerification
+- }
+- }
+- if sLen < 0 {
++ psLen := bytes.IndexByte(db, 0x01)
++ if psLen < 0 {
+ return ErrVerification
+ }
+- } else {
+- // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
+- // or if the octet at position emLen - hLen - sLen - 1 (the leftmost
+- // position is "position 1") does not have hexadecimal value 0x01,
+- // output "inconsistent" and stop.
+- for _, e := range db[:emLen-hLen-sLen-2] {
+- if e != 0x00 {
+- return ErrVerification
+- }
+- }
+- if db[emLen-hLen-sLen-2] != 0x01 {
++ sLen = len(db) - psLen - 1
++ }
++
++ // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
++ // or if the octet at position emLen - hLen - sLen - 1 (the leftmost
++ // position is "position 1") does not have hexadecimal value 0x01,
++ // output "inconsistent" and stop.
++ psLen := emLen - hLen - sLen - 2
++ for _, e := range db[:psLen] {
++ if e != 0x00 {
+ return ErrVerification
+ }
+ }
++ if db[psLen] != 0x01 {
++ return ErrVerification
++ }
+
+ // 11. Let salt be the last sLen octets of DB.
+ salt := db[len(db)-sLen:]
+@@ -181,19 +197,19 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
+ h0 := hash.Sum(nil)
+
+ // 14. If H = H', output "consistent." Otherwise, output "inconsistent."
+- if !bytes.Equal(h0, h) {
++ if !bytes.Equal(h0, h) { // TODO: constant time?
+ return ErrVerification
+ }
+ return nil
+ }
+
+-// signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt.
++// signPSSWithSalt calculates the signature of hashed using PSS with specified salt.
+ // Note that hashed must be the result of hashing the input message using the
+ // given hash function. salt is a random sequence of bytes whose length will be
+ // later used to verify the signature.
+ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
+- nBits := priv.N.BitLen()
+- em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New())
++ emBits := priv.N.BitLen() - 1
++ em, err := emsaPSSEncode(hashed, emBits, salt, hash.New())
+ if err != nil {
+ return
+ }
+@@ -202,7 +218,7 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed,
+ if err != nil {
+ return
+ }
+- s = make([]byte, (nBits+7)/8)
++ s = make([]byte, priv.Size())
+ copyWithLeftPad(s, c.Bytes())
+ return
+ }
+@@ -223,16 +239,15 @@ type PSSOptions struct {
+ // PSSSaltLength constants.
+ SaltLength int
+
+- // Hash, if not zero, overrides the hash function passed to SignPSS.
+- // This is the only way to specify the hash function when using the
+- // crypto.Signer interface.
++ // Hash is the hash function used to generate the message digest. If not
++ // zero, it overrides the hash function passed to SignPSS. It's required
++ // when using PrivateKey.Sign.
+ Hash crypto.Hash
+ }
+
+-// HashFunc returns pssOpts.Hash so that PSSOptions implements
+-// crypto.SignerOpts.
+-func (pssOpts *PSSOptions) HashFunc() crypto.Hash {
+- return pssOpts.Hash
++// HashFunc returns opts.Hash so that PSSOptions implements crypto.SignerOpts.
++func (opts *PSSOptions) HashFunc() crypto.Hash {
++ return opts.Hash
+ }
+
+ func (opts *PSSOptions) saltLength() int {
+@@ -242,56 +257,50 @@ func (opts *PSSOptions) saltLength() int {
+ return opts.SaltLength
+ }
+
+-// SignPSS calculates the signature of hashed using RSASSA-PSS [1].
+-// Note that hashed must be the result of hashing the input message using the
+-// given hash function. The opts argument may be nil, in which case sensible
+-// defaults are used.
+-func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) ([]byte, error) {
++// SignPSS calculates the signature of digest using PSS.
++//
++// digest must be the result of hashing the input message using the given hash
++// function. The opts argument may be nil, in which case sensible defaults are
++// used. If opts.Hash is set, it overrides hash.
++func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) {
++ if opts != nil && opts.Hash != 0 {
++ hash = opts.Hash
++ }
++
+ saltLength := opts.saltLength()
+ switch saltLength {
+ case PSSSaltLengthAuto:
+- saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size()
++ saltLength = priv.Size() - 2 - hash.Size()
+ case PSSSaltLengthEqualsHash:
+ saltLength = hash.Size()
+ }
+
+- if opts != nil && opts.Hash != 0 {
+- hash = opts.Hash
+- }
+-
+ salt := make([]byte, saltLength)
+ if _, err := io.ReadFull(rand, salt); err != nil {
+ return nil, err
+ }
+- return signPSSWithSalt(rand, priv, hash, hashed, salt)
++ return signPSSWithSalt(rand, priv, hash, digest, salt)
+ }
+
+ // VerifyPSS verifies a PSS signature.
+-// hashed is the result of hashing the input message using the given hash
+-// function and sig is the signature. A valid signature is indicated by
+-// returning a nil error. The opts argument may be nil, in which case sensible
+-// defaults are used.
+-func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error {
+- return verifyPSS(pub, hash, hashed, sig, opts.saltLength())
+-}
+-
+-// verifyPSS verifies a PSS signature with the given salt length.
+-func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
+- nBits := pub.N.BitLen()
+- if len(sig) != (nBits+7)/8 {
++//
++// A valid signature is indicated by returning a nil error. digest must be the
++// result of hashing the input message using the given hash function. The opts
++// argument may be nil, in which case sensible defaults are used. opts.Hash is
++// ignored.
++func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error {
++ if len(sig) != pub.Size() {
+ return ErrVerification
+ }
+ s := new(big.Int).SetBytes(sig)
+ m := encrypt(new(big.Int), pub, s)
+- emBits := nBits - 1
++ emBits := pub.N.BitLen() - 1
+ emLen := (emBits + 7) / 8
+- if emLen < len(m.Bytes()) {
++ emBytes := m.Bytes()
++ if emLen < len(emBytes) {
+ return ErrVerification
+ }
+ em := make([]byte, emLen)
+- copyWithLeftPad(em, m.Bytes())
+- if saltLen == PSSSaltLengthEqualsHash {
+- saltLen = hash.Size()
+- }
+- return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New())
++ copyWithLeftPad(em, emBytes)
++ return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New())
+ }
+diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
+index 5a42990640164..b4bfa13defbdf 100644
+--- a/src/crypto/rsa/rsa.go
++++ b/src/crypto/rsa/rsa.go
+@@ -2,7 +2,7 @@
+ // Use of this source code is governed by a BSD-style
+ // license that can be found in the LICENSE file.
+
+-// Package rsa implements RSA encryption as specified in PKCS#1.
++// Package rsa implements RSA encryption as specified in PKCS#1 and RFC 8017.
+ //
+ // RSA is a single, fundamental operation that is used in this package to
+ // implement either public-key encryption or public-key signatures.
+@@ -10,13 +10,13 @@
+ // The original specification for encryption and signatures with RSA is PKCS#1
+ // and the terms "RSA encryption" and "RSA signatures" by default refer to
+ // PKCS#1 version 1.5. However, that specification has flaws and new designs
+-// should use version two, usually called by just OAEP and PSS, where
++// should use version 2, usually called by just OAEP and PSS, where
+ // possible.
+ //
+ // Two sets of interfaces are included in this package. When a more abstract
+ // interface isn't necessary, there are functions for encrypting/decrypting
+ // with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract
+-// over the public-key primitive, the PrivateKey struct implements the
++// over the public key primitive, the PrivateKey type implements the
+ // Decrypter and Signer interfaces from the crypto package.
+ //
+ // The RSA operations in this package are not implemented using constant-time algorithms.
+@@ -111,7 +111,8 @@ func (priv *PrivateKey) Public() crypto.PublicKey {
+
+ // Sign signs digest with priv, reading randomness from rand. If opts is a
+ // *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will
+-// be used.
++// be used. digest must be the result of hashing the input message using
++// opts.HashFunc().
+ //
+ // This method implements crypto.Signer, which is an interface to support keys
+ // where the private part is kept in, for example, a hardware module. Common
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre2.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre2.patch
new file mode 100644
index 0000000000..1327b44545
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre2.patch
@@ -0,0 +1,401 @@
+From c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3 Mon Sep 17 00:00:00 2001
+From: Filippo Valsorda <filippo@golang.org>
+Date: Mon, 27 Apr 2020 21:52:38 -0400
+Subject: [PATCH] math/big: add (*Int).FillBytes
+
+Replaced almost every use of Bytes with FillBytes.
+
+Note that the approved proposal was for
+
+ func (*Int) FillBytes(buf []byte)
+
+while this implements
+
+ func (*Int) FillBytes(buf []byte) []byte
+
+because the latter was far nicer to use in all callsites.
+
+Fixes #35833
+
+Change-Id: Ia912df123e5d79b763845312ea3d9a8051343c0a
+Reviewed-on: https://go-review.googlesource.com/c/go/+/230397
+Reviewed-by: Robert Griesemer <gri@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3]
+CVE: CVE-2023-45287 #Dependency Patch2
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/crypto/elliptic/elliptic.go | 13 ++++----
+ src/crypto/rsa/pkcs1v15.go | 20 +++---------
+ src/crypto/rsa/pss.go | 17 +++++------
+ src/crypto/rsa/rsa.go | 32 +++----------------
+ src/crypto/tls/key_schedule.go | 7 ++---
+ src/crypto/x509/sec1.go | 7 ++---
+ src/math/big/int.go | 15 +++++++++
+ src/math/big/int_test.go | 54 +++++++++++++++++++++++++++++++++
+ src/math/big/nat.go | 15 ++++++---
+ 9 files changed, 106 insertions(+), 74 deletions(-)
+
+diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go
+index e2f71cdb63bab..bd5168c5fd842 100644
+--- a/src/crypto/elliptic/elliptic.go
++++ b/src/crypto/elliptic/elliptic.go
+@@ -277,7 +277,7 @@ var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
+ func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) {
+ N := curve.Params().N
+ bitSize := N.BitLen()
+- byteLen := (bitSize + 7) >> 3
++ byteLen := (bitSize + 7) / 8
+ priv = make([]byte, byteLen)
+
+ for x == nil {
+@@ -304,15 +304,14 @@ func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err e
+
+ // Marshal converts a point into the uncompressed form specified in section 4.3.6 of ANSI X9.62.
+ func Marshal(curve Curve, x, y *big.Int) []byte {
+- byteLen := (curve.Params().BitSize + 7) >> 3
++ byteLen := (curve.Params().BitSize + 7) / 8
+
+ ret := make([]byte, 1+2*byteLen)
+ ret[0] = 4 // uncompressed point
+
+- xBytes := x.Bytes()
+- copy(ret[1+byteLen-len(xBytes):], xBytes)
+- yBytes := y.Bytes()
+- copy(ret[1+2*byteLen-len(yBytes):], yBytes)
++ x.FillBytes(ret[1 : 1+byteLen])
++ y.FillBytes(ret[1+byteLen : 1+2*byteLen])
++
+ return ret
+ }
+
+@@ -320,7 +319,7 @@ func Marshal(curve Curve, x, y *big.Int) []byte {
+ // It is an error if the point is not in uncompressed form or is not on the curve.
+ // On error, x = nil.
+ func Unmarshal(curve Curve, data []byte) (x, y *big.Int) {
+- byteLen := (curve.Params().BitSize + 7) >> 3
++ byteLen := (curve.Params().BitSize + 7) / 8
+ if len(data) != 1+2*byteLen {
+ return
+ }
+diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go
+index 499242ffc5b57..3208119ae1ff4 100644
+--- a/src/crypto/rsa/pkcs1v15.go
++++ b/src/crypto/rsa/pkcs1v15.go
+@@ -61,8 +61,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)
+ m := new(big.Int).SetBytes(em)
+ c := encrypt(new(big.Int), pub, m)
+
+- copyWithLeftPad(em, c.Bytes())
+- return em, nil
++ return c.FillBytes(em), nil
+ }
+
+ // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
+@@ -150,7 +149,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
+ return
+ }
+
+- em = leftPad(m.Bytes(), k)
++ em = m.FillBytes(make([]byte, k))
+ firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
+ secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
+
+@@ -256,8 +255,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
+ return nil, err
+ }
+
+- copyWithLeftPad(em, c.Bytes())
+- return em, nil
++ return c.FillBytes(em), nil
+ }
+
+ // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
+@@ -286,7 +284,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
+
+ c := new(big.Int).SetBytes(sig)
+ m := encrypt(new(big.Int), pub, c)
+- em := leftPad(m.Bytes(), k)
++ em := m.FillBytes(make([]byte, k))
+ // EM = 0x00 || 0x01 || PS || 0x00 || T
+
+ ok := subtle.ConstantTimeByteEq(em[0], 0)
+@@ -323,13 +321,3 @@ func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte,
+ }
+ return
+ }
+-
+-// copyWithLeftPad copies src to the end of dest, padding with zero bytes as
+-// needed.
+-func copyWithLeftPad(dest, src []byte) {
+- numPaddingBytes := len(dest) - len(src)
+- for i := 0; i < numPaddingBytes; i++ {
+- dest[i] = 0
+- }
+- copy(dest[numPaddingBytes:], src)
+-}
+diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
+index f9844d87329a8..b2adbedb28fa8 100644
+--- a/src/crypto/rsa/pss.go
++++ b/src/crypto/rsa/pss.go
+@@ -207,20 +207,19 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
+ // Note that hashed must be the result of hashing the input message using the
+ // given hash function. salt is a random sequence of bytes whose length will be
+ // later used to verify the signature.
+-func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
++func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) {
+ emBits := priv.N.BitLen() - 1
+ em, err := emsaPSSEncode(hashed, emBits, salt, hash.New())
+ if err != nil {
+- return
++ return nil, err
+ }
+ m := new(big.Int).SetBytes(em)
+ c, err := decryptAndCheck(rand, priv, m)
+ if err != nil {
+- return
++ return nil, err
+ }
+- s = make([]byte, priv.Size())
+- copyWithLeftPad(s, c.Bytes())
+- return
++ s := make([]byte, priv.Size())
++ return c.FillBytes(s), nil
+ }
+
+ const (
+@@ -296,11 +295,9 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts
+ m := encrypt(new(big.Int), pub, s)
+ emBits := pub.N.BitLen() - 1
+ emLen := (emBits + 7) / 8
+- emBytes := m.Bytes()
+- if emLen < len(emBytes) {
++ if m.BitLen() > emLen*8 {
+ return ErrVerification
+ }
+- em := make([]byte, emLen)
+- copyWithLeftPad(em, emBytes)
++ em := m.FillBytes(make([]byte, emLen))
+ return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New())
+ }
+diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
+index b4bfa13defbdf..28eb5926c1a54 100644
+--- a/src/crypto/rsa/rsa.go
++++ b/src/crypto/rsa/rsa.go
+@@ -416,16 +416,9 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
+ m := new(big.Int)
+ m.SetBytes(em)
+ c := encrypt(new(big.Int), pub, m)
+- out := c.Bytes()
+
+- if len(out) < k {
+- // If the output is too small, we need to left-pad with zeros.
+- t := make([]byte, k)
+- copy(t[k-len(out):], out)
+- out = t
+- }
+-
+- return out, nil
++ out := make([]byte, k)
++ return c.FillBytes(out), nil
+ }
+
+ // ErrDecryption represents a failure to decrypt a message.
+@@ -597,12 +590,9 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
+ lHash := hash.Sum(nil)
+ hash.Reset()
+
+- // Converting the plaintext number to bytes will strip any
+- // leading zeros so we may have to left pad. We do this unconditionally
+- // to avoid leaking timing information. (Although we still probably
+- // leak the number of leading zeros. It's not clear that we can do
+- // anything about this.)
+- em := leftPad(m.Bytes(), k)
++ // We probably leak the number of leading zeros.
++ // It's not clear that we can do anything about this.
++ em := m.FillBytes(make([]byte, k))
+
+ firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
+
+@@ -643,15 +633,3 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
+
+ return rest[index+1:], nil
+ }
+-
+-// leftPad returns a new slice of length size. The contents of input are right
+-// aligned in the new slice.
+-func leftPad(input []byte, size int) (out []byte) {
+- n := len(input)
+- if n > size {
+- n = size
+- }
+- out = make([]byte, size)
+- copy(out[len(out)-n:], input)
+- return
+-}
+diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go
+index 2aab323202f7d..314016979afb8 100644
+--- a/src/crypto/tls/key_schedule.go
++++ b/src/crypto/tls/key_schedule.go
+@@ -173,11 +173,8 @@ func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte {
+ }
+
+ xShared, _ := curve.ScalarMult(x, y, p.privateKey)
+- sharedKey := make([]byte, (curve.Params().BitSize+7)>>3)
+- xBytes := xShared.Bytes()
+- copy(sharedKey[len(sharedKey)-len(xBytes):], xBytes)
+-
+- return sharedKey
++ sharedKey := make([]byte, (curve.Params().BitSize+7)/8)
++ return xShared.FillBytes(sharedKey)
+ }
+
+ type x25519Parameters struct {
+diff --git a/src/crypto/x509/sec1.go b/src/crypto/x509/sec1.go
+index 0bfb90cd5464a..52c108ff1d624 100644
+--- a/src/crypto/x509/sec1.go
++++ b/src/crypto/x509/sec1.go
+@@ -52,13 +52,10 @@ func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
+ // marshalECPrivateKey marshals an EC private key into ASN.1, DER format and
+ // sets the curve ID to the given OID, or omits it if OID is nil.
+ func marshalECPrivateKeyWithOID(key *ecdsa.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) {
+- privateKeyBytes := key.D.Bytes()
+- paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
+- copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
+-
++ privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
+ return asn1.Marshal(ecPrivateKey{
+ Version: 1,
+- PrivateKey: paddedPrivateKey,
++ PrivateKey: key.D.FillBytes(privateKey),
+ NamedCurveOID: oid,
+ PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
+ })
+diff --git a/src/math/big/int.go b/src/math/big/int.go
+index 8816cf5266cc4..65f32487b58c0 100644
+--- a/src/math/big/int.go
++++ b/src/math/big/int.go
+@@ -447,11 +447,26 @@ func (z *Int) SetBytes(buf []byte) *Int {
+ }
+
+ // Bytes returns the absolute value of x as a big-endian byte slice.
++//
++// To use a fixed length slice, or a preallocated one, use FillBytes.
+ func (x *Int) Bytes() []byte {
+ buf := make([]byte, len(x.abs)*_S)
+ return buf[x.abs.bytes(buf):]
+ }
+
++// FillBytes sets buf to the absolute value of x, storing it as a zero-extended
++// big-endian byte slice, and returns buf.
++//
++// If the absolute value of x doesn't fit in buf, FillBytes will panic.
++func (x *Int) FillBytes(buf []byte) []byte {
++ // Clear whole buffer. (This gets optimized into a memclr.)
++ for i := range buf {
++ buf[i] = 0
++ }
++ x.abs.bytes(buf)
++ return buf
++}
++
+ // BitLen returns the length of the absolute value of x in bits.
+ // The bit length of 0 is 0.
+ func (x *Int) BitLen() int {
+diff --git a/src/math/big/int_test.go b/src/math/big/int_test.go
+index e3a1587b3f0ad..3c8557323a032 100644
+--- a/src/math/big/int_test.go
++++ b/src/math/big/int_test.go
+@@ -1840,3 +1840,57 @@ func BenchmarkDiv(b *testing.B) {
+ })
+ }
+ }
++
++func TestFillBytes(t *testing.T) {
++ checkResult := func(t *testing.T, buf []byte, want *Int) {
++ t.Helper()
++ got := new(Int).SetBytes(buf)
++ if got.CmpAbs(want) != 0 {
++ t.Errorf("got 0x%x, want 0x%x: %x", got, want, buf)
++ }
++ }
++ panics := func(f func()) (panic bool) {
++ defer func() { panic = recover() != nil }()
++ f()
++ return
++ }
++
++ for _, n := range []string{
++ "0",
++ "1000",
++ "0xffffffff",
++ "-0xffffffff",
++ "0xffffffffffffffff",
++ "0x10000000000000000",
++ "0xabababababababababababababababababababababababababa",
++ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
++ } {
++ t.Run(n, func(t *testing.T) {
++ t.Logf(n)
++ x, ok := new(Int).SetString(n, 0)
++ if !ok {
++ panic("invalid test entry")
++ }
++
++ // Perfectly sized buffer.
++ byteLen := (x.BitLen() + 7) / 8
++ buf := make([]byte, byteLen)
++ checkResult(t, x.FillBytes(buf), x)
++
++ // Way larger, checking all bytes get zeroed.
++ buf = make([]byte, 100)
++ for i := range buf {
++ buf[i] = 0xff
++ }
++ checkResult(t, x.FillBytes(buf), x)
++
++ // Too small.
++ if byteLen > 0 {
++ buf = make([]byte, byteLen-1)
++ if !panics(func() { x.FillBytes(buf) }) {
++ t.Errorf("expected panic for small buffer and value %x", x)
++ }
++ }
++ })
++ }
++}
+diff --git a/src/math/big/nat.go b/src/math/big/nat.go
+index c31ec5156b81d..6a3989bf9d82b 100644
+--- a/src/math/big/nat.go
++++ b/src/math/big/nat.go
+@@ -1476,19 +1476,26 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
+ }
+
+ // bytes writes the value of z into buf using big-endian encoding.
+-// len(buf) must be >= len(z)*_S. The value of z is encoded in the
+-// slice buf[i:]. The number i of unused bytes at the beginning of
+-// buf is returned as result.
++// The value of z is encoded in the slice buf[i:]. If the value of z
++// cannot be represented in buf, bytes panics. The number i of unused
++// bytes at the beginning of buf is returned as result.
+ func (z nat) bytes(buf []byte) (i int) {
+ i = len(buf)
+ for _, d := range z {
+ for j := 0; j < _S; j++ {
+ i--
+- buf[i] = byte(d)
++ if i >= 0 {
++ buf[i] = byte(d)
++ } else if byte(d) != 0 {
++ panic("math/big: buffer too small to fit value")
++ }
+ d >>= 8
+ }
+ }
+
++ if i < 0 {
++ i = 0
++ }
+ for i < len(buf) && buf[i] == 0 {
+ i++
+ }
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre3.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre3.patch
new file mode 100644
index 0000000000..ae9fcc170c
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre3.patch
@@ -0,0 +1,86 @@
+From 8f676144ad7b7c91adb0c6e1ec89aaa6283c6807 Mon Sep 17 00:00:00 2001
+From: Himanshu Kishna Srivastava <28himanshu@gmail.com>
+Date: Tue, 16 Mar 2021 22:37:46 +0530
+Subject: [PATCH] crypto/rsa: fix salt length calculation with
+ PSSSaltLengthAuto
+
+When PSSSaltLength is set, the maximum salt length must equal:
+
+ (modulus_key_size - 1 + 7)/8 - hash_length - 2
+and for example, with a 4096 bit modulus key, and a SHA-1 hash,
+it should be:
+
+ (4096 -1 + 7)/8 - 20 - 2 = 490
+Previously we'd encounter this error:
+
+ crypto/rsa: key size too small for PSS signature
+
+Fixes #42741
+
+Change-Id: I18bb82c41c511d564b3f4c443f4b3a38ab010ac5
+Reviewed-on: https://go-review.googlesource.com/c/go/+/302230
+Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
+Reviewed-by: Filippo Valsorda <filippo@golang.org>
+Trust: Emmanuel Odeke <emmanuel@orijtech.com>
+Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
+TryBot-Result: Go Bot <gobot@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/8f676144ad7b7c91adb0c6e1ec89aaa6283c6807]
+CVE: CVE-2023-45287 #Dependency Patch3
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/crypto/rsa/pss.go | 2 +-
+ src/crypto/rsa/pss_test.go | 20 +++++++++++++++++++-
+ 2 files changed, 20 insertions(+), 2 deletions(-)
+
+diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
+index b2adbedb28fa8..814522de8181f 100644
+--- a/src/crypto/rsa/pss.go
++++ b/src/crypto/rsa/pss.go
+@@ -269,7 +269,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
+ saltLength := opts.saltLength()
+ switch saltLength {
+ case PSSSaltLengthAuto:
+- saltLength = priv.Size() - 2 - hash.Size()
++ saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size()
+ case PSSSaltLengthEqualsHash:
+ saltLength = hash.Size()
+ }
+diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go
+index dfa8d8bb5ad02..c3a6d468497cd 100644
+--- a/src/crypto/rsa/pss_test.go
++++ b/src/crypto/rsa/pss_test.go
+@@ -12,7 +12,7 @@ import (
+ _ "crypto/md5"
+ "crypto/rand"
+ "crypto/sha1"
+- _ "crypto/sha256"
++ "crypto/sha256"
+ "encoding/hex"
+ "math/big"
+ "os"
+@@ -233,6 +233,24 @@ func TestPSSSigning(t *testing.T) {
+ }
+ }
+
++func TestSignWithPSSSaltLengthAuto(t *testing.T) {
++ key, err := GenerateKey(rand.Reader, 513)
++ if err != nil {
++ t.Fatal(err)
++ }
++ digest := sha256.Sum256([]byte("message"))
++ signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{
++ SaltLength: PSSSaltLengthAuto,
++ Hash: crypto.SHA256,
++ })
++ if err != nil {
++ t.Fatal(err)
++ }
++ if len(signature) == 0 {
++ t.Fatal("empty signature returned")
++ }
++}
++
+ func bigFromHex(hex string) *big.Int {
+ n, ok := new(big.Int).SetString(hex, 16)
+ if !ok {
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45287.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287.patch
new file mode 100644
index 0000000000..90a74255db
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287.patch
@@ -0,0 +1,1697 @@
+From 8a81fdf165facdcefa06531de5af98a4db343035 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?L=C3=BAc=C3=A1s=20Meier?= <cronokirby@gmail.com>
+Date: Tue, 8 Jun 2021 21:36:06 +0200
+Subject: [PATCH] crypto/rsa: replace big.Int for encryption and decryption
+
+Infamously, big.Int does not provide constant-time arithmetic, making
+its use in cryptographic code quite tricky. RSA uses big.Int
+pervasively, in its public API, for key generation, precomputation, and
+for encryption and decryption. This is a known problem. One mitigation,
+blinding, is already in place during decryption. This helps mitigate the
+very leaky exponentiation operation. Because big.Int is fundamentally
+not constant-time, it's unfortunately difficult to guarantee that
+mitigations like these are completely effective.
+
+This patch removes the use of big.Int for encryption and decryption,
+replacing it with an internal nat type instead. Signing and verification
+are also affected, because they depend on encryption and decryption.
+
+Overall, this patch degrades performance by 55% for private key
+operations, and 4-5x for (much faster) public key operations.
+(Signatures do both, so the slowdown is worse than decryption.)
+
+name old time/op new time/op delta
+DecryptPKCS1v15/2048-8 1.50ms ± 0% 2.34ms ± 0% +56.44% (p=0.000 n=8+10)
+DecryptPKCS1v15/3072-8 4.40ms ± 0% 6.79ms ± 0% +54.33% (p=0.000 n=10+9)
+DecryptPKCS1v15/4096-8 9.31ms ± 0% 15.14ms ± 0% +62.60% (p=0.000 n=10+10)
+EncryptPKCS1v15/2048-8 8.16µs ± 0% 355.58µs ± 0% +4258.90% (p=0.000 n=10+9)
+DecryptOAEP/2048-8 1.50ms ± 0% 2.34ms ± 0% +55.68% (p=0.000 n=10+9)
+EncryptOAEP/2048-8 8.51µs ± 0% 355.95µs ± 0% +4082.75% (p=0.000 n=10+9)
+SignPKCS1v15/2048-8 1.51ms ± 0% 2.69ms ± 0% +77.94% (p=0.000 n=10+10)
+VerifyPKCS1v15/2048-8 7.25µs ± 0% 354.34µs ± 0% +4789.52% (p=0.000 n=9+9)
+SignPSS/2048-8 1.51ms ± 0% 2.70ms ± 0% +78.80% (p=0.000 n=9+10)
+VerifyPSS/2048-8 8.27µs ± 1% 355.65µs ± 0% +4199.39% (p=0.000 n=10+10)
+
+Keep in mind that this is without any assembly at all, and that further
+improvements are likely possible. I think having a review of the logic
+and the cryptography would be a good idea at this stage, before we
+complicate the code too much through optimization.
+
+The bulk of the work is in nat.go. This introduces two new types: nat,
+representing natural numbers, and modulus, representing moduli used in
+modular arithmetic.
+
+A nat has an "announced size", which may be larger than its "true size",
+the number of bits needed to represent this number. Operations on a nat
+will only ever leak its announced size, never its true size, or other
+information about its value. The size of a nat is always clear based on
+how its value is set. For example, x.mod(y, m) will make the announced
+size of x match that of m, since x is reduced modulo m.
+
+Operations assume that the announced size of the operands match what's
+expected (with a few exceptions). For example, x.modAdd(y, m) assumes
+that x and y have the same announced size as m, and that they're reduced
+modulo m.
+
+Nats are represented over unsatured bits.UintSize - 1 bit limbs. This
+means that we can't reuse the assembly routines for big.Int, which use
+saturated bits.UintSize limbs. The advantage of unsaturated limbs is
+that it makes Montgomery multiplication faster, by needing fewer
+registers in a hot loop. This makes exponentiation faster, which
+consists of many Montgomery multiplications.
+
+Moduli use nat internally. Unlike nat, the true size of a modulus always
+matches its announced size. When creating a modulus, any zero padding is
+removed. Moduli will also precompute constants when created, which is
+another reason why having a separate type is desirable.
+
+Updates #20654
+
+Co-authored-by: Filippo Valsorda <filippo@golang.org>
+Change-Id: I73b61f87d58ab912e80a9644e255d552cbadcced
+Reviewed-on: https://go-review.googlesource.com/c/go/+/326012
+Run-TryBot: Filippo Valsorda <filippo@golang.org>
+TryBot-Result: Gopher Robot <gobot@golang.org>
+Reviewed-by: Roland Shoemaker <roland@golang.org>
+Reviewed-by: Joedian Reid <joedian@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/8a81fdf165facdcefa06531de5af98a4db343035]
+CVE: CVE-2023-45287
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/crypto/rsa/example_test.go | 21 +-
+ src/crypto/rsa/nat.go | 626 +++++++++++++++++++++++++++++++++
+ src/crypto/rsa/nat_test.go | 384 ++++++++++++++++++++
+ src/crypto/rsa/pkcs1v15.go | 47 +--
+ src/crypto/rsa/pss.go | 50 ++-
+ src/crypto/rsa/pss_test.go | 10 +-
+ src/crypto/rsa/rsa.go | 174 ++++-----
+ 7 files changed, 1143 insertions(+), 169 deletions(-)
+ create mode 100644 src/crypto/rsa/nat.go
+ create mode 100644 src/crypto/rsa/nat_test.go
+
+diff --git a/src/crypto/rsa/example_test.go b/src/crypto/rsa/example_test.go
+index 1435b70..1963609 100644
+--- a/src/crypto/rsa/example_test.go
++++ b/src/crypto/rsa/example_test.go
+@@ -12,7 +12,6 @@ import (
+ "crypto/sha256"
+ "encoding/hex"
+ "fmt"
+- "io"
+ "os"
+ )
+
+@@ -36,21 +35,17 @@ import (
+ // a buffer that contains a random key. Thus, if the RSA result isn't
+ // well-formed, the implementation uses a random key in constant time.
+ func ExampleDecryptPKCS1v15SessionKey() {
+- // crypto/rand.Reader is a good source of entropy for blinding the RSA
+- // operation.
+- rng := rand.Reader
+-
+ // The hybrid scheme should use at least a 16-byte symmetric key. Here
+ // we read the random key that will be used if the RSA decryption isn't
+ // well-formed.
+ key := make([]byte, 32)
+- if _, err := io.ReadFull(rng, key); err != nil {
++ if _, err := rand.Read(key); err != nil {
+ panic("RNG failure")
+ }
+
+ rsaCiphertext, _ := hex.DecodeString("aabbccddeeff")
+
+- if err := DecryptPKCS1v15SessionKey(rng, rsaPrivateKey, rsaCiphertext, key); err != nil {
++ if err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, rsaCiphertext, key); err != nil {
+ // Any errors that result will be “public” – meaning that they
+ // can be determined without any secret information. (For
+ // instance, if the length of key is impossible given the RSA
+@@ -86,10 +81,6 @@ func ExampleDecryptPKCS1v15SessionKey() {
+ }
+
+ func ExampleSignPKCS1v15() {
+- // crypto/rand.Reader is a good source of entropy for blinding the RSA
+- // operation.
+- rng := rand.Reader
+-
+ message := []byte("message to be signed")
+
+ // Only small messages can be signed directly; thus the hash of a
+@@ -99,7 +90,7 @@ func ExampleSignPKCS1v15() {
+ // of writing (2016).
+ hashed := sha256.Sum256(message)
+
+- signature, err := SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA256, hashed[:])
++ signature, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA256, hashed[:])
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err)
+ return
+@@ -151,11 +142,7 @@ func ExampleDecryptOAEP() {
+ ciphertext, _ := hex.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc54d2cb80c08fcd19dacbc265ee1c6014616b0e04ea0328c2a04e73460")
+ label := []byte("orders")
+
+- // crypto/rand.Reader is a good source of entropy for blinding the RSA
+- // operation.
+- rng := rand.Reader
+-
+- plaintext, err := DecryptOAEP(sha256.New(), rng, test2048Key, ciphertext, label)
++ plaintext, err := DecryptOAEP(sha256.New(), nil, test2048Key, ciphertext, label)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
+ return
+diff --git a/src/crypto/rsa/nat.go b/src/crypto/rsa/nat.go
+new file mode 100644
+index 0000000..da521c2
+--- /dev/null
++++ b/src/crypto/rsa/nat.go
+@@ -0,0 +1,626 @@
++// Copyright 2021 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package rsa
++
++import (
++ "math/big"
++ "math/bits"
++)
++
++const (
++ // _W is the number of bits we use for our limbs.
++ _W = bits.UintSize - 1
++ // _MASK selects _W bits from a full machine word.
++ _MASK = (1 << _W) - 1
++)
++
++// choice represents a constant-time boolean. The value of choice is always
++// either 1 or 0. We use an int instead of bool in order to make decisions in
++// constant time by turning it into a mask.
++type choice uint
++
++func not(c choice) choice { return 1 ^ c }
++
++const yes = choice(1)
++const no = choice(0)
++
++// ctSelect returns x if on == 1, and y if on == 0. The execution time of this
++// function does not depend on its inputs. If on is any value besides 1 or 0,
++// the result is undefined.
++func ctSelect(on choice, x, y uint) uint {
++ // When on == 1, mask is 0b111..., otherwise mask is 0b000...
++ mask := -uint(on)
++ // When mask is all zeros, we just have y, otherwise, y cancels with itself.
++ return y ^ (mask & (y ^ x))
++}
++
++// ctEq returns 1 if x == y, and 0 otherwise. The execution time of this
++// function does not depend on its inputs.
++func ctEq(x, y uint) choice {
++ // If x != y, then either x - y or y - x will generate a carry.
++ _, c1 := bits.Sub(x, y, 0)
++ _, c2 := bits.Sub(y, x, 0)
++ return not(choice(c1 | c2))
++}
++
++// ctGeq returns 1 if x >= y, and 0 otherwise. The execution time of this
++// function does not depend on its inputs.
++func ctGeq(x, y uint) choice {
++ // If x < y, then x - y generates a carry.
++ _, carry := bits.Sub(x, y, 0)
++ return not(choice(carry))
++}
++
++// nat represents an arbitrary natural number
++//
++// Each nat has an announced length, which is the number of limbs it has stored.
++// Operations on this number are allowed to leak this length, but will not leak
++// any information about the values contained in those limbs.
++type nat struct {
++ // limbs is a little-endian representation in base 2^W with
++ // W = bits.UintSize - 1. The top bit is always unset between operations.
++ //
++ // The top bit is left unset to optimize Montgomery multiplication, in the
++ // inner loop of exponentiation. Using fully saturated limbs would leave us
++ // working with 129-bit numbers on 64-bit platforms, wasting a lot of space,
++ // and thus time.
++ limbs []uint
++}
++
++// expand expands x to n limbs, leaving its value unchanged.
++func (x *nat) expand(n int) *nat {
++ for len(x.limbs) > n {
++ if x.limbs[len(x.limbs)-1] != 0 {
++ panic("rsa: internal error: shrinking nat")
++ }
++ x.limbs = x.limbs[:len(x.limbs)-1]
++ }
++ if cap(x.limbs) < n {
++ newLimbs := make([]uint, n)
++ copy(newLimbs, x.limbs)
++ x.limbs = newLimbs
++ return x
++ }
++ extraLimbs := x.limbs[len(x.limbs):n]
++ for i := range extraLimbs {
++ extraLimbs[i] = 0
++ }
++ x.limbs = x.limbs[:n]
++ return x
++}
++
++// reset returns a zero nat of n limbs, reusing x's storage if n <= cap(x.limbs).
++func (x *nat) reset(n int) *nat {
++ if cap(x.limbs) < n {
++ x.limbs = make([]uint, n)
++ return x
++ }
++ for i := range x.limbs {
++ x.limbs[i] = 0
++ }
++ x.limbs = x.limbs[:n]
++ return x
++}
++
++// clone returns a new nat, with the same value and announced length as x.
++func (x *nat) clone() *nat {
++ out := &nat{make([]uint, len(x.limbs))}
++ copy(out.limbs, x.limbs)
++ return out
++}
++
++// natFromBig creates a new natural number from a big.Int.
++//
++// The announced length of the resulting nat is based on the actual bit size of
++// the input, ignoring leading zeroes.
++func natFromBig(x *big.Int) *nat {
++ xLimbs := x.Bits()
++ bitSize := bigBitLen(x)
++ requiredLimbs := (bitSize + _W - 1) / _W
++
++ out := &nat{make([]uint, requiredLimbs)}
++ outI := 0
++ shift := 0
++ for i := range xLimbs {
++ xi := uint(xLimbs[i])
++ out.limbs[outI] |= (xi << shift) & _MASK
++ outI++
++ if outI == requiredLimbs {
++ return out
++ }
++ out.limbs[outI] = xi >> (_W - shift)
++ shift++ // this assumes bits.UintSize - _W = 1
++ if shift == _W {
++ shift = 0
++ outI++
++ }
++ }
++ return out
++}
++
++// fillBytes sets bytes to x as a zero-extended big-endian byte slice.
++//
++// If bytes is not long enough to contain the number or at least len(x.limbs)-1
++// limbs, or has zero length, fillBytes will panic.
++func (x *nat) fillBytes(bytes []byte) []byte {
++ if len(bytes) == 0 {
++ panic("nat: fillBytes invoked with too small buffer")
++ }
++ for i := range bytes {
++ bytes[i] = 0
++ }
++ shift := 0
++ outI := len(bytes) - 1
++ for i, limb := range x.limbs {
++ remainingBits := _W
++ for remainingBits >= 8 {
++ bytes[outI] |= byte(limb) << shift
++ consumed := 8 - shift
++ limb >>= consumed
++ remainingBits -= consumed
++ shift = 0
++ outI--
++ if outI < 0 {
++ if limb != 0 || i < len(x.limbs)-1 {
++ panic("nat: fillBytes invoked with too small buffer")
++ }
++ return bytes
++ }
++ }
++ bytes[outI] = byte(limb)
++ shift = remainingBits
++ }
++ return bytes
++}
++
++// natFromBytes converts a slice of big-endian bytes into a nat.
++//
++// The announced length of the output depends on the length of bytes. Unlike
++// big.Int, creating a nat will not remove leading zeros.
++func natFromBytes(bytes []byte) *nat {
++ bitSize := len(bytes) * 8
++ requiredLimbs := (bitSize + _W - 1) / _W
++
++ out := &nat{make([]uint, requiredLimbs)}
++ outI := 0
++ shift := 0
++ for i := len(bytes) - 1; i >= 0; i-- {
++ bi := bytes[i]
++ out.limbs[outI] |= uint(bi) << shift
++ shift += 8
++ if shift >= _W {
++ shift -= _W
++ out.limbs[outI] &= _MASK
++ outI++
++ if shift > 0 {
++ out.limbs[outI] = uint(bi) >> (8 - shift)
++ }
++ }
++ }
++ return out
++}
++
++// cmpEq returns 1 if x == y, and 0 otherwise.
++//
++// Both operands must have the same announced length.
++func (x *nat) cmpEq(y *nat) choice {
++ // Eliminate bounds checks in the loop.
++ size := len(x.limbs)
++ xLimbs := x.limbs[:size]
++ yLimbs := y.limbs[:size]
++
++ equal := yes
++ for i := 0; i < size; i++ {
++ equal &= ctEq(xLimbs[i], yLimbs[i])
++ }
++ return equal
++}
++
++// cmpGeq returns 1 if x >= y, and 0 otherwise.
++//
++// Both operands must have the same announced length.
++func (x *nat) cmpGeq(y *nat) choice {
++ // Eliminate bounds checks in the loop.
++ size := len(x.limbs)
++ xLimbs := x.limbs[:size]
++ yLimbs := y.limbs[:size]
++
++ var c uint
++ for i := 0; i < size; i++ {
++ c = (xLimbs[i] - yLimbs[i] - c) >> _W
++ }
++ // If there was a carry, then subtracting y underflowed, so
++ // x is not greater than or equal to y.
++ return not(choice(c))
++}
++
++// assign sets x <- y if on == 1, and does nothing otherwise.
++//
++// Both operands must have the same announced length.
++func (x *nat) assign(on choice, y *nat) *nat {
++ // Eliminate bounds checks in the loop.
++ size := len(x.limbs)
++ xLimbs := x.limbs[:size]
++ yLimbs := y.limbs[:size]
++
++ for i := 0; i < size; i++ {
++ xLimbs[i] = ctSelect(on, yLimbs[i], xLimbs[i])
++ }
++ return x
++}
++
++// add computes x += y if on == 1, and does nothing otherwise. It returns the
++// carry of the addition regardless of on.
++//
++// Both operands must have the same announced length.
++func (x *nat) add(on choice, y *nat) (c uint) {
++ // Eliminate bounds checks in the loop.
++ size := len(x.limbs)
++ xLimbs := x.limbs[:size]
++ yLimbs := y.limbs[:size]
++
++ for i := 0; i < size; i++ {
++ res := xLimbs[i] + yLimbs[i] + c
++ xLimbs[i] = ctSelect(on, res&_MASK, xLimbs[i])
++ c = res >> _W
++ }
++ return
++}
++
++// sub computes x -= y if on == 1, and does nothing otherwise. It returns the
++// borrow of the subtraction regardless of on.
++//
++// Both operands must have the same announced length.
++func (x *nat) sub(on choice, y *nat) (c uint) {
++ // Eliminate bounds checks in the loop.
++ size := len(x.limbs)
++ xLimbs := x.limbs[:size]
++ yLimbs := y.limbs[:size]
++
++ for i := 0; i < size; i++ {
++ res := xLimbs[i] - yLimbs[i] - c
++ xLimbs[i] = ctSelect(on, res&_MASK, xLimbs[i])
++ c = res >> _W
++ }
++ return
++}
++
++// modulus is used for modular arithmetic, precomputing relevant constants.
++//
++// Moduli are assumed to be odd numbers. Moduli can also leak the exact
++// number of bits needed to store their value, and are stored without padding.
++//
++// Their actual value is still kept secret.
++type modulus struct {
++ // The underlying natural number for this modulus.
++ //
++ // This will be stored without any padding, and shouldn't alias with any
++ // other natural number being used.
++ nat *nat
++ leading int // number of leading zeros in the modulus
++ m0inv uint // -nat.limbs[0]⁻¹ mod _W
++}
++
++// minusInverseModW computes -x⁻¹ mod _W with x odd.
++//
++// This operation is used to precompute a constant involved in Montgomery
++// multiplication.
++func minusInverseModW(x uint) uint {
++ // Every iteration of this loop doubles the least-significant bits of
++ // correct inverse in y. The first three bits are already correct (1⁻¹ = 1,
++ // 3⁻¹ = 3, 5⁻¹ = 5, and 7⁻¹ = 7 mod 8), so doubling five times is enough
++ // for 61 bits (and wastes only one iteration for 31 bits).
++ //
++ // See https://crypto.stackexchange.com/a/47496.
++ y := x
++ for i := 0; i < 5; i++ {
++ y = y * (2 - x*y)
++ }
++ return (1 << _W) - (y & _MASK)
++}
++
++// modulusFromNat creates a new modulus from a nat.
++//
++// The nat should be odd, nonzero, and the number of significant bits in the
++// number should be leakable. The nat shouldn't be reused.
++func modulusFromNat(nat *nat) *modulus {
++ m := &modulus{}
++ m.nat = nat
++ size := len(m.nat.limbs)
++ for m.nat.limbs[size-1] == 0 {
++ size--
++ }
++ m.nat.limbs = m.nat.limbs[:size]
++ m.leading = _W - bitLen(m.nat.limbs[size-1])
++ m.m0inv = minusInverseModW(m.nat.limbs[0])
++ return m
++}
++
++// bitLen is a version of bits.Len that only leaks the bit length of n, but not
++// its value. bits.Len and bits.LeadingZeros use a lookup table for the
++// low-order bits on some architectures.
++func bitLen(n uint) int {
++ var len int
++ // We assume, here and elsewhere, that comparison to zero is constant time
++ // with respect to different non-zero values.
++ for n != 0 {
++ len++
++ n >>= 1
++ }
++ return len
++}
++
++// bigBitLen is a version of big.Int.BitLen that only leaks the bit length of x,
++// but not its value. big.Int.BitLen uses bits.Len.
++func bigBitLen(x *big.Int) int {
++ xLimbs := x.Bits()
++ fullLimbs := len(xLimbs) - 1
++ topLimb := uint(xLimbs[len(xLimbs)-1])
++ return fullLimbs*bits.UintSize + bitLen(topLimb)
++}
++
++// modulusSize returns the size of m in bytes.
++func modulusSize(m *modulus) int {
++ bits := len(m.nat.limbs)*_W - int(m.leading)
++ return (bits + 7) / 8
++}
++
++// shiftIn calculates x = x << _W + y mod m.
++//
++// This assumes that x is already reduced mod m, and that y < 2^_W.
++func (x *nat) shiftIn(y uint, m *modulus) *nat {
++ d := new(nat).resetFor(m)
++
++ // Eliminate bounds checks in the loop.
++ size := len(m.nat.limbs)
++ xLimbs := x.limbs[:size]
++ dLimbs := d.limbs[:size]
++ mLimbs := m.nat.limbs[:size]
++
++ // Each iteration of this loop computes x = 2x + b mod m, where b is a bit
++ // from y. Effectively, it left-shifts x and adds y one bit at a time,
++ // reducing it every time.
++ //
++ // To do the reduction, each iteration computes both 2x + b and 2x + b - m.
++ // The next iteration (and finally the return line) will use either result
++ // based on whether the subtraction underflowed.
++ needSubtraction := no
++ for i := _W - 1; i >= 0; i-- {
++ carry := (y >> i) & 1
++ var borrow uint
++ for i := 0; i < size; i++ {
++ l := ctSelect(needSubtraction, dLimbs[i], xLimbs[i])
++
++ res := l<<1 + carry
++ xLimbs[i] = res & _MASK
++ carry = res >> _W
++
++ res = xLimbs[i] - mLimbs[i] - borrow
++ dLimbs[i] = res & _MASK
++ borrow = res >> _W
++ }
++ // See modAdd for how carry (aka overflow), borrow (aka underflow), and
++ // needSubtraction relate.
++ needSubtraction = ctEq(carry, borrow)
++ }
++ return x.assign(needSubtraction, d)
++}
++
++// mod calculates out = x mod m.
++//
++// This works regardless how large the value of x is.
++//
++// The output will be resized to the size of m and overwritten.
++func (out *nat) mod(x *nat, m *modulus) *nat {
++ out.resetFor(m)
++ // Working our way from the most significant to the least significant limb,
++ // we can insert each limb at the least significant position, shifting all
++ // previous limbs left by _W. This way each limb will get shifted by the
++ // correct number of bits. We can insert at least N - 1 limbs without
++ // overflowing m. After that, we need to reduce every time we shift.
++ i := len(x.limbs) - 1
++ // For the first N - 1 limbs we can skip the actual shifting and position
++ // them at the shifted position, which starts at min(N - 2, i).
++ start := len(m.nat.limbs) - 2
++ if i < start {
++ start = i
++ }
++ for j := start; j >= 0; j-- {
++ out.limbs[j] = x.limbs[i]
++ i--
++ }
++ // We shift in the remaining limbs, reducing modulo m each time.
++ for i >= 0 {
++ out.shiftIn(x.limbs[i], m)
++ i--
++ }
++ return out
++}
++
++// expandFor ensures out has the right size to work with operations modulo m.
++//
++// This assumes that out has as many or fewer limbs than m, or that the extra
++// limbs are all zero (which may happen when decoding a value that has leading
++// zeroes in its bytes representation that spill over the limb threshold).
++func (out *nat) expandFor(m *modulus) *nat {
++ return out.expand(len(m.nat.limbs))
++}
++
++// resetFor ensures out has the right size to work with operations modulo m.
++//
++// out is zeroed and may start at any size.
++func (out *nat) resetFor(m *modulus) *nat {
++ return out.reset(len(m.nat.limbs))
++}
++
++// modSub computes x = x - y mod m.
++//
++// The length of both operands must be the same as the modulus. Both operands
++// must already be reduced modulo m.
++func (x *nat) modSub(y *nat, m *modulus) *nat {
++ underflow := x.sub(yes, y)
++ // If the subtraction underflowed, add m.
++ x.add(choice(underflow), m.nat)
++ return x
++}
++
++// modAdd computes x = x + y mod m.
++//
++// The length of both operands must be the same as the modulus. Both operands
++// must already be reduced modulo m.
++func (x *nat) modAdd(y *nat, m *modulus) *nat {
++ overflow := x.add(yes, y)
++ underflow := not(x.cmpGeq(m.nat)) // x < m
++
++ // Three cases are possible:
++ //
++ // - overflow = 0, underflow = 0
++ //
++ // In this case, addition fits in our limbs, but we can still subtract away
++ // m without an underflow, so we need to perform the subtraction to reduce
++ // our result.
++ //
++ // - overflow = 0, underflow = 1
++ //
++ // The addition fits in our limbs, but we can't subtract m without
++ // underflowing. The result is already reduced.
++ //
++ // - overflow = 1, underflow = 1
++ //
++ // The addition does not fit in our limbs, and the subtraction's borrow
++ // would cancel out with the addition's carry. We need to subtract m to
++ // reduce our result.
++ //
++ // The overflow = 1, underflow = 0 case is not possible, because y is at
++ // most m - 1, and if adding m - 1 overflows, then subtracting m must
++ // necessarily underflow.
++ needSubtraction := ctEq(overflow, uint(underflow))
++
++ x.sub(needSubtraction, m.nat)
++ return x
++}
++
++// montgomeryRepresentation calculates x = x * R mod m, with R = 2^(_W * n) and
++// n = len(m.nat.limbs).
++//
++// Faster Montgomery multiplication replaces standard modular multiplication for
++// numbers in this representation.
++//
++// This assumes that x is already reduced mod m.
++func (x *nat) montgomeryRepresentation(m *modulus) *nat {
++ for i := 0; i < len(m.nat.limbs); i++ {
++ x.shiftIn(0, m) // x = x * 2^_W mod m
++ }
++ return x
++}
++
++// montgomeryMul calculates d = a * b / R mod m, with R = 2^(_W * n) and
++// n = len(m.nat.limbs), using the Montgomery Multiplication technique.
++//
++// All inputs should be the same length, not aliasing d, and already
++// reduced modulo m. d will be resized to the size of m and overwritten.
++func (d *nat) montgomeryMul(a *nat, b *nat, m *modulus) *nat {
++ // See https://bearssl.org/bigint.html#montgomery-reduction-and-multiplication
++ // for a description of the algorithm.
++
++ // Eliminate bounds checks in the loop.
++ size := len(m.nat.limbs)
++ aLimbs := a.limbs[:size]
++ bLimbs := b.limbs[:size]
++ dLimbs := d.resetFor(m).limbs[:size]
++ mLimbs := m.nat.limbs[:size]
++
++ var overflow uint
++ for i := 0; i < size; i++ {
++ f := ((dLimbs[0] + aLimbs[i]*bLimbs[0]) * m.m0inv) & _MASK
++ carry := uint(0)
++ for j := 0; j < size; j++ {
++ // z = d[j] + a[i] * b[j] + f * m[j] + carry <= 2^(2W+1) - 2^(W+1) + 2^W
++ hi, lo := bits.Mul(aLimbs[i], bLimbs[j])
++ z_lo, c := bits.Add(dLimbs[j], lo, 0)
++ z_hi, _ := bits.Add(0, hi, c)
++ hi, lo = bits.Mul(f, mLimbs[j])
++ z_lo, c = bits.Add(z_lo, lo, 0)
++ z_hi, _ = bits.Add(z_hi, hi, c)
++ z_lo, c = bits.Add(z_lo, carry, 0)
++ z_hi, _ = bits.Add(z_hi, 0, c)
++ if j > 0 {
++ dLimbs[j-1] = z_lo & _MASK
++ }
++ carry = z_hi<<1 | z_lo>>_W // carry <= 2^(W+1) - 2
++ }
++ z := overflow + carry // z <= 2^(W+1) - 1
++ dLimbs[size-1] = z & _MASK
++ overflow = z >> _W // overflow <= 1
++ }
++ // See modAdd for how overflow, underflow, and needSubtraction relate.
++ underflow := not(d.cmpGeq(m.nat)) // d < m
++ needSubtraction := ctEq(overflow, uint(underflow))
++ d.sub(needSubtraction, m.nat)
++
++ return d
++}
++
++// modMul calculates x *= y mod m.
++//
++// x and y must already be reduced modulo m, they must share its announced
++// length, and they may not alias.
++func (x *nat) modMul(y *nat, m *modulus) *nat {
++ // A Montgomery multiplication by a value out of the Montgomery domain
++ // takes the result out of Montgomery representation.
++ xR := x.clone().montgomeryRepresentation(m) // xR = x * R mod m
++ return x.montgomeryMul(xR, y, m) // x = xR * y / R mod m
++}
++
++// exp calculates out = x^e mod m.
++//
++// The exponent e is represented in big-endian order. The output will be resized
++// to the size of m and overwritten. x must already be reduced modulo m.
++func (out *nat) exp(x *nat, e []byte, m *modulus) *nat {
++ // We use a 4 bit window. For our RSA workload, 4 bit windows are faster
++ // than 2 bit windows, but use an extra 12 nats worth of scratch space.
++ // Using bit sizes that don't divide 8 are more complex to implement.
++ table := make([]*nat, (1<<4)-1) // table[i] = x ^ (i+1)
++ table[0] = x.clone().montgomeryRepresentation(m)
++ for i := 1; i < len(table); i++ {
++ table[i] = new(nat).expandFor(m)
++ table[i].montgomeryMul(table[i-1], table[0], m)
++ }
++
++ out.resetFor(m)
++ out.limbs[0] = 1
++ out.montgomeryRepresentation(m)
++ t0 := new(nat).expandFor(m)
++ t1 := new(nat).expandFor(m)
++ for _, b := range e {
++ for _, j := range []int{4, 0} {
++ // Square four times.
++ t1.montgomeryMul(out, out, m)
++ out.montgomeryMul(t1, t1, m)
++ t1.montgomeryMul(out, out, m)
++ out.montgomeryMul(t1, t1, m)
++
++ // Select x^k in constant time from the table.
++ k := uint((b >> j) & 0b1111)
++ for i := range table {
++ t0.assign(ctEq(k, uint(i+1)), table[i])
++ }
++
++ // Multiply by x^k, discarding the result if k = 0.
++ t1.montgomeryMul(out, t0, m)
++ out.assign(not(ctEq(k, 0)), t1)
++ }
++ }
++
++ // By Montgomery multiplying with 1 not in Montgomery representation, we
++ // convert out back from Montgomery representation, because it works out to
++ // dividing by R.
++ t0.assign(yes, out)
++ t1.resetFor(m)
++ t1.limbs[0] = 1
++ out.montgomeryMul(t0, t1, m)
++
++ return out
++}
+diff --git a/src/crypto/rsa/nat_test.go b/src/crypto/rsa/nat_test.go
+new file mode 100644
+index 0000000..3e6eb10
+--- /dev/null
++++ b/src/crypto/rsa/nat_test.go
+@@ -0,0 +1,384 @@
++// Copyright 2021 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package rsa
++
++import (
++ "bytes"
++ "math/big"
++ "math/bits"
++ "math/rand"
++ "reflect"
++ "testing"
++ "testing/quick"
++)
++
++// Generate generates an even nat. It's used by testing/quick to produce random
++// *nat values for quick.Check invocations.
++func (*nat) Generate(r *rand.Rand, size int) reflect.Value {
++ limbs := make([]uint, size)
++ for i := 0; i < size; i++ {
++ limbs[i] = uint(r.Uint64()) & ((1 << _W) - 2)
++ }
++ return reflect.ValueOf(&nat{limbs})
++}
++
++func testModAddCommutative(a *nat, b *nat) bool {
++ mLimbs := make([]uint, len(a.limbs))
++ for i := 0; i < len(mLimbs); i++ {
++ mLimbs[i] = _MASK
++ }
++ m := modulusFromNat(&nat{mLimbs})
++ aPlusB := a.clone()
++ aPlusB.modAdd(b, m)
++ bPlusA := b.clone()
++ bPlusA.modAdd(a, m)
++ return aPlusB.cmpEq(bPlusA) == 1
++}
++
++func TestModAddCommutative(t *testing.T) {
++ err := quick.Check(testModAddCommutative, &quick.Config{})
++ if err != nil {
++ t.Error(err)
++ }
++}
++
++func testModSubThenAddIdentity(a *nat, b *nat) bool {
++ mLimbs := make([]uint, len(a.limbs))
++ for i := 0; i < len(mLimbs); i++ {
++ mLimbs[i] = _MASK
++ }
++ m := modulusFromNat(&nat{mLimbs})
++ original := a.clone()
++ a.modSub(b, m)
++ a.modAdd(b, m)
++ return a.cmpEq(original) == 1
++}
++
++func TestModSubThenAddIdentity(t *testing.T) {
++ err := quick.Check(testModSubThenAddIdentity, &quick.Config{})
++ if err != nil {
++ t.Error(err)
++ }
++}
++
++func testMontgomeryRoundtrip(a *nat) bool {
++ one := &nat{make([]uint, len(a.limbs))}
++ one.limbs[0] = 1
++ aPlusOne := a.clone()
++ aPlusOne.add(1, one)
++ m := modulusFromNat(aPlusOne)
++ monty := a.clone()
++ monty.montgomeryRepresentation(m)
++ aAgain := monty.clone()
++ aAgain.montgomeryMul(monty, one, m)
++ return a.cmpEq(aAgain) == 1
++}
++
++func TestMontgomeryRoundtrip(t *testing.T) {
++ err := quick.Check(testMontgomeryRoundtrip, &quick.Config{})
++ if err != nil {
++ t.Error(err)
++ }
++}
++
++func TestFromBig(t *testing.T) {
++ expected := []byte{0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
++ theBig := new(big.Int).SetBytes(expected)
++ actual := natFromBig(theBig).fillBytes(make([]byte, len(expected)))
++ if !bytes.Equal(actual, expected) {
++ t.Errorf("%+x != %+x", actual, expected)
++ }
++}
++
++func TestFillBytes(t *testing.T) {
++ xBytes := []byte{0xAA, 0xFF, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}
++ x := natFromBytes(xBytes)
++ for l := 20; l >= len(xBytes); l-- {
++ buf := make([]byte, l)
++ rand.Read(buf)
++ actual := x.fillBytes(buf)
++ expected := make([]byte, l)
++ copy(expected[l-len(xBytes):], xBytes)
++ if !bytes.Equal(actual, expected) {
++ t.Errorf("%d: %+v != %+v", l, actual, expected)
++ }
++ }
++ for l := len(xBytes) - 1; l >= 0; l-- {
++ (func() {
++ defer func() {
++ if recover() == nil {
++ t.Errorf("%d: expected panic", l)
++ }
++ }()
++ x.fillBytes(make([]byte, l))
++ })()
++ }
++}
++
++func TestFromBytes(t *testing.T) {
++ f := func(xBytes []byte) bool {
++ if len(xBytes) == 0 {
++ return true
++ }
++ actual := natFromBytes(xBytes).fillBytes(make([]byte, len(xBytes)))
++ if !bytes.Equal(actual, xBytes) {
++ t.Errorf("%+x != %+x", actual, xBytes)
++ return false
++ }
++ return true
++ }
++
++ err := quick.Check(f, &quick.Config{})
++ if err != nil {
++ t.Error(err)
++ }
++
++ f([]byte{0xFF, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
++ f(bytes.Repeat([]byte{0xFF}, _W))
++}
++
++func TestShiftIn(t *testing.T) {
++ if bits.UintSize != 64 {
++ t.Skip("examples are only valid in 64 bit")
++ }
++ examples := []struct {
++ m, x, expected []byte
++ y uint64
++ }{{
++ m: []byte{13},
++ x: []byte{0},
++ y: 0x7FFF_FFFF_FFFF_FFFF,
++ expected: []byte{7},
++ }, {
++ m: []byte{13},
++ x: []byte{7},
++ y: 0x7FFF_FFFF_FFFF_FFFF,
++ expected: []byte{11},
++ }, {
++ m: []byte{0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d},
++ x: make([]byte, 9),
++ y: 0x7FFF_FFFF_FFFF_FFFF,
++ expected: []byte{0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
++ }, {
++ m: []byte{0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d},
++ x: []byte{0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
++ y: 0,
++ expected: []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08},
++ }}
++
++ for i, tt := range examples {
++ m := modulusFromNat(natFromBytes(tt.m))
++ got := natFromBytes(tt.x).expandFor(m).shiftIn(uint(tt.y), m)
++ if got.cmpEq(natFromBytes(tt.expected).expandFor(m)) != 1 {
++ t.Errorf("%d: got %x, expected %x", i, got, tt.expected)
++ }
++ }
++}
++
++func TestModulusAndNatSizes(t *testing.T) {
++ // These are 126 bit (2 * _W on 64-bit architectures) values, serialized as
++ // 128 bits worth of bytes. If leading zeroes are stripped, they fit in two
++ // limbs, if they are not, they fit in three. This can be a problem because
++ // modulus strips leading zeroes and nat does not.
++ m := modulusFromNat(natFromBytes([]byte{
++ 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}))
++ x := natFromBytes([]byte{
++ 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe})
++ x.expandFor(m) // must not panic for shrinking
++}
++
++func TestExpand(t *testing.T) {
++ sliced := []uint{1, 2, 3, 4}
++ examples := []struct {
++ in []uint
++ n int
++ out []uint
++ }{{
++ []uint{1, 2},
++ 4,
++ []uint{1, 2, 0, 0},
++ }, {
++ sliced[:2],
++ 4,
++ []uint{1, 2, 0, 0},
++ }, {
++ []uint{1, 2},
++ 2,
++ []uint{1, 2},
++ }, {
++ []uint{1, 2, 0},
++ 2,
++ []uint{1, 2},
++ }}
++
++ for i, tt := range examples {
++ got := (&nat{tt.in}).expand(tt.n)
++ if len(got.limbs) != len(tt.out) || got.cmpEq(&nat{tt.out}) != 1 {
++ t.Errorf("%d: got %x, expected %x", i, got, tt.out)
++ }
++ }
++}
++
++func TestMod(t *testing.T) {
++ m := modulusFromNat(natFromBytes([]byte{0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d}))
++ x := natFromBytes([]byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})
++ out := new(nat)
++ out.mod(x, m)
++ expected := natFromBytes([]byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09})
++ if out.cmpEq(expected) != 1 {
++ t.Errorf("%+v != %+v", out, expected)
++ }
++}
++
++func TestModSub(t *testing.T) {
++ m := modulusFromNat(&nat{[]uint{13}})
++ x := &nat{[]uint{6}}
++ y := &nat{[]uint{7}}
++ x.modSub(y, m)
++ expected := &nat{[]uint{12}}
++ if x.cmpEq(expected) != 1 {
++ t.Errorf("%+v != %+v", x, expected)
++ }
++ x.modSub(y, m)
++ expected = &nat{[]uint{5}}
++ if x.cmpEq(expected) != 1 {
++ t.Errorf("%+v != %+v", x, expected)
++ }
++}
++
++func TestModAdd(t *testing.T) {
++ m := modulusFromNat(&nat{[]uint{13}})
++ x := &nat{[]uint{6}}
++ y := &nat{[]uint{7}}
++ x.modAdd(y, m)
++ expected := &nat{[]uint{0}}
++ if x.cmpEq(expected) != 1 {
++ t.Errorf("%+v != %+v", x, expected)
++ }
++ x.modAdd(y, m)
++ expected = &nat{[]uint{7}}
++ if x.cmpEq(expected) != 1 {
++ t.Errorf("%+v != %+v", x, expected)
++ }
++}
++
++func TestExp(t *testing.T) {
++ m := modulusFromNat(&nat{[]uint{13}})
++ x := &nat{[]uint{3}}
++ out := &nat{[]uint{0}}
++ out.exp(x, []byte{12}, m)
++ expected := &nat{[]uint{1}}
++ if out.cmpEq(expected) != 1 {
++ t.Errorf("%+v != %+v", out, expected)
++ }
++}
++
++func makeBenchmarkModulus() *modulus {
++ m := make([]uint, 32)
++ for i := 0; i < 32; i++ {
++ m[i] = _MASK
++ }
++ return modulusFromNat(&nat{limbs: m})
++}
++
++func makeBenchmarkValue() *nat {
++ x := make([]uint, 32)
++ for i := 0; i < 32; i++ {
++ x[i] = _MASK - 1
++ }
++ return &nat{limbs: x}
++}
++
++func makeBenchmarkExponent() []byte {
++ e := make([]byte, 256)
++ for i := 0; i < 32; i++ {
++ e[i] = 0xFF
++ }
++ return e
++}
++
++func BenchmarkModAdd(b *testing.B) {
++ x := makeBenchmarkValue()
++ y := makeBenchmarkValue()
++ m := makeBenchmarkModulus()
++
++ b.ResetTimer()
++ for i := 0; i < b.N; i++ {
++ x.modAdd(y, m)
++ }
++}
++
++func BenchmarkModSub(b *testing.B) {
++ x := makeBenchmarkValue()
++ y := makeBenchmarkValue()
++ m := makeBenchmarkModulus()
++
++ b.ResetTimer()
++ for i := 0; i < b.N; i++ {
++ x.modSub(y, m)
++ }
++}
++
++func BenchmarkMontgomeryRepr(b *testing.B) {
++ x := makeBenchmarkValue()
++ m := makeBenchmarkModulus()
++
++ b.ResetTimer()
++ for i := 0; i < b.N; i++ {
++ x.montgomeryRepresentation(m)
++ }
++}
++
++func BenchmarkMontgomeryMul(b *testing.B) {
++ x := makeBenchmarkValue()
++ y := makeBenchmarkValue()
++ out := makeBenchmarkValue()
++ m := makeBenchmarkModulus()
++
++ b.ResetTimer()
++ for i := 0; i < b.N; i++ {
++ out.montgomeryMul(x, y, m)
++ }
++}
++
++func BenchmarkModMul(b *testing.B) {
++ x := makeBenchmarkValue()
++ y := makeBenchmarkValue()
++ m := makeBenchmarkModulus()
++
++ b.ResetTimer()
++ for i := 0; i < b.N; i++ {
++ x.modMul(y, m)
++ }
++}
++
++func BenchmarkExpBig(b *testing.B) {
++ out := new(big.Int)
++ exponentBytes := makeBenchmarkExponent()
++ x := new(big.Int).SetBytes(exponentBytes)
++ e := new(big.Int).SetBytes(exponentBytes)
++ n := new(big.Int).SetBytes(exponentBytes)
++ one := new(big.Int).SetUint64(1)
++ n.Add(n, one)
++
++ b.ResetTimer()
++ for i := 0; i < b.N; i++ {
++ out.Exp(x, e, n)
++ }
++}
++
++func BenchmarkExp(b *testing.B) {
++ x := makeBenchmarkValue()
++ e := makeBenchmarkExponent()
++ out := makeBenchmarkValue()
++ m := makeBenchmarkModulus()
++
++ b.ResetTimer()
++ for i := 0; i < b.N; i++ {
++ out.exp(x, e, m)
++ }
++}
+diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go
+index a216be3..ce89f92 100644
+--- a/src/crypto/rsa/pkcs1v15.go
++++ b/src/crypto/rsa/pkcs1v15.go
+@@ -9,7 +9,6 @@ import (
+ "crypto/subtle"
+ "errors"
+ "io"
+- "math/big"
+
+ "crypto/internal/randutil"
+ )
+@@ -58,14 +57,11 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)
+ em[len(em)-len(msg)-1] = 0
+ copy(mm, msg)
+
+- m := new(big.Int).SetBytes(em)
+- c := encrypt(new(big.Int), pub, m)
+-
+- return c.FillBytes(em), nil
++ return encrypt(pub, em), nil
+ }
+
+ // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
+-// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
++// The rand parameter is legacy and ignored, and it can be as nil.
+ //
+ // Note that whether this function returns an error or not discloses secret
+ // information. If an attacker can cause this function to run repeatedly and
+@@ -76,7 +72,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byt
+ if err := checkPub(&priv.PublicKey); err != nil {
+ return nil, err
+ }
+- valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext)
++ valid, out, index, err := decryptPKCS1v15(priv, ciphertext)
+ if err != nil {
+ return nil, err
+ }
+@@ -87,7 +83,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byt
+ }
+
+ // DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5.
+-// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
++// The rand parameter is legacy and ignored, and it can be as nil.
+ // It returns an error if the ciphertext is the wrong length or if the
+ // ciphertext is greater than the public modulus. Otherwise, no error is
+ // returned. If the padding is valid, the resulting plaintext message is copied
+@@ -114,7 +110,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by
+ return ErrDecryption
+ }
+
+- valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext)
++ valid, em, index, err := decryptPKCS1v15(priv, ciphertext)
+ if err != nil {
+ return err
+ }
+@@ -130,26 +126,24 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by
+ return nil
+ }
+
+-// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if
+-// rand is not nil. It returns one or zero in valid that indicates whether the
+-// plaintext was correctly structured. In either case, the plaintext is
+-// returned in em so that it may be read independently of whether it was valid
+-// in order to maintain constant memory access patterns. If the plaintext was
+-// valid then index contains the index of the original message in em.
+-func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
++// decryptPKCS1v15 decrypts ciphertext using priv. It returns one or zero in
++// valid that indicates whether the plaintext was correctly structured.
++// In either case, the plaintext is returned in em so that it may be read
++// independently of whether it was valid in order to maintain constant memory
++// access patterns. If the plaintext was valid then index contains the index of
++// the original message in em, to allow constant time padding removal.
++func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
+ k := priv.Size()
+ if k < 11 {
+ err = ErrDecryption
+ return
+ }
+
+- c := new(big.Int).SetBytes(ciphertext)
+- m, err := decrypt(rand, priv, c)
++ em, err = decrypt(priv, ciphertext)
+ if err != nil {
+ return
+ }
+
+- em = m.FillBytes(make([]byte, k))
+ firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
+ secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
+
+@@ -221,8 +215,7 @@ var hashPrefixes = map[crypto.Hash][]byte{
+ // function. If hash is zero, hashed is signed directly. This isn't
+ // advisable except for interoperability.
+ //
+-// If rand is not nil then RSA blinding will be used to avoid timing
+-// side-channel attacks.
++// The rand parameter is legacy and ignored, and it can be as nil.
+ //
+ // This function is deterministic. Thus, if the set of possible
+ // messages is small, an attacker may be able to build a map from
+@@ -249,13 +242,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
+ copy(em[k-tLen:k-hashLen], prefix)
+ copy(em[k-hashLen:k], hashed)
+
+- m := new(big.Int).SetBytes(em)
+- c, err := decryptAndCheck(rand, priv, m)
+- if err != nil {
+- return nil, err
+- }
+-
+- return c.FillBytes(em), nil
++ return decryptAndCheck(priv, em)
+ }
+
+ // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
+@@ -275,9 +262,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
+ return ErrVerification
+ }
+
+- c := new(big.Int).SetBytes(sig)
+- m := encrypt(new(big.Int), pub, c)
+- em := m.FillBytes(make([]byte, k))
++ em := encrypt(pub, sig)
+ // EM = 0x00 || 0x01 || PS || 0x00 || T
+
+ ok := subtle.ConstantTimeByteEq(em[0], 0)
+diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
+index 814522d..eaba4be 100644
+--- a/src/crypto/rsa/pss.go
++++ b/src/crypto/rsa/pss.go
+@@ -12,7 +12,6 @@ import (
+ "errors"
+ "hash"
+ "io"
+- "math/big"
+ )
+
+ // Per RFC 8017, Section 9.1
+@@ -207,19 +206,27 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
+ // Note that hashed must be the result of hashing the input message using the
+ // given hash function. salt is a random sequence of bytes whose length will be
+ // later used to verify the signature.
+-func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) {
+- emBits := priv.N.BitLen() - 1
++func signPSSWithSalt(priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) {
++ emBits := bigBitLen(priv.N) - 1
+ em, err := emsaPSSEncode(hashed, emBits, salt, hash.New())
+ if err != nil {
+ return nil, err
+ }
+- m := new(big.Int).SetBytes(em)
+- c, err := decryptAndCheck(rand, priv, m)
+- if err != nil {
+- return nil, err
++
++ // RFC 8017: "Note that the octet length of EM will be one less than k if
++ // modBits - 1 is divisible by 8 and equal to k otherwise, where k is the
++ // length in octets of the RSA modulus n."
++ //
++ // This is extremely annoying, as all other encrypt and decrypt inputs are
++ // always the exact same size as the modulus. Since it only happens for
++ // weird modulus sizes, fix it by padding inefficiently.
++ if emLen, k := len(em), priv.Size(); emLen < k {
++ emNew := make([]byte, k)
++ copy(emNew[k-emLen:], em)
++ em = emNew
+ }
+- s := make([]byte, priv.Size())
+- return c.FillBytes(s), nil
++
++ return decryptAndCheck(priv, em)
+ }
+
+ const (
+@@ -269,7 +276,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
+ saltLength := opts.saltLength()
+ switch saltLength {
+ case PSSSaltLengthAuto:
+- saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size()
++ saltLength = (bigBitLen(priv.N)-1+7)/8 - 2 - hash.Size()
+ case PSSSaltLengthEqualsHash:
+ saltLength = hash.Size()
+ }
+@@ -278,7 +285,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
+ if _, err := io.ReadFull(rand, salt); err != nil {
+ return nil, err
+ }
+- return signPSSWithSalt(rand, priv, hash, digest, salt)
++ return signPSSWithSalt(priv, hash, digest, salt)
+ }
+
+ // VerifyPSS verifies a PSS signature.
+@@ -291,13 +298,22 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts
+ if len(sig) != pub.Size() {
+ return ErrVerification
+ }
+- s := new(big.Int).SetBytes(sig)
+- m := encrypt(new(big.Int), pub, s)
+- emBits := pub.N.BitLen() - 1
++
++ emBits := bigBitLen(pub.N) - 1
+ emLen := (emBits + 7) / 8
+- if m.BitLen() > emLen*8 {
+- return ErrVerification
++ em := encrypt(pub, sig)
++
++ // Like in signPSSWithSalt, deal with mismatches between emLen and the size
++ // of the modulus. The spec would have us wire emLen into the encoding
++ // function, but we'd rather always encode to the size of the modulus and
++ // then strip leading zeroes if necessary. This only happens for weird
++ // modulus sizes anyway.
++ for len(em) > emLen && len(em) > 0 {
++ if em[0] != 0 {
++ return ErrVerification
++ }
++ em = em[1:]
+ }
+- em := m.FillBytes(make([]byte, emLen))
++
+ return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New())
+ }
+diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go
+index c3a6d46..d018b43 100644
+--- a/src/crypto/rsa/pss_test.go
++++ b/src/crypto/rsa/pss_test.go
+@@ -233,7 +233,10 @@ func TestPSSSigning(t *testing.T) {
+ }
+ }
+
+-func TestSignWithPSSSaltLengthAuto(t *testing.T) {
++func TestPSS513(t *testing.T) {
++ // See Issue 42741, and separately, RFC 8017: "Note that the octet length of
++ // EM will be one less than k if modBits - 1 is divisible by 8 and equal to
++ // k otherwise, where k is the length in octets of the RSA modulus n."
+ key, err := GenerateKey(rand.Reader, 513)
+ if err != nil {
+ t.Fatal(err)
+@@ -246,8 +249,9 @@ func TestSignWithPSSSaltLengthAuto(t *testing.T) {
+ if err != nil {
+ t.Fatal(err)
+ }
+- if len(signature) == 0 {
+- t.Fatal("empty signature returned")
++ err = VerifyPSS(&key.PublicKey, crypto.SHA256, digest[:], signature, nil)
++ if err != nil {
++ t.Error(err)
+ }
+ }
+
+diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
+index 5a00ed2..29d9d31 100644
+--- a/src/crypto/rsa/rsa.go
++++ b/src/crypto/rsa/rsa.go
+@@ -19,13 +19,17 @@
+ // over the public key primitive, the PrivateKey type implements the
+ // Decrypter and Signer interfaces from the crypto package.
+ //
+-// The RSA operations in this package are not implemented using constant-time algorithms.
++// Operations in this package are implemented using constant-time algorithms,
++// except for [GenerateKey], [PrivateKey.Precompute], and [PrivateKey.Validate].
++// Every other operation only leaks the bit size of the involved values, which
++// all depend on the selected key size.
+ package rsa
+
+ import (
+ "crypto"
+ "crypto/rand"
+ "crypto/subtle"
++ "encoding/binary"
+ "errors"
+ "hash"
+ "io"
+@@ -35,7 +39,6 @@ import (
+ "crypto/internal/randutil"
+ )
+
+-var bigZero = big.NewInt(0)
+ var bigOne = big.NewInt(1)
+
+ // A PublicKey represents the public part of an RSA key.
+@@ -47,7 +50,7 @@ type PublicKey struct {
+ // Size returns the modulus size in bytes. Raw signatures and ciphertexts
+ // for or by this public key will have the same size.
+ func (pub *PublicKey) Size() int {
+- return (pub.N.BitLen() + 7) / 8
++ return (bigBitLen(pub.N) + 7) / 8
+ }
+
+ // OAEPOptions is an interface for passing options to OAEP decryption using the
+@@ -351,10 +354,19 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
+ // too large for the size of the public key.
+ var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size")
+
+-func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
+- e := big.NewInt(int64(pub.E))
+- c.Exp(m, e, pub.N)
+- return c
++func encrypt(pub *PublicKey, plaintext []byte) []byte {
++
++ N := modulusFromNat(natFromBig(pub.N))
++ m := natFromBytes(plaintext).expandFor(N)
++
++ e := make([]byte, 8)
++ binary.BigEndian.PutUint64(e, uint64(pub.E))
++ for len(e) > 1 && e[0] == 0 {
++ e = e[1:]
++ }
++
++ out := make([]byte, modulusSize(N))
++ return new(nat).exp(m, e, N).fillBytes(out)
+ }
+
+ // EncryptOAEP encrypts the given message with RSA-OAEP.
+@@ -404,12 +416,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
+ mgf1XOR(db, hash, seed)
+ mgf1XOR(seed, hash, db)
+
+- m := new(big.Int)
+- m.SetBytes(em)
+- c := encrypt(new(big.Int), pub, m)
+-
+- out := make([]byte, k)
+- return c.FillBytes(out), nil
++ return encrypt(pub, em), nil
+ }
+
+ // ErrDecryption represents a failure to decrypt a message.
+@@ -451,98 +458,71 @@ func (priv *PrivateKey) Precompute() {
+ }
+ }
+
+-// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
+-// random source is given, RSA blinding is used.
+-func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
+- // TODO(agl): can we get away with reusing blinds?
+- if c.Cmp(priv.N) > 0 {
+- err = ErrDecryption
+- return
++// decrypt performs an RSA decryption of ciphertext into out.
++func decrypt(priv *PrivateKey, ciphertext []byte) ([]byte, error) {
++
++ N := modulusFromNat(natFromBig(priv.N))
++ c := natFromBytes(ciphertext).expandFor(N)
++ if c.cmpGeq(N.nat) == 1 {
++ return nil, ErrDecryption
+ }
+ if priv.N.Sign() == 0 {
+ return nil, ErrDecryption
+ }
+
+- var ir *big.Int
+- if random != nil {
+- randutil.MaybeReadByte(random)
+-
+- // Blinding enabled. Blinding involves multiplying c by r^e.
+- // Then the decryption operation performs (m^e * r^e)^d mod n
+- // which equals mr mod n. The factor of r can then be removed
+- // by multiplying by the multiplicative inverse of r.
+-
+- var r *big.Int
+- ir = new(big.Int)
+- for {
+- r, err = rand.Int(random, priv.N)
+- if err != nil {
+- return
+- }
+- if r.Cmp(bigZero) == 0 {
+- r = bigOne
+- }
+- ok := ir.ModInverse(r, priv.N)
+- if ok != nil {
+- break
+- }
+- }
+- bigE := big.NewInt(int64(priv.E))
+- rpowe := new(big.Int).Exp(r, bigE, priv.N) // N != 0
+- cCopy := new(big.Int).Set(c)
+- cCopy.Mul(cCopy, rpowe)
+- cCopy.Mod(cCopy, priv.N)
+- c = cCopy
+- }
+-
++ // Note that because our private decryption exponents are stored as big.Int,
++ // we potentially leak the exact number of bits of these exponents. This
++ // isn't great, but should be fine.
+ if priv.Precomputed.Dp == nil {
+- m = new(big.Int).Exp(c, priv.D, priv.N)
+- } else {
+- // We have the precalculated values needed for the CRT.
+- m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
+- m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
+- m.Sub(m, m2)
+- if m.Sign() < 0 {
+- m.Add(m, priv.Primes[0])
+- }
+- m.Mul(m, priv.Precomputed.Qinv)
+- m.Mod(m, priv.Primes[0])
+- m.Mul(m, priv.Primes[1])
+- m.Add(m, m2)
+-
+- for i, values := range priv.Precomputed.CRTValues {
+- prime := priv.Primes[2+i]
+- m2.Exp(c, values.Exp, prime)
+- m2.Sub(m2, m)
+- m2.Mul(m2, values.Coeff)
+- m2.Mod(m2, prime)
+- if m2.Sign() < 0 {
+- m2.Add(m2, prime)
+- }
+- m2.Mul(m2, values.R)
+- m.Add(m, m2)
+- }
+- }
+-
+- if ir != nil {
+- // Unblind.
+- m.Mul(m, ir)
+- m.Mod(m, priv.N)
+- }
+-
+- return
++ out := make([]byte, modulusSize(N))
++ return new(nat).exp(c, priv.D.Bytes(), N).fillBytes(out), nil
++ }
++
++ t0 := new(nat)
++ P := modulusFromNat(natFromBig(priv.Primes[0]))
++ Q := modulusFromNat(natFromBig(priv.Primes[1]))
++ // m = c ^ Dp mod p
++ m := new(nat).exp(t0.mod(c, P), priv.Precomputed.Dp.Bytes(), P)
++ // m2 = c ^ Dq mod q
++ m2 := new(nat).exp(t0.mod(c, Q), priv.Precomputed.Dq.Bytes(), Q)
++ // m = m - m2 mod p
++ m.modSub(t0.mod(m2, P), P)
++ // m = m * Qinv mod p
++ m.modMul(natFromBig(priv.Precomputed.Qinv).expandFor(P), P)
++ // m = m * q mod N
++ m.expandFor(N).modMul(t0.mod(Q.nat, N), N)
++ // m = m + m2 mod N
++ m.modAdd(m2.expandFor(N), N)
++
++ for i, values := range priv.Precomputed.CRTValues {
++ p := modulusFromNat(natFromBig(priv.Primes[2+i]))
++ // m2 = c ^ Exp mod p
++ m2.exp(t0.mod(c, p), values.Exp.Bytes(), p)
++ // m2 = m2 - m mod p
++ m2.modSub(t0.mod(m, p), p)
++ // m2 = m2 * Coeff mod p
++ m2.modMul(natFromBig(values.Coeff).expandFor(p), p)
++ // m2 = m2 * R mod N
++ R := natFromBig(values.R).expandFor(N)
++ m2.expandFor(N).modMul(R, N)
++ // m = m + m2 mod N
++ m.modAdd(m2, N)
++ }
++
++ out := make([]byte, modulusSize(N))
++ return m.fillBytes(out), nil
+ }
+
+-func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
+- m, err = decrypt(random, priv, c)
++func decryptAndCheck(priv *PrivateKey, ciphertext []byte) (m []byte, err error) {
++ m, err = decrypt(priv, ciphertext)
+ if err != nil {
+ return nil, err
+ }
+
+ // In order to defend against errors in the CRT computation, m^e is
+ // calculated, which should match the original ciphertext.
+- check := encrypt(new(big.Int), &priv.PublicKey, m)
+- if c.Cmp(check) != 0 {
++ check := encrypt(&priv.PublicKey, m)
++ if subtle.ConstantTimeCompare(ciphertext, check) != 1 {
+ return nil, errors.New("rsa: internal error")
+ }
+ return m, nil
+@@ -554,9 +534,7 @@ func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int
+ // Encryption and decryption of a given message must use the same hash function
+ // and sha256.New() is a reasonable choice.
+ //
+-// The random parameter, if not nil, is used to blind the private-key operation
+-// and avoid timing side-channel attacks. Blinding is purely internal to this
+-// function – the random data need not match that used when encrypting.
++// The random parameter is legacy and ignored, and it can be as nil.
+ //
+ // The label parameter must match the value given when encrypting. See
+ // EncryptOAEP for details.
+@@ -570,9 +548,7 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
+ return nil, ErrDecryption
+ }
+
+- c := new(big.Int).SetBytes(ciphertext)
+-
+- m, err := decrypt(random, priv, c)
++ em, err := decrypt(priv, ciphertext)
+ if err != nil {
+ return nil, err
+ }
+@@ -581,10 +557,6 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
+ lHash := hash.Sum(nil)
+ hash.Reset()
+
+- // We probably leak the number of leading zeros.
+- // It's not clear that we can do anything about this.
+- em := m.FillBytes(make([]byte, k))
+-
+ firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
+
+ seed := em[1 : hash.Size()+1]
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45289.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45289.patch
new file mode 100644
index 0000000000..13d3510504
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45289.patch
@@ -0,0 +1,121 @@
+From 20586c0dbe03d144f914155f879fa5ee287591a1 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Thu, 11 Jan 2024 11:31:57 -0800
+Subject: [PATCH] [release-branch.go1.21] net/http, net/http/cookiejar: avoid
+ subdomain matches on IPv6 zones
+
+When deciding whether to forward cookies or sensitive headers
+across a redirect, do not attempt to interpret an IPv6 address
+as a domain name.
+
+Avoids a case where a maliciously-crafted redirect to an
+IPv6 address with a scoped addressing zone could be
+misinterpreted as a within-domain redirect. For example,
+we could interpret "::1%.www.example.com" as a subdomain
+of "www.example.com".
+
+Thanks to Juho Nurminen of Mattermost for reporting this issue.
+
+Fixes CVE-2023-45289
+Fixes #65385
+For #65065
+
+Change-Id: I8f463f59f0e700c8a18733d2b264a8bcb3a19599
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2131938
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173775
+Reviewed-by: Carlos Amedee <amedee@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/569239
+Reviewed-by: Carlos Amedee <carlos@golang.org>
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+TryBot-Bypass: Michael Knyszek <mknyszek@google.com>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/20586c0dbe03d144f914155f879fa5ee287591a1]
+CVE: CVE-2023-45289
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/net/http/client.go | 6 ++++++
+ src/net/http/client_test.go | 1 +
+ src/net/http/cookiejar/jar.go | 7 +++++++
+ src/net/http/cookiejar/jar_test.go | 10 ++++++++++
+ 4 files changed, 24 insertions(+)
+
+diff --git a/src/net/http/client.go b/src/net/http/client.go
+index a496f1c..2031834 100644
+--- a/src/net/http/client.go
++++ b/src/net/http/client.go
+@@ -973,6 +973,12 @@ func isDomainOrSubdomain(sub, parent string) bool {
+ if sub == parent {
+ return true
+ }
++ // If sub contains a :, it's probably an IPv6 address (and is definitely not a hostname).
++ // Don't check the suffix in this case, to avoid matching the contents of a IPv6 zone.
++ // For example, "::1%.www.example.com" is not a subdomain of "www.example.com".
++ if strings.ContainsAny(sub, ":%") {
++ return false
++ }
+ // If sub is "foo.example.com" and parent is "example.com",
+ // that means sub must end in "."+parent.
+ // Do it without allocating.
+diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
+index 2b4f53f..442fe35 100644
+--- a/src/net/http/client_test.go
++++ b/src/net/http/client_test.go
+@@ -1703,6 +1703,7 @@ func TestShouldCopyHeaderOnRedirect(t *testing.T) {
+ {"cookie2", "http://foo.com/", "http://bar.com/", false},
+ {"authorization", "http://foo.com/", "http://bar.com/", false},
+ {"www-authenticate", "http://foo.com/", "http://bar.com/", false},
++ {"authorization", "http://foo.com/", "http://[::1%25.foo.com]/", false},
+
+ // But subdomains should work:
+ {"www-authenticate", "http://foo.com/", "http://foo.com/", true},
+diff --git a/src/net/http/cookiejar/jar.go b/src/net/http/cookiejar/jar.go
+index 9f19917..18cbfc2 100644
+--- a/src/net/http/cookiejar/jar.go
++++ b/src/net/http/cookiejar/jar.go
+@@ -356,6 +356,13 @@ func jarKey(host string, psl PublicSuffixList) string {
+
+ // isIP reports whether host is an IP address.
+ func isIP(host string) bool {
++ if strings.ContainsAny(host, ":%") {
++ // Probable IPv6 address.
++ // Hostnames can't contain : or %, so this is definitely not a valid host.
++ // Treating it as an IP is the more conservative option, and avoids the risk
++ // of interpeting ::1%.www.example.com as a subtomain of www.example.com.
++ return true
++ }
+ return net.ParseIP(host) != nil
+ }
+
+diff --git a/src/net/http/cookiejar/jar_test.go b/src/net/http/cookiejar/jar_test.go
+index 47fb1ab..fd8d40e 100644
+--- a/src/net/http/cookiejar/jar_test.go
++++ b/src/net/http/cookiejar/jar_test.go
+@@ -251,6 +251,7 @@ var isIPTests = map[string]bool{
+ "127.0.0.1": true,
+ "1.2.3.4": true,
+ "2001:4860:0:2001::68": true,
++ "::1%zone": true,
+ "example.com": false,
+ "1.1.1.300": false,
+ "www.foo.bar.net": false,
+@@ -613,6 +614,15 @@ var basicsTests = [...]jarTest{
+ {"http://www.host.test:1234/", "a=1"},
+ },
+ },
++ {
++ "IPv6 zone is not treated as a host.",
++ "https://example.com/",
++ []string{"a=1"},
++ "a=1",
++ []query{
++ {"https://[::1%25.example.com]:80/", ""},
++ },
++ },
+ }
+
+ func TestBasics(t *testing.T) {
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch
new file mode 100644
index 0000000000..ddc2f67c96
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45290.patch
@@ -0,0 +1,271 @@
+From bf80213b121074f4ad9b449410a4d13bae5e9be0 Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Tue, 16 Jan 2024 15:37:52 -0800
+Subject: [PATCH] [release-branch.go1.21] net/textproto, mime/multipart: avoid
+ unbounded read in MIME header
+
+mime/multipart.Reader.ReadForm allows specifying the maximum amount
+of memory that will be consumed by the form. While this limit is
+correctly applied to the parsed form data structure, it was not
+being applied to individual header lines in a form.
+
+For example, when presented with a form containing a header line
+that never ends, ReadForm will continue to read the line until it
+runs out of memory.
+
+Limit the amount of data consumed when reading a header.
+
+Fixes CVE-2023-45290
+Fixes #65389
+For #65383
+
+Change-Id: I7f9264d25752009e95f6b2c80e3d76aaf321d658
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2134435
+Reviewed-by: Roland Shoemaker <bracewell@google.com>
+Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
+Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173776
+Reviewed-by: Carlos Amedee <amedee@google.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/569240
+Auto-Submit: Michael Knyszek <mknyszek@google.com>
+LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
+Reviewed-by: Carlos Amedee <carlos@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/bf80213b121074f4ad9b449410a4d13bae5e9be0]
+CVE: CVE-2023-45290
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/mime/multipart/formdata_test.go | 42 +++++++++++++++++++++++++
+ src/net/textproto/reader.go | 48 ++++++++++++++++++++---------
+ src/net/textproto/reader_test.go | 12 ++++++++
+ 3 files changed, 87 insertions(+), 15 deletions(-)
+
+diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
+index c78eeb7..f729da6 100644
+--- a/src/mime/multipart/formdata_test.go
++++ b/src/mime/multipart/formdata_test.go
+@@ -421,6 +421,48 @@ func TestReadFormLimits(t *testing.T) {
+ }
+ }
+
++func TestReadFormEndlessHeaderLine(t *testing.T) {
++ for _, test := range []struct {
++ name string
++ prefix string
++ }{{
++ name: "name",
++ prefix: "X-",
++ }, {
++ name: "value",
++ prefix: "X-Header: ",
++ }, {
++ name: "continuation",
++ prefix: "X-Header: foo\r\n ",
++ }} {
++ t.Run(test.name, func(t *testing.T) {
++ const eol = "\r\n"
++ s := `--boundary` + eol
++ s += `Content-Disposition: form-data; name="a"` + eol
++ s += `Content-Type: text/plain` + eol
++ s += test.prefix
++ fr := io.MultiReader(
++ strings.NewReader(s),
++ neverendingReader('X'),
++ )
++ r := NewReader(fr, "boundary")
++ _, err := r.ReadForm(1 << 20)
++ if err != ErrMessageTooLarge {
++ t.Fatalf("ReadForm(1 << 20): %v, want ErrMessageTooLarge", err)
++ }
++ })
++ }
++}
++
++type neverendingReader byte
++
++func (r neverendingReader) Read(p []byte) (n int, err error) {
++ for i := range p {
++ p[i] = byte(r)
++ }
++ return len(p), nil
++}
++
+ func BenchmarkReadForm(b *testing.B) {
+ for _, test := range []struct {
+ name string
+diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
+index ad2d777..cea6613 100644
+--- a/src/net/textproto/reader.go
++++ b/src/net/textproto/reader.go
+@@ -17,6 +17,10 @@ import (
+ "sync"
+ )
+
++// TODO: This should be a distinguishable error (ErrMessageTooLarge)
++// to allow mime/multipart to detect it.
++var errMessageTooLarge = errors.New("message too large")
++
+ // A Reader implements convenience methods for reading requests
+ // or responses from a text protocol network connection.
+ type Reader struct {
+@@ -38,13 +42,13 @@ func NewReader(r *bufio.Reader) *Reader {
+ // ReadLine reads a single line from r,
+ // eliding the final \n or \r\n from the returned string.
+ func (r *Reader) ReadLine() (string, error) {
+- line, err := r.readLineSlice()
++ line, err := r.readLineSlice(-1)
+ return string(line), err
+ }
+
+ // ReadLineBytes is like ReadLine but returns a []byte instead of a string.
+ func (r *Reader) ReadLineBytes() ([]byte, error) {
+- line, err := r.readLineSlice()
++ line, err := r.readLineSlice(-1)
+ if line != nil {
+ buf := make([]byte, len(line))
+ copy(buf, line)
+@@ -53,7 +57,10 @@ func (r *Reader) ReadLineBytes() ([]byte, error) {
+ return line, err
+ }
+
+-func (r *Reader) readLineSlice() ([]byte, error) {
++// readLineSlice reads a single line from r,
++// up to lim bytes long (or unlimited if lim is less than 0),
++// eliding the final \r or \r\n from the returned string.
++func (r *Reader) readLineSlice(lim int64) ([]byte, error) {
+ r.closeDot()
+ var line []byte
+ for {
+@@ -61,6 +68,9 @@ func (r *Reader) readLineSlice() ([]byte, error) {
+ if err != nil {
+ return nil, err
+ }
++ if lim >= 0 && int64(len(line))+int64(len(l)) > lim {
++ return nil, errMessageTooLarge
++ }
+ // Avoid the copy if the first call produced a full line.
+ if line == nil && !more {
+ return l, nil
+@@ -93,7 +103,7 @@ func (r *Reader) readLineSlice() ([]byte, error) {
+ // A line consisting of only white space is never continued.
+ //
+ func (r *Reader) ReadContinuedLine() (string, error) {
+- line, err := r.readContinuedLineSlice(noValidation)
++ line, err := r.readContinuedLineSlice(-1, noValidation)
+ return string(line), err
+ }
+
+@@ -114,7 +124,7 @@ func trim(s []byte) []byte {
+ // ReadContinuedLineBytes is like ReadContinuedLine but
+ // returns a []byte instead of a string.
+ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
+- line, err := r.readContinuedLineSlice(noValidation)
++ line, err := r.readContinuedLineSlice(-1, noValidation)
+ if line != nil {
+ buf := make([]byte, len(line))
+ copy(buf, line)
+@@ -127,13 +137,14 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
+ // returning a byte slice with all lines. The validateFirstLine function
+ // is run on the first read line, and if it returns an error then this
+ // error is returned from readContinuedLineSlice.
+-func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([]byte, error) {
++// It reads up to lim bytes of data (or unlimited if lim is less than 0).
++func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) {
+ if validateFirstLine == nil {
+ return nil, fmt.Errorf("missing validateFirstLine func")
+ }
+
+ // Read the first line.
+- line, err := r.readLineSlice()
++ line, err := r.readLineSlice(lim)
+ if err != nil {
+ return nil, err
+ }
+@@ -161,13 +172,21 @@ func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([
+ // copy the slice into buf.
+ r.buf = append(r.buf[:0], trim(line)...)
+
++ if lim < 0 {
++ lim = math.MaxInt64
++ }
++ lim -= int64(len(r.buf))
++
+ // Read continuation lines.
+ for r.skipSpace() > 0 {
+- line, err := r.readLineSlice()
++ r.buf = append(r.buf, ' ')
++ if int64(len(r.buf)) >= lim {
++ return nil, errMessageTooLarge
++ }
++ line, err := r.readLineSlice(lim - int64(len(r.buf)))
+ if err != nil {
+ break
+ }
+- r.buf = append(r.buf, ' ')
+ r.buf = append(r.buf, trim(line)...)
+ }
+ return r.buf, nil
+@@ -512,7 +531,8 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
+
+ // The first line cannot start with a leading space.
+ if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
+- line, err := r.readLineSlice()
++ const errorLimit = 80 // arbitrary limit on how much of the line we'll quote
++ line, err := r.readLineSlice(errorLimit)
+ if err != nil {
+ return m, err
+ }
+@@ -520,7 +540,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
+ }
+
+ for {
+- kv, err := r.readContinuedLineSlice(mustHaveFieldNameColon)
++ kv, err := r.readContinuedLineSlice(maxMemory, mustHaveFieldNameColon)
+ if len(kv) == 0 {
+ return m, err
+ }
+@@ -541,7 +561,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
+
+ maxHeaders--
+ if maxHeaders < 0 {
+- return nil, errors.New("message too large")
++ return nil, errMessageTooLarge
+ }
+
+ // backport 5c55ac9bf1e5f779220294c843526536605f42ab
+@@ -567,9 +587,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
+ }
+ maxMemory -= int64(len(value))
+ if maxMemory < 0 {
+- // TODO: This should be a distinguishable error (ErrMessageTooLarge)
+- // to allow mime/multipart to detect it.
+- return m, errors.New("message too large")
++ return m, errMessageTooLarge
+ }
+ if vv == nil && len(strs) > 0 {
+ // More than likely this will be a single-element key.
+diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
+index 3ae0de1..db1ed91 100644
+--- a/src/net/textproto/reader_test.go
++++ b/src/net/textproto/reader_test.go
+@@ -34,6 +34,18 @@ func TestReadLine(t *testing.T) {
+ }
+ }
+
++func TestReadLineLongLine(t *testing.T) {
++ line := strings.Repeat("12345", 10000)
++ r := reader(line + "\r\n")
++ s, err := r.ReadLine()
++ if err != nil {
++ t.Fatalf("Line 1: %v", err)
++ }
++ if s != line {
++ t.Fatalf("%v-byte line does not match expected %v-byte line", len(s), len(line))
++ }
++}
++
+ func TestReadContinuedLine(t *testing.T) {
+ r := reader("line1\nline\n 2\nline3\n")
+ s, err := r.ReadContinuedLine()
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2024-24784.patch b/meta/recipes-devtools/go/go-1.14/CVE-2024-24784.patch
new file mode 100644
index 0000000000..e9d9d972b9
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2024-24784.patch
@@ -0,0 +1,205 @@
+From 5330cd225ba54c7dc78c1b46dcdf61a4671a632c Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <bracewell@google.com>
+Date: Wed, 10 Jan 2024 11:02:14 -0800
+Subject: [PATCH] [release-branch.go1.22] net/mail: properly handle special
+ characters in phrase and obs-phrase
+
+Fixes a couple of misalignments with RFC 5322 which introduce
+significant diffs between (mostly) conformant parsers.
+
+This change reverts the changes made in CL50911, which allowed certain
+special RFC 5322 characters to appear unquoted in the "phrase" syntax.
+It is unclear why this change was made in the first place, and created
+a divergence from comformant parsers. In particular this resulted in
+treating comments in display names incorrectly.
+
+Additionally properly handle trailing malformed comments in the group
+syntax.
+
+For #65083
+Fixed #65849
+
+Change-Id: I00dddc044c6ae3381154e43236632604c390f672
+Reviewed-on: https://go-review.googlesource.com/c/go/+/555596
+Reviewed-by: Damien Neil <dneil@google.com>
+LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
+Reviewed-on: https://go-review.googlesource.com/c/go/+/566215
+Reviewed-by: Carlos Amedee <carlos@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/5330cd225ba54c7dc78c1b46dcdf61a4671a632c]
+CVE: CVE-2024-24784
+Signed-off-by: Ashish Sharma <asharma@mvista.com>
+
+ src/net/mail/message.go | 30 +++++++++++++++------------
+ src/net/mail/message_test.go | 40 ++++++++++++++++++++++++++----------
+ 2 files changed, 46 insertions(+), 24 deletions(-)
+
+diff --git a/src/net/mail/message.go b/src/net/mail/message.go
+index af516fc30f470..fc2a9e46f811b 100644
+--- a/src/net/mail/message.go
++++ b/src/net/mail/message.go
+@@ -280,7 +280,7 @@ func (a *Address) String() string {
+ // Add quotes if needed
+ quoteLocal := false
+ for i, r := range local {
+- if isAtext(r, false, false) {
++ if isAtext(r, false) {
+ continue
+ }
+ if r == '.' {
+@@ -444,7 +444,7 @@ func (p *addrParser) parseAddress(handleGroup bool) ([]*Address, error) {
+ if !p.consume('<') {
+ atext := true
+ for _, r := range displayName {
+- if !isAtext(r, true, false) {
++ if !isAtext(r, true) {
+ atext = false
+ break
+ }
+@@ -479,7 +479,9 @@ func (p *addrParser) consumeGroupList() ([]*Address, error) {
+ // handle empty group.
+ p.skipSpace()
+ if p.consume(';') {
+- p.skipCFWS()
++ if !p.skipCFWS() {
++ return nil, errors.New("mail: misformatted parenthetical comment")
++ }
+ return group, nil
+ }
+
+@@ -496,7 +498,9 @@ func (p *addrParser) consumeGroupList() ([]*Address, error) {
+ return nil, errors.New("mail: misformatted parenthetical comment")
+ }
+ if p.consume(';') {
+- p.skipCFWS()
++ if !p.skipCFWS() {
++ return nil, errors.New("mail: misformatted parenthetical comment")
++ }
+ break
+ }
+ if !p.consume(',') {
+@@ -566,6 +570,12 @@ func (p *addrParser) consumePhrase() (phrase string, err error) {
+ var words []string
+ var isPrevEncoded bool
+ for {
++ // obs-phrase allows CFWS after one word
++ if len(words) > 0 {
++ if !p.skipCFWS() {
++ return "", errors.New("mail: misformatted parenthetical comment")
++ }
++ }
+ // word = atom / quoted-string
+ var word string
+ p.skipSpace()
+@@ -661,7 +671,6 @@ Loop:
+ // If dot is true, consumeAtom parses an RFC 5322 dot-atom instead.
+ // If permissive is true, consumeAtom will not fail on:
+ // - leading/trailing/double dots in the atom (see golang.org/issue/4938)
+-// - special characters (RFC 5322 3.2.3) except '<', '>', ':' and '"' (see golang.org/issue/21018)
+ func (p *addrParser) consumeAtom(dot bool, permissive bool) (atom string, err error) {
+ i := 0
+
+@@ -672,7 +681,7 @@ Loop:
+ case size == 1 && r == utf8.RuneError:
+ return "", fmt.Errorf("mail: invalid utf-8 in address: %q", p.s)
+
+- case size == 0 || !isAtext(r, dot, permissive):
++ case size == 0 || !isAtext(r, dot):
+ break Loop
+
+ default:
+@@ -850,18 +859,13 @@ func (e charsetError) Error() string {
+
+ // isAtext reports whether r is an RFC 5322 atext character.
+ // If dot is true, period is included.
+-// If permissive is true, RFC 5322 3.2.3 specials is included,
+-// except '<', '>', ':' and '"'.
+-func isAtext(r rune, dot, permissive bool) bool {
++func isAtext(r rune, dot bool) bool {
+ switch r {
+ case '.':
+ return dot
+
+ // RFC 5322 3.2.3. specials
+- case '(', ')', '[', ']', ';', '@', '\\', ',':
+- return permissive
+-
+- case '<', '>', '"', ':':
++ case '(', ')', '<', '>', '[', ']', ':', ';', '@', '\\', ',', '"': // RFC 5322 3.2.3. specials
+ return false
+ }
+ return isVchar(r)
+diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go
+index 1e1bb4092f659..1f2f62afbf406 100644
+--- a/src/net/mail/message_test.go
++++ b/src/net/mail/message_test.go
+@@ -385,8 +385,11 @@ func TestAddressParsingError(t *testing.T) {
+ 13: {"group not closed: null@example.com", "expected comma"},
+ 14: {"group: first@example.com, second@example.com;", "group with multiple addresses"},
+ 15: {"john.doe", "missing '@' or angle-addr"},
+- 16: {"john.doe@", "no angle-addr"},
++ 16: {"john.doe@", "missing '@' or angle-addr"},
+ 17: {"John Doe@foo.bar", "no angle-addr"},
++ 18: {" group: null@example.com; (asd", "misformatted parenthetical comment"},
++ 19: {" group: ; (asd", "misformatted parenthetical comment"},
++ 20: {`(John) Doe <jdoe@machine.example>`, "missing word in phrase:"},
+ }
+
+ for i, tc := range mustErrTestCases {
+@@ -436,24 +439,19 @@ func TestAddressParsing(t *testing.T) {
+ Address: "john.q.public@example.com",
+ }},
+ },
+- {
+- `"John (middle) Doe" <jdoe@machine.example>`,
+- []*Address{{
+- Name: "John (middle) Doe",
+- Address: "jdoe@machine.example",
+- }},
+- },
++ // Comment in display name
+ {
+ `John (middle) Doe <jdoe@machine.example>`,
+ []*Address{{
+- Name: "John (middle) Doe",
++ Name: "John Doe",
+ Address: "jdoe@machine.example",
+ }},
+ },
++ // Display name is quoted string, so comment is not a comment
+ {
+- `John !@M@! Doe <jdoe@machine.example>`,
++ `"John (middle) Doe" <jdoe@machine.example>`,
+ []*Address{{
+- Name: "John !@M@! Doe",
++ Name: "John (middle) Doe",
+ Address: "jdoe@machine.example",
+ }},
+ },
+@@ -788,6 +786,26 @@ func TestAddressParsing(t *testing.T) {
+ },
+ },
+ },
++ // Comment in group display name
++ {
++ `group (comment:): a@example.com, b@example.com;`,
++ []*Address{
++ {
++ Address: "a@example.com",
++ },
++ {
++ Address: "b@example.com",
++ },
++ },
++ },
++ {
++ `x(:"):"@a.example;("@b.example;`,
++ []*Address{
++ {
++ Address: `@a.example;(@b.example`,
++ },
++ },
++ },
+ }
+ for _, test := range tests {
+ if len(test.exp) == 1 {
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2024-24785.patch b/meta/recipes-devtools/go/go-1.14/CVE-2024-24785.patch
new file mode 100644
index 0000000000..1398a2ca48
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2024-24785.patch
@@ -0,0 +1,197 @@
+From 3643147a29352ca2894fd5d0d2069bc4b4335a7e Mon Sep 17 00:00:00 2001
+From: Roland Shoemaker <roland@golang.org>
+Date: Wed, 14 Feb 2024 17:18:36 -0800
+Subject: [PATCH] [release-branch.go1.21] html/template: escape additional
+ tokens in MarshalJSON errors
+
+Escape "</script" and "<!--" in errors returned from MarshalJSON errors
+when attempting to marshal types in script blocks. This prevents any
+user controlled content from prematurely terminating the script block.
+
+Updates #65697
+Fixes #65968
+
+Change-Id: Icf0e26c54ea7d9c1deed0bff11b6506c99ddef1b
+Reviewed-on: https://go-review.googlesource.com/c/go/+/564196
+LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
+Reviewed-by: Damien Neil <dneil@google.com>
+(cherry picked from commit ccbc725f2d678255df1bd326fa511a492aa3a0aa)
+Reviewed-on: https://go-review.googlesource.com/c/go/+/567515
+Reviewed-by: Carlos Amedee <carlos@golang.org>
+
+Upstream-Status: Backport [https://github.com/golang/go/commit/3643147a29352ca2894fd5d0d2069bc4b4335a7e]
+CVE: CVE-2024-24785
+Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
+---
+ src/html/template/js.go | 22 ++++++++-
+ src/html/template/js_test.go | 96 ++++++++++++++++++++----------------
+ 2 files changed, 74 insertions(+), 44 deletions(-)
+
+diff --git a/src/html/template/js.go b/src/html/template/js.go
+index 35994f0..4d3b25d 100644
+--- a/src/html/template/js.go
++++ b/src/html/template/js.go
+@@ -171,13 +171,31 @@ func jsValEscaper(args ...interface{}) string {
+ // cyclic data. This may be an unacceptable DoS risk.
+ b, err := json.Marshal(a)
+ if err != nil {
+- // Put a space before comment so that if it is flush against
++ // While the standard JSON marshaller does not include user controlled
++ // information in the error message, if a type has a MarshalJSON method,
++ // the content of the error message is not guaranteed. Since we insert
++ // the error into the template, as part of a comment, we attempt to
++ // prevent the error from either terminating the comment, or the script
++ // block itself.
++ //
++ // In particular we:
++ // * replace "*/" comment end tokens with "* /", which does not
++ // terminate the comment
++ // * replace "</script" with "\x3C/script", and "<!--" with
++ // "\x3C!--", which prevents confusing script block termination
++ // semantics
++ //
++ // We also put a space before the comment so that if it is flush against
+ // a division operator it is not turned into a line comment:
+ // x/{{y}}
+ // turning into
+ // x//* error marshaling y:
+ // second line of error message */null
+- return fmt.Sprintf(" /* %s */null ", strings.ReplaceAll(err.Error(), "*/", "* /"))
++ errStr := err.Error()
++ errStr = strings.ReplaceAll(errStr, "*/", "* /")
++ errStr = strings.ReplaceAll(errStr, "</script", `\x3C/script`)
++ errStr = strings.ReplaceAll(errStr, "<!--", `\x3C!--`)
++ return fmt.Sprintf(" /* %s */null ", errStr)
+ }
+
+ // TODO: maybe post-process output to prevent it from containing
+diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go
+index de9ef28..3fc3baf 100644
+--- a/src/html/template/js_test.go
++++ b/src/html/template/js_test.go
+@@ -5,6 +5,7 @@
+ package template
+
+ import (
++ "errors"
+ "bytes"
+ "math"
+ "strings"
+@@ -104,61 +105,72 @@ func TestNextJsCtx(t *testing.T) {
+ }
+ }
+
++type jsonErrType struct{}
++
++func (e *jsonErrType) MarshalJSON() ([]byte, error) {
++ return nil, errors.New("beep */ boop </script blip <!--")
++}
++
+ func TestJSValEscaper(t *testing.T) {
+ tests := []struct {
+- x interface{}
+- js string
++ x interface{}
++ js string
++ skipNest bool
+ }{
+- {int(42), " 42 "},
+- {uint(42), " 42 "},
+- {int16(42), " 42 "},
+- {uint16(42), " 42 "},
+- {int32(-42), " -42 "},
+- {uint32(42), " 42 "},
+- {int16(-42), " -42 "},
+- {uint16(42), " 42 "},
+- {int64(-42), " -42 "},
+- {uint64(42), " 42 "},
+- {uint64(1) << 53, " 9007199254740992 "},
++ {int(42), " 42 ", false},
++ {uint(42), " 42 ", false},
++ {int16(42), " 42 ", false},
++ {uint16(42), " 42 ", false},
++ {int32(-42), " -42 ", false},
++ {uint32(42), " 42 ", false},
++ {int16(-42), " -42 ", false},
++ {uint16(42), " 42 ", false},
++ {int64(-42), " -42 ", false},
++ {uint64(42), " 42 ", false},
++ {uint64(1) << 53, " 9007199254740992 ", false},
+ // ulp(1 << 53) > 1 so this loses precision in JS
+ // but it is still a representable integer literal.
+- {uint64(1)<<53 + 1, " 9007199254740993 "},
+- {float32(1.0), " 1 "},
+- {float32(-1.0), " -1 "},
+- {float32(0.5), " 0.5 "},
+- {float32(-0.5), " -0.5 "},
+- {float32(1.0) / float32(256), " 0.00390625 "},
+- {float32(0), " 0 "},
+- {math.Copysign(0, -1), " -0 "},
+- {float64(1.0), " 1 "},
+- {float64(-1.0), " -1 "},
+- {float64(0.5), " 0.5 "},
+- {float64(-0.5), " -0.5 "},
+- {float64(0), " 0 "},
+- {math.Copysign(0, -1), " -0 "},
+- {"", `""`},
+- {"foo", `"foo"`},
++ {uint64(1)<<53 + 1, " 9007199254740993 ", false},
++ {float32(1.0), " 1 ", false},
++ {float32(-1.0), " -1 ", false},
++ {float32(0.5), " 0.5 ", false},
++ {float32(-0.5), " -0.5 ", false},
++ {float32(1.0) / float32(256), " 0.00390625 ", false},
++ {float32(0), " 0 ", false},
++ {math.Copysign(0, -1), " -0 ", false},
++ {float64(1.0), " 1 ", false},
++ {float64(-1.0), " -1 ", false},
++ {float64(0.5), " 0.5 ", false},
++ {float64(-0.5), " -0.5 ", false},
++ {float64(0), " 0 ", false},
++ {math.Copysign(0, -1), " -0 ", false},
++ {"", `""`, false},
++ {"foo", `"foo"`, false},
+ // Newlines.
+- {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
++ {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`, false},
+ // "\v" == "v" on IE 6 so use "\u000b" instead.
+- {"\t\x0b", `"\t\u000b"`},
+- {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
+- {[]interface{}{}, "[]"},
+- {[]interface{}{42, "foo", nil}, `[42,"foo",null]`},
+- {[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`},
+- {"<!--", `"\u003c!--"`},
+- {"-->", `"--\u003e"`},
+- {"<![CDATA[", `"\u003c![CDATA["`},
+- {"]]>", `"]]\u003e"`},
+- {"</script", `"\u003c/script"`},
+- {"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E"
+- {nil, " null "},
++ {"\t\x0b", `"\t\u000b"`, false},
++ {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`, false},
++ {[]interface{}{}, "[]", false},
++ {[]interface{}{42, "foo", nil}, `[42,"foo",null]`, false},
++ {[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`, false},
++ {"<!--", `"\u003c!--"`, false},
++ {"-->", `"--\u003e"`, false},
++ {"<![CDATA[", `"\u003c![CDATA["`, false},
++ {"]]>", `"]]\u003e"`, false},
++ {"</script", `"\u003c/script"`, false},
++ {"\U0001D11E", "\"\U0001D11E\"", false}, // or "\uD834\uDD1E"
++ {nil, " null ", false},
++ {&jsonErrType{}, " /* json: error calling MarshalJSON for type *template.jsonErrType: beep * / boop \\x3C/script blip \\x3C!-- */null ", true},
+ }
+
+ for _, test := range tests {
+ if js := jsValEscaper(test.x); js != test.js {
+ t.Errorf("%+v: want\n\t%q\ngot\n\t%q", test.x, test.js, js)
+ }
++ if test.skipNest {
++ continue
++ }
+ // Make sure that escaping corner cases are not broken
+ // by nesting.
+ a := []interface{}{test.x}
+--
+2.25.1
+
diff --git a/meta/recipes-devtools/go/go-crosssdk.inc b/meta/recipes-devtools/go/go-crosssdk.inc
index f0bec79719..36c9b12af8 100644
--- a/meta/recipes-devtools/go/go-crosssdk.inc
+++ b/meta/recipes-devtools/go/go-crosssdk.inc
@@ -4,6 +4,8 @@ DEPENDS = "go-native virtual/${TARGET_PREFIX}gcc-crosssdk virtual/nativesdk-${TA
PN = "go-crosssdk-${SDK_SYS}"
PROVIDES = "virtual/${TARGET_PREFIX}go-crosssdk"
+export GOCACHE = "${B}/.cache"
+
do_configure[noexec] = "1"
do_compile() {
diff --git a/meta/recipes-devtools/go/go-dep_0.5.4.bb b/meta/recipes-devtools/go/go-dep_0.5.4.bb
index 0da2c6607c..e29e53433e 100644
--- a/meta/recipes-devtools/go/go-dep_0.5.4.bb
+++ b/meta/recipes-devtools/go/go-dep_0.5.4.bb
@@ -4,7 +4,7 @@ LICENSE = "BSD-3-Clause"
LIC_FILES_CHKSUM = "file://src/${GO_IMPORT}/LICENSE;md5=1bad315647751fab0007812f70d42c0d"
GO_IMPORT = "github.com/golang/dep"
-SRC_URI = "git://${GO_IMPORT} \
+SRC_URI = "git://${GO_IMPORT};branch=master \
file://0001-Add-support-for-mips-mips64.patch;patchdir=src/github.com/golang/dep \
file://0001-bolt_riscv64-Add-support-for-riscv64.patch;patchdir=src/github.com/golang/dep \
"
diff --git a/meta/recipes-devtools/go/go_1.14.bb b/meta/recipes-devtools/go/go_1.14.bb
index bc90a1329e..76ff788238 100644
--- a/meta/recipes-devtools/go/go_1.14.bb
+++ b/meta/recipes-devtools/go/go_1.14.bb
@@ -3,12 +3,12 @@ require go-target.inc
export GOBUILDMODE=""
export CGO_ENABLED_riscv64 = ""
-# Add pie to GOBUILDMODE to satisfy "textrel" QA checking, but mips/riscv
-# doesn't support -buildmode=pie, so skip the QA checking for mips/riscv and its
-# variants.
+# Add pie to GOBUILDMODE to satisfy "textrel" QA checking, but
+# windows/mips/riscv doesn't support -buildmode=pie, so skip the QA checking
+# for windows/mips/riscv and their variants.
python() {
- if 'mips' in d.getVar('TARGET_ARCH',True) or 'riscv' in d.getVar('TARGET_ARCH',True):
- d.appendVar('INSANE_SKIP_%s' % d.getVar('PN',True), " textrel")
+ if 'mips' in d.getVar('TARGET_ARCH') or 'riscv' in d.getVar('TARGET_ARCH') or 'windows' in d.getVar('TARGET_GOOS'):
+ d.appendVar('INSANE_SKIP_%s' % d.getVar('PN'), " textrel")
else:
d.setVar('GOBUILDMODE', 'pie')
}