summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.14
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/go/go-1.14')
-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
76 files changed, 14406 insertions, 0 deletions
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 @@
1From 755f2dc35a19e6806de3ecbf836fa06ad875c67a Mon Sep 17 00:00:00 2001
2From: Carl Johnson <me@carlmjohnson.net>
3Date: Fri, 4 Mar 2022 14:49:52 +0000
4Subject: [PATCH 1/4] net/url: add JoinPath, URL.JoinPath
5
6Builds on CL 332209.
7
8Fixes #47005
9
10Change-Id: I82708dede05d79a196ca63f5a4e7cb5ac9a041ea
11GitHub-Last-Rev: 51b735066eef74f5e67c3e8899c58f44c0383c61
12GitHub-Pull-Request: golang/go#50383
13Reviewed-on: https://go-review.googlesource.com/c/go/+/374654
14Reviewed-by: Russ Cox <rsc@golang.org>
15Auto-Submit: Russ Cox <rsc@golang.org>
16Trust: Ian Lance Taylor <iant@golang.org>
17Reviewed-by: Damien Neil <dneil@google.com>
18Run-TryBot: Ian Lance Taylor <iant@golang.org>
19TryBot-Result: Gopher Robot <gobot@golang.org>
20
21Upstream-Status: Backport [https://github.com/golang/go/commit/604140d93111f89911e17cb147dcf6a02d2700d0]
22CVE: CVE-2022-32190
23Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
24---
25 src/net/url/url.go | 23 +++++++++++++++++++++++
26 1 file changed, 23 insertions(+)
27
28diff --git a/src/net/url/url.go b/src/net/url/url.go
29index 2880e82..dea8bfe 100644
30--- a/src/net/url/url.go
31+++ b/src/net/url/url.go
32@@ -13,6 +13,7 @@ package url
33 import (
34 "errors"
35 "fmt"
36+ "path"
37 "sort"
38 "strconv"
39 "strings"
40@@ -1104,6 +1105,17 @@ func (u *URL) UnmarshalBinary(text []byte) error {
41 return nil
42 }
43
44+// JoinPath returns a new URL with the provided path elements joined to
45+// any existing path and the resulting path cleaned of any ./ or ../ elements.
46+func (u *URL) JoinPath(elem ...string) *URL {
47+ url := *u
48+ if len(elem) > 0 {
49+ elem = append([]string{u.Path}, elem...)
50+ url.setPath(path.Join(elem...))
51+ }
52+ return &url
53+}
54+
55 // validUserinfo reports whether s is a valid userinfo string per RFC 3986
56 // Section 3.2.1:
57 // userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
58@@ -1144,3 +1156,14 @@ func stringContainsCTLByte(s string) bool {
59 }
60 return false
61 }
62+
63+// JoinPath returns a URL string with the provided path elements joined to
64+// the existing path of base and the resulting path cleaned of any ./ or ../ elements.
65+func JoinPath(base string, elem ...string) (result string, err error) {
66+ url, err := Parse(base)
67+ if err != nil {
68+ return
69+ }
70+ result = url.JoinPath(elem...).String()
71+ return
72+}
73--
742.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 @@
1From 985108de87e7d2ecb2b28cb53b323d530387b884 Mon Sep 17 00:00:00 2001
2From: Ian Lance Taylor <iant@golang.org>
3Date: Thu, 31 Mar 2022 13:21:39 -0700
4Subject: [PATCH 2/4] net/url: preserve a trailing slash in JoinPath
5
6Fixes #52074
7
8Change-Id: I30897f32e70a6ca0c4e11aaf07088c27336efaba
9Reviewed-on: https://go-review.googlesource.com/c/go/+/397256
10Trust: Ian Lance Taylor <iant@golang.org>
11Run-TryBot: Ian Lance Taylor <iant@golang.org>
12TryBot-Result: Gopher Robot <gobot@golang.org>
13Reviewed-by: Matt Layher <mdlayher@gmail.com>
14Trust: Matt Layher <mdlayher@gmail.com>
15
16Upstream-Status: Backport [https://github.com/golang/go/commit/dbb52cc9f3e83a3040f46c2ae7650c15ab342179]
17CVE: CVE-2022-32190
18Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
19---
20 src/net/url/url.go | 9 ++++++++-
21 1 file changed, 8 insertions(+), 1 deletion(-)
22
23diff --git a/src/net/url/url.go b/src/net/url/url.go
24index dea8bfe..3436707 100644
25--- a/src/net/url/url.go
26+++ b/src/net/url/url.go
27@@ -1107,11 +1107,18 @@ func (u *URL) UnmarshalBinary(text []byte) error {
28
29 // JoinPath returns a new URL with the provided path elements joined to
30 // any existing path and the resulting path cleaned of any ./ or ../ elements.
31+// Any sequences of multiple / characters will be reduced to a single /.
32 func (u *URL) JoinPath(elem ...string) *URL {
33 url := *u
34 if len(elem) > 0 {
35 elem = append([]string{u.Path}, elem...)
36- url.setPath(path.Join(elem...))
37+ p := path.Join(elem...)
38+ // path.Join will remove any trailing slashes.
39+ // Preserve at least one.
40+ if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
41+ p += "/"
42+ }
43+ url.setPath(p)
44 }
45 return &url
46 }
47--
482.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 @@
1From 2c632b883b0f11084cc247c8b50ad6c71fa7b447 Mon Sep 17 00:00:00 2001
2From: Sean Liao <sean@liao.dev>
3Date: Sat, 9 Jul 2022 18:38:45 +0100
4Subject: [PATCH 3/4] net/url: use EscapedPath for url.JoinPath
5
6Fixes #53763
7
8Change-Id: I08b53f159ebdce7907e8cc17316fd0c982363239
9Reviewed-on: https://go-review.googlesource.com/c/go/+/416774
10TryBot-Result: Gopher Robot <gobot@golang.org>
11Reviewed-by: Damien Neil <dneil@google.com>
12Reviewed-by: Bryan Mills <bcmills@google.com>
13Run-TryBot: Ian Lance Taylor <iant@golang.org>
14
15Upstream-Status: Backport [https://github.com/golang/go/commit/bf5898ef53d1693aa572da0da746c05e9a6f15c5]
16CVE: CVE-2022-32190
17Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
18---
19 src/net/url/url.go | 2 +-
20 1 file changed, 1 insertion(+), 1 deletion(-)
21
22diff --git a/src/net/url/url.go b/src/net/url/url.go
23index 3436707..73079a5 100644
24--- a/src/net/url/url.go
25+++ b/src/net/url/url.go
26@@ -1111,7 +1111,7 @@ func (u *URL) UnmarshalBinary(text []byte) error {
27 func (u *URL) JoinPath(elem ...string) *URL {
28 url := *u
29 if len(elem) > 0 {
30- elem = append([]string{u.Path}, elem...)
31+ elem = append([]string{u.EscapedPath()}, elem...)
32 p := path.Join(elem...)
33 // path.Join will remove any trailing slashes.
34 // Preserve at least one.
35--
362.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 @@
1From f61e428699cbb52bab31fe2c124f49d085a209fe Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Fri, 12 Aug 2022 16:21:09 -0700
4Subject: [PATCH 4/4] net/url: consistently remove ../ elements in JoinPath
5
6JoinPath would fail to remove relative elements from the start of
7the path when the first path element is "".
8
9In addition, JoinPath would return the original path unmodified
10when provided with no elements to join, violating the documented
11behavior of always cleaning the resulting path.
12
13Correct both these cases.
14
15 JoinPath("http://go.dev", "../go")
16 // before: http://go.dev/../go
17 // after: http://go.dev/go
18
19 JoinPath("http://go.dev/../go")
20 // before: http://go.dev/../go
21 // after: http://go.dev/go
22
23For #54385.
24Fixes #54635.
25Fixes CVE-2022-32190.
26
27Change-Id: I6d22cd160d097c50703dd96e4f453c6c118fd5d9
28Reviewed-on: https://go-review.googlesource.com/c/go/+/423514
29Reviewed-by: David Chase <drchase@google.com>
30Reviewed-by: Alan Donovan <adonovan@google.com>
31(cherry picked from commit 0765da5884adcc8b744979303a36a27092d8fc51)
32Reviewed-on: https://go-review.googlesource.com/c/go/+/425357
33Run-TryBot: Damien Neil <dneil@google.com>
34TryBot-Result: Gopher Robot <gobot@golang.org>
35
36Upstream-Status: Backport [https://github.com/golang/go/commit/28335508913a46e05ef0c04a18e8a1a6beb775ec]
37CVE: CVE-2022-32190
38Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
39---
40 src/net/url/url.go | 26 ++++++++++++++++----------
41 1 file changed, 16 insertions(+), 10 deletions(-)
42
43diff --git a/src/net/url/url.go b/src/net/url/url.go
44index 73079a5..1e8baf9 100644
45--- a/src/net/url/url.go
46+++ b/src/net/url/url.go
47@@ -1109,17 +1109,23 @@ func (u *URL) UnmarshalBinary(text []byte) error {
48 // any existing path and the resulting path cleaned of any ./ or ../ elements.
49 // Any sequences of multiple / characters will be reduced to a single /.
50 func (u *URL) JoinPath(elem ...string) *URL {
51- url := *u
52- if len(elem) > 0 {
53- elem = append([]string{u.EscapedPath()}, elem...)
54- p := path.Join(elem...)
55- // path.Join will remove any trailing slashes.
56- // Preserve at least one.
57- if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
58- p += "/"
59- }
60- url.setPath(p)
61+ elem = append([]string{u.EscapedPath()}, elem...)
62+ var p string
63+ if !strings.HasPrefix(elem[0], "/") {
64+ // Return a relative path if u is relative,
65+ // but ensure that it contains no ../ elements.
66+ elem[0] = "/" + elem[0]
67+ p = path.Join(elem...)[1:]
68+ } else {
69+ p = path.Join(elem...)
70 }
71+ // path.Join will remove any trailing slashes.
72+ // Preserve at least one.
73+ if strings.HasSuffix(elem[len(elem)-1], "/") && !strings.HasSuffix(p, "/") {
74+ p += "/"
75+ }
76+ url := *u
77+ url.setPath(p)
78 return &url
79 }
80
81--
822.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 @@
1From a0bf4d38dc2057d28396594264bbdd43d412de22 Mon Sep 17 00:00:00 2001
2From: Filippo Valsorda <filippo@golang.org>
3Date: Tue, 27 Oct 2020 00:21:30 +0100
4Subject: [PATCH] encoding/xml: replace comments inside directives with a space
5
6A Directive (like <!ENTITY xxx []>) can't have other nodes nested inside
7it (in our data structure representation), so there is no way to
8preserve comments. The previous behavior was to just elide them, which
9however might change the semantic meaning of the surrounding markup.
10Instead, replace them with a space which hopefully has the same semantic
11effect of the comment.
12
13Directives are not actually a node type in the XML spec, which instead
14specifies each of them separately (<!ENTITY, <!DOCTYPE, etc.), each with
15its own grammar. The rules for where and when the comments are allowed
16are not straightforward, and can't be implemented without implementing
17custom logic for each of the directives.
18
19Simply preserving the comments in the body of the directive would be
20problematic, as there can be unmatched quotes inside the comment.
21Whether those quotes are considered meaningful semantically or not,
22other parsers might disagree and interpret the output differently.
23
24This issue was reported by Juho Nurminen of Mattermost as it leads to
25round-trip mismatches. See #43168. It's not being fixed in a security
26release because round-trip stability is not a currently supported
27security property of encoding/xml, and we don't believe these fixes
28would be sufficient to reliably guarantee it in the future.
29
30Fixes CVE-2020-29510
31Updates #43168
32
33Change-Id: Icd86c75beff3e1e0689543efebdad10ed5178ce3
34Reviewed-on: https://go-review.googlesource.com/c/go/+/277893
35Run-TryBot: Filippo Valsorda <filippo@golang.org>
36TryBot-Result: Go Bot <gobot@golang.org>
37Trust: Filippo Valsorda <filippo@golang.org>
38Reviewed-by: Katie Hockman <katie@golang.org>
39
40Upstream-Status: Backport from https://github.com/golang/go/commit/a9cfd55e2b09735a25976d1b008a0a3c767494f8
41CVE: CVE-2020-29510
42Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
43---
44 src/encoding/xml/xml.go | 6 ++++++
45 1 file changed, 6 insertions(+)
46
47diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go
48index 01a1460..98647b2 100644
49--- a/src/encoding/xml/xml.go
50+++ b/src/encoding/xml/xml.go
51@@ -768,6 +768,12 @@ func (d *Decoder) rawToken() (Token, error) {
52 }
53 b0, b1 = b1, b
54 }
55+
56+ // Replace the comment with a space in the returned Directive
57+ // body, so that markup parts that were separated by the comment
58+ // (like a "<" and a "!") don't get joined when re-encoding the
59+ // Directive, taking new semantic meaning.
60+ d.buf.WriteByte(' ')
61 }
62 }
63 return Directive(d.buf.Bytes()), nil
64--
652.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 @@
1From d0b79e3513a29628f3599dc8860666b6eed75372 Mon Sep 17 00:00:00 2001
2From: Katie Hockman <katie@golang.org>
3Date: Mon, 1 Mar 2021 09:54:00 -0500
4Subject: [PATCH] encoding/xml: prevent infinite loop while decoding
5
6This change properly handles a TokenReader which
7returns an EOF in the middle of an open XML
8element.
9
10Thanks to Sam Whited for reporting this.
11
12Fixes CVE-2021-27918
13Fixes #44913
14
15Change-Id: Id02a3f3def4a1b415fa2d9a8e3b373eb6cb0f433
16Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1004594
17Reviewed-by: Russ Cox <rsc@google.com>
18Reviewed-by: Roland Shoemaker <bracewell@google.com>
19Reviewed-by: Filippo Valsorda <valsorda@google.com>
20Reviewed-on: https://go-review.googlesource.com/c/go/+/300391
21Trust: Katie Hockman <katie@golang.org>
22Run-TryBot: Katie Hockman <katie@golang.org>
23TryBot-Result: Go Bot <gobot@golang.org>
24Reviewed-by: Alexander Rakoczy <alex@golang.org>
25Reviewed-by: Filippo Valsorda <filippo@golang.org>
26
27https://github.com/golang/go/commit/d0b79e3513a29628f3599dc8860666b6eed75372
28CVE: CVE-2021-27918
29Upstream-Status: Backport
30Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
31---
32 src/encoding/xml/xml.go | 19 ++++---
33 src/encoding/xml/xml_test.go | 104 +++++++++++++++++++++++++++--------
34 2 files changed, 92 insertions(+), 31 deletions(-)
35
36diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go
37index adaf4daf198b9..6f9594d7ba7a3 100644
38--- a/src/encoding/xml/xml.go
39+++ b/src/encoding/xml/xml.go
40@@ -271,7 +271,7 @@ func NewTokenDecoder(t TokenReader) *Decoder {
41 // it will return an error.
42 //
43 // Token implements XML name spaces as described by
44-// https://www.w3.org/TR/REC-xml-names/. Each of the
45+// https://www.w3.org/TR/REC-xml-names/. Each of the
46 // Name structures contained in the Token has the Space
47 // set to the URL identifying its name space when known.
48 // If Token encounters an unrecognized name space prefix,
49@@ -285,16 +285,17 @@ func (d *Decoder) Token() (Token, error) {
50 if d.nextToken != nil {
51 t = d.nextToken
52 d.nextToken = nil
53- } else if t, err = d.rawToken(); err != nil {
54- switch {
55- case err == io.EOF && d.t != nil:
56- err = nil
57- case err == io.EOF && d.stk != nil && d.stk.kind != stkEOF:
58- err = d.syntaxError("unexpected EOF")
59+ } else {
60+ if t, err = d.rawToken(); t == nil && err != nil {
61+ if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF {
62+ err = d.syntaxError("unexpected EOF")
63+ }
64+ return nil, err
65 }
66- return t, err
67+ // We still have a token to process, so clear any
68+ // errors (e.g. EOF) and proceed.
69+ err = nil
70 }
71-
72 if !d.Strict {
73 if t1, ok := d.autoClose(t); ok {
74 d.nextToken = t
75diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go
76index efddca43e9102..5672ebb375f0d 100644
77--- a/src/encoding/xml/xml_test.go
78+++ b/src/encoding/xml/xml_test.go
79@@ -33,30 +33,90 @@ func (t *toks) Token() (Token, error) {
80
81 func TestDecodeEOF(t *testing.T) {
82 start := StartElement{Name: Name{Local: "test"}}
83- t.Run("EarlyEOF", func(t *testing.T) {
84- d := NewTokenDecoder(&toks{earlyEOF: true, t: []Token{
85- start,
86- start.End(),
87- }})
88- err := d.Decode(&struct {
89- XMLName Name `xml:"test"`
90- }{})
91- if err != nil {
92- t.Error(err)
93+ tests := []struct {
94+ name string
95+ tokens []Token
96+ ok bool
97+ }{
98+ {
99+ name: "OK",
100+ tokens: []Token{
101+ start,
102+ start.End(),
103+ },
104+ ok: true,
105+ },
106+ {
107+ name: "Malformed",
108+ tokens: []Token{
109+ start,
110+ StartElement{Name: Name{Local: "bad"}},
111+ start.End(),
112+ },
113+ ok: false,
114+ },
115+ }
116+ for _, tc := range tests {
117+ for _, eof := range []bool{true, false} {
118+ name := fmt.Sprintf("%s/earlyEOF=%v", tc.name, eof)
119+ t.Run(name, func(t *testing.T) {
120+ d := NewTokenDecoder(&toks{
121+ earlyEOF: eof,
122+ t: tc.tokens,
123+ })
124+ err := d.Decode(&struct {
125+ XMLName Name `xml:"test"`
126+ }{})
127+ if tc.ok && err != nil {
128+ t.Fatalf("d.Decode: expected nil error, got %v", err)
129+ }
130+ if _, ok := err.(*SyntaxError); !tc.ok && !ok {
131+ t.Errorf("d.Decode: expected syntax error, got %v", err)
132+ }
133+ })
134 }
135- })
136- t.Run("LateEOF", func(t *testing.T) {
137- d := NewTokenDecoder(&toks{t: []Token{
138- start,
139- start.End(),
140- }})
141- err := d.Decode(&struct {
142- XMLName Name `xml:"test"`
143- }{})
144- if err != nil {
145- t.Error(err)
146+ }
147+}
148+
149+type toksNil struct {
150+ returnEOF bool
151+ t []Token
152+}
153+
154+func (t *toksNil) Token() (Token, error) {
155+ if len(t.t) == 0 {
156+ if !t.returnEOF {
157+ // Return nil, nil before returning an EOF. It's legal, but
158+ // discouraged.
159+ t.returnEOF = true
160+ return nil, nil
161 }
162- })
163+ return nil, io.EOF
164+ }
165+ var tok Token
166+ tok, t.t = t.t[0], t.t[1:]
167+ return tok, nil
168+}
169+
170+func TestDecodeNilToken(t *testing.T) {
171+ for _, strict := range []bool{true, false} {
172+ name := fmt.Sprintf("Strict=%v", strict)
173+ t.Run(name, func(t *testing.T) {
174+ start := StartElement{Name: Name{Local: "test"}}
175+ bad := StartElement{Name: Name{Local: "bad"}}
176+ d := NewTokenDecoder(&toksNil{
177+ // Malformed
178+ t: []Token{start, bad, start.End()},
179+ })
180+ d.Strict = strict
181+ err := d.Decode(&struct {
182+ XMLName Name `xml:"test"`
183+ }{})
184+ if _, ok := err.(*SyntaxError); !ok {
185+ t.Errorf("d.Decode: expected syntax error, got %v", err)
186+ }
187+ })
188+ }
189 }
190
191 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 @@
1From efb465ada003d23353a91ef930be408eb575dba6 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 16 Jun 2022 17:40:12 +0530
4Subject: [PATCH] CVE-2021-31525
5
6Upstream-Status: Backport [https://github.com/argoheyard/lang-net/commit/701957006ef151feb43f86aa99c8a1f474f69282]
7CVE: CVE-2021-31525
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9
10---
11 src/vendor/golang.org/x/net/http/httpguts/httplex.go | 10 ++++++----
12 1 file changed, 6 insertions(+), 4 deletions(-)
13
14diff --git a/src/vendor/golang.org/x/net/http/httpguts/httplex.go b/src/vendor/golang.org/x/net/http/httpguts/httplex.go
15index e7de24e..c79aa73 100644
16--- a/src/vendor/golang.org/x/net/http/httpguts/httplex.go
17+++ b/src/vendor/golang.org/x/net/http/httpguts/httplex.go
18@@ -137,11 +137,13 @@ func trimOWS(x string) string {
19 // contains token amongst its comma-separated tokens, ASCII
20 // case-insensitively.
21 func headerValueContainsToken(v string, token string) bool {
22- v = trimOWS(v)
23- if comma := strings.IndexByte(v, ','); comma != -1 {
24- return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
25+ for comma := strings.IndexByte(v, ','); comma != -1; comma = strings.IndexByte(v, ',') {
26+ if tokenEqual(trimOWS(v[:comma]), token) {
27+ return true
28+ }
29+ v = v[comma+1:]
30 }
31- return tokenEqual(v, token)
32+ return tokenEqual(trimOWS(v), token)
33 }
34
35 // lowerASCII returns the ASCII lowercase version of b.
36--
372.25.1
38
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 @@
1From 9324d7e53151e9dfa4b25af994a28c2e0b11f729 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <roland@golang.org>
3Date: Thu, 27 May 2021 10:40:06 -0700
4Subject: [PATCH] net: verify results from Lookup* are valid domain names
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/31d60cda1f58b7558fc5725d2b9e4531655d980e]
7CVE: CVE-2021-33195
8Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
9
10
11For the methods LookupCNAME, LookupSRV, LookupMX, LookupNS, and
12LookupAddr check that the returned domain names are in fact valid DNS
13names using the existing isDomainName function.
14
15Thanks to Philipp Jeitner and Haya Shulman from Fraunhofer SIT for
16reporting this issue.
17
18Updates #46241
19Fixes #46356
20Fixes CVE-2021-33195
21
22Change-Id: I47a4f58c031cb752f732e88bbdae7f819f0af4f3
23Reviewed-on: https://go-review.googlesource.com/c/go/+/323131
24Trust: Roland Shoemaker <roland@golang.org>
25Run-TryBot: Roland Shoemaker <roland@golang.org>
26TryBot-Result: Go Bot <gobot@golang.org>
27Reviewed-by: Filippo Valsorda <filippo@golang.org>
28Reviewed-by: Katie Hockman <katie@golang.org>
29(cherry picked from commit cdcd02842da7c004efd023881e3719105209c908)
30Reviewed-on: https://go-review.googlesource.com/c/go/+/323269
31---
32 src/net/dnsclient_unix_test.go | 157 +++++++++++++++++++++++++++++++++
33 src/net/lookup.go | 111 ++++++++++++++++++++---
34 2 files changed, 255 insertions(+), 13 deletions(-)
35
36diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
37index 2ad40df..b8617d9 100644
38--- a/src/net/dnsclient_unix_test.go
39+++ b/src/net/dnsclient_unix_test.go
40@@ -1800,3 +1800,160 @@ func TestPTRandNonPTR(t *testing.T) {
41 t.Errorf("names = %q; want %q", names, want)
42 }
43 }
44+
45+func TestCVE202133195(t *testing.T) {
46+ fake := fakeDNSServer{
47+ rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
48+ r := dnsmessage.Message{
49+ Header: dnsmessage.Header{
50+ ID: q.Header.ID,
51+ Response: true,
52+ RCode: dnsmessage.RCodeSuccess,
53+ RecursionAvailable: true,
54+ },
55+ Questions: q.Questions,
56+ }
57+ switch q.Questions[0].Type {
58+ case dnsmessage.TypeCNAME:
59+ r.Answers = []dnsmessage.Resource{}
60+ case dnsmessage.TypeA: // CNAME lookup uses a A/AAAA as a proxy
61+ r.Answers = append(r.Answers,
62+ dnsmessage.Resource{
63+ Header: dnsmessage.ResourceHeader{
64+ Name: dnsmessage.MustNewName("<html>.golang.org."),
65+ Type: dnsmessage.TypeA,
66+ Class: dnsmessage.ClassINET,
67+ Length: 4,
68+ },
69+ Body: &dnsmessage.AResource{
70+ A: TestAddr,
71+ },
72+ },
73+ )
74+ case dnsmessage.TypeSRV:
75+ n := q.Questions[0].Name
76+ if n.String() == "_hdr._tcp.golang.org." {
77+ n = dnsmessage.MustNewName("<html>.golang.org.")
78+ }
79+ r.Answers = append(r.Answers,
80+ dnsmessage.Resource{
81+ Header: dnsmessage.ResourceHeader{
82+ Name: n,
83+ Type: dnsmessage.TypeSRV,
84+ Class: dnsmessage.ClassINET,
85+ Length: 4,
86+ },
87+ Body: &dnsmessage.SRVResource{
88+ Target: dnsmessage.MustNewName("<html>.golang.org."),
89+ },
90+ },
91+ )
92+ case dnsmessage.TypeMX:
93+ r.Answers = append(r.Answers,
94+ dnsmessage.Resource{
95+ Header: dnsmessage.ResourceHeader{
96+ Name: dnsmessage.MustNewName("<html>.golang.org."),
97+ Type: dnsmessage.TypeMX,
98+ Class: dnsmessage.ClassINET,
99+ Length: 4,
100+ },
101+ Body: &dnsmessage.MXResource{
102+ MX: dnsmessage.MustNewName("<html>.golang.org."),
103+ },
104+ },
105+ )
106+ case dnsmessage.TypeNS:
107+ r.Answers = append(r.Answers,
108+ dnsmessage.Resource{
109+ Header: dnsmessage.ResourceHeader{
110+ Name: dnsmessage.MustNewName("<html>.golang.org."),
111+ Type: dnsmessage.TypeNS,
112+ Class: dnsmessage.ClassINET,
113+ Length: 4,
114+ },
115+ Body: &dnsmessage.NSResource{
116+ NS: dnsmessage.MustNewName("<html>.golang.org."),
117+ },
118+ },
119+ )
120+ case dnsmessage.TypePTR:
121+ r.Answers = append(r.Answers,
122+ dnsmessage.Resource{
123+ Header: dnsmessage.ResourceHeader{
124+ Name: dnsmessage.MustNewName("<html>.golang.org."),
125+ Type: dnsmessage.TypePTR,
126+ Class: dnsmessage.ClassINET,
127+ Length: 4,
128+ },
129+ Body: &dnsmessage.PTRResource{
130+ PTR: dnsmessage.MustNewName("<html>.golang.org."),
131+ },
132+ },
133+ )
134+ }
135+ return r, nil
136+ },
137+ }
138+
139+ r := Resolver{PreferGo: true, Dial: fake.DialContext}
140+ // Change the default resolver to match our manipulated resolver
141+ originalDefault := DefaultResolver
142+ DefaultResolver = &r
143+ defer func() {
144+ DefaultResolver = originalDefault
145+ }()
146+
147+ _, err := r.LookupCNAME(context.Background(), "golang.org")
148+ if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
149+ t.Errorf("Resolver.LookupCNAME returned unexpected error, got %q, want %q", err.Error(), expected)
150+ }
151+ _, err = LookupCNAME("golang.org")
152+ if expected := "lookup golang.org: CNAME target is invalid"; err == nil || err.Error() != expected {
153+ t.Errorf("LookupCNAME returned unexpected error, got %q, want %q", err.Error(), expected)
154+ }
155+
156+ _, _, err = r.LookupSRV(context.Background(), "target", "tcp", "golang.org")
157+ if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
158+ t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected)
159+ }
160+ _, _, err = LookupSRV("target", "tcp", "golang.org")
161+ if expected := "lookup golang.org: SRV target is invalid"; err == nil || err.Error() != expected {
162+ t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected)
163+ }
164+
165+ _, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org")
166+ if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
167+ t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected)
168+ }
169+ _, _, err = LookupSRV("hdr", "tcp", "golang.org")
170+ if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
171+ t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err.Error(), expected)
172+ }
173+
174+ _, err = r.LookupMX(context.Background(), "golang.org")
175+ if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
176+ t.Errorf("Resolver.LookupMX returned unexpected error, got %q, want %q", err.Error(), expected)
177+ }
178+ _, err = LookupMX("golang.org")
179+ if expected := "lookup golang.org: MX target is invalid"; err == nil || err.Error() != expected {
180+ t.Errorf("LookupMX returned unexpected error, got %q, want %q", err.Error(), expected)
181+ }
182+
183+ _, err = r.LookupNS(context.Background(), "golang.org")
184+ if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
185+ t.Errorf("Resolver.LookupNS returned unexpected error, got %q, want %q", err.Error(), expected)
186+ }
187+ _, err = LookupNS("golang.org")
188+ if expected := "lookup golang.org: NS target is invalid"; err == nil || err.Error() != expected {
189+ t.Errorf("LookupNS returned unexpected error, got %q, want %q", err.Error(), expected)
190+ }
191+
192+ _, err = r.LookupAddr(context.Background(), "1.2.3.4")
193+ if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected {
194+ t.Errorf("Resolver.LookupAddr returned unexpected error, got %q, want %q", err.Error(), expected)
195+ }
196+ _, err = LookupAddr("1.2.3.4")
197+ if expected := "lookup 1.2.3.4: PTR target is invalid"; err == nil || err.Error() != expected {
198+ t.Errorf("LookupAddr returned unexpected error, got %q, want %q", err.Error(), expected)
199+ }
200+}
201diff --git a/src/net/lookup.go b/src/net/lookup.go
202index 9cebd10..05e88e4 100644
203--- a/src/net/lookup.go
204+++ b/src/net/lookup.go
205@@ -364,8 +364,11 @@ func (r *Resolver) LookupPort(ctx context.Context, network, service string) (por
206 // LookupCNAME does not return an error if host does not
207 // contain DNS "CNAME" records, as long as host resolves to
208 // address records.
209+//
210+// The returned canonical name is validated to be a properly
211+// formatted presentation-format domain name.
212 func LookupCNAME(host string) (cname string, err error) {
213- return DefaultResolver.lookupCNAME(context.Background(), host)
214+ return DefaultResolver.LookupCNAME(context.Background(), host)
215 }
216
217 // LookupCNAME returns the canonical name for the given host.
218@@ -378,8 +381,18 @@ func LookupCNAME(host string) (cname string, err error) {
219 // LookupCNAME does not return an error if host does not
220 // contain DNS "CNAME" records, as long as host resolves to
221 // address records.
222-func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string, err error) {
223- return r.lookupCNAME(ctx, host)
224+//
225+// The returned canonical name is validated to be a properly
226+// formatted presentation-format domain name.
227+func (r *Resolver) LookupCNAME(ctx context.Context, host string) (string, error) {
228+ cname, err := r.lookupCNAME(ctx, host)
229+ if err != nil {
230+ return "", err
231+ }
232+ if !isDomainName(cname) {
233+ return "", &DNSError{Err: "CNAME target is invalid", Name: host}
234+ }
235+ return cname, nil
236 }
237
238 // LookupSRV tries to resolve an SRV query of the given service,
239@@ -391,8 +404,11 @@ func (r *Resolver) LookupCNAME(ctx context.Context, host string) (cname string,
240 // That is, it looks up _service._proto.name. To accommodate services
241 // publishing SRV records under non-standard names, if both service
242 // and proto are empty strings, LookupSRV looks up name directly.
243+//
244+// The returned service names are validated to be properly
245+// formatted presentation-format domain names.
246 func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err error) {
247- return DefaultResolver.lookupSRV(context.Background(), service, proto, name)
248+ return DefaultResolver.LookupSRV(context.Background(), service, proto, name)
249 }
250
251 // LookupSRV tries to resolve an SRV query of the given service,
252@@ -404,28 +420,82 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
253 // That is, it looks up _service._proto.name. To accommodate services
254 // publishing SRV records under non-standard names, if both service
255 // and proto are empty strings, LookupSRV looks up name directly.
256-func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
257- return r.lookupSRV(ctx, service, proto, name)
258+//
259+// The returned service names are validated to be properly
260+// formatted presentation-format domain names.
261+func (r *Resolver) LookupSRV(ctx context.Context, service, proto, name string) (string, []*SRV, error) {
262+ cname, addrs, err := r.lookupSRV(ctx, service, proto, name)
263+ if err != nil {
264+ return "", nil, err
265+ }
266+ if cname != "" && !isDomainName(cname) {
267+ return "", nil, &DNSError{Err: "SRV header name is invalid", Name: name}
268+ }
269+ for _, addr := range addrs {
270+ if addr == nil {
271+ continue
272+ }
273+ if !isDomainName(addr.Target) {
274+ return "", nil, &DNSError{Err: "SRV target is invalid", Name: name}
275+ }
276+ }
277+ return cname, addrs, nil
278 }
279
280 // LookupMX returns the DNS MX records for the given domain name sorted by preference.
281+//
282+// The returned mail server names are validated to be properly
283+// formatted presentation-format domain names.
284 func LookupMX(name string) ([]*MX, error) {
285- return DefaultResolver.lookupMX(context.Background(), name)
286+ return DefaultResolver.LookupMX(context.Background(), name)
287 }
288
289 // LookupMX returns the DNS MX records for the given domain name sorted by preference.
290+//
291+// The returned mail server names are validated to be properly
292+// formatted presentation-format domain names.
293 func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
294- return r.lookupMX(ctx, name)
295+ records, err := r.lookupMX(ctx, name)
296+ if err != nil {
297+ return nil, err
298+ }
299+ for _, mx := range records {
300+ if mx == nil {
301+ continue
302+ }
303+ if !isDomainName(mx.Host) {
304+ return nil, &DNSError{Err: "MX target is invalid", Name: name}
305+ }
306+ }
307+ return records, nil
308 }
309
310 // LookupNS returns the DNS NS records for the given domain name.
311+//
312+// The returned name server names are validated to be properly
313+// formatted presentation-format domain names.
314 func LookupNS(name string) ([]*NS, error) {
315- return DefaultResolver.lookupNS(context.Background(), name)
316+ return DefaultResolver.LookupNS(context.Background(), name)
317 }
318
319 // LookupNS returns the DNS NS records for the given domain name.
320+//
321+// The returned name server names are validated to be properly
322+// formatted presentation-format domain names.
323 func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) {
324- return r.lookupNS(ctx, name)
325+ records, err := r.lookupNS(ctx, name)
326+ if err != nil {
327+ return nil, err
328+ }
329+ for _, ns := range records {
330+ if ns == nil {
331+ continue
332+ }
333+ if !isDomainName(ns.Host) {
334+ return nil, &DNSError{Err: "NS target is invalid", Name: name}
335+ }
336+ }
337+ return records, nil
338 }
339
340 // LookupTXT returns the DNS TXT records for the given domain name.
341@@ -441,14 +511,29 @@ func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error)
342 // LookupAddr performs a reverse lookup for the given address, returning a list
343 // of names mapping to that address.
344 //
345+// The returned names are validated to be properly formatted presentation-format
346+// domain names.
347+//
348 // When using the host C library resolver, at most one result will be
349 // returned. To bypass the host resolver, use a custom Resolver.
350 func LookupAddr(addr string) (names []string, err error) {
351- return DefaultResolver.lookupAddr(context.Background(), addr)
352+ return DefaultResolver.LookupAddr(context.Background(), addr)
353 }
354
355 // LookupAddr performs a reverse lookup for the given address, returning a list
356 // of names mapping to that address.
357-func (r *Resolver) LookupAddr(ctx context.Context, addr string) (names []string, err error) {
358- return r.lookupAddr(ctx, addr)
359+//
360+// The returned names are validated to be properly formatted presentation-format
361+// domain names.
362+func (r *Resolver) LookupAddr(ctx context.Context, addr string) ([]string, error) {
363+ names, err := r.lookupAddr(ctx, addr)
364+ if err != nil {
365+ return nil, err
366+ }
367+ for _, name := range names {
368+ if !isDomainName(name) {
369+ return nil, &DNSError{Err: "PTR target is invalid", Name: addr}
370+ }
371+ }
372+ return names, nil
373 }
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 @@
1From 74242baa4136c7a9132a8ccd9881354442788c8c Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <roland@golang.org>
3Date: Tue, 11 May 2021 11:31:31 -0700
4Subject: [PATCH] archive/zip: only preallocate File slice if reasonably sized
5
6Since the number of files in the EOCD record isn't validated, it isn't
7safe to preallocate Reader.Files using that field. A malformed archive
8can indicate it contains up to 1 << 128 - 1 files. We can still safely
9preallocate the slice by checking if the specified number of files in
10the archive is reasonable, given the size of the archive.
11
12Thanks to the OSS-Fuzz project for discovering this issue and to
13Emmanuel Odeke for reporting it.
14
15Fixes #46242
16Fixes CVE-2021-33196
17
18Change-Id: I3c76d8eec178468b380d87fdb4a3f2cb06f0ee76
19Reviewed-on: https://go-review.googlesource.com/c/go/+/318909
20Trust: Roland Shoemaker <roland@golang.org>
21Trust: Katie Hockman <katie@golang.org>
22Trust: Joe Tsai <thebrokentoaster@gmail.com>
23Run-TryBot: Roland Shoemaker <roland@golang.org>
24TryBot-Result: Go Bot <gobot@golang.org>
25Reviewed-by: Katie Hockman <katie@golang.org>
26Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
27
28Upstream-Status: Backport
29CVE: CVE-2021-33196
30Signed-off-by: Armin Kuster <akuster@mvista.com>
31
32---
33 src/archive/zip/reader.go | 10 +++++-
34 src/archive/zip/reader_test.go | 59 ++++++++++++++++++++++++++++++++++
35 2 files changed, 68 insertions(+), 1 deletion(-)
36
37Index: go/src/archive/zip/reader.go
38===================================================================
39--- go.orig/src/archive/zip/reader.go
40+++ go/src/archive/zip/reader.go
41@@ -84,7 +84,15 @@ func (z *Reader) init(r io.ReaderAt, siz
42 return err
43 }
44 z.r = r
45- z.File = make([]*File, 0, end.directoryRecords)
46+ // Since the number of directory records is not validated, it is not
47+ // safe to preallocate z.File without first checking that the specified
48+ // number of files is reasonable, since a malformed archive may
49+ // indicate it contains up to 1 << 128 - 1 files. Since each file has a
50+ // header which will be _at least_ 30 bytes we can safely preallocate
51+ // if (data size / 30) >= end.directoryRecords.
52+ if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
53+ z.File = make([]*File, 0, end.directoryRecords)
54+ }
55 z.Comment = end.comment
56 rs := io.NewSectionReader(r, 0, size)
57 if _, err = rs.Seek(int64(end.directoryOffset), io.SeekStart); err != nil {
58Index: go/src/archive/zip/reader_test.go
59===================================================================
60--- go.orig/src/archive/zip/reader_test.go
61+++ go/src/archive/zip/reader_test.go
62@@ -1070,3 +1070,62 @@ func TestIssue12449(t *testing.T) {
63 t.Errorf("Error reading the archive: %v", err)
64 }
65 }
66+
67+func TestCVE202133196(t *testing.T) {
68+ // Archive that indicates it has 1 << 128 -1 files,
69+ // this would previously cause a panic due to attempting
70+ // to allocate a slice with 1 << 128 -1 elements.
71+ data := []byte{
72+ 0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x08,
73+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x02,
76+ 0x03, 0x62, 0x61, 0x65, 0x03, 0x04, 0x00, 0x00,
77+ 0xff, 0xff, 0x50, 0x4b, 0x07, 0x08, 0xbe, 0x20,
78+ 0x5c, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00,
79+ 0x00, 0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00,
80+ 0x14, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
81+ 0x00, 0x00, 0xbe, 0x20, 0x5c, 0x6c, 0x09, 0x00,
82+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00,
83+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85+ 0x01, 0x02, 0x03, 0x50, 0x4b, 0x06, 0x06, 0x2c,
86+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d,
87+ 0x00, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
89+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
90+ 0xff, 0xff, 0xff, 0x31, 0x00, 0x00, 0x00, 0x00,
91+ 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
92+ 0x00, 0x00, 0x00, 0x50, 0x4b, 0x06, 0x07, 0x00,
93+ 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00,
94+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50,
95+ 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0xff,
96+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
97+ 0xff, 0xff, 0xff, 0x00, 0x00,
98+ }
99+ _, err := NewReader(bytes.NewReader(data), int64(len(data)))
100+ if err != ErrFormat {
101+ t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
102+ }
103+
104+ // Also check that an archive containing a handful of empty
105+ // files doesn't cause an issue
106+ b := bytes.NewBuffer(nil)
107+ w := NewWriter(b)
108+ for i := 0; i < 5; i++ {
109+ _, err := w.Create("")
110+ if err != nil {
111+ t.Fatalf("Writer.Create failed: %s", err)
112+ }
113+ }
114+ if err := w.Close(); err != nil {
115+ t.Fatalf("Writer.Close failed: %s", err)
116+ }
117+ r, err := NewReader(bytes.NewReader(b.Bytes()), int64(b.Len()))
118+ if err != nil {
119+ t.Fatalf("NewReader failed: %s", err)
120+ }
121+ if len(r.File) != 5 {
122+ t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
123+ }
124+}
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 @@
1From cbd1ca84453fecf3825a6bb9f985823e8bc32b76 Mon Sep 17 00:00:00 2001
2From: Filippo Valsorda <filippo@golang.org>
3Date: Fri, 21 May 2021 14:02:30 -0400
4Subject: [PATCH] [release-branch.go1.15] net/http/httputil: always remove
5 hop-by-hop headers
6
7Previously, we'd fail to remove the Connection header from a request
8like this:
9
10 Connection:
11 Connection: x-header
12
13Updates #46313
14Fixes #46314
15Fixes CVE-2021-33197
16
17Change-Id: Ie3009e926ceecfa86dfa6bcc6fe14ff01086be7d
18Reviewed-on: https://go-review.googlesource.com/c/go/+/321929
19Run-TryBot: Filippo Valsorda <filippo@golang.org>
20Reviewed-by: Katie Hockman <katie@golang.org>
21Trust: Katie Hockman <katie@golang.org>
22Trust: Filippo Valsorda <filippo@golang.org>
23TryBot-Result: Go Bot <gobot@golang.org>
24Reviewed-on: https://go-review.googlesource.com/c/go/+/323091
25Run-TryBot: Katie Hockman <katie@golang.org>
26
27Upstream-Status: Backport
28CVE: CVE-2021-33197
29Signed-off-by: Armin Kuster <akuster@mvista.com>
30
31---
32 src/net/http/httputil/reverseproxy.go | 22 ++++----
33 src/net/http/httputil/reverseproxy_test.go | 63 +++++++++++++++++++++-
34 2 files changed, 70 insertions(+), 15 deletions(-)
35
36Index: go/src/net/http/httputil/reverseproxy.go
37===================================================================
38--- go.orig/src/net/http/httputil/reverseproxy.go
39+++ go/src/net/http/httputil/reverseproxy.go
40@@ -221,22 +221,18 @@ func (p *ReverseProxy) ServeHTTP(rw http
41 // important is "Connection" because we want a persistent
42 // connection, regardless of what the client sent to us.
43 for _, h := range hopHeaders {
44- hv := outreq.Header.Get(h)
45- if hv == "" {
46- continue
47- }
48- if h == "Te" && hv == "trailers" {
49- // Issue 21096: tell backend applications that
50- // care about trailer support that we support
51- // trailers. (We do, but we don't go out of
52- // our way to advertise that unless the
53- // incoming client request thought it was
54- // worth mentioning)
55- continue
56- }
57 outreq.Header.Del(h)
58 }
59
60+ // Issue 21096: tell backend applications that care about trailer support
61+ // that we support trailers. (We do, but we don't go out of our way to
62+ // advertise that unless the incoming client request thought it was worth
63+ // mentioning.) Note that we look at req.Header, not outreq.Header, since
64+ // the latter has passed through removeConnectionHeaders.
65+ if httpguts.HeaderValuesContainsToken(req.Header["Te"], "trailers") {
66+ outreq.Header.Set("Te", "trailers")
67+ }
68+
69 // After stripping all the hop-by-hop connection headers above, add back any
70 // necessary for protocol upgrades, such as for websockets.
71 if reqUpType != "" {
72Index: go/src/net/http/httputil/reverseproxy_test.go
73===================================================================
74--- go.orig/src/net/http/httputil/reverseproxy_test.go
75+++ go/src/net/http/httputil/reverseproxy_test.go
76@@ -91,8 +91,9 @@ func TestReverseProxy(t *testing.T) {
77
78 getReq, _ := http.NewRequest("GET", frontend.URL, nil)
79 getReq.Host = "some-name"
80- getReq.Header.Set("Connection", "close")
81- getReq.Header.Set("Te", "trailers")
82+ getReq.Header.Set("Connection", "close, TE")
83+ getReq.Header.Add("Te", "foo")
84+ getReq.Header.Add("Te", "bar, trailers")
85 getReq.Header.Set("Proxy-Connection", "should be deleted")
86 getReq.Header.Set("Upgrade", "foo")
87 getReq.Close = true
88@@ -236,6 +237,64 @@ func TestReverseProxyStripHeadersPresent
89 }
90 }
91
92+func TestReverseProxyStripEmptyConnection(t *testing.T) {
93+ // See Issue 46313.
94+ const backendResponse = "I am the backend"
95+
96+ // someConnHeader is some arbitrary header to be declared as a hop-by-hop header
97+ // in the Request's Connection header.
98+ const someConnHeader = "X-Some-Conn-Header"
99+
100+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
101+ if c := r.Header.Values("Connection"); len(c) != 0 {
102+ t.Errorf("handler got header %q = %v; want empty", "Connection", c)
103+ }
104+ if c := r.Header.Get(someConnHeader); c != "" {
105+ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
106+ }
107+ w.Header().Add("Connection", "")
108+ w.Header().Add("Connection", someConnHeader)
109+ w.Header().Set(someConnHeader, "should be deleted")
110+ io.WriteString(w, backendResponse)
111+ }))
112+ defer backend.Close()
113+ backendURL, err := url.Parse(backend.URL)
114+ if err != nil {
115+ t.Fatal(err)
116+ }
117+ proxyHandler := NewSingleHostReverseProxy(backendURL)
118+ frontend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
119+ proxyHandler.ServeHTTP(w, r)
120+ if c := r.Header.Get(someConnHeader); c != "should be deleted" {
121+ t.Errorf("handler modified header %q = %q; want %q", someConnHeader, c, "should be deleted")
122+ }
123+ }))
124+ defer frontend.Close()
125+
126+ getReq, _ := http.NewRequest("GET", frontend.URL, nil)
127+ getReq.Header.Add("Connection", "")
128+ getReq.Header.Add("Connection", someConnHeader)
129+ getReq.Header.Set(someConnHeader, "should be deleted")
130+ res, err := frontend.Client().Do(getReq)
131+ if err != nil {
132+ t.Fatalf("Get: %v", err)
133+ }
134+ defer res.Body.Close()
135+ bodyBytes, err := ioutil.ReadAll(res.Body)
136+ if err != nil {
137+ t.Fatalf("reading body: %v", err)
138+ }
139+ if got, want := string(bodyBytes), backendResponse; got != want {
140+ t.Errorf("got body %q; want %q", got, want)
141+ }
142+ if c := res.Header.Get("Connection"); c != "" {
143+ t.Errorf("handler got header %q = %q; want empty", "Connection", c)
144+ }
145+ if c := res.Header.Get(someConnHeader); c != "" {
146+ t.Errorf("handler got header %q = %q; want empty", someConnHeader, c)
147+ }
148+}
149+
150 func TestXForwardedFor(t *testing.T) {
151 const prevForwardedFor = "client ip"
152 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 @@
1From c8866491ac424cdf39aedb325e6dec9e54418cfb Mon Sep 17 00:00:00 2001
2From: Robert Griesemer <gri@golang.org>
3Date: Sun, 2 May 2021 11:27:03 -0700
4Subject: [PATCH] math/big: check for excessive exponents in Rat.SetString
5
6CVE-2021-33198
7
8Upstream-Status: Backport [https://github.com/golang/go/commit/df9ce19db6df32d94eae8760927bdfbc595433c3]
9CVE: CVE-2021-33198
10Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
11
12
13Found by OSS-Fuzz https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=33284
14
15Thanks to Emmanuel Odeke for reporting this issue.
16
17Updates #45910
18Fixes #46305
19Fixes CVE-2021-33198
20
21Change-Id: I61e7b04dbd80343420b57eede439e361c0f7b79c
22Reviewed-on: https://go-review.googlesource.com/c/go/+/316149
23Trust: Robert Griesemer <gri@golang.org>
24Trust: Katie Hockman <katie@golang.org>
25Run-TryBot: Robert Griesemer <gri@golang.org>
26TryBot-Result: Go Bot <gobot@golang.org>
27Reviewed-by: Katie Hockman <katie@golang.org>
28Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
29(cherry picked from commit 6c591f79b0b5327549bd4e94970f7a279efb4ab0)
30Reviewed-on: https://go-review.googlesource.com/c/go/+/321831
31Run-TryBot: Katie Hockman <katie@golang.org>
32Reviewed-by: Roland Shoemaker <roland@golang.org>
33---
34 src/math/big/ratconv.go | 15 ++++++++-------
35 src/math/big/ratconv_test.go | 25 +++++++++++++++++++++++++
36 2 files changed, 33 insertions(+), 7 deletions(-)
37
38diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go
39index e8cbdbe..90053a9 100644
40--- a/src/math/big/ratconv.go
41+++ b/src/math/big/ratconv.go
42@@ -51,7 +51,8 @@ func (z *Rat) Scan(s fmt.ScanState, ch rune) error {
43 // An optional base-10 ``e'' or base-2 ``p'' (or their upper-case variants)
44 // exponent may be provided as well, except for hexadecimal floats which
45 // only accept an (optional) ``p'' exponent (because an ``e'' or ``E'' cannot
46-// be distinguished from a mantissa digit).
47+// be distinguished from a mantissa digit). If the exponent's absolute value
48+// is too large, the operation may fail.
49 // The entire string, not just a prefix, must be valid for success. If the
50 // operation failed, the value of z is undefined but the returned value is nil.
51 func (z *Rat) SetString(s string) (*Rat, bool) {
52@@ -174,6 +175,9 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
53 return nil, false
54 }
55 }
56+ if n > 1e6 {
57+ return nil, false // avoid excessively large exponents
58+ }
59 pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil) // use underlying array of z.b.abs
60 if exp5 > 0 {
61 z.a.abs = z.a.abs.mul(z.a.abs, pow5)
62@@ -186,15 +190,12 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
63 }
64
65 // apply exp2 contributions
66+ if exp2 < -1e7 || exp2 > 1e7 {
67+ return nil, false // avoid excessively large exponents
68+ }
69 if exp2 > 0 {
70- if int64(uint(exp2)) != exp2 {
71- panic("exponent too large")
72- }
73 z.a.abs = z.a.abs.shl(z.a.abs, uint(exp2))
74 } else if exp2 < 0 {
75- if int64(uint(-exp2)) != -exp2 {
76- panic("exponent too large")
77- }
78 z.b.abs = z.b.abs.shl(z.b.abs, uint(-exp2))
79 }
80
81diff --git a/src/math/big/ratconv_test.go b/src/math/big/ratconv_test.go
82index b820df4..e55e655 100644
83--- a/src/math/big/ratconv_test.go
84+++ b/src/math/big/ratconv_test.go
85@@ -590,3 +590,28 @@ func TestIssue31184(t *testing.T) {
86 }
87 }
88 }
89+
90+func TestIssue45910(t *testing.T) {
91+ var x Rat
92+ for _, test := range []struct {
93+ input string
94+ want bool
95+ }{
96+ {"1e-1000001", false},
97+ {"1e-1000000", true},
98+ {"1e+1000000", true},
99+ {"1e+1000001", false},
100+
101+ {"0p1000000000000", true},
102+ {"1p-10000001", false},
103+ {"1p-10000000", true},
104+ {"1p+10000000", true},
105+ {"1p+10000001", false},
106+ {"1.770p02041010010011001001", false}, // test case from issue
107+ } {
108+ _, got := x.SetString(test.input)
109+ if got != test.want {
110+ t.Errorf("SetString(%s) got ok = %v; want %v", test.input, got, test.want)
111+ }
112+ }
113+}
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 @@
1From a98589711da5e9d935e8d690cfca92892e86d557 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <roland@golang.org>
3Date: Wed, 9 Jun 2021 11:31:27 -0700
4Subject: [PATCH] crypto/tls: test key type when casting
5
6When casting the certificate public key in generateClientKeyExchange,
7check the type is appropriate. This prevents a panic when a server
8agrees to a RSA based key exchange, but then sends an ECDSA (or
9other) certificate.
10
11Fixes #47143
12Fixes CVE-2021-34558
13
14Thanks to Imre Rad for reporting this issue.
15
16Change-Id: Iabccacca6052769a605cccefa1216a9f7b7f6aea
17Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1116723
18Reviewed-by: Filippo Valsorda <valsorda@google.com>
19Reviewed-by: Katie Hockman <katiehockman@google.com>
20Reviewed-on: https://go-review.googlesource.com/c/go/+/334031
21Trust: Filippo Valsorda <filippo@golang.org>
22Run-TryBot: Filippo Valsorda <filippo@golang.org>
23TryBot-Result: Go Bot <gobot@golang.org>
24Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
25
26Upstream-Status: Backport
27https://github.com/golang/go/commit/a98589711da5e9d935e8d690cfca92892e86d557
28CVE: CVE-2021-34558
29Signed-off-by: Armin Kuster <akuster@mvista.com>
30
31---
32 src/crypto/tls/key_agreement.go | 6 +++++-
33 1 file changed, 5 insertions(+), 1 deletion(-)
34
35Index: go/src/crypto/tls/key_agreement.go
36===================================================================
37--- go.orig/src/crypto/tls/key_agreement.go
38+++ go/src/crypto/tls/key_agreement.go
39@@ -67,7 +67,11 @@ func (ka rsaKeyAgreement) generateClient
40 return nil, nil, err
41 }
42
43- encrypted, err := rsa.EncryptPKCS1v15(config.rand(), cert.PublicKey.(*rsa.PublicKey), preMasterSecret)
44+ rsaKey, ok := cert.PublicKey.(*rsa.PublicKey)
45+ if !ok {
46+ return nil, nil, errors.New("tls: server certificate contains incorrect key type for selected ciphersuite")
47+ }
48+ encrypted, err := rsa.EncryptPKCS1v15(config.rand(), rsaKey, preMasterSecret)
49 if err != nil {
50 return nil, nil, err
51 }
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 @@
1From b7a85e0003cedb1b48a1fd3ae5b746ec6330102e Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Wed, 7 Jul 2021 16:34:34 -0700
4Subject: [PATCH] net/http/httputil: close incoming ReverseProxy request body
5
6Reading from an incoming request body after the request handler aborts
7with a panic can cause a panic, becuse http.Server does not (contrary
8to its documentation) close the request body in this case.
9
10Always close the incoming request body in ReverseProxy.ServeHTTP to
11ensure that any in-flight outgoing requests using the body do not
12read from it.
13
14Updates #46866
15Fixes CVE-2021-36221
16
17Change-Id: I310df269200ad8732c5d9f1a2b00de68725831df
18Reviewed-on: https://go-review.googlesource.com/c/go/+/333191
19Trust: Damien Neil <dneil@google.com>
20Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
21Reviewed-by: Filippo Valsorda <filippo@golang.org>
22
23https://github.com/golang/go/commit/b7a85e0003cedb1b48a1fd3ae5b746ec6330102e
24CVE: CVE-2021-36221
25Upstream-Status: Backport
26Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
27---
28 src/net/http/httputil/reverseproxy.go | 9 +++++
29 src/net/http/httputil/reverseproxy_test.go | 39 ++++++++++++++++++++++
30 2 files changed, 48 insertions(+)
31
32diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
33index 5d39955d62d15..8b63368386f43 100644
34--- a/src/net/http/httputil/reverseproxy.go
35+++ b/src/net/http/httputil/reverseproxy.go
36@@ -235,6 +235,15 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
37 if req.ContentLength == 0 {
38 outreq.Body = nil // Issue 16036: nil Body for http.Transport retries
39 }
40+ if outreq.Body != nil {
41+ // Reading from the request body after returning from a handler is not
42+ // allowed, and the RoundTrip goroutine that reads the Body can outlive
43+ // this handler. This can lead to a crash if the handler panics (see
44+ // Issue 46866). Although calling Close doesn't guarantee there isn't
45+ // any Read in flight after the handle returns, in practice it's safe to
46+ // read after closing it.
47+ defer outreq.Body.Close()
48+ }
49 if outreq.Header == nil {
50 outreq.Header = make(http.Header) // Issue 33142: historical behavior was to always allocate
51 }
52diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
53index 1898ed8b8afde..4b6ad77a29466 100644
54--- a/src/net/http/httputil/reverseproxy_test.go
55+++ b/src/net/http/httputil/reverseproxy_test.go
56@@ -1122,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) {
57 rproxy.ServeHTTP(httptest.NewRecorder(), req)
58 }
59
60+// Issue #46866: panic without closing incoming request body causes a panic
61+func TestReverseProxy_PanicClosesIncomingBody(t *testing.T) {
62+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
63+ out := "this call was relayed by the reverse proxy"
64+ // Coerce a wrong content length to induce io.ErrUnexpectedEOF
65+ w.Header().Set("Content-Length", fmt.Sprintf("%d", len(out)*2))
66+ fmt.Fprintln(w, out)
67+ }))
68+ defer backend.Close()
69+ backendURL, err := url.Parse(backend.URL)
70+ if err != nil {
71+ t.Fatal(err)
72+ }
73+ proxyHandler := NewSingleHostReverseProxy(backendURL)
74+ proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
75+ frontend := httptest.NewServer(proxyHandler)
76+ defer frontend.Close()
77+ frontendClient := frontend.Client()
78+
79+ var wg sync.WaitGroup
80+ for i := 0; i < 2; i++ {
81+ wg.Add(1)
82+ go func() {
83+ defer wg.Done()
84+ for j := 0; j < 10; j++ {
85+ const reqLen = 6 * 1024 * 1024
86+ req, _ := http.NewRequest("POST", frontend.URL, &io.LimitedReader{R: neverEnding('x'), N: reqLen})
87+ req.ContentLength = reqLen
88+ resp, _ := frontendClient.Transport.RoundTrip(req)
89+ if resp != nil {
90+ io.Copy(io.Discard, resp.Body)
91+ resp.Body.Close()
92+ }
93+ }
94+ }()
95+ }
96+ wg.Wait()
97+}
98+
99 func TestSelectFlushInterval(t *testing.T) {
100 tests := []struct {
101 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 @@
1From 4548fcc8dfd933c237f29bba6f90040a85922564 Mon Sep 17 00:00:00 2001
2From: Michael Knyszek <mknyszek@google.com>
3Date: Thu, 2 Sep 2021 16:51:59 -0400
4Subject: [PATCH] [release-branch.go1.16] misc/wasm, cmd/link: do not let
5 command line args overwrite global data
6
7On Wasm, wasm_exec.js puts command line arguments at the beginning
8of the linear memory (following the "zero page"). Currently there
9is no limit for this, and a very long command line can overwrite
10the program's data section. Prevent this by limiting the command
11line to 4096 bytes, and in the linker ensuring the data section
12starts at a high enough address (8192).
13
14(Arguably our address assignment on Wasm is a bit confusing. This
15is the minimum fix I can come up with.)
16
17Thanks to Ben Lubar for reporting this issue.
18
19Change by Cherry Mui <cherryyz@google.com>.
20
21For #48797
22Fixes #48799
23Fixes CVE-2021-38297
24
25Change-Id: I0f50fbb2a5b6d0d047e3c134a88988d9133e4ab3
26Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1205933
27Reviewed-by: Roland Shoemaker <bracewell@google.com>
28Reviewed-by: Than McIntosh <thanm@google.com>
29Reviewed-on: https://go-review.googlesource.com/c/go/+/354591
30Trust: Michael Knyszek <mknyszek@google.com>
31Reviewed-by: Heschi Kreinick <heschi@google.com>
32
33CVE: CVE-2021-38297
34
35Upstream-Status: Backport:
36https://github.com/golang/go/commit/4548fcc8dfd933c237f29bba6f90040a85922564
37
38Inline of ctxt.isWAsm followin this implemetation:
39https://github.com/golang/go/blob/4548fcc8dfd933c237f29bba6f90040a85922564/src/cmd/link/internal/ld/target.go#L127
40
41Signed-off-by: Davide Gardenal <davide.gardenal@huawei.com>
42---
43 misc/wasm/wasm_exec.js | 7 +++++++
44 src/cmd/link/internal/ld/data.go | 11 ++++++++++-
45 2 files changed, 17 insertions(+), 1 deletion(-)
46
47diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js
48index 82041e6bb901..a0a264278b1b 100644
49--- a/misc/wasm/wasm_exec.js
50+++ b/misc/wasm/wasm_exec.js
51@@ -564,6 +564,13 @@
52 offset += 8;
53 });
54
55+ // The linker guarantees global data starts from at least wasmMinDataAddr.
56+ // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
57+ const wasmMinDataAddr = 4096 + 4096;
58+ if (offset >= wasmMinDataAddr) {
59+ throw new Error("command line too long");
60+ }
61+
62 this._inst.exports.run(argc, argv);
63 if (this.exited) {
64 this._resolveExitPromise();
65diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
66index 52035e96301c..54a1d188cdb9 100644
67--- a/src/cmd/link/internal/ld/data.go
68+++ b/src/cmd/link/internal/ld/data.go
69@@ -2330,6 +2330,11 @@ func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64
70 return sect, n, va
71 }
72
73+// On Wasm, we reserve 4096 bytes for zero page, then 4096 bytes for wasm_exec.js
74+// to store command line args. Data sections starts from at least address 8192.
75+// Keep in sync with wasm_exec.js.
76+const wasmMinDataAddr = 4096 + 4096
77+
78 // address assigns virtual addresses to all segments and sections and
79 // returns all segments in file order.
80 func (ctxt *Link) address() []*sym.Segment {
81@@ -2339,10 +2344,14 @@ func (ctxt *Link) address() []*sym.Segment {
82 order = append(order, &Segtext)
83 Segtext.Rwx = 05
84 Segtext.Vaddr = va
85- for _, s := range Segtext.Sections {
86+ for i, s := range Segtext.Sections {
87 va = uint64(Rnd(int64(va), int64(s.Align)))
88 s.Vaddr = va
89 va += s.Length
90+
91+ if ctxt.Arch.Family == sys.Wasm && i == 0 && va < wasmMinDataAddr {
92+ va = wasmMinDataAddr
93+ }
94 }
95
96 Segtext.Length = va - uint64(*FlagTextAddr)
97 \ 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 @@
1From 6c480017ae600b2c90a264a922e041df04dfa785 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <roland@golang.org>
3Date: Wed, 18 Aug 2021 11:49:29 -0700
4Subject: [PATCH] [release-branch.go1.16] archive/zip: prevent preallocation
5 check from overflowing
6
7If the indicated directory size in the archive header is so large that
8subtracting it from the archive size overflows a uint64, the check that
9the indicated number of files in the archive can be effectively
10bypassed. Prevent this from happening by checking that the indicated
11directory size is less than the size of the archive.
12
13Thanks to the OSS-Fuzz project for discovering this issue and to
14Emmanuel Odeke for reporting it.
15
16Fixes #47985
17Updates #47801
18Fixes CVE-2021-39293
19
20Change-Id: Ifade26b98a40f3b37398ca86bd5252d12394dd24
21Reviewed-on: https://go-review.googlesource.com/c/go/+/343434
22Trust: Roland Shoemaker <roland@golang.org>
23Run-TryBot: Roland Shoemaker <roland@golang.org>
24TryBot-Result: Go Bot <gobot@golang.org>
25Reviewed-by: Russ Cox <rsc@golang.org>
26(cherry picked from commit bacbc33439b124ffd7392c91a5f5d96eca8c0c0b)
27Reviewed-on: https://go-review.googlesource.com/c/go/+/345409
28Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
29Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
30Trust: Cherry Mui <cherryyz@google.com>
31
32https://github.com/golang/go/commit/6c480017ae600b2c90a264a922e041df04dfa785
33CVE: CVE-2021-39293
34Upstream-Status: Backport
35Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
36---
37 src/archive/zip/reader.go | 2 +-
38 src/archive/zip/reader_test.go | 18 ++++++++++++++++++
39 2 files changed, 19 insertions(+), 1 deletion(-)
40
41diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go
42index ddef2b7b5a517..801d1313b6c32 100644
43--- a/src/archive/zip/reader.go
44+++ b/src/archive/zip/reader.go
45@@ -105,7 +105,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
46 // indicate it contains up to 1 << 128 - 1 files. Since each file has a
47 // header which will be _at least_ 30 bytes we can safely preallocate
48 // if (data size / 30) >= end.directoryRecords.
49- if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
50+ if end.directorySize < uint64(size) && (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
51 z.File = make([]*File, 0, end.directoryRecords)
52 }
53 z.Comment = end.comment
54diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go
55index 471be27bb1004..99f13345d8d06 100644
56--- a/src/archive/zip/reader_test.go
57+++ b/src/archive/zip/reader_test.go
58@@ -1225,3 +1225,21 @@ func TestCVE202133196(t *testing.T) {
59 t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
60 }
61 }
62+
63+func TestCVE202139293(t *testing.T) {
64+ // directory size is so large, that the check in Reader.init
65+ // overflows when subtracting from the archive size, causing
66+ // the pre-allocation check to be bypassed.
67+ data := []byte{
68+ 0x50, 0x4b, 0x06, 0x06, 0x05, 0x06, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
69+ 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
70+ 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
71+ 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
72+ 0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
73+ 0xff, 0x50, 0xfe, 0x00, 0xff, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xff,
74+ }
75+ _, err := NewReader(bytes.NewReader(data), int64(len(data)))
76+ if err != ErrFormat {
77+ t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
78+ }
79+}
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 @@
1From d19c5bdb24e093a2d5097b7623284eb02726cede Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <roland@golang.org>
3Date: Thu, 14 Oct 2021 13:02:01 -0700
4Subject: [PATCH] [release-branch.go1.16] debug/macho: fail on invalid dynamic
5 symbol table command
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10Fail out when loading a file that contains a dynamic symbol table
11command that indicates a larger number of symbols than exist in the
12loaded symbol table.
13
14Thanks to Burak Çarıkçı - Yunus Yıldırım (CT-Zer0 Crypttech) for
15reporting this issue.
16
17Updates #48990
18Fixes #48991
19Fixes CVE-2021-41771
20
21Change-Id: Ic3d6e6529241afcc959544b326b21b663262bad5
22Reviewed-on: https://go-review.googlesource.com/c/go/+/355990
23Reviewed-by: Julie Qiu <julie@golang.org>
24Reviewed-by: Katie Hockman <katie@golang.org>
25Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
26Run-TryBot: Roland Shoemaker <roland@golang.org>
27TryBot-Result: Go Bot <gobot@golang.org>
28Trust: Katie Hockman <katie@golang.org>
29(cherry picked from commit 61536ec03063b4951163bd09609c86d82631fa27)
30Reviewed-on: https://go-review.googlesource.com/c/go/+/359454
31Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
32
33https://github.com/golang/go/commit/d19c5bdb24e093a2d5097b7623284eb02726cede
34CVE: CVE-2021-41771
35Upstream-Status: Backport
36Signed-off-by: Chee Yang Lee <chee.yang.lee@intel.com>
37---
38 src/debug/macho/file.go | 9 +++++++++
39 src/debug/macho/file_test.go | 7 +++++++
40 .../testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64 | 1 +
41 3 files changed, 17 insertions(+)
42 create mode 100644 src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64
43
44diff --git a/src/debug/macho/file.go b/src/debug/macho/file.go
45index 085b0c8219bad..73cfce3c7606e 100644
46--- a/src/debug/macho/file.go
47+++ b/src/debug/macho/file.go
48@@ -345,6 +345,15 @@ func NewFile(r io.ReaderAt) (*File, error) {
49 if err := binary.Read(b, bo, &hdr); err != nil {
50 return nil, err
51 }
52+ if hdr.Iundefsym > uint32(len(f.Symtab.Syms)) {
53+ return nil, &FormatError{offset, fmt.Sprintf(
54+ "undefined symbols index in dynamic symbol table command is greater than symbol table length (%d > %d)",
55+ hdr.Iundefsym, len(f.Symtab.Syms)), nil}
56+ } else if hdr.Iundefsym+hdr.Nundefsym > uint32(len(f.Symtab.Syms)) {
57+ return nil, &FormatError{offset, fmt.Sprintf(
58+ "number of undefined symbols after index in dynamic symbol table command is greater than symbol table length (%d > %d)",
59+ hdr.Iundefsym+hdr.Nundefsym, len(f.Symtab.Syms)), nil}
60+ }
61 dat := make([]byte, hdr.Nindirectsyms*4)
62 if _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil {
63 return nil, err
64diff --git a/src/debug/macho/file_test.go b/src/debug/macho/file_test.go
65index 03915c86e23d9..9beeb80dd27c1 100644
66--- a/src/debug/macho/file_test.go
67+++ b/src/debug/macho/file_test.go
68@@ -416,3 +416,10 @@ func TestTypeString(t *testing.T) {
69 t.Errorf("got %v, want %v", TypeExec.GoString(), "macho.Exec")
70 }
71 }
72+
73+func TestOpenBadDysymCmd(t *testing.T) {
74+ _, err := openObscured("testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64")
75+ if err == nil {
76+ t.Fatal("openObscured did not fail when opening a file with an invalid dynamic symbol table command")
77+ }
78+}
79diff --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
80new file mode 100644
81index 0000000000000..8e0436639c109
82--- /dev/null
83+++ b/src/debug/macho/testdata/gcc-amd64-darwin-exec-with-bad-dysym.base64
84@@ -0,0 +1 @@
85+z/rt/gcAAAEDAACAAgAAAAsAAABoBQAAhQAAAAAAAAAZAAAASAAAAF9fUEFHRVpFUk8AAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZAAAA2AEAAF9fVEVYVAAAAAAAAAAAAAAAAAAAAQAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAcAAAAFAAAABQAAAAAAAABfX3RleHQAAAAAAAAAAAAAX19URVhUAAAAAAAAAAAAABQPAAABAAAAbQAAAAAAAAAUDwAAAgAAAAAAAAAAAAAAAAQAgAAAAAAAAAAAAAAAAF9fc3ltYm9sX3N0dWIxAABfX1RFWFQAAAAAAAAAAAAAgQ8AAAEAAAAMAAAAAAAAAIEPAAAAAAAAAAAAAAAAAAAIBACAAAAAAAYAAAAAAAAAX19zdHViX2hlbHBlcgAAAF9fVEVYVAAAAAAAAAAAAACQDwAAAQAAABgAAAAAAAAAkA8AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfX2NzdHJpbmcAAAAAAAAAX19URVhUAAAAAAAAAAAAAKgPAAABAAAADQAAAAAAAACoDwAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAF9fZWhfZnJhbWUAAAAAAABfX1RFWFQAAAAAAAAAAAAAuA8AAAEAAABIAAAAAAAAALgPAAADAAAAAAAAAAAAAAALAABgAAAAAAAAAAAAAAAAGQAAADgBAABfX0RBVEEAAAAAAAAAAAAAABAAAAEAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAHAAAAAwAAAAMAAAAAAAAAX19kYXRhAAAAAAAAAAAAAF9fREFUQQAAAAAAAAAAAAAAEAAAAQAAABwAAAAAAAAAABAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfX2R5bGQAAAAAAAAAAAAAX19EQVRBAAAAAAAAAAAAACAQAAABAAAAOAAAAAAAAAAgEAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF9fbGFfc3ltYm9sX3B0cgBfX0RBVEEAAAAAAAAAAAAAWBAAAAEAAAAQAAAAAAAAAFgQAAACAAAAAAAAAAAAAAAHAAAAAgAAAAAAAAAAAAAAGQAAAEgAAABfX0xJTktFRElUAAAAAAAAACAAAAEAAAAAEAAAAAAAAAAgAAAAAAAAQAEAAAAAAAAHAAAAAQAAAAAAAAAAAAAAAgAAABgAAAAAIAAACwAAAMAgAACAAAAACwAAAFAAAAAAAAAAAgAAAAIAAAAHAAAACQAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwIAAABAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAIAAAAAwAAAAvdXNyL2xpYi9keWxkAAAAAAAAABsAAAAYAAAAOyS4cg5FdtQoqu6JsMEhXQUAAAC4AAAABAAAACoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQPAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAOAAAABgAAAACAAAAAAABAAAAAQAvdXNyL2xpYi9saWJnY2Nfcy4xLmR5bGliAAAAAAAAAAwAAAA4AAAAGAAAAAIAAAAEAW8AAAABAC91c3IvbGliL2xpYlN5c3RlbS5CLmR5bGliAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqAEiJ5UiD5PBIi30ISI11EIn6g8IBweIDSAHySInR6wRIg8EISIM5AHX2SIPBCOgiAAAAicfoMgAAAPRBU0yNHafw//9BU/8lvwAAAA8fAP8lvgAAAFVIieVIjT0zAAAA6A0AAAC4AAAAAMnD/yXRAAAA/yXTAAAAAAAATI0dwQAAAOm0////TI0dvQAAAOmo////aGVsbG8sIHdvcmxkAAAAABQAAAAAAAAAAXpSAAF4EAEQDAcIkAEAACwAAAAcAAAAkv////////8XAAAAAAAAAAAEAQAAAA4QhgIEAwAAAA0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABDAX/9/AAAIEMBf/38AAAAAAAABAAAAGBAAAAEAAAAQEAAAAQAAAAgQAAABAAAAABAAAAEAAACQDwAAAQAAAJwPAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAHgEAAFAPAAABAAAAGwAAAB4BAABkDwAAAQAAAC4AAAAPBgAAGBAAAAEAAAA2AAAADwYAABAQAAABAAAAPgAAAA8GAAAAEAAAAQAAAEoAAAADABAAAAAAAAEAAABeAAAADwYAAAgQAAABAAAAZwAAAA8BAABqDwAAAQAAAG0AAAAPAQAAFA8AAAEAAABzAAAAAQABAgAAAAAAAAAAeQAAAAEAAQIAAAAAAAAAAAkAAAAKAAAACQAAAAoAAAAgAGR5bGRfc3R1Yl9iaW5kaW5nX2hlbHBlcgBfX2R5bGRfZnVuY19sb29rdXAAX05YQXJnYwBfTlhBcmd2AF9fX3Byb2duYW1lAF9fbWhfZXhlY3V0ZV9oZWFkZXIAX2Vudmlyb24AX21haW4Ac3RhcnQAX2V4aXQAX3B1dHMAAA==
86\ 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 @@
1From 9f1860075990e7bf908ca7cc329d1d3ef91741c8 Mon Sep 17 00:00:00 2001
2From: Filippo Valsorda <filippo@golang.org>
3Date: Thu, 9 Dec 2021 06:13:31 -0500
4Subject: [PATCH] net/http: update bundled golang.org/x/net/http2
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/d0aebe3e74fe14799f97ddd3f01129697c6a290a]
7CVE: CVE-2021-44716
8Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
9
10
11Pull in security fix
12
13 a5309b3 http2: cap the size of the server's canonical header cache
14
15Updates #50058
16Fixes CVE-2021-44716
17
18Change-Id: Ifdd13f97fce168de5fb4b2e74ef2060d059800b9
19Reviewed-on: https://go-review.googlesource.com/c/go/+/370575
20Trust: Filippo Valsorda <filippo@golang.org>
21Run-TryBot: Filippo Valsorda <filippo@golang.org>
22Reviewed-by: Alex Rakoczy <alex@golang.org>
23TryBot-Result: Gopher Robot <gobot@golang.org>
24(cherry picked from commit d0aebe3e74fe14799f97ddd3f01129697c6a290a)
25---
26 src/go.mod | 2 +-
27 src/go.sum | 4 ++--
28 src/net/http/h2_bundle.go | 10 +++++++++-
29 src/vendor/modules.txt | 2 +-
30 4 files changed, 13 insertions(+), 5 deletions(-)
31
32diff --git a/src/go.mod b/src/go.mod
33index ec6bd98..56f2fbb 100644
34--- a/src/go.mod
35+++ b/src/go.mod
36@@ -4,7 +4,7 @@ go 1.14
37
38 require (
39 golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d
40- golang.org/x/net v0.0.0-20210129194117-4acb7895a057
41+ golang.org/x/net v0.0.0-20211209100217-a5309b321dca
42 golang.org/x/sys v0.0.0-20200201011859-915c9c3d4ccf // indirect
43 golang.org/x/text v0.3.3-0.20191031172631-4b67af870c6f // indirect
44 )
45diff --git a/src/go.sum b/src/go.sum
46index 171e083..1ceba05 100644
47--- a/src/go.sum
48+++ b/src/go.sum
49@@ -2,8 +2,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
50 golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U=
51 golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
52 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
53-golang.org/x/net v0.0.0-20210129194117-4acb7895a057 h1:HThQeV5c0Ab/Puir+q6mC97b7+3dfZdsLWMLoBrzo68=
54-golang.org/x/net v0.0.0-20210129194117-4acb7895a057/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
55+golang.org/x/net v0.0.0-20211209100217-a5309b321dca h1:UmeWAm8AwB6NA/e4FSaGlK1EKTLXKX3utx4Si+6kfPg=
56+golang.org/x/net v0.0.0-20211209100217-a5309b321dca/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
57 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
58 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
59 golang.org/x/sys v0.0.0-20200201011859-915c9c3d4ccf h1:+4j7oujXP478CVb/AFvHJmVX5+Pczx2NGts5yirA0oY=
60diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
61index 702fd5a..83f2a72 100644
62--- a/src/net/http/h2_bundle.go
63+++ b/src/net/http/h2_bundle.go
64@@ -4293,7 +4293,15 @@ func (sc *http2serverConn) canonicalHeader(v string) string {
65 sc.canonHeader = make(map[string]string)
66 }
67 cv = CanonicalHeaderKey(v)
68- sc.canonHeader[v] = cv
69+ // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
70+ // entries in the canonHeader cache. This should be larger than the number
71+ // of unique, uncommon header keys likely to be sent by the peer, while not
72+ // so high as to permit unreaasonable memory usage if the peer sends an unbounded
73+ // number of unique header keys.
74+ const maxCachedCanonicalHeaders = 32
75+ if len(sc.canonHeader) < maxCachedCanonicalHeaders {
76+ sc.canonHeader[v] = cv
77+ }
78 return cv
79 }
80
81diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt
82index 669bd9b..1d67183 100644
83--- a/src/vendor/modules.txt
84+++ b/src/vendor/modules.txt
85@@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519
86 golang.org/x/crypto/hkdf
87 golang.org/x/crypto/internal/subtle
88 golang.org/x/crypto/poly1305
89-# golang.org/x/net v0.0.0-20210129194117-4acb7895a057
90+# golang.org/x/net v0.0.0-20211209100217-a5309b321dca
91 ## explicit
92 golang.org/x/net/dns/dnsmessage
93 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 @@
1From 9171c664e7af479aa26bc72f2e7cf4e69d8e0a6f Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Fri, 17 Jun 2022 10:22:47 +0530
4Subject: [PATCH] CVE-2021-44717
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/44a3fb49]
7CVE: CVE-2021-44717
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9
10syscall: fix ForkLock spurious close(0) on pipe failure
11Pipe (and therefore forkLockPipe) does not make any guarantees
12about the state of p after a failed Pipe(p). Avoid that assumption
13and the too-clever goto, so that we don't accidentally Close a real fd
14if the failed pipe leaves p[0] or p[1] set >= 0.
15
16Updates #50057
17Fixes CVE-2021-44717
18
19Change-Id: Iff8e19a6efbba0c73cc8b13ecfae381c87600bb4
20Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1291270
21Reviewed-by: Ian Lance Taylor <iant@google.com>
22Reviewed-on: https://go-review.googlesource.com/c/go/+/370514
23Trust: Filippo Valsorda <filippo@golang.org>
24Run-TryBot: Filippo Valsorda <filippo@golang.org>
25TryBot-Result: Gopher Robot <gobot@golang.org>
26Reviewed-by: Alex Rakoczy <alex@golang.org>
27---
28 src/syscall/exec_unix.go | 20 ++++++--------------
29 1 file changed, 6 insertions(+), 14 deletions(-)
30
31diff --git a/src/syscall/exec_unix.go b/src/syscall/exec_unix.go
32index b3798b6..b73782c 100644
33--- a/src/syscall/exec_unix.go
34+++ b/src/syscall/exec_unix.go
35@@ -151,9 +151,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
36 sys = &zeroSysProcAttr
37 }
38
39- p[0] = -1
40- p[1] = -1
41-
42 // Convert args to C form.
43 argv0p, err := BytePtrFromString(argv0)
44 if err != nil {
45@@ -194,14 +191,17 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
46
47 // Allocate child status pipe close on exec.
48 if err = forkExecPipe(p[:]); err != nil {
49- goto error
50+ ForkLock.Unlock()
51+ return 0, err
52 }
53
54 // Kick off child.
55 pid, err1 = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
56 if err1 != 0 {
57- err = Errno(err1)
58- goto error
59+ Close(p[0])
60+ Close(p[1])
61+ ForkLock.Unlock()
62+ return 0, Errno(err1)
63 }
64 ForkLock.Unlock()
65
66@@ -228,14 +228,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
67
68 // Read got EOF, so pipe closed on exec, so exec succeeded.
69 return pid, nil
70-
71-error:
72- if p[0] >= 0 {
73- Close(p[0])
74- Close(p[1])
75- }
76- ForkLock.Unlock()
77- return 0, err
78 }
79
80 // Combination of fork and exec, careful to be thread safe.
81--
822.25.1
83
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 @@
1From ba8788ebcead55e99e631c6a1157ad7b35535d11 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Wed, 15 Jun 2022 10:43:05 -0700
4Subject: [PATCH] [release-branch.go1.17] go/parser: limit recursion depth
5
6Limit nested parsing to 100,000, which prevents stack exhaustion when
7parsing deeply nested statements, types, and expressions. Also limit
8the scope depth to 1,000 during object resolution.
9
10Thanks to Juho Nurminen of Mattermost for reporting this issue.
11
12Fixes #53707
13Updates #53616
14Fixes CVE-2022-1962
15
16Change-Id: I4d7b86c1d75d0bf3c7af1fdea91582aa74272c64
17Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1491025
18Reviewed-by: Russ Cox <rsc@google.com>
19Reviewed-by: Damien Neil <dneil@google.com>
20(cherry picked from commit 6a856f08d58e4b6705c0c337d461c540c1235c83)
21Reviewed-on: https://go-review.googlesource.com/c/go/+/417070
22Reviewed-by: Heschi Kreinick <heschi@google.com>
23TryBot-Result: Gopher Robot <gobot@golang.org>
24Run-TryBot: Michael Knyszek <mknyszek@google.com>
25
26Upstream-Status: Backport [https://github.com/golang/go/commit/ba8788ebcead55e99e631c6a1157ad7b35535d11]
27CVE: CVE-2022-1962
28Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
29---
30 src/go/parser/interface.go | 10 ++-
31 src/go/parser/parser.go | 48 ++++++++--
32 src/go/parser/parser_test.go | 169 +++++++++++++++++++++++++++++++++++
33 3 files changed, 220 insertions(+), 7 deletions(-)
34
35diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go
36index 54f9d7b..537b327 100644
37--- a/src/go/parser/interface.go
38+++ b/src/go/parser/interface.go
39@@ -92,8 +92,11 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode)
40 defer func() {
41 if e := recover(); e != nil {
42 // resume same panic if it's not a bailout
43- if _, ok := e.(bailout); !ok {
44+ bail, ok := e.(bailout)
45+ if !ok {
46 panic(e)
47+ } else if bail.msg != "" {
48+ p.errors.Add(p.file.Position(bail.pos), bail.msg)
49 }
50 }
51
52@@ -188,8 +191,11 @@ func ParseExprFrom(fset *token.FileSet, filename string, src interface{}, mode M
53 defer func() {
54 if e := recover(); e != nil {
55 // resume same panic if it's not a bailout
56- if _, ok := e.(bailout); !ok {
57+ bail, ok := e.(bailout)
58+ if !ok {
59 panic(e)
60+ } else if bail.msg != "" {
61+ p.errors.Add(p.file.Position(bail.pos), bail.msg)
62 }
63 }
64 p.errors.Sort()
65diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go
66index 31a7398..586fe90 100644
67--- a/src/go/parser/parser.go
68+++ b/src/go/parser/parser.go
69@@ -64,6 +64,10 @@ type parser struct {
70 unresolved []*ast.Ident // unresolved identifiers
71 imports []*ast.ImportSpec // list of imports
72
73+ // nestLev is used to track and limit the recursion depth
74+ // during parsing.
75+ nestLev int
76+
77 // Label scopes
78 // (maintained by open/close LabelScope)
79 labelScope *ast.Scope // label scope for current function
80@@ -236,6 +240,24 @@ func un(p *parser) {
81 p.printTrace(")")
82 }
83
84+// maxNestLev is the deepest we're willing to recurse during parsing
85+const maxNestLev int = 1e5
86+
87+func incNestLev(p *parser) *parser {
88+ p.nestLev++
89+ if p.nestLev > maxNestLev {
90+ p.error(p.pos, "exceeded max nesting depth")
91+ panic(bailout{})
92+ }
93+ return p
94+}
95+
96+// decNestLev is used to track nesting depth during parsing to prevent stack exhaustion.
97+// It is used along with incNestLev in a similar fashion to how un and trace are used.
98+func decNestLev(p *parser) {
99+ p.nestLev--
100+}
101+
102 // Advance to the next token.
103 func (p *parser) next0() {
104 // Because of one-token look-ahead, print the previous token
105@@ -348,8 +370,12 @@ func (p *parser) next() {
106 }
107 }
108
109-// A bailout panic is raised to indicate early termination.
110-type bailout struct{}
111+// A bailout panic is raised to indicate early termination. pos and msg are
112+// only populated when bailing out of object resolution.
113+type bailout struct {
114+ pos token.Pos
115+ msg string
116+}
117
118 func (p *parser) error(pos token.Pos, msg string) {
119 epos := p.file.Position(pos)
120@@ -1030,6 +1056,8 @@ func (p *parser) parseChanType() *ast.ChanType {
121
122 // If the result is an identifier, it is not resolved.
123 func (p *parser) tryIdentOrType() ast.Expr {
124+ defer decNestLev(incNestLev(p))
125+
126 switch p.tok {
127 case token.IDENT:
128 return p.parseTypeName()
129@@ -1609,7 +1637,13 @@ func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
130 }
131
132 x := p.parseUnaryExpr(lhs)
133- for {
134+ // We track the nesting here rather than at the entry for the function,
135+ // since it can iteratively produce a nested output, and we want to
136+ // limit how deep a structure we generate.
137+ var n int
138+ defer func() { p.nestLev -= n }()
139+ for n = 1; ; n++ {
140+ incNestLev(p)
141 op, oprec := p.tokPrec()
142 if oprec < prec1 {
143 return x
144@@ -1628,7 +1662,7 @@ func (p *parser) parseBinaryExpr(lhs bool, prec1 int) ast.Expr {
145 // The result may be a type or even a raw type ([...]int). Callers must
146 // check the result (using checkExpr or checkExprOrType), depending on
147 // context.
148-func (p *parser) parseExpr(lhs bool) ast.Expr {
149+func (p *parser) parseExpr(lhs bool) ast.Expr {
150 if p.trace {
151 defer un(trace(p, "Expression"))
152 }
153@@ -1899,6 +1933,8 @@ func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) {
154 }
155
156 func (p *parser) parseIfStmt() *ast.IfStmt {
157+ defer decNestLev(incNestLev(p))
158+
159 if p.trace {
160 defer un(trace(p, "IfStmt"))
161 }
162@@ -2214,6 +2250,8 @@ func (p *parser) parseForStmt() ast.Stmt {
163 }
164
165 func (p *parser) parseStmt() (s ast.Stmt) {
166+ defer decNestLev(incNestLev(p))
167+
168 if p.trace {
169 defer un(trace(p, "Statement"))
170 }
171diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go
172index 25a374e..37a6a2b 100644
173--- a/src/go/parser/parser_test.go
174+++ b/src/go/parser/parser_test.go
175@@ -10,6 +10,7 @@ import (
176 "go/ast"
177 "go/token"
178 "os"
179+ "runtime"
180 "strings"
181 "testing"
182 )
183@@ -569,3 +570,171 @@ type x int // comment
184 t.Errorf("got %q, want %q", comment, "// comment")
185 }
186 }
187+
188+var parseDepthTests = []struct {
189+ name string
190+ format string
191+ // multipler is used when a single statement may result in more than one
192+ // change in the depth level, for instance "1+(..." produces a BinaryExpr
193+ // followed by a UnaryExpr, which increments the depth twice. The test
194+ // case comment explains which nodes are triggering the multiple depth
195+ // changes.
196+ parseMultiplier int
197+ // scope is true if we should also test the statement for the resolver scope
198+ // depth limit.
199+ scope bool
200+ // scopeMultiplier does the same as parseMultiplier, but for the scope
201+ // depths.
202+ scopeMultiplier int
203+}{
204+ // The format expands the part inside « » many times.
205+ // A second set of brackets nested inside the first stops the repetition,
206+ // so that for example «(«1»)» expands to (((...((((1))))...))).
207+ {name: "array", format: "package main; var x «[1]»int"},
208+ {name: "slice", format: "package main; var x «[]»int"},
209+ {name: "struct", format: "package main; var x «struct { X «int» }»", scope: true},
210+ {name: "pointer", format: "package main; var x «*»int"},
211+ {name: "func", format: "package main; var x «func()»int", scope: true},
212+ {name: "chan", format: "package main; var x «chan »int"},
213+ {name: "chan2", format: "package main; var x «<-chan »int"},
214+ {name: "interface", format: "package main; var x «interface { M() «int» }»", scope: true, scopeMultiplier: 2}, // Scopes: InterfaceType, FuncType
215+ {name: "map", format: "package main; var x «map[int]»int"},
216+ {name: "slicelit", format: "package main; var x = «[]any{«»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
217+ {name: "arraylit", format: "package main; var x = «[1]any{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
218+ {name: "structlit", format: "package main; var x = «struct{x any}{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
219+ {name: "maplit", format: "package main; var x = «map[int]any{1:«nil»}»", parseMultiplier: 2}, // Parser nodes: CompositeLit, KeyValueExpr
220+ {name: "dot", format: "package main; var x = «x.»x"},
221+ {name: "index", format: "package main; var x = x«[1]»"},
222+ {name: "slice", format: "package main; var x = x«[1:2]»"},
223+ {name: "slice3", format: "package main; var x = x«[1:2:3]»"},
224+ {name: "dottype", format: "package main; var x = x«.(any)»"},
225+ {name: "callseq", format: "package main; var x = x«()»"},
226+ {name: "methseq", format: "package main; var x = x«.m()»", parseMultiplier: 2}, // Parser nodes: SelectorExpr, CallExpr
227+ {name: "binary", format: "package main; var x = «1+»1"},
228+ {name: "binaryparen", format: "package main; var x = «1+(«1»)»", parseMultiplier: 2}, // Parser nodes: BinaryExpr, ParenExpr
229+ {name: "unary", format: "package main; var x = «^»1"},
230+ {name: "addr", format: "package main; var x = «& »x"},
231+ {name: "star", format: "package main; var x = «*»x"},
232+ {name: "recv", format: "package main; var x = «<-»x"},
233+ {name: "call", format: "package main; var x = «f(«1»)»", parseMultiplier: 2}, // Parser nodes: Ident, CallExpr
234+ {name: "conv", format: "package main; var x = «(*T)(«1»)»", parseMultiplier: 2}, // Parser nodes: ParenExpr, CallExpr
235+ {name: "label", format: "package main; func main() { «Label:» }"},
236+ {name: "if", format: "package main; func main() { «if true { «» }»}", parseMultiplier: 2, scope: true, scopeMultiplier: 2}, // Parser nodes: IfStmt, BlockStmt. Scopes: IfStmt, BlockStmt
237+ {name: "ifelse", format: "package main; func main() { «if true {} else » {} }", scope: true},
238+ {name: "switch", format: "package main; func main() { «switch { default: «» }»}", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause
239+ {name: "typeswitch", format: "package main; func main() { «switch x.(type) { default: «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: TypeSwitchStmt, CaseClause
240+ {name: "for0", format: "package main; func main() { «for { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt
241+ {name: "for1", format: "package main; func main() { «for x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt
242+ {name: "for3", format: "package main; func main() { «for f(); g(); h() { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: ForStmt, BlockStmt
243+ {name: "forrange0", format: "package main; func main() { «for range x { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt
244+ {name: "forrange1", format: "package main; func main() { «for x = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt
245+ {name: "forrange2", format: "package main; func main() { «for x, y = range z { «» }» }", scope: true, scopeMultiplier: 2}, // Scopes: RangeStmt, BlockStmt
246+ {name: "go", format: "package main; func main() { «go func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: GoStmt, FuncLit
247+ {name: "defer", format: "package main; func main() { «defer func() { «» }()» }", parseMultiplier: 2, scope: true}, // Parser nodes: DeferStmt, FuncLit
248+ {name: "select", format: "package main; func main() { «select { default: «» }» }", scope: true},
249+}
250+
251+// split splits pre«mid»post into pre, mid, post.
252+// If the string does not have that form, split returns x, "", "".
253+func split(x string) (pre, mid, post string) {
254+ start, end := strings.Index(x, "«"), strings.LastIndex(x, "»")
255+ if start < 0 || end < 0 {
256+ return x, "", ""
257+ }
258+ return x[:start], x[start+len("«") : end], x[end+len("»"):]
259+}
260+
261+func TestParseDepthLimit(t *testing.T) {
262+ if runtime.GOARCH == "wasm" {
263+ t.Skip("causes call stack exhaustion on js/wasm")
264+ }
265+ for _, tt := range parseDepthTests {
266+ for _, size := range []string{"small", "big"} {
267+ t.Run(tt.name+"/"+size, func(t *testing.T) {
268+ n := maxNestLev + 1
269+ if tt.parseMultiplier > 0 {
270+ n /= tt.parseMultiplier
271+ }
272+ if size == "small" {
273+ // Decrease the number of statements by 10, in order to check
274+ // that we do not fail when under the limit. 10 is used to
275+ // provide some wiggle room for cases where the surrounding
276+ // scaffolding syntax adds some noise to the depth that changes
277+ // on a per testcase basis.
278+ n -= 10
279+ }
280+
281+ pre, mid, post := split(tt.format)
282+ if strings.Contains(mid, "«") {
283+ left, base, right := split(mid)
284+ mid = strings.Repeat(left, n) + base + strings.Repeat(right, n)
285+ } else {
286+ mid = strings.Repeat(mid, n)
287+ }
288+ input := pre + mid + post
289+
290+ fset := token.NewFileSet()
291+ _, err := ParseFile(fset, "", input, ParseComments|SkipObjectResolution)
292+ if size == "small" {
293+ if err != nil {
294+ t.Errorf("ParseFile(...): %v (want success)", err)
295+ }
296+ } else {
297+ expected := "exceeded max nesting depth"
298+ if err == nil || !strings.HasSuffix(err.Error(), expected) {
299+ t.Errorf("ParseFile(...) = _, %v, want %q", err, expected)
300+ }
301+ }
302+ })
303+ }
304+ }
305+}
306+
307+func TestScopeDepthLimit(t *testing.T) {
308+ if runtime.GOARCH == "wasm" {
309+ t.Skip("causes call stack exhaustion on js/wasm")
310+ }
311+ for _, tt := range parseDepthTests {
312+ if !tt.scope {
313+ continue
314+ }
315+ for _, size := range []string{"small", "big"} {
316+ t.Run(tt.name+"/"+size, func(t *testing.T) {
317+ n := maxScopeDepth + 1
318+ if tt.scopeMultiplier > 0 {
319+ n /= tt.scopeMultiplier
320+ }
321+ if size == "small" {
322+ // Decrease the number of statements by 10, in order to check
323+ // that we do not fail when under the limit. 10 is used to
324+ // provide some wiggle room for cases where the surrounding
325+ // scaffolding syntax adds some noise to the depth that changes
326+ // on a per testcase basis.
327+ n -= 10
328+ }
329+
330+ pre, mid, post := split(tt.format)
331+ if strings.Contains(mid, "«") {
332+ left, base, right := split(mid)
333+ mid = strings.Repeat(left, n) + base + strings.Repeat(right, n)
334+ } else {
335+ mid = strings.Repeat(mid, n)
336+ }
337+ input := pre + mid + post
338+
339+ fset := token.NewFileSet()
340+ _, err := ParseFile(fset, "", input, DeclarationErrors)
341+ if size == "small" {
342+ if err != nil {
343+ t.Errorf("ParseFile(...): %v (want success)", err)
344+ }
345+ } else {
346+ expected := "exceeded max scope depth during object resolution"
347+ if err == nil || !strings.HasSuffix(err.Error(), expected) {
348+ t.Errorf("ParseFile(...) = _, %v, want %q", err, expected)
349+ }
350+ }
351+ })
352+ }
353+ }
354+}
355--
3562.30.2
357
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 @@
1From 70882eedccac803ddcf1c3215e0ae8fd59847e39 Mon Sep 17 00:00:00 2001
2From: Katie Hockman <katie@golang.org>
3Date: Sat, 26 Feb 2022 20:03:38 +0000
4Subject: [PATCH] [release-branch.go1.16] math/big: prevent overflow in
5 (*Rat).SetString
6
7Credit to rsc@ for the original patch.
8
9Thanks to the OSS-Fuzz project for discovering this
10issue and to Emmanuel Odeke (@odeke_et) for reporting it.
11
12Updates #50699
13Fixes #50700
14Fixes CVE-2022-23772
15---
16 src/math/big/ratconv.go | 5 +++++
17 src/math/big/ratconv_test.go | 1 +
18 2 files changed, 6 insertions(+)
19
20diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go
21index 941139e..e8cbdbe 100644
22--- a/src/math/big/ratconv.go
23+++ b/src/math/big/ratconv.go
24@@ -168,6 +168,11 @@ func (z *Rat) SetString(s string) (*Rat, bool) {
25 n := exp5
26 if n < 0 {
27 n = -n
28+ if n < 0 {
29+ // This can occur if -n overflows. -(-1 << 63) would become
30+ // -1 << 63, which is still negative.
31+ return nil, false
32+ }
33 }
34 pow5 := z.b.abs.expNN(natFive, nat(nil).setWord(Word(n)), nil) // use underlying array of z.b.abs
35 if exp5 > 0 {
36diff --git a/src/math/big/ratconv_test.go b/src/math/big/ratconv_test.go
37index ba0d1ba..b820df4 100644
38--- a/src/math/big/ratconv_test.go
39+++ b/src/math/big/ratconv_test.go
40@@ -104,6 +104,7 @@ var setStringTests = []StringTest{
41 {in: "4/3/"},
42 {in: "4/3."},
43 {in: "4/"},
44+ {in: "13e-9223372036854775808"}, // CVE-2022-23772
45
46 // valid
47 {"0", "0", true},
48--
492.17.1
50
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 @@
1From 5b376a209d1c61e10847e062d78c4b1aa90dff0c Mon Sep 17 00:00:00 2001
2From: Filippo Valsorda <filippo@golang.org>
3Date: Sat, 26 Feb 2022 10:40:57 +0000
4Subject: [PATCH] crypto/elliptic: make IsOnCurve return false for invalid
5
6 field elements
7
8Updates #50974
9Fixes #50977
10Fixes CVE-2022-23806
11
12Signed-off-by: Minjae Kim <flowergom@gmail.com>
13
14---
15 src/crypto/elliptic/elliptic.go | 6 +++
16 src/crypto/elliptic/elliptic_test.go | 81 ++++++++++++++++++++++++++++
17 src/crypto/elliptic/p224.go | 6 +++
18 3 files changed, 93 insertions(+)
19
20diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go
21index e2f71cd..bd574a4 100644
22--- a/src/crypto/elliptic/elliptic.go
23+++ b/src/crypto/elliptic/elliptic.go
24@@ -53,6 +53,12 @@ func (curve *CurveParams) Params() *CurveParams {
25 }
26
27 func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
28+
29+ if x.Sign() < 0 || x.Cmp(curve.P) >= 0 ||
30+ y.Sign() < 0 || y.Cmp(curve.P) >= 0 {
31+ return false
32+ }
33+
34 // y² = x³ - 3x + b
35 y2 := new(big.Int).Mul(y, y)
36 y2.Mod(y2, curve.P)
37diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go
38index 09c5483..b13a620 100644
39--- a/src/crypto/elliptic/elliptic_test.go
40+++ b/src/crypto/elliptic/elliptic_test.go
41@@ -628,3 +628,84 @@ func TestUnmarshalToLargeCoordinates(t *testing.T) {
42 t.Errorf("Unmarshal accepts invalid Y coordinate")
43 }
44 }
45+
46+func testAllCurves(t *testing.T, f func(*testing.T, Curve)) {
47+ tests := []struct {
48+ name string
49+ curve Curve
50+ }{
51+ {"P256", P256()},
52+ {"P256/Params", P256().Params()},
53+ {"P224", P224()},
54+ {"P224/Params", P224().Params()},
55+ {"P384", P384()},
56+ {"P384/Params", P384().Params()},
57+ {"P521", P521()},
58+ {"P521/Params", P521().Params()},
59+ }
60+ if testing.Short() {
61+ tests = tests[:1]
62+ }
63+ for _, test := range tests {
64+ curve := test.curve
65+ t.Run(test.name, func(t *testing.T) {
66+ t.Parallel()
67+ f(t, curve)
68+ })
69+ }
70+}
71+
72+// TestInvalidCoordinates tests big.Int values that are not valid field elements
73+// (negative or bigger than P). They are expected to return false from
74+// IsOnCurve, all other behavior is undefined.
75+func TestInvalidCoordinates(t *testing.T) {
76+ testAllCurves(t, testInvalidCoordinates)
77+}
78+
79+func testInvalidCoordinates(t *testing.T, curve Curve) {
80+ checkIsOnCurveFalse := func(name string, x, y *big.Int) {
81+ if curve.IsOnCurve(x, y) {
82+ t.Errorf("IsOnCurve(%s) unexpectedly returned true", name)
83+ }
84+ }
85+
86+ p := curve.Params().P
87+ _, x, y, _ := GenerateKey(curve, rand.Reader)
88+ xx, yy := new(big.Int), new(big.Int)
89+
90+ // Check if the sign is getting dropped.
91+ xx.Neg(x)
92+ checkIsOnCurveFalse("-x, y", xx, y)
93+ yy.Neg(y)
94+ checkIsOnCurveFalse("x, -y", x, yy)
95+
96+ // Check if negative values are reduced modulo P.
97+ xx.Sub(x, p)
98+ checkIsOnCurveFalse("x-P, y", xx, y)
99+ yy.Sub(y, p)
100+ checkIsOnCurveFalse("x, y-P", x, yy)
101+
102+ // Check if positive values are reduced modulo P.
103+ xx.Add(x, p)
104+ checkIsOnCurveFalse("x+P, y", xx, y)
105+ yy.Add(y, p)
106+ checkIsOnCurveFalse("x, y+P", x, yy)
107+
108+ // Check if the overflow is dropped.
109+ xx.Add(x, new(big.Int).Lsh(big.NewInt(1), 535))
110+ checkIsOnCurveFalse("x+2⁵³⁵, y", xx, y)
111+ yy.Add(y, new(big.Int).Lsh(big.NewInt(1), 535))
112+ checkIsOnCurveFalse("x, y+2⁵³⁵", x, yy)
113+
114+ // Check if P is treated like zero (if possible).
115+ // y^2 = x^3 - 3x + B
116+ // y = mod_sqrt(x^3 - 3x + B)
117+ // y = mod_sqrt(B) if x = 0
118+ // If there is no modsqrt, there is no point with x = 0, can't test x = P.
119+ if yy := new(big.Int).ModSqrt(curve.Params().B, p); yy != nil {
120+ if !curve.IsOnCurve(big.NewInt(0), yy) {
121+ t.Fatal("(0, mod_sqrt(B)) is not on the curve?")
122+ }
123+ checkIsOnCurveFalse("P, y", p, yy)
124+ }
125+}
126diff --git a/src/crypto/elliptic/p224.go b/src/crypto/elliptic/p224.go
127index 8c76021..f1bfd7e 100644
128--- a/src/crypto/elliptic/p224.go
129+++ b/src/crypto/elliptic/p224.go
130@@ -48,6 +48,12 @@ func (curve p224Curve) Params() *CurveParams {
131 }
132
133 func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool {
134+
135+ if bigX.Sign() < 0 || bigX.Cmp(curve.P) >= 0 ||
136+ bigY.Sign() < 0 || bigY.Cmp(curve.P) >= 0 {
137+ return false
138+ }
139+
140 var x, y p224FieldElement
141 p224FromBig(&x, bigX)
142 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 @@
1From 1eb931d60a24501a9668e5cb4647593e19115507 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Fri, 17 Jun 2022 12:22:53 +0530
4Subject: [PATCH] CVE-2022-24675
5
6Upstream-Status: Backport [https://go-review.googlesource.com/c/go/+/399816/]
7CVE: CVE-2022-24675
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/encoding/pem/pem.go | 174 +++++++++++++++--------------------
11 src/encoding/pem/pem_test.go | 28 +++++-
12 2 files changed, 101 insertions(+), 101 deletions(-)
13
14diff --git a/src/encoding/pem/pem.go b/src/encoding/pem/pem.go
15index a7272da..1bee1c1 100644
16--- a/src/encoding/pem/pem.go
17+++ b/src/encoding/pem/pem.go
18@@ -87,123 +87,97 @@ func Decode(data []byte) (p *Block, rest []byte) {
19 // pemStart begins with a newline. However, at the very beginning of
20 // the byte array, we'll accept the start string without it.
21 rest = data
22- if bytes.HasPrefix(data, pemStart[1:]) {
23- rest = rest[len(pemStart)-1 : len(data)]
24- } else if i := bytes.Index(data, pemStart); i >= 0 {
25- rest = rest[i+len(pemStart) : len(data)]
26- } else {
27- return nil, data
28- }
29-
30- typeLine, rest := getLine(rest)
31- if !bytes.HasSuffix(typeLine, pemEndOfLine) {
32- return decodeError(data, rest)
33- }
34- typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)]
35-
36- p = &Block{
37- Headers: make(map[string]string),
38- Type: string(typeLine),
39- }
40-
41 for {
42- // This loop terminates because getLine's second result is
43- // always smaller than its argument.
44- if len(rest) == 0 {
45+ if bytes.HasPrefix(rest, pemStart[1:]) {
46+ rest = rest[len(pemStart)-1:]
47+ } else if i := bytes.Index(rest, pemStart); i >= 0 {
48+ rest = rest[i+len(pemStart) : len(rest)]
49+ } else {
50 return nil, data
51 }
52- line, next := getLine(rest)
53
54- i := bytes.IndexByte(line, ':')
55- if i == -1 {
56- break
57+ var typeLine []byte
58+ typeLine, rest = getLine(rest)
59+ if !bytes.HasSuffix(typeLine, pemEndOfLine) {
60+ continue
61 }
62+ typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)]
63
64- // TODO(agl): need to cope with values that spread across lines.
65- key, val := line[:i], line[i+1:]
66- key = bytes.TrimSpace(key)
67- val = bytes.TrimSpace(val)
68- p.Headers[string(key)] = string(val)
69- rest = next
70- }
71+ p = &Block{
72+ Headers: make(map[string]string),
73+ Type: string(typeLine),
74+ }
75
76- var endIndex, endTrailerIndex int
77+ for {
78+ // This loop terminates because getLine's second result is
79+ // always smaller than its argument.
80+ if len(rest) == 0 {
81+ return nil, data
82+ }
83+ line, next := getLine(rest)
84
85- // If there were no headers, the END line might occur
86- // immediately, without a leading newline.
87- if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) {
88- endIndex = 0
89- endTrailerIndex = len(pemEnd) - 1
90- } else {
91- endIndex = bytes.Index(rest, pemEnd)
92- endTrailerIndex = endIndex + len(pemEnd)
93- }
94+ i := bytes.IndexByte(line, ':')
95+ if i == -1 {
96+ break
97+ }
98
99- if endIndex < 0 {
100- return decodeError(data, rest)
101- }
102+ // TODO(agl): need to cope with values that spread across lines.
103+ key, val := line[:i], line[i+1:]
104+ key = bytes.TrimSpace(key)
105+ val = bytes.TrimSpace(val)
106+ p.Headers[string(key)] = string(val)
107+ rest = next
108+ }
109
110- // After the "-----" of the ending line, there should be the same type
111- // and then a final five dashes.
112- endTrailer := rest[endTrailerIndex:]
113- endTrailerLen := len(typeLine) + len(pemEndOfLine)
114- if len(endTrailer) < endTrailerLen {
115- return decodeError(data, rest)
116- }
117+ var endIndex, endTrailerIndex int
118
119- restOfEndLine := endTrailer[endTrailerLen:]
120- endTrailer = endTrailer[:endTrailerLen]
121- if !bytes.HasPrefix(endTrailer, typeLine) ||
122- !bytes.HasSuffix(endTrailer, pemEndOfLine) {
123- return decodeError(data, rest)
124- }
125+ // If there were no headers, the END line might occur
126+ // immediately, without a leading newline.
127+ if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) {
128+ endIndex = 0
129+ endTrailerIndex = len(pemEnd) - 1
130+ } else {
131+ endIndex = bytes.Index(rest, pemEnd)
132+ endTrailerIndex = endIndex + len(pemEnd)
133+ }
134
135- // The line must end with only whitespace.
136- if s, _ := getLine(restOfEndLine); len(s) != 0 {
137- return decodeError(data, rest)
138- }
139+ if endIndex < 0 {
140+ continue
141+ }
142
143- base64Data := removeSpacesAndTabs(rest[:endIndex])
144- p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
145- n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
146- if err != nil {
147- return decodeError(data, rest)
148- }
149- p.Bytes = p.Bytes[:n]
150+ // After the "-----" of the ending line, there should be the same type
151+ // and then a final five dashes.
152+ endTrailer := rest[endTrailerIndex:]
153+ endTrailerLen := len(typeLine) + len(pemEndOfLine)
154+ if len(endTrailer) < endTrailerLen {
155+ continue
156+ }
157+
158+ restOfEndLine := endTrailer[endTrailerLen:]
159+ endTrailer = endTrailer[:endTrailerLen]
160+ if !bytes.HasPrefix(endTrailer, typeLine) ||
161+ !bytes.HasSuffix(endTrailer, pemEndOfLine) {
162+ continue
163+ }
164
165- // the -1 is because we might have only matched pemEnd without the
166- // leading newline if the PEM block was empty.
167- _, rest = getLine(rest[endIndex+len(pemEnd)-1:])
168+ // The line must end with only whitespace.
169+ if s, _ := getLine(restOfEndLine); len(s) != 0 {
170+ continue
171+ }
172
173- return
174-}
175+ base64Data := removeSpacesAndTabs(rest[:endIndex])
176+ p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
177+ n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
178+ if err != nil {
179+ continue
180+ }
181+ p.Bytes = p.Bytes[:n]
182
183-func decodeError(data, rest []byte) (*Block, []byte) {
184- // If we get here then we have rejected a likely looking, but
185- // ultimately invalid PEM block. We need to start over from a new
186- // position. We have consumed the preamble line and will have consumed
187- // any lines which could be header lines. However, a valid preamble
188- // line is not a valid header line, therefore we cannot have consumed
189- // the preamble line for the any subsequent block. Thus, we will always
190- // find any valid block, no matter what bytes precede it.
191- //
192- // For example, if the input is
193- //
194- // -----BEGIN MALFORMED BLOCK-----
195- // junk that may look like header lines
196- // or data lines, but no END line
197- //
198- // -----BEGIN ACTUAL BLOCK-----
199- // realdata
200- // -----END ACTUAL BLOCK-----
201- //
202- // we've failed to parse using the first BEGIN line
203- // and now will try again, using the second BEGIN line.
204- p, rest := Decode(rest)
205- if p == nil {
206- rest = data
207+ // the -1 is because we might have only matched pemEnd without the
208+ // leading newline if the PEM block was empty.
209+ _, rest = getLine(rest[endIndex+len(pemEnd)-1:])
210+ return p, rest
211 }
212- return p, rest
213 }
214
215 const pemLineLength = 64
216diff --git a/src/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go
217index 8515b46..4485581 100644
218--- a/src/encoding/pem/pem_test.go
219+++ b/src/encoding/pem/pem_test.go
220@@ -107,6 +107,12 @@ const pemMissingEndingSpace = `
221 dGVzdA==
222 -----ENDBAR-----`
223
224+const pemMissingEndLine = `
225+-----BEGIN FOO-----
226+Header: 1`
227+
228+var pemRepeatingBegin = strings.Repeat("-----BEGIN \n", 10)
229+
230 var badPEMTests = []struct {
231 name string
232 input string
233@@ -131,14 +137,34 @@ var badPEMTests = []struct {
234 "missing ending space",
235 pemMissingEndingSpace,
236 },
237+ {
238+ "repeating begin",
239+ pemRepeatingBegin,
240+ },
241+ {
242+ "missing end line",
243+ pemMissingEndLine,
244+ },
245 }
246
247 func TestBadDecode(t *testing.T) {
248 for _, test := range badPEMTests {
249- result, _ := Decode([]byte(test.input))
250+ result, rest := Decode([]byte(test.input))
251 if result != nil {
252 t.Errorf("unexpected success while parsing %q", test.name)
253 }
254+ if string(rest) != test.input {
255+ t.Errorf("unexpected rest: %q; want = %q", rest, test.input)
256+ }
257+ }
258+}
259+
260+func TestCVE202224675(t *testing.T) {
261+ // Prior to CVE-2022-24675, this input would cause a stack overflow.
262+ input := []byte(strings.Repeat("-----BEGIN \n", 10000000))
263+ result, rest := Decode(input)
264+ if result != nil || !reflect.DeepEqual(rest, input) {
265+ t.Errorf("Encode of %#v decoded as %#v", input, rest)
266 }
267 }
268
269--
2702.25.1
271
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 @@
1From ba99f699d26483ea1045f47c760e9be30799e311 Mon Sep 17 00:00:00 2001
2From: Russ Cox <rsc@golang.org>
3Date: Wed, 2 Feb 2022 16:41:32 -0500
4Subject: [PATCH] regexp/syntax: reject very deeply nested regexps in Parse
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Upstream-Status: Backport [https://github.com/golang/go/commit/2b65cde5868d8245ef8a0b8eba1e361440252d3b]
10CVE: CVE-2022-24921
11Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org
12
13
14The regexp code assumes it can recurse over the structure of
15a regexp safely. Go's growable stacks make that reasonable
16for all plausible regexps, but implausible ones can reach the
17“infinite recursion?” stack limit.
18
19This CL limits the depth of any parsed regexp to 1000.
20That is, the depth of the parse tree is required to be ≤ 1000.
21Regexps that require deeper parse trees will return ErrInternalError.
22A future CL will change the error to ErrInvalidDepth,
23but using ErrInternalError for now avoids introducing new API
24in point releases when this is backported.
25
26Fixes #51112.
27Fixes #51117.
28
29Change-Id: I97d2cd82195946eb43a4ea8561f5b95f91fb14c5
30Reviewed-on: https://go-review.googlesource.com/c/go/+/384616
31Trust: Russ Cox <rsc@golang.org>
32Run-TryBot: Russ Cox <rsc@golang.org>
33Reviewed-by: Ian Lance Taylor <iant@golang.org>
34Reviewed-on: https://go-review.googlesource.com/c/go/+/384855
35---
36 src/regexp/syntax/parse.go | 72 ++++++++++++++++++++++++++++++++-
37 src/regexp/syntax/parse_test.go | 7 ++++
38 2 files changed, 77 insertions(+), 2 deletions(-)
39
40diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go
41index 8c6d43a..55bd20d 100644
42--- a/src/regexp/syntax/parse.go
43+++ b/src/regexp/syntax/parse.go
44@@ -76,13 +76,29 @@ const (
45 opVerticalBar
46 )
47
48+// maxHeight is the maximum height of a regexp parse tree.
49+// It is somewhat arbitrarily chosen, but the idea is to be large enough
50+// that no one will actually hit in real use but at the same time small enough
51+// that recursion on the Regexp tree will not hit the 1GB Go stack limit.
52+// The maximum amount of stack for a single recursive frame is probably
53+// closer to 1kB, so this could potentially be raised, but it seems unlikely
54+// that people have regexps nested even this deeply.
55+// We ran a test on Google's C++ code base and turned up only
56+// a single use case with depth > 100; it had depth 128.
57+// Using depth 1000 should be plenty of margin.
58+// As an optimization, we don't even bother calculating heights
59+// until we've allocated at least maxHeight Regexp structures.
60+const maxHeight = 1000
61+
62 type parser struct {
63 flags Flags // parse mode flags
64 stack []*Regexp // stack of parsed expressions
65 free *Regexp
66 numCap int // number of capturing groups seen
67 wholeRegexp string
68- tmpClass []rune // temporary char class work space
69+ tmpClass []rune // temporary char class work space
70+ numRegexp int // number of regexps allocated
71+ height map[*Regexp]int // regexp height for height limit check
72 }
73
74 func (p *parser) newRegexp(op Op) *Regexp {
75@@ -92,16 +108,52 @@ func (p *parser) newRegexp(op Op) *Regexp {
76 *re = Regexp{}
77 } else {
78 re = new(Regexp)
79+ p.numRegexp++
80 }
81 re.Op = op
82 return re
83 }
84
85 func (p *parser) reuse(re *Regexp) {
86+ if p.height != nil {
87+ delete(p.height, re)
88+ }
89 re.Sub0[0] = p.free
90 p.free = re
91 }
92
93+func (p *parser) checkHeight(re *Regexp) {
94+ if p.numRegexp < maxHeight {
95+ return
96+ }
97+ if p.height == nil {
98+ p.height = make(map[*Regexp]int)
99+ for _, re := range p.stack {
100+ p.checkHeight(re)
101+ }
102+ }
103+ if p.calcHeight(re, true) > maxHeight {
104+ panic(ErrInternalError)
105+ }
106+}
107+
108+func (p *parser) calcHeight(re *Regexp, force bool) int {
109+ if !force {
110+ if h, ok := p.height[re]; ok {
111+ return h
112+ }
113+ }
114+ h := 1
115+ for _, sub := range re.Sub {
116+ hsub := p.calcHeight(sub, false)
117+ if h < 1+hsub {
118+ h = 1 + hsub
119+ }
120+ }
121+ p.height[re] = h
122+ return h
123+}
124+
125 // Parse stack manipulation.
126
127 // push pushes the regexp re onto the parse stack and returns the regexp.
128@@ -137,6 +189,7 @@ func (p *parser) push(re *Regexp) *Regexp {
129 }
130
131 p.stack = append(p.stack, re)
132+ p.checkHeight(re)
133 return re
134 }
135
136@@ -252,6 +305,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (
137 re.Sub = re.Sub0[:1]
138 re.Sub[0] = sub
139 p.stack[n-1] = re
140+ p.checkHeight(re)
141
142 if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
143 return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
144@@ -699,6 +753,21 @@ func literalRegexp(s string, flags Flags) *Regexp {
145 // Flags, and returns a regular expression parse tree. The syntax is
146 // described in the top-level comment.
147 func Parse(s string, flags Flags) (*Regexp, error) {
148+ return parse(s, flags)
149+}
150+
151+func parse(s string, flags Flags) (_ *Regexp, err error) {
152+ defer func() {
153+ switch r := recover(); r {
154+ default:
155+ panic(r)
156+ case nil:
157+ // ok
158+ case ErrInternalError:
159+ err = &Error{Code: ErrInternalError, Expr: s}
160+ }
161+ }()
162+
163 if flags&Literal != 0 {
164 // Trivial parser for literal string.
165 if err := checkUTF8(s); err != nil {
166@@ -710,7 +779,6 @@ func Parse(s string, flags Flags) (*Regexp, error) {
167 // Otherwise, must do real work.
168 var (
169 p parser
170- err error
171 c rune
172 op Op
173 lastRepeat string
174diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go
175index 5581ba1..1ef6d8a 100644
176--- a/src/regexp/syntax/parse_test.go
177+++ b/src/regexp/syntax/parse_test.go
178@@ -207,6 +207,11 @@ var parseTests = []parseTest{
179 // Valid repetitions.
180 {`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``},
181 {`((((((((((x{1}){2}){2}){2}){2}){2}){2}){2}){2}){2})`, ``},
182+
183+ // Valid nesting.
184+ {strings.Repeat("(", 999) + strings.Repeat(")", 999), ``},
185+ {strings.Repeat("(?:", 999) + strings.Repeat(")*", 999), ``},
186+ {"(" + strings.Repeat("|", 12345) + ")", ``}, // not nested at all
187 }
188
189 const testFlags = MatchNL | PerlX | UnicodeGroups
190@@ -482,6 +487,8 @@ var invalidRegexps = []string{
191 `a{100000}`,
192 `a{100000,}`,
193 "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
194+ strings.Repeat("(", 1000) + strings.Repeat(")", 1000),
195+ strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000),
196 `\Q\E*`,
197 }
198
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 @@
1From 48c9076dcfc2dc894842ff758c8cfae7957c9565 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 29 Sep 2022 17:06:18 +0530
4Subject: [PATCH] CVE-2022-27664
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/5bc9106458fc07851ac324a4157132a91b1f3479]
7CVE: CVE-2022-27664
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/net/http/h2_bundle.go | 21 +++++++++++++--------
11 1 file changed, 13 insertions(+), 8 deletions(-)
12
13diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
14index 65d851d..83f2a72 100644
15--- a/src/net/http/h2_bundle.go
16+++ b/src/net/http/h2_bundle.go
17@@ -3254,10 +3254,11 @@ var (
18 // name (key). See httpguts.ValidHeaderName for the base rules.
19 //
20 // Further, http2 says:
21-// "Just as in HTTP/1.x, header field names are strings of ASCII
22-// characters that are compared in a case-insensitive
23-// fashion. However, header field names MUST be converted to
24-// lowercase prior to their encoding in HTTP/2. "
25+//
26+// "Just as in HTTP/1.x, header field names are strings of ASCII
27+// characters that are compared in a case-insensitive
28+// fashion. However, header field names MUST be converted to
29+// lowercase prior to their encoding in HTTP/2. "
30 func http2validWireHeaderFieldName(v string) bool {
31 if len(v) == 0 {
32 return false
33@@ -3446,8 +3447,8 @@ func (s *http2sorter) SortStrings(ss []string) {
34 // validPseudoPath reports whether v is a valid :path pseudo-header
35 // value. It must be either:
36 //
37-// *) a non-empty string starting with '/'
38-// *) the string '*', for OPTIONS requests.
39+// *) a non-empty string starting with '/'
40+// *) the string '*', for OPTIONS requests.
41 //
42 // For now this is only used a quick check for deciding when to clean
43 // up Opaque URLs before sending requests from the Transport.
44@@ -4897,6 +4898,9 @@ func (sc *http2serverConn) startGracefulShutdownInternal() {
45 func (sc *http2serverConn) goAway(code http2ErrCode) {
46 sc.serveG.check()
47 if sc.inGoAway {
48+ if sc.goAwayCode == http2ErrCodeNo {
49+ sc.goAwayCode = code
50+ }
51 return
52 }
53 sc.inGoAway = true
54@@ -6091,8 +6095,9 @@ func (rws *http2responseWriterState) writeChunk(p []byte) (n int, err error) {
55 // prior to the headers being written. If the set of trailers is fixed
56 // or known before the header is written, the normal Go trailers mechanism
57 // is preferred:
58-// https://golang.org/pkg/net/http/#ResponseWriter
59-// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
60+//
61+// https://golang.org/pkg/net/http/#ResponseWriter
62+// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
63 const http2TrailerPrefix = "Trailer:"
64
65 // promoteUndeclaredTrailers permits http.Handlers to set trailers
66--
672.25.1
68
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 @@
1From 8136eb2e5c316a51d0da710fbd0504cbbefee526 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <roland@golang.org>
3Date: Mon, 28 Mar 2022 18:41:26 -0700
4Subject: [PATCH] encoding/xml: use iterative Skip, rather than recursive
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/58facfbe7db2fbb9afed794b281a70bdb12a60ae]
7CVE: CVE-2022-28131
8Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
9
10
11Prevents exhausting the stack limit in _incredibly_ deeply nested
12structures.
13
14Fixes #53711
15Updates #53614
16Fixes CVE-2022-28131
17
18Change-Id: I47db4595ce10cecc29fbd06afce7b299868599e6
19Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1419912
20Reviewed-by: Julie Qiu <julieqiu@google.com>
21Reviewed-by: Damien Neil <dneil@google.com>
22(cherry picked from commit 9278cb78443d2b4deb24cbb5b61c9ba5ac688d49)
23Reviewed-on: https://go-review.googlesource.com/c/go/+/417068
24TryBot-Result: Gopher Robot <gobot@golang.org>
25Reviewed-by: Heschi Kreinick <heschi@google.com>
26Run-TryBot: Michael Knyszek <mknyszek@google.com>
27---
28 src/encoding/xml/read.go | 15 ++++++++-------
29 src/encoding/xml/read_test.go | 18 ++++++++++++++++++
30 2 files changed, 26 insertions(+), 7 deletions(-)
31
32diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go
33index 4ffed80..3fac859 100644
34--- a/src/encoding/xml/read.go
35+++ b/src/encoding/xml/read.go
36@@ -743,12 +743,12 @@ Loop:
37 }
38
39 // Skip reads tokens until it has consumed the end element
40-// matching the most recent start element already consumed.
41-// It recurs if it encounters a start element, so it can be used to
42-// skip nested structures.
43+// matching the most recent start element already consumed,
44+// skipping nested structures.
45 // It returns nil if it finds an end element matching the start
46 // element; otherwise it returns an error describing the problem.
47 func (d *Decoder) Skip() error {
48+ var depth int64
49 for {
50 tok, err := d.Token()
51 if err != nil {
52@@ -756,11 +756,12 @@ func (d *Decoder) Skip() error {
53 }
54 switch tok.(type) {
55 case StartElement:
56- if err := d.Skip(); err != nil {
57- return err
58- }
59+ depth++
60 case EndElement:
61- return nil
62+ if depth == 0 {
63+ return nil
64+ }
65+ depth--
66 }
67 }
68 }
69diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go
70index 6a20b1a..7a621a5 100644
71--- a/src/encoding/xml/read_test.go
72+++ b/src/encoding/xml/read_test.go
73@@ -5,9 +5,11 @@
74 package xml
75
76 import (
77+ "bytes"
78 "errors"
79 "io"
80 "reflect"
81+ "runtime"
82 "strings"
83 "testing"
84 "time"
85@@ -1093,3 +1095,19 @@ func TestCVE202228131(t *testing.T) {
86 t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth)
87 }
88 }
89+
90+func TestCVE202230633(t *testing.T) {
91+ if runtime.GOARCH == "wasm" {
92+ t.Skip("causes memory exhaustion on js/wasm")
93+ }
94+ defer func() {
95+ p := recover()
96+ if p != nil {
97+ t.Fatal("Unmarshal panicked")
98+ }
99+ }()
100+ var example struct {
101+ Things []string
102+ }
103+ Unmarshal(bytes.Repeat([]byte("<a>"), 17_000_000), &example)
104+}
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 @@
1From 34d9ab78568d63d8097911237897b188bdaba9c2 Mon Sep 17 00:00:00 2001
2From: Filippo Valsorda <filippo@golang.org>
3Date: Thu, 31 Mar 2022 12:31:58 -0400
4Subject: [PATCH] crypto/elliptic: tolerate zero-padded scalars in generic
5 P-256
6
7Upstream-Status: Backport [https://github.com/golang/go/commit/7139e8b024604ab168b51b99c6e8168257a5bf58]
8CVE: CVE-2022-28327
9Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org>
10
11
12Updates #52075
13Fixes #52076
14Fixes CVE-2022-28327
15
16Change-Id: I595a7514c9a0aa1b9c76aedfc2307e1124271f27
17Reviewed-on: https://go-review.googlesource.com/c/go/+/397136
18Trust: Filippo Valsorda <filippo@golang.org>
19Reviewed-by: Julie Qiu <julie@golang.org>
20---
21 src/crypto/elliptic/p256.go | 2 +-
22 1 file changed, 1 insertion(+), 1 deletion(-)
23
24diff --git a/src/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go
25index c23e414..787e3e7 100644
26--- a/src/crypto/elliptic/p256.go
27+++ b/src/crypto/elliptic/p256.go
28@@ -51,7 +51,7 @@ func p256GetScalar(out *[32]byte, in []byte) {
29 n := new(big.Int).SetBytes(in)
30 var scalarBytes []byte
31
32- if n.Cmp(p256Params.N) >= 0 {
33+ if n.Cmp(p256Params.N) >= 0 || len(in) > len(out) {
34 n.Mod(n, p256Params.N)
35 scalarBytes = n.Bytes()
36 } 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 @@
1From 9d339f1d0f53c4116a7cb4acfa895f31a07212ee Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Fri, 2 Sep 2022 20:45:18 -0700
4Subject: [PATCH] archive/tar: limit size of headers
5
6Set a 1MiB limit on special file blocks (PAX headers, GNU long names,
7GNU link names), to avoid reading arbitrarily large amounts of data
8into memory.
9
10Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting
11this issue.
12
13Fixes CVE-2022-2879
14Updates #54853
15Fixes #55926
16
17Change-Id: I85136d6ff1e0af101a112190e027987ab4335680
18Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1565555
19Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
20Run-TryBot: Roland Shoemaker <bracewell@google.com>
21Reviewed-by: Roland Shoemaker <bracewell@google.com>
22(cherry picked from commit 6ee768cef6b82adf7a90dcf367a1699ef694f3b2)
23Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1591053
24Reviewed-by: Julie Qiu <julieqiu@google.com>
25Reviewed-by: Damien Neil <dneil@google.com>
26Reviewed-on: https://go-review.googlesource.com/c/go/+/438498
27TryBot-Result: Gopher Robot <gobot@golang.org>
28Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
29Reviewed-by: Carlos Amedee <carlos@golang.org>
30Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
31Run-TryBot: Carlos Amedee <carlos@golang.org>
32
33Upstream-Status: Backport [https://github.com/golang/go/commit/0a723816cd2]
34CVE: CVE-2022-2879
35Signed-off-by: Sunil Kumar <sukumar@mvista.com>
36---
37 src/archive/tar/format.go | 4 ++++
38 src/archive/tar/reader.go | 14 ++++++++++++--
39 src/archive/tar/writer.go | 3 +++
40 3 files changed, 19 insertions(+), 2 deletions(-)
41
42diff --git a/src/archive/tar/format.go b/src/archive/tar/format.go
43index cfe24a5..6642364 100644
44--- a/src/archive/tar/format.go
45+++ b/src/archive/tar/format.go
46@@ -143,6 +143,10 @@ const (
47 blockSize = 512 // Size of each block in a tar stream
48 nameSize = 100 // Max length of the name field in USTAR format
49 prefixSize = 155 // Max length of the prefix field in USTAR format
50+
51+ // Max length of a special file (PAX header, GNU long name or link).
52+ // This matches the limit used by libarchive.
53+ maxSpecialFileSize = 1 << 20
54 )
55
56 // blockPadding computes the number of bytes needed to pad offset up to the
57diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go
58index 4f9135b..e996595 100644
59--- a/src/archive/tar/reader.go
60+++ b/src/archive/tar/reader.go
61@@ -104,7 +104,7 @@ func (tr *Reader) next() (*Header, error) {
62 continue // This is a meta header affecting the next header
63 case TypeGNULongName, TypeGNULongLink:
64 format.mayOnlyBe(FormatGNU)
65- realname, err := ioutil.ReadAll(tr)
66+ realname, err := readSpecialFile(tr)
67 if err != nil {
68 return nil, err
69 }
70@@ -294,7 +294,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) {
71 // parsePAX parses PAX headers.
72 // If an extended header (type 'x') is invalid, ErrHeader is returned
73 func parsePAX(r io.Reader) (map[string]string, error) {
74- buf, err := ioutil.ReadAll(r)
75+ buf, err := readSpecialFile(r)
76 if err != nil {
77 return nil, err
78 }
79@@ -827,6 +827,16 @@ func tryReadFull(r io.Reader, b []byte) (n int, err error) {
80 return n, err
81 }
82
83+// readSpecialFile is like ioutil.ReadAll except it returns
84+// ErrFieldTooLong if more than maxSpecialFileSize is read.
85+func readSpecialFile(r io.Reader) ([]byte, error) {
86+ buf, err := ioutil.ReadAll(io.LimitReader(r, maxSpecialFileSize+1))
87+ if len(buf) > maxSpecialFileSize {
88+ return nil, ErrFieldTooLong
89+ }
90+ return buf, err
91+}
92+
93 // discard skips n bytes in r, reporting an error if unable to do so.
94 func discard(r io.Reader, n int64) error {
95 // If possible, Seek to the last byte before the end of the data section.
96diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go
97index e80498d..893eac0 100644
98--- a/src/archive/tar/writer.go
99+++ b/src/archive/tar/writer.go
100@@ -199,6 +199,9 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error {
101 flag = TypeXHeader
102 }
103 data := buf.String()
104+ if len(data) > maxSpecialFileSize {
105+ return ErrFieldTooLong
106+ }
107 if err := tw.writeRawFile(name, data, flag, FormatPAX); err != nil || isGlobal {
108 return err // Global headers return here
109 }
110--
1112.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 @@
1From 753e3f8da191c2ac400407d83c70f46900769417 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 27 Oct 2022 12:22:41 +0530
4Subject: [PATCH] CVE-2022-2880
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/9d2c73a9fd69e45876509bb3bdb2af99bf77da1e]
7CVE: CVE-2022-2880
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9
10net/http/httputil: avoid query parameter
11
12Query parameter smuggling occurs when a proxy's interpretation
13of query parameters differs from that of a downstream server.
14Change ReverseProxy to avoid forwarding ignored query parameters.
15
16Remove unparsable query parameters from the outbound request
17
18 * if req.Form != nil after calling ReverseProxy.Director; and
19 * before calling ReverseProxy.Rewrite.
20
21This change preserves the existing behavior of forwarding the
22raw query untouched if a Director hook does not parse the query
23by calling Request.ParseForm (possibly indirectly).
24---
25 src/net/http/httputil/reverseproxy.go | 36 +++++++++++
26 src/net/http/httputil/reverseproxy_test.go | 74 ++++++++++++++++++++++
27 2 files changed, 110 insertions(+)
28
29diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
30index 2072a5f..c6fb873 100644
31--- a/src/net/http/httputil/reverseproxy.go
32+++ b/src/net/http/httputil/reverseproxy.go
33@@ -212,6 +212,9 @@ func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
34 }
35
36 p.Director(outreq)
37+ if outreq.Form != nil {
38+ outreq.URL.RawQuery = cleanQueryParams(outreq.URL.RawQuery)
39+ }
40 outreq.Close = false
41
42 reqUpType := upgradeType(outreq.Header)
43@@ -561,3 +564,36 @@ func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
44 _, err := io.Copy(c.backend, c.user)
45 errc <- err
46 }
47+
48+func cleanQueryParams(s string) string {
49+ reencode := func(s string) string {
50+ v, _ := url.ParseQuery(s)
51+ return v.Encode()
52+ }
53+ for i := 0; i < len(s); {
54+ switch s[i] {
55+ case ';':
56+ return reencode(s)
57+ case '%':
58+ if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
59+ return reencode(s)
60+ }
61+ i += 3
62+ default:
63+ i++
64+ }
65+ }
66+ return s
67+}
68+
69+func ishex(c byte) bool {
70+ switch {
71+ case '0' <= c && c <= '9':
72+ return true
73+ case 'a' <= c && c <= 'f':
74+ return true
75+ case 'A' <= c && c <= 'F':
76+ return true
77+ }
78+ return false
79+}
80diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
81index 9a7223a..bc87a3b 100644
82--- a/src/net/http/httputil/reverseproxy_test.go
83+++ b/src/net/http/httputil/reverseproxy_test.go
84@@ -1269,3 +1269,77 @@ func TestSingleJoinSlash(t *testing.T) {
85 }
86 }
87 }
88+
89+const (
90+ testWantsCleanQuery = true
91+ testWantsRawQuery = false
92+)
93+
94+func TestReverseProxyQueryParameterSmugglingDirectorDoesNotParseForm(t *testing.T) {
95+ testReverseProxyQueryParameterSmuggling(t, testWantsRawQuery, func(u *url.URL) *ReverseProxy {
96+ proxyHandler := NewSingleHostReverseProxy(u)
97+ oldDirector := proxyHandler.Director
98+ proxyHandler.Director = func(r *http.Request) {
99+ oldDirector(r)
100+ }
101+ return proxyHandler
102+ })
103+}
104+
105+func TestReverseProxyQueryParameterSmugglingDirectorParsesForm(t *testing.T) {
106+ testReverseProxyQueryParameterSmuggling(t, testWantsCleanQuery, func(u *url.URL) *ReverseProxy {
107+ proxyHandler := NewSingleHostReverseProxy(u)
108+ oldDirector := proxyHandler.Director
109+ proxyHandler.Director = func(r *http.Request) {
110+ // Parsing the form causes ReverseProxy to remove unparsable
111+ // query parameters before forwarding.
112+ r.FormValue("a")
113+ oldDirector(r)
114+ }
115+ return proxyHandler
116+ })
117+}
118+
119+func testReverseProxyQueryParameterSmuggling(t *testing.T, wantCleanQuery bool, newProxy func(*url.URL) *ReverseProxy) {
120+ const content = "response_content"
121+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
122+ w.Write([]byte(r.URL.RawQuery))
123+ }))
124+ defer backend.Close()
125+ backendURL, err := url.Parse(backend.URL)
126+ if err != nil {
127+ t.Fatal(err)
128+ }
129+ proxyHandler := newProxy(backendURL)
130+ frontend := httptest.NewServer(proxyHandler)
131+ defer frontend.Close()
132+
133+ // Don't spam output with logs of queries containing semicolons.
134+ backend.Config.ErrorLog = log.New(io.Discard, "", 0)
135+ frontend.Config.ErrorLog = log.New(io.Discard, "", 0)
136+
137+ for _, test := range []struct {
138+ rawQuery string
139+ cleanQuery string
140+ }{{
141+ rawQuery: "a=1&a=2;b=3",
142+ cleanQuery: "a=1",
143+ }, {
144+ rawQuery: "a=1&a=%zz&b=3",
145+ cleanQuery: "a=1&b=3",
146+ }} {
147+ res, err := frontend.Client().Get(frontend.URL + "?" + test.rawQuery)
148+ if err != nil {
149+ t.Fatalf("Get: %v", err)
150+ }
151+ defer res.Body.Close()
152+ body, _ := io.ReadAll(res.Body)
153+ wantQuery := test.rawQuery
154+ if wantCleanQuery {
155+ wantQuery = test.cleanQuery
156+ }
157+ if got, want := string(body), wantQuery; got != want {
158+ t.Errorf("proxy forwarded raw query %q as %q, want %q", test.rawQuery, got, want)
159+ }
160+ }
161+}
162--
1632.25.1
164
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 @@
1From 8d0bbb5a6280c2cf951241ec7f6579c90d38df57 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 25 Aug 2022 10:55:08 +0530
4Subject: [PATCH] CVE-2022-30629
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/c15a8e2dbb5ac376a6ed890735341b812d6b965c]
7CVE: CVE-2022-30629
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/crypto/tls/handshake_server_tls13.go | 14 ++++++++++++++
11 1 file changed, 14 insertions(+)
12
13diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go
14index 5432145..d91797e 100644
15--- a/src/crypto/tls/handshake_server_tls13.go
16+++ b/src/crypto/tls/handshake_server_tls13.go
17@@ -9,6 +9,7 @@ import (
18 "crypto"
19 "crypto/hmac"
20 "crypto/rsa"
21+ "encoding/binary"
22 "errors"
23 "hash"
24 "io"
25@@ -742,6 +743,19 @@ func (hs *serverHandshakeStateTLS13) sendSessionTickets() error {
26 }
27 m.lifetime = uint32(maxSessionTicketLifetime / time.Second)
28
29+ // ticket_age_add is a random 32-bit value. See RFC 8446, section 4.6.1
30+ // The value is not stored anywhere; we never need to check the ticket age
31+ // because 0-RTT is not supported.
32+ ageAdd := make([]byte, 4)
33+ _, err = hs.c.config.rand().Read(ageAdd)
34+ if err != nil {
35+ return err
36+ }
37+ m.ageAdd = binary.LittleEndian.Uint32(ageAdd)
38+
39+ // ticket_nonce, which must be unique per connection, is always left at
40+ // zero because we only ever send one ticket per connection.
41+
42 if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
43 return err
44 }
45--
462.25.1
47
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 @@
1From d10fc3a84e3344f2421c1dd3046faa50709ab4d5 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 25 Aug 2022 11:01:21 +0530
4Subject: [PATCH] CVE-2022-30631
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/0117dee7dccbbd7803d88f65a2ce8bd686219ad3]
7CVE: CVE-2022-30631
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/compress/gzip/gunzip.go | 60 +++++++++++++++-----------------
11 src/compress/gzip/gunzip_test.go | 16 +++++++++
12 2 files changed, 45 insertions(+), 31 deletions(-)
13
14diff --git a/src/compress/gzip/gunzip.go b/src/compress/gzip/gunzip.go
15index 924bce1..237b2b9 100644
16--- a/src/compress/gzip/gunzip.go
17+++ b/src/compress/gzip/gunzip.go
18@@ -248,42 +248,40 @@ func (z *Reader) Read(p []byte) (n int, err error) {
19 return 0, z.err
20 }
21
22- n, z.err = z.decompressor.Read(p)
23- z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n])
24- z.size += uint32(n)
25- if z.err != io.EOF {
26- // In the normal case we return here.
27- return n, z.err
28- }
29+ for n == 0 {
30+ n, z.err = z.decompressor.Read(p)
31+ z.digest = crc32.Update(z.digest, crc32.IEEETable, p[:n])
32+ z.size += uint32(n)
33+ if z.err != io.EOF {
34+ // In the normal case we return here.
35+ return n, z.err
36+ }
37
38- // Finished file; check checksum and size.
39- if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil {
40- z.err = noEOF(err)
41- return n, z.err
42- }
43- digest := le.Uint32(z.buf[:4])
44- size := le.Uint32(z.buf[4:8])
45- if digest != z.digest || size != z.size {
46- z.err = ErrChecksum
47- return n, z.err
48- }
49- z.digest, z.size = 0, 0
50+ // Finished file; check checksum and size.
51+ if _, err := io.ReadFull(z.r, z.buf[:8]); err != nil {
52+ z.err = noEOF(err)
53+ return n, z.err
54+ }
55+ digest := le.Uint32(z.buf[:4])
56+ size := le.Uint32(z.buf[4:8])
57+ if digest != z.digest || size != z.size {
58+ z.err = ErrChecksum
59+ return n, z.err
60+ }
61+ z.digest, z.size = 0, 0
62
63- // File is ok; check if there is another.
64- if !z.multistream {
65- return n, io.EOF
66- }
67- z.err = nil // Remove io.EOF
68+ // File is ok; check if there is another.
69+ if !z.multistream {
70+ return n, io.EOF
71+ }
72+ z.err = nil // Remove io.EOF
73
74- if _, z.err = z.readHeader(); z.err != nil {
75- return n, z.err
76+ if _, z.err = z.readHeader(); z.err != nil {
77+ return n, z.err
78+ }
79 }
80
81- // Read from next file, if necessary.
82- if n > 0 {
83- return n, nil
84- }
85- return z.Read(p)
86+ return n, nil
87 }
88
89 // Close closes the Reader. It does not close the underlying io.Reader.
90diff --git a/src/compress/gzip/gunzip_test.go b/src/compress/gzip/gunzip_test.go
91index 1b01404..95220ae 100644
92--- a/src/compress/gzip/gunzip_test.go
93+++ b/src/compress/gzip/gunzip_test.go
94@@ -516,3 +516,19 @@ func TestTruncatedStreams(t *testing.T) {
95 }
96 }
97 }
98+
99+func TestCVE202230631(t *testing.T) {
100+ var empty = []byte{0x1f, 0x8b, 0x08, 0x00, 0xa7, 0x8f, 0x43, 0x62, 0x00,
101+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
102+ r := bytes.NewReader(bytes.Repeat(empty, 4e6))
103+ z, err := NewReader(r)
104+ if err != nil {
105+ t.Fatalf("NewReader: got %v, want nil", err)
106+ }
107+ // Prior to CVE-2022-30631 fix, this would cause an unrecoverable panic due
108+ // to stack exhaustion.
109+ _, err = z.Read(make([]byte, 10))
110+ if err != io.EOF {
111+ t.Errorf("Reader.Read: got %v, want %v", err, io.EOF)
112+ }
113+}
114--
1152.25.1
116
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 @@
1From 35d1dfe9746029aea9027b405c75555d41ffd2f8 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 25 Aug 2022 13:12:40 +0530
4Subject: [PATCH] CVE-2022-30632
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/76f8b7304d1f7c25834e2a0cc9e88c55276c47df]
7CVE: CVE-2022-30632
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/path/filepath/match.go | 16 +++++++++++++++-
11 src/path/filepath/match_test.go | 10 ++++++++++
12 2 files changed, 25 insertions(+), 1 deletion(-)
13
14diff --git a/src/path/filepath/match.go b/src/path/filepath/match.go
15index 46badb5..ba68daa 100644
16--- a/src/path/filepath/match.go
17+++ b/src/path/filepath/match.go
18@@ -232,6 +232,20 @@ func getEsc(chunk string) (r rune, nchunk string, err error) {
19 // The only possible returned error is ErrBadPattern, when pattern
20 // is malformed.
21 func Glob(pattern string) (matches []string, err error) {
22+ return globWithLimit(pattern, 0)
23+}
24+
25+func globWithLimit(pattern string, depth int) (matches []string, err error) {
26+ // This limit is used prevent stack exhaustion issues. See CVE-2022-30632.
27+ const pathSeparatorsLimit = 10000
28+ if depth == pathSeparatorsLimit {
29+ return nil, ErrBadPattern
30+ }
31+
32+ // Check pattern is well-formed.
33+ if _, err := Match(pattern, ""); err != nil {
34+ return nil, err
35+ }
36 if !hasMeta(pattern) {
37 if _, err = os.Lstat(pattern); err != nil {
38 return nil, nil
39@@ -257,7 +271,7 @@ func Glob(pattern string) (matches []string, err error) {
40 }
41
42 var m []string
43- m, err = Glob(dir)
44+ m, err = globWithLimit(dir, depth+1)
45 if err != nil {
46 return
47 }
48diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go
49index b865762..c37c812 100644
50--- a/src/path/filepath/match_test.go
51+++ b/src/path/filepath/match_test.go
52@@ -154,6 +154,16 @@ func TestGlob(t *testing.T) {
53 }
54 }
55
56+func TestCVE202230632(t *testing.T) {
57+ // Prior to CVE-2022-30632, this would cause a stack exhaustion given a
58+ // large number of separators (more than 4,000,000). There is now a limit
59+ // of 10,000.
60+ _, err := Glob("/*" + strings.Repeat("/", 10001))
61+ if err != ErrBadPattern {
62+ t.Fatalf("Glob returned err=%v, want ErrBadPattern", err)
63+ }
64+}
65+
66 func TestGlobError(t *testing.T) {
67 _, err := Glob("[]")
68 if err == nil {
69--
702.25.1
71
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 @@
1From ab6e2ffdcab0501bcc2de4b196c1c18ae2301d4b Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Thu, 25 Aug 2022 13:29:55 +0530
4Subject: [PATCH] CVE-2022-30633
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/2678d0c957193dceef336c969a9da74dd716a827]
7CVE: CVE-2022-30633
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/encoding/xml/read.go | 27 +++++++++++++++++++--------
11 src/encoding/xml/read_test.go | 14 ++++++++++++++
12 2 files changed, 33 insertions(+), 8 deletions(-)
13
14diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go
15index 10a60ee..4ffed80 100644
16--- a/src/encoding/xml/read.go
17+++ b/src/encoding/xml/read.go
18@@ -148,7 +148,7 @@ func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error {
19 if val.Kind() != reflect.Ptr {
20 return errors.New("non-pointer passed to Unmarshal")
21 }
22- return d.unmarshal(val.Elem(), start)
23+ return d.unmarshal(val.Elem(), start, 0)
24 }
25
26 // An UnmarshalError represents an error in the unmarshaling process.
27@@ -304,8 +304,15 @@ var (
28 textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
29 )
30
31+const maxUnmarshalDepth = 10000
32+
33+var errExeceededMaxUnmarshalDepth = errors.New("exceeded max depth")
34+
35 // Unmarshal a single XML element into val.
36-func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
37+func (d *Decoder) unmarshal(val reflect.Value, start *StartElement, depth int) error {
38+ if depth >= maxUnmarshalDepth {
39+ return errExeceededMaxUnmarshalDepth
40+ }
41 // Find start element if we need it.
42 if start == nil {
43 for {
44@@ -398,7 +405,7 @@ func (d *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
45 v.Set(reflect.Append(val, reflect.Zero(v.Type().Elem())))
46
47 // Recur to read element into slice.
48- if err := d.unmarshal(v.Index(n), start); err != nil {
49+ if err := d.unmarshal(v.Index(n), start, depth+1); err != nil {
50 v.SetLen(n)
51 return err
52 }
53@@ -521,13 +528,15 @@ Loop:
54 case StartElement:
55 consumed := false
56 if sv.IsValid() {
57- consumed, err = d.unmarshalPath(tinfo, sv, nil, &t)
58+ // unmarshalPath can call unmarshal, so we need to pass the depth through so that
59+ // we can continue to enforce the maximum recusion limit.
60+ consumed, err = d.unmarshalPath(tinfo, sv, nil, &t, depth)
61 if err != nil {
62 return err
63 }
64 if !consumed && saveAny.IsValid() {
65 consumed = true
66- if err := d.unmarshal(saveAny, &t); err != nil {
67+ if err := d.unmarshal(saveAny, &t, depth+1); err != nil {
68 return err
69 }
70 }
71@@ -672,7 +681,7 @@ func copyValue(dst reflect.Value, src []byte) (err error) {
72 // The consumed result tells whether XML elements have been consumed
73 // from the Decoder until start's matching end element, or if it's
74 // still untouched because start is uninteresting for sv's fields.
75-func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement) (consumed bool, err error) {
76+func (d *Decoder) unmarshalPath(tinfo *typeInfo, sv reflect.Value, parents []string, start *StartElement, depth int) (consumed bool, err error) {
77 recurse := false
78 Loop:
79 for i := range tinfo.fields {
80@@ -687,7 +696,7 @@ Loop:
81 }
82 if len(finfo.parents) == len(parents) && finfo.name == start.Name.Local {
83 // It's a perfect match, unmarshal the field.
84- return true, d.unmarshal(finfo.value(sv), start)
85+ return true, d.unmarshal(finfo.value(sv), start, depth+1)
86 }
87 if len(finfo.parents) > len(parents) && finfo.parents[len(parents)] == start.Name.Local {
88 // It's a prefix for the field. Break and recurse
89@@ -716,7 +725,9 @@ Loop:
90 }
91 switch t := tok.(type) {
92 case StartElement:
93- consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t)
94+ // the recursion depth of unmarshalPath is limited to the path length specified
95+ // by the struct field tag, so we don't increment the depth here.
96+ consumed2, err := d.unmarshalPath(tinfo, sv, parents, &t, depth)
97 if err != nil {
98 return true, err
99 }
100diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go
101index 8c2e70f..6a20b1a 100644
102--- a/src/encoding/xml/read_test.go
103+++ b/src/encoding/xml/read_test.go
104@@ -5,6 +5,7 @@
105 package xml
106
107 import (
108+ "errors"
109 "io"
110 "reflect"
111 "strings"
112@@ -1079,3 +1080,16 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) {
113 t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want)
114 }
115 }
116+
117+func TestCVE202228131(t *testing.T) {
118+ type nested struct {
119+ Parent *nested `xml:",any"`
120+ }
121+ var n nested
122+ err := Unmarshal(bytes.Repeat([]byte("<a>"), maxUnmarshalDepth+1), &n)
123+ if err == nil {
124+ t.Fatal("Unmarshal did not fail")
125+ } else if !errors.Is(err, errExeceededMaxUnmarshalDepth) {
126+ t.Fatalf("Unmarshal unexpected error: got %q, want %q", err, errExeceededMaxUnmarshalDepth)
127+ }
128+}
129--
1302.25.1
131
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 @@
1From fdd4316737ed5681689a1f40802ffa0805e5b11c Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Fri, 26 Aug 2022 12:17:05 +0530
4Subject: [PATCH] CVE-2022-30635
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/cd54600b866db0ad068ab8df06c7f5f6cb55c9b3]
7CVE-2022-30635
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/encoding/gob/decode.go | 19 ++++++++++++-------
11 src/encoding/gob/gobencdec_test.go | 24 ++++++++++++++++++++++++
12 2 files changed, 36 insertions(+), 7 deletions(-)
13
14diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go
15index d2f6c74..0e0ec75 100644
16--- a/src/encoding/gob/decode.go
17+++ b/src/encoding/gob/decode.go
18@@ -871,8 +871,13 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
19 return &op
20 }
21
22+var maxIgnoreNestingDepth = 10000
23+
24 // decIgnoreOpFor returns the decoding op for a field that has no destination.
25-func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp {
26+func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, depth int) *decOp {
27+ if depth > maxIgnoreNestingDepth {
28+ error_(errors.New("invalid nesting depth"))
29+ }
30 // If this type is already in progress, it's a recursive type (e.g. map[string]*T).
31 // Return the pointer to the op we're already building.
32 if opPtr := inProgress[wireId]; opPtr != nil {
33@@ -896,7 +901,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp)
34 errorf("bad data: undefined type %s", wireId.string())
35 case wire.ArrayT != nil:
36 elemId := wire.ArrayT.Elem
37- elemOp := dec.decIgnoreOpFor(elemId, inProgress)
38+ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
39 op = func(i *decInstr, state *decoderState, value reflect.Value) {
40 state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len)
41 }
42@@ -904,15 +909,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp)
43 case wire.MapT != nil:
44 keyId := dec.wireType[wireId].MapT.Key
45 elemId := dec.wireType[wireId].MapT.Elem
46- keyOp := dec.decIgnoreOpFor(keyId, inProgress)
47- elemOp := dec.decIgnoreOpFor(elemId, inProgress)
48+ keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1)
49+ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
50 op = func(i *decInstr, state *decoderState, value reflect.Value) {
51 state.dec.ignoreMap(state, *keyOp, *elemOp)
52 }
53
54 case wire.SliceT != nil:
55 elemId := wire.SliceT.Elem
56- elemOp := dec.decIgnoreOpFor(elemId, inProgress)
57+ elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
58 op = func(i *decInstr, state *decoderState, value reflect.Value) {
59 state.dec.ignoreSlice(state, *elemOp)
60 }
61@@ -1073,7 +1078,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de
62 func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine {
63 engine := new(decEngine)
64 engine.instr = make([]decInstr, 1) // one item
65- op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp))
66+ op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp), 0)
67 ovfl := overflow(dec.typeString(remoteId))
68 engine.instr[0] = decInstr{*op, 0, nil, ovfl}
69 engine.numInstr = 1
70@@ -1118,7 +1123,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
71 localField, present := srt.FieldByName(wireField.Name)
72 // TODO(r): anonymous names
73 if !present || !isExported(wireField.Name) {
74- op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp))
75+ op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp), 0)
76 engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl}
77 continue
78 }
79diff --git a/src/encoding/gob/gobencdec_test.go b/src/encoding/gob/gobencdec_test.go
80index 6d2c8db..1b52ecc 100644
81--- a/src/encoding/gob/gobencdec_test.go
82+++ b/src/encoding/gob/gobencdec_test.go
83@@ -12,6 +12,7 @@ import (
84 "fmt"
85 "io"
86 "net"
87+ "reflect"
88 "strings"
89 "testing"
90 "time"
91@@ -796,3 +797,26 @@ func TestNetIP(t *testing.T) {
92 t.Errorf("decoded to %v, want 1.2.3.4", ip.String())
93 }
94 }
95+
96+func TestIngoreDepthLimit(t *testing.T) {
97+ // We don't test the actual depth limit because it requires building an
98+ // extremely large message, which takes quite a while.
99+ oldNestingDepth := maxIgnoreNestingDepth
100+ maxIgnoreNestingDepth = 100
101+ defer func() { maxIgnoreNestingDepth = oldNestingDepth }()
102+ b := new(bytes.Buffer)
103+ enc := NewEncoder(b)
104+ typ := reflect.TypeOf(int(0))
105+ nested := reflect.ArrayOf(1, typ)
106+ for i := 0; i < 100; i++ {
107+ nested = reflect.ArrayOf(1, nested)
108+ }
109+ badStruct := reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}}))
110+ enc.Encode(badStruct.Interface())
111+ dec := NewDecoder(b)
112+ var output struct{ Hello int }
113+ expectedErr := "invalid nesting depth"
114+ if err := dec.Decode(&output); err == nil || err.Error() != expectedErr {
115+ t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err)
116+ }
117+}
118--
1192.25.1
120
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 @@
1From 0fe3adec199e8cd2c101933f75d8cd617de70350 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Fri, 26 Aug 2022 12:48:13 +0530
4Subject: [PATCH] CVE-2022-32148
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/ed2f33e1a7e0d18f61bd56f7ee067331d612c27e]
7CVE: CVE-2022-32148
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/net/http/header.go | 6 ++++++
11 src/net/http/header_test.go | 5 +++++
12 2 files changed, 11 insertions(+)
13
14diff --git a/src/net/http/header.go b/src/net/http/header.go
15index b9b5391..221f613 100644
16--- a/src/net/http/header.go
17+++ b/src/net/http/header.go
18@@ -100,6 +100,12 @@ func (h Header) Clone() Header {
19 sv := make([]string, nv) // shared backing array for headers' values
20 h2 := make(Header, len(h))
21 for k, vv := range h {
22+ if vv == nil {
23+ // Preserve nil values. ReverseProxy distinguishes
24+ // between nil and zero-length header values.
25+ h2[k] = nil
26+ continue
27+ }
28 n := copy(sv, vv)
29 h2[k] = sv[:n:n]
30 sv = sv[n:]
31diff --git a/src/net/http/header_test.go b/src/net/http/header_test.go
32index 4789362..80c0035 100644
33--- a/src/net/http/header_test.go
34+++ b/src/net/http/header_test.go
35@@ -235,6 +235,11 @@ func TestCloneOrMakeHeader(t *testing.T) {
36 in: Header{"foo": {"bar"}},
37 want: Header{"foo": {"bar"}},
38 },
39+ {
40+ name: "nil value",
41+ in: Header{"foo": nil},
42+ want: Header{"foo": nil},
43+ },
44 }
45
46 for _, tt := range tests {
47--
482.25.1
49
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 @@
1From 027e7e1578d3d7614f7586eff3894b83d9709e14 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Mon, 29 Aug 2022 10:08:34 +0530
4Subject: [PATCH] CVE-2022-32189
5
6Upstream-Status: Backport [https://github.com/golang/go/commit/703c8ab7e5ba75c95553d4e249309297abad7102]
7CVE: CVE-2022-32189
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/math/big/floatmarsh.go | 7 +++++++
11 src/math/big/floatmarsh_test.go | 12 ++++++++++++
12 src/math/big/ratmarsh.go | 6 ++++++
13 src/math/big/ratmarsh_test.go | 12 ++++++++++++
14 4 files changed, 37 insertions(+)
15
16diff --git a/src/math/big/floatmarsh.go b/src/math/big/floatmarsh.go
17index d1c1dab..990e085 100644
18--- a/src/math/big/floatmarsh.go
19+++ b/src/math/big/floatmarsh.go
20@@ -8,6 +8,7 @@ package big
21
22 import (
23 "encoding/binary"
24+ "errors"
25 "fmt"
26 )
27
28@@ -67,6 +68,9 @@ func (z *Float) GobDecode(buf []byte) error {
29 *z = Float{}
30 return nil
31 }
32+ if len(buf) < 6 {
33+ return errors.New("Float.GobDecode: buffer too small")
34+ }
35
36 if buf[0] != floatGobVersion {
37 return fmt.Errorf("Float.GobDecode: encoding version %d not supported", buf[0])
38@@ -83,6 +87,9 @@ func (z *Float) GobDecode(buf []byte) error {
39 z.prec = binary.BigEndian.Uint32(buf[2:])
40
41 if z.form == finite {
42+ if len(buf) < 10 {
43+ return errors.New("Float.GobDecode: buffer too small for finite form float")
44+ }
45 z.exp = int32(binary.BigEndian.Uint32(buf[6:]))
46 z.mant = z.mant.setBytes(buf[10:])
47 }
48diff --git a/src/math/big/floatmarsh_test.go b/src/math/big/floatmarsh_test.go
49index c056d78..401f45a 100644
50--- a/src/math/big/floatmarsh_test.go
51+++ b/src/math/big/floatmarsh_test.go
52@@ -137,3 +137,15 @@ func TestFloatJSONEncoding(t *testing.T) {
53 }
54 }
55 }
56+
57+func TestFloatGobDecodeShortBuffer(t *testing.T) {
58+ for _, tc := range [][]byte{
59+ []byte{0x1, 0x0, 0x0, 0x0},
60+ []byte{0x1, 0xfa, 0x0, 0x0, 0x0, 0x0},
61+ } {
62+ err := NewFloat(0).GobDecode(tc)
63+ if err == nil {
64+ t.Error("expected GobDecode to return error for malformed input")
65+ }
66+ }
67+}
68diff --git a/src/math/big/ratmarsh.go b/src/math/big/ratmarsh.go
69index fbc7b60..56102e8 100644
70--- a/src/math/big/ratmarsh.go
71+++ b/src/math/big/ratmarsh.go
72@@ -45,12 +45,18 @@ func (z *Rat) GobDecode(buf []byte) error {
73 *z = Rat{}
74 return nil
75 }
76+ if len(buf) < 5 {
77+ return errors.New("Rat.GobDecode: buffer too small")
78+ }
79 b := buf[0]
80 if b>>1 != ratGobVersion {
81 return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
82 }
83 const j = 1 + 4
84 i := j + binary.BigEndian.Uint32(buf[j-4:j])
85+ if len(buf) < int(i) {
86+ return errors.New("Rat.GobDecode: buffer too small")
87+ }
88 z.a.neg = b&1 != 0
89 z.a.abs = z.a.abs.setBytes(buf[j:i])
90 z.b.abs = z.b.abs.setBytes(buf[i:])
91diff --git a/src/math/big/ratmarsh_test.go b/src/math/big/ratmarsh_test.go
92index 351d109..55a9878 100644
93--- a/src/math/big/ratmarsh_test.go
94+++ b/src/math/big/ratmarsh_test.go
95@@ -123,3 +123,15 @@ func TestRatXMLEncoding(t *testing.T) {
96 }
97 }
98 }
99+
100+func TestRatGobDecodeShortBuffer(t *testing.T) {
101+ for _, tc := range [][]byte{
102+ []byte{0x2},
103+ []byte{0x2, 0x0, 0x0, 0x0, 0xff},
104+ } {
105+ err := NewRat(1, 2).GobDecode(tc)
106+ if err == nil {
107+ t.Error("expected GobDecode to return error for malformed input")
108+ }
109+ }
110+}
111--
1122.25.1
113
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 @@
1From e9017c2416ad0ef642f5e0c2eab2dbf3cba4d997 Mon Sep 17 00:00:00 2001
2From: Russ Cox <rsc@golang.org>
3Date: Wed, 28 Sep 2022 11:18:51 -0400
4Subject: [PATCH] [release-branch.go1.18] regexp: limit size of parsed regexps
5
6Set a 128 MB limit on the amount of space used by []syntax.Inst
7in the compiled form corresponding to a given regexp.
8
9Also set a 128 MB limit on the rune storage in the *syntax.Regexp
10tree itself.
11
12Thanks to Adam Korczynski (ADA Logics) and OSS-Fuzz for reporting this issue.
13
14Fixes CVE-2022-41715.
15Updates #55949.
16Fixes #55950.
17
18Change-Id: Ia656baed81564436368cf950e1c5409752f28e1b
19Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1592136
20TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
21Reviewed-by: Damien Neil <dneil@google.com>
22Run-TryBot: Roland Shoemaker <bracewell@google.com>
23Reviewed-by: Julie Qiu <julieqiu@google.com>
24Reviewed-on: https://go-review.googlesource.com/c/go/+/438501
25Run-TryBot: Carlos Amedee <carlos@golang.org>
26Reviewed-by: Carlos Amedee <carlos@golang.org>
27Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
28TryBot-Result: Gopher Robot <gobot@golang.org>
29Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
30
31Upstream-Status: Backport [https://github.com/golang/go/commit/e9017c2416ad0ef642f5e0c2eab2dbf3cba4d997]
32CVE: CVE-2022-41715
33Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
34
35---
36 src/regexp/syntax/parse.go | 145 ++++++++++++++++++++++++++++++--
37 src/regexp/syntax/parse_test.go | 13 +--
38 2 files changed, 148 insertions(+), 10 deletions(-)
39
40diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go
41index 55bd20d..60491d5 100644
42--- a/src/regexp/syntax/parse.go
43+++ b/src/regexp/syntax/parse.go
44@@ -90,15 +90,49 @@ const (
45 // until we've allocated at least maxHeight Regexp structures.
46 const maxHeight = 1000
47
48+// maxSize is the maximum size of a compiled regexp in Insts.
49+// It too is somewhat arbitrarily chosen, but the idea is to be large enough
50+// to allow significant regexps while at the same time small enough that
51+// the compiled form will not take up too much memory.
52+// 128 MB is enough for a 3.3 million Inst structures, which roughly
53+// corresponds to a 3.3 MB regexp.
54+const (
55+ maxSize = 128 << 20 / instSize
56+ instSize = 5 * 8 // byte, 2 uint32, slice is 5 64-bit words
57+)
58+
59+// maxRunes is the maximum number of runes allowed in a regexp tree
60+// counting the runes in all the nodes.
61+// Ignoring character classes p.numRunes is always less than the length of the regexp.
62+// Character classes can make it much larger: each \pL adds 1292 runes.
63+// 128 MB is enough for 32M runes, which is over 26k \pL instances.
64+// Note that repetitions do not make copies of the rune slices,
65+// so \pL{1000} is only one rune slice, not 1000.
66+// We could keep a cache of character classes we've seen,
67+// so that all the \pL we see use the same rune list,
68+// but that doesn't remove the problem entirely:
69+// consider something like [\pL01234][\pL01235][\pL01236]...[\pL^&*()].
70+// And because the Rune slice is exposed directly in the Regexp,
71+// there is not an opportunity to change the representation to allow
72+// partial sharing between different character classes.
73+// So the limit is the best we can do.
74+const (
75+ maxRunes = 128 << 20 / runeSize
76+ runeSize = 4 // rune is int32
77+)
78+
79 type parser struct {
80 flags Flags // parse mode flags
81 stack []*Regexp // stack of parsed expressions
82 free *Regexp
83 numCap int // number of capturing groups seen
84 wholeRegexp string
85- tmpClass []rune // temporary char class work space
86- numRegexp int // number of regexps allocated
87- height map[*Regexp]int // regexp height for height limit check
88+ tmpClass []rune // temporary char class work space
89+ numRegexp int // number of regexps allocated
90+ numRunes int // number of runes in char classes
91+ repeats int64 // product of all repetitions seen
92+ height map[*Regexp]int // regexp height, for height limit check
93+ size map[*Regexp]int64 // regexp compiled size, for size limit check
94 }
95
96 func (p *parser) newRegexp(op Op) *Regexp {
97@@ -122,6 +156,104 @@ func (p *parser) reuse(re *Regexp) {
98 p.free = re
99 }
100
101+func (p *parser) checkLimits(re *Regexp) {
102+ if p.numRunes > maxRunes {
103+ panic(ErrInternalError)
104+ }
105+ p.checkSize(re)
106+ p.checkHeight(re)
107+}
108+
109+func (p *parser) checkSize(re *Regexp) {
110+ if p.size == nil {
111+ // We haven't started tracking size yet.
112+ // Do a relatively cheap check to see if we need to start.
113+ // Maintain the product of all the repeats we've seen
114+ // and don't track if the total number of regexp nodes
115+ // we've seen times the repeat product is in budget.
116+ if p.repeats == 0 {
117+ p.repeats = 1
118+ }
119+ if re.Op == OpRepeat {
120+ n := re.Max
121+ if n == -1 {
122+ n = re.Min
123+ }
124+ if n <= 0 {
125+ n = 1
126+ }
127+ if int64(n) > maxSize/p.repeats {
128+ p.repeats = maxSize
129+ } else {
130+ p.repeats *= int64(n)
131+ }
132+ }
133+ if int64(p.numRegexp) < maxSize/p.repeats {
134+ return
135+ }
136+
137+ // We need to start tracking size.
138+ // Make the map and belatedly populate it
139+ // with info about everything we've constructed so far.
140+ p.size = make(map[*Regexp]int64)
141+ for _, re := range p.stack {
142+ p.checkSize(re)
143+ }
144+ }
145+
146+ if p.calcSize(re, true) > maxSize {
147+ panic(ErrInternalError)
148+ }
149+}
150+
151+func (p *parser) calcSize(re *Regexp, force bool) int64 {
152+ if !force {
153+ if size, ok := p.size[re]; ok {
154+ return size
155+ }
156+ }
157+
158+ var size int64
159+ switch re.Op {
160+ case OpLiteral:
161+ size = int64(len(re.Rune))
162+ case OpCapture, OpStar:
163+ // star can be 1+ or 2+; assume 2 pessimistically
164+ size = 2 + p.calcSize(re.Sub[0], false)
165+ case OpPlus, OpQuest:
166+ size = 1 + p.calcSize(re.Sub[0], false)
167+ case OpConcat:
168+ for _, sub := range re.Sub {
169+ size += p.calcSize(sub, false)
170+ }
171+ case OpAlternate:
172+ for _, sub := range re.Sub {
173+ size += p.calcSize(sub, false)
174+ }
175+ if len(re.Sub) > 1 {
176+ size += int64(len(re.Sub)) - 1
177+ }
178+ case OpRepeat:
179+ sub := p.calcSize(re.Sub[0], false)
180+ if re.Max == -1 {
181+ if re.Min == 0 {
182+ size = 2 + sub // x*
183+ } else {
184+ size = 1 + int64(re.Min)*sub // xxx+
185+ }
186+ break
187+ }
188+ // x{2,5} = xx(x(x(x)?)?)?
189+ size = int64(re.Max)*sub + int64(re.Max-re.Min)
190+ }
191+
192+ if size < 1 {
193+ size = 1
194+ }
195+ p.size[re] = size
196+ return size
197+}
198+
199 func (p *parser) checkHeight(re *Regexp) {
200 if p.numRegexp < maxHeight {
201 return
202@@ -158,6 +290,7 @@ func (p *parser) calcHeight(re *Regexp, force bool) int {
203
204 // push pushes the regexp re onto the parse stack and returns the regexp.
205 func (p *parser) push(re *Regexp) *Regexp {
206+ p.numRunes += len(re.Rune)
207 if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] {
208 // Single rune.
209 if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) {
210@@ -189,7 +322,7 @@ func (p *parser) push(re *Regexp) *Regexp {
211 }
212
213 p.stack = append(p.stack, re)
214- p.checkHeight(re)
215+ p.checkLimits(re)
216 return re
217 }
218
219@@ -305,7 +438,7 @@ func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (
220 re.Sub = re.Sub0[:1]
221 re.Sub[0] = sub
222 p.stack[n-1] = re
223- p.checkHeight(re)
224+ p.checkLimits(re)
225
226 if op == OpRepeat && (min >= 2 || max >= 2) && !repeatIsValid(re, 1000) {
227 return "", &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
228@@ -509,6 +642,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp {
229
230 for j := start; j < i; j++ {
231 sub[j] = p.removeLeadingString(sub[j], len(str))
232+ p.checkLimits(sub[j])
233 }
234 suffix := p.collapse(sub[start:i], OpAlternate) // recurse
235
236@@ -566,6 +700,7 @@ func (p *parser) factor(sub []*Regexp) []*Regexp {
237 for j := start; j < i; j++ {
238 reuse := j != start // prefix came from sub[start]
239 sub[j] = p.removeLeadingRegexp(sub[j], reuse)
240+ p.checkLimits(sub[j])
241 }
242 suffix := p.collapse(sub[start:i], OpAlternate) // recurse
243
244diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go
245index 1ef6d8a..67e3c56 100644
246--- a/src/regexp/syntax/parse_test.go
247+++ b/src/regexp/syntax/parse_test.go
248@@ -484,12 +484,15 @@ var invalidRegexps = []string{
249 `(?P<>a)`,
250 `[a-Z]`,
251 `(?i)[a-Z]`,
252- `a{100000}`,
253- `a{100000,}`,
254- "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
255- strings.Repeat("(", 1000) + strings.Repeat(")", 1000),
256- strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000),
257 `\Q\E*`,
258+ `a{100000}`, // too much repetition
259+ `a{100000,}`, // too much repetition
260+ "((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})", // too much repetition
261+ strings.Repeat("(", 1000) + strings.Repeat(")", 1000), // too deep
262+ strings.Repeat("(?:", 1000) + strings.Repeat(")*", 1000), // too deep
263+ "(" + strings.Repeat("(xx?)", 1000) + "){1000}", // too long
264+ strings.Repeat("(xx?){1000}", 1000), // too long
265+ strings.Repeat(`\pL`, 27000), // too many runes
266 }
267
268 var onlyPerl = []string{
269--
2702.25.1
271
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 @@
1From 618120c165669c00a1606505defea6ca755cdc27 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Wed, 30 Nov 2022 16:46:33 -0500
4Subject: [PATCH] [release-branch.go1.19] net/http: update bundled
5 golang.org/x/net/http2
6
7Disable cmd/internal/moddeps test, since this update includes PRIVATE
8track fixes.
9
10For #56350.
11For #57009.
12Fixes CVE-2022-41717.
13
14Change-Id: I5c6ce546add81f361dcf0d5123fa4eaaf8f0a03b
15Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1663835
16Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
17Reviewed-by: Julie Qiu <julieqiu@google.com>
18Reviewed-on: https://go-review.googlesource.com/c/go/+/455363
19TryBot-Result: Gopher Robot <gobot@golang.org>
20Run-TryBot: Jenny Rakoczy <jenny@golang.org>
21Reviewed-by: Michael Pratt <mpratt@google.com>
22
23Upstream-Status: Backport [https://github.com/golang/go/commit/618120c165669c00a1606505defea6ca755cdc27]
24CVE-2022-41717
25Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
26---
27 src/net/http/h2_bundle.go | 18 +++++++++++-------
28 1 file changed, 11 insertions(+), 7 deletions(-)
29
30diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
31index 83f2a72..cc03a62 100644
32--- a/src/net/http/h2_bundle.go
33+++ b/src/net/http/h2_bundle.go
34@@ -4096,6 +4096,7 @@ type http2serverConn struct {
35 headerTableSize uint32
36 peerMaxHeaderListSize uint32 // zero means unknown (default)
37 canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
38+ canonHeaderKeysSize int // canonHeader keys size in bytes
39 writingFrame bool // started writing a frame (on serve goroutine or separate)
40 writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
41 needsFrameFlush bool // last frame write wasn't a flush
42@@ -4278,6 +4279,13 @@ func (sc *http2serverConn) condlogf(err error, format string, args ...interface{
43 }
44 }
45
46+// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size
47+// of the entries in the canonHeader cache.
48+// This should be larger than the size of unique, uncommon header keys likely to
49+// be sent by the peer, while not so high as to permit unreasonable memory usage
50+// if the peer sends an unbounded number of unique header keys.
51+const http2maxCachedCanonicalHeadersKeysSize = 2048
52+
53 func (sc *http2serverConn) canonicalHeader(v string) string {
54 sc.serveG.check()
55 http2buildCommonHeaderMapsOnce()
56@@ -4293,14 +4301,10 @@ func (sc *http2serverConn) canonicalHeader(v string) string {
57 sc.canonHeader = make(map[string]string)
58 }
59 cv = CanonicalHeaderKey(v)
60- // maxCachedCanonicalHeaders is an arbitrarily-chosen limit on the number of
61- // entries in the canonHeader cache. This should be larger than the number
62- // of unique, uncommon header keys likely to be sent by the peer, while not
63- // so high as to permit unreaasonable memory usage if the peer sends an unbounded
64- // number of unique header keys.
65- const maxCachedCanonicalHeaders = 32
66- if len(sc.canonHeader) < maxCachedCanonicalHeaders {
67+ size := 100 + len(v)*2 // 100 bytes of map overhead + key + value
68+ if sc.canonHeaderKeysSize+size <= http2maxCachedCanonicalHeadersKeysSize {
69 sc.canonHeader[v] = cv
70+ sc.canonHeaderKeysSize += size
71 }
72 return cv
73 }
74--
752.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 @@
1From 94e0c36694fb044e81381d112fef3692de7cdf52 Mon Sep 17 00:00:00 2001
2From: Yasuhiro Matsumoto <mattn.jp@gmail.com>
3Date: Fri, 22 Apr 2022 10:07:51 +0900
4Subject: [PATCH 1/2] path/filepath: do not remove prefix "." when following
5 path contains ":".
6
7Fixes #52476
8
9Change-Id: I9eb72ac7dbccd6322d060291f31831dc389eb9bb
10Reviewed-on: https://go-review.googlesource.com/c/go/+/401595
11Auto-Submit: Ian Lance Taylor <iant@google.com>
12Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
13Run-TryBot: Ian Lance Taylor <iant@google.com>
14Reviewed-by: Ian Lance Taylor <iant@google.com>
15Reviewed-by: Damien Neil <dneil@google.com>
16TryBot-Result: Gopher Robot <gobot@golang.org>
17
18Upstream-Status: Backport from https://github.com/golang/go/commit/9cd1818a7d019c02fa4898b3e45a323e35033290
19CVE: CVE-2022-41722
20Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
21---
22 src/path/filepath/path.go | 14 +++++++++++++-
23 1 file changed, 13 insertions(+), 1 deletion(-)
24
25diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go
26index 26f1833..92dc090 100644
27--- a/src/path/filepath/path.go
28+++ b/src/path/filepath/path.go
29@@ -116,9 +116,21 @@ func Clean(path string) string {
30 case os.IsPathSeparator(path[r]):
31 // empty path element
32 r++
33- case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
34+ case path[r] == '.' && r+1 == n:
35 // . element
36 r++
37+ case path[r] == '.' && os.IsPathSeparator(path[r+1]):
38+ // ./ element
39+ r++
40+
41+ for r < len(path) && os.IsPathSeparator(path[r]) {
42+ r++
43+ }
44+ if out.w == 0 && volumeNameLen(path[r:]) > 0 {
45+ // When joining prefix "." and an absolute path on Windows,
46+ // the prefix should not be removed.
47+ out.append('.')
48+ }
49 case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
50 // .. element: remove to last separator
51 r += 2
52--
532.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 @@
1From b8803cb711ae163b8e67897deb6cf8c49702227c Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Mon, 12 Dec 2022 16:43:37 -0800
4Subject: [PATCH 2/2] path/filepath: do not Clean("a/../c:/b") into c:\b on
5 Windows
6
7Do not permit Clean to convert a relative path into one starting
8with a drive reference. This change causes Clean to insert a .
9path element at the start of a path when the original path does not
10start with a volume name, and the first path element would contain
11a colon.
12
13This may introduce a spurious but harmless . path element under
14some circumstances. For example, Clean("a/../b:/../c") becomes `.\c`.
15
16This reverts CL 401595, since the change here supersedes the one
17in that CL.
18
19Thanks to RyotaK (https://twitter.com/ryotkak) for reporting this issue.
20
21Updates #57274
22Fixes #57276
23Fixes CVE-2022-41722
24
25Change-Id: I837446285a03aa74c79d7642720e01f354c2ca17
26Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1675249
27Reviewed-by: Roland Shoemaker <bracewell@google.com>
28Run-TryBot: Damien Neil <dneil@google.com>
29Reviewed-by: Julie Qiu <julieqiu@google.com>
30TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
31(cherry picked from commit 8ca37f4813ef2f64600c92b83f17c9f3ca6c03a5)
32Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1728944
33Run-TryBot: Roland Shoemaker <bracewell@google.com>
34Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
35Reviewed-by: Damien Neil <dneil@google.com>
36Reviewed-on: https://go-review.googlesource.com/c/go/+/468119
37Reviewed-by: Than McIntosh <thanm@google.com>
38Run-TryBot: Michael Pratt <mpratt@google.com>
39TryBot-Result: Gopher Robot <gobot@golang.org>
40Auto-Submit: Michael Pratt <mpratt@google.com>
41
42Upstream-Status: Backport from https://github.com/golang/go/commit/bdf07c2e168baf736e4c057279ca12a4d674f18c
43CVE: CVE-2022-41722
44Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
45---
46 src/path/filepath/path.go | 27 ++++++++++++++-------------
47 1 file changed, 14 insertions(+), 13 deletions(-)
48
49diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go
50index 92dc090..f0f095e 100644
51--- a/src/path/filepath/path.go
52+++ b/src/path/filepath/path.go
53@@ -14,6 +14,7 @@ package filepath
54 import (
55 "errors"
56 "os"
57+ "runtime"
58 "sort"
59 "strings"
60 )
61@@ -116,21 +117,9 @@ func Clean(path string) string {
62 case os.IsPathSeparator(path[r]):
63 // empty path element
64 r++
65- case path[r] == '.' && r+1 == n:
66+ case path[r] == '.' && (r+1 == n || os.IsPathSeparator(path[r+1])):
67 // . element
68 r++
69- case path[r] == '.' && os.IsPathSeparator(path[r+1]):
70- // ./ element
71- r++
72-
73- for r < len(path) && os.IsPathSeparator(path[r]) {
74- r++
75- }
76- if out.w == 0 && volumeNameLen(path[r:]) > 0 {
77- // When joining prefix "." and an absolute path on Windows,
78- // the prefix should not be removed.
79- out.append('.')
80- }
81 case path[r] == '.' && path[r+1] == '.' && (r+2 == n || os.IsPathSeparator(path[r+2])):
82 // .. element: remove to last separator
83 r += 2
84@@ -156,6 +145,18 @@ func Clean(path string) string {
85 if rooted && out.w != 1 || !rooted && out.w != 0 {
86 out.append(Separator)
87 }
88+ // If a ':' appears in the path element at the start of a Windows path,
89+ // insert a .\ at the beginning to avoid converting relative paths
90+ // like a/../c: into c:.
91+ if runtime.GOOS == "windows" && out.w == 0 && out.volLen == 0 && r != 0 {
92+ for i := r; i < n && !os.IsPathSeparator(path[i]); i++ {
93+ if path[i] == ':' {
94+ out.append('.')
95+ out.append(Separator)
96+ break
97+ }
98+ }
99+ }
100 // copy element
101 for ; r < n && !os.IsPathSeparator(path[r]); r++ {
102 out.append(path[r])
103--
1042.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 @@
1From 451766789f646617157c725e20c955d4a9a70d4e Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Mon, 6 Feb 2023 10:03:44 -0800
4Subject: [PATCH] net/http: update bundled golang.org/x/net/http2
5
6Disable cmd/internal/moddeps test, since this update includes PRIVATE
7track fixes.
8
9Fixes CVE-2022-41723
10Fixes #58355
11Updates #57855
12
13Change-Id: Ie870562a6f6e44e4e8f57db6a0dde1a41a2b090c
14Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1728939
15Reviewed-by: Damien Neil <dneil@google.com>
16Reviewed-by: Julie Qiu <julieqiu@google.com>
17Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
18Run-TryBot: Roland Shoemaker <bracewell@google.com>
19Reviewed-on: https://go-review.googlesource.com/c/go/+/468118
20TryBot-Result: Gopher Robot <gobot@golang.org>
21Run-TryBot: Michael Pratt <mpratt@google.com>
22Auto-Submit: Michael Pratt <mpratt@google.com>
23Reviewed-by: Than McIntosh <thanm@google.com>
24
25Upstream-Status: Backport [https://github.com/golang/go/commit/5c3e11bd0b5c0a86e5beffcd4339b86a902b21c3]
26CVE: CVE-2022-41723
27Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
28---
29 src/vendor/golang.org/x/net/http2/hpack/hpack.go | 79 +++++++++++++++---------
30 1 file changed, 49 insertions(+), 30 deletions(-)
31
32diff --git a/src/vendor/golang.org/x/net/http2/hpack/hpack.go b/src/vendor/golang.org/x/net/http2/hpack/hpack.go
33index 85f18a2..02e80e3 100644
34--- a/src/vendor/golang.org/x/net/http2/hpack/hpack.go
35+++ b/src/vendor/golang.org/x/net/http2/hpack/hpack.go
36@@ -359,6 +359,7 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
37
38 var hf HeaderField
39 wantStr := d.emitEnabled || it.indexed()
40+ var undecodedName undecodedString
41 if nameIdx > 0 {
42 ihf, ok := d.at(nameIdx)
43 if !ok {
44@@ -366,15 +367,27 @@ func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
45 }
46 hf.Name = ihf.Name
47 } else {
48- hf.Name, buf, err = d.readString(buf, wantStr)
49+ undecodedName, buf, err = d.readString(buf)
50 if err != nil {
51 return err
52 }
53 }
54- hf.Value, buf, err = d.readString(buf, wantStr)
55+ undecodedValue, buf, err := d.readString(buf)
56 if err != nil {
57 return err
58 }
59+ if wantStr {
60+ if nameIdx <= 0 {
61+ hf.Name, err = d.decodeString(undecodedName)
62+ if err != nil {
63+ return err
64+ }
65+ }
66+ hf.Value, err = d.decodeString(undecodedValue)
67+ if err != nil {
68+ return err
69+ }
70+ }
71 d.buf = buf
72 if it.indexed() {
73 d.dynTab.add(hf)
74@@ -459,46 +472,52 @@ func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
75 return 0, origP, errNeedMore
76 }
77
78-// readString decodes an hpack string from p.
79+// readString reads an hpack string from p.
80 //
81-// wantStr is whether s will be used. If false, decompression and
82-// []byte->string garbage are skipped if s will be ignored
83-// anyway. This does mean that huffman decoding errors for non-indexed
84-// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
85-// is returning an error anyway, and because they're not indexed, the error
86-// won't affect the decoding state.
87-func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
88+// It returns a reference to the encoded string data to permit deferring decode costs
89+// until after the caller verifies all data is present.
90+func (d *Decoder) readString(p []byte) (u undecodedString, remain []byte, err error) {
91 if len(p) == 0 {
92- return "", p, errNeedMore
93+ return u, p, errNeedMore
94 }
95 isHuff := p[0]&128 != 0
96 strLen, p, err := readVarInt(7, p)
97 if err != nil {
98- return "", p, err
99+ return u, p, err
100 }
101 if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
102- return "", nil, ErrStringLength
103+ // Returning an error here means Huffman decoding errors
104+ // for non-indexed strings past the maximum string length
105+ // are ignored, but the server is returning an error anyway
106+ // and because the string is not indexed the error will not
107+ // affect the decoding state.
108+ return u, nil, ErrStringLength
109 }
110 if uint64(len(p)) < strLen {
111- return "", p, errNeedMore
112- }
113- if !isHuff {
114- if wantStr {
115- s = string(p[:strLen])
116- }
117- return s, p[strLen:], nil
118+ return u, p, errNeedMore
119 }
120+ u.isHuff = isHuff
121+ u.b = p[:strLen]
122+ return u, p[strLen:], nil
123+}
124
125- if wantStr {
126- buf := bufPool.Get().(*bytes.Buffer)
127- buf.Reset() // don't trust others
128- defer bufPool.Put(buf)
129- if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
130- buf.Reset()
131- return "", nil, err
132- }
133+type undecodedString struct {
134+ isHuff bool
135+ b []byte
136+}
137+
138+func (d *Decoder) decodeString(u undecodedString) (string, error) {
139+ if !u.isHuff {
140+ return string(u.b), nil
141+ }
142+ buf := bufPool.Get().(*bytes.Buffer)
143+ buf.Reset() // don't trust others
144+ var s string
145+ err := huffmanDecode(buf, d.maxStrLen, u.b)
146+ if err == nil {
147 s = buf.String()
148- buf.Reset() // be nice to GC
149 }
150- return s, p[strLen:], nil
151+ buf.Reset() // be nice to GC
152+ bufPool.Put(buf)
153+ return s, err
154 }
155--
1562.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 @@
1From 874b3132a84cf76da6a48978826c04c380a37a50 Mon Sep 17 00:00:00 2001
2From: avivklas <avivklas@gmail.com>
3Date: Fri, 7 Aug 2020 21:50:12 +0300
4Subject: [PATCH] mime/multipart: return overflow errors in Reader.ReadForm
5
6Updates Reader.ReadForm to check for overflow errors that may
7result from a leeway addition of 10MiB to the input argument
8maxMemory.
9
10Fixes #40430
11
12Change-Id: I510b8966c95c51d04695ba9d08fcfe005fd11a5d
13Reviewed-on: https://go-review.googlesource.com/c/go/+/247477
14Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
15Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
16Trust: Emmanuel Odeke <emm.odeke@gmail.com>
17TryBot-Result: Go Bot <gobot@golang.org>
18Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
19
20Upstream-Status: Backport [https://github.com/golang/go/commit/874b3132a84cf76da6a48978826c04c380a37a50]
21CVE: CVE-2022-41725 #Dependency Patch1
22Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
23---
24 src/mime/multipart/formdata.go | 4 ++++
25 src/mime/multipart/formdata_test.go | 18 ++++++++++++++++++
26 2 files changed, 22 insertions(+)
27
28diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
29index 832d0ad693666..4eb31012941ac 100644
30--- a/src/mime/multipart/formdata.go
31+++ b/src/mime/multipart/formdata.go
32@@ -7,6 +7,7 @@ package multipart
33 import (
34 "bytes"
35 "errors"
36+ "fmt"
37 "io"
38 "io/ioutil"
39 "net/textproto"
40@@ -41,6 +42,9 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
41
42 // Reserve an additional 10 MB for non-file parts.
43 maxValueBytes := maxMemory + int64(10<<20)
44+ if maxValueBytes <= 0 {
45+ return nil, fmt.Errorf("multipart: integer overflow from maxMemory(%d) + 10MiB for non-file parts", maxMemory)
46+ }
47 for {
48 p, err := r.NextPart()
49 if err == io.EOF {
50diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
51index 7d756c8c244a0..7112e0d3727fe 100644
52--- a/src/mime/multipart/formdata_test.go
53+++ b/src/mime/multipart/formdata_test.go
54@@ -7,6 +7,7 @@ package multipart
55 import (
56 "bytes"
57 "io"
58+ "math"
59 "os"
60 "strings"
61 "testing"
62@@ -52,6 +53,23 @@ func TestReadFormWithNamelessFile(t *testing.T) {
63 }
64 }
65
66+// Issue 40430: Ensure that we report integer overflows in additions of maxMemory,
67+// instead of silently and subtly failing without indication.
68+func TestReadFormMaxMemoryOverflow(t *testing.T) {
69+ b := strings.NewReader(strings.ReplaceAll(messageWithTextContentType, "\n", "\r\n"))
70+ r := NewReader(b, boundary)
71+ f, err := r.ReadForm(math.MaxInt64)
72+ if err == nil {
73+ t.Fatal("Unexpected a non-nil error")
74+ }
75+ if f != nil {
76+ t.Fatalf("Unexpected returned a non-nil form: %v\n", f)
77+ }
78+ if g, w := err.Error(), "integer overflow from maxMemory"; !strings.Contains(g, w) {
79+ t.Errorf(`Error mismatch\n%q\ndid not contain\n%q`, g, w)
80+ }
81+}
82+
83 func TestReadFormWithTextContentType(t *testing.T) {
84 // From https://github.com/golang/go/issues/24041
85 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 @@
1From 4e5a313524da62600eb59dbf98624cfe946456f8 Mon Sep 17 00:00:00 2001
2From: Emmanuel T Odeke <emmanuel@orijtech.com>
3Date: Tue, 20 Oct 2020 04:11:12 -0700
4Subject: [PATCH] net/http: test that ParseMultipartForm catches overflows
5
6Tests that if the combination of:
7* HTTP multipart file payload size
8* ParseMultipartForm's maxMemory parameter
9* the internal leeway buffer size of 10MiB
10
11overflows, then we'll report an overflow instead of silently
12passing.
13
14Reapplies and fixes CL 254977, which was reverted in CL 263658.
15
16The prior test lacked a res.Body.Close(), so fixed that and
17added a leaked Transport check to verify correctness.
18
19Updates 40430.
20
21Change-Id: I3c0f7ef43d621f6eb00f07755f04f9f36c51f98f
22Reviewed-on: https://go-review.googlesource.com/c/go/+/263817
23Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
24TryBot-Result: Go Bot <gobot@golang.org>
25Reviewed-by: Bryan C. Mills <bcmills@google.com>
26Trust: Damien Neil <dneil@google.com>
27
28Upstream-Status: Backport [https://github.com/golang/go/commit/4e5a313524da62600eb59dbf98624cfe946456f8]
29CVE: CVE-2022-41725 #Dependency Patch2
30Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
31---
32 src/net/http/request_test.go | 45 ++++++++++++++++++++++++++++++++++++
33 1 file changed, 45 insertions(+)
34
35diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
36index b4ef472e71229..19526b9ad791a 100644
37--- a/src/net/http/request_test.go
38+++ b/src/net/http/request_test.go
39@@ -13,6 +13,7 @@ import (
40 "fmt"
41 "io"
42 "io/ioutil"
43+ "math"
44 "mime/multipart"
45 . "net/http"
46 "net/http/httptest"
47@@ -245,6 +246,50 @@ func TestParseMultipartForm(t *testing.T) {
48 }
49 }
50
51+// Issue #40430: Test that if maxMemory for ParseMultipartForm when combined with
52+// the payload size and the internal leeway buffer size of 10MiB overflows, that we
53+// correctly return an error.
54+func TestMaxInt64ForMultipartFormMaxMemoryOverflow(t *testing.T) {
55+ defer afterTest(t)
56+
57+ payloadSize := 1 << 10
58+ cst := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
59+ // The combination of:
60+ // MaxInt64 + payloadSize + (internal spare of 10MiB)
61+ // triggers the overflow. See issue https://golang.org/issue/40430/
62+ if err := req.ParseMultipartForm(math.MaxInt64); err != nil {
63+ Error(rw, err.Error(), StatusBadRequest)
64+ return
65+ }
66+ }))
67+ defer cst.Close()
68+ fBuf := new(bytes.Buffer)
69+ mw := multipart.NewWriter(fBuf)
70+ mf, err := mw.CreateFormFile("file", "myfile.txt")
71+ if err != nil {
72+ t.Fatal(err)
73+ }
74+ if _, err := mf.Write(bytes.Repeat([]byte("abc"), payloadSize)); err != nil {
75+ t.Fatal(err)
76+ }
77+ if err := mw.Close(); err != nil {
78+ t.Fatal(err)
79+ }
80+ req, err := NewRequest("POST", cst.URL, fBuf)
81+ if err != nil {
82+ t.Fatal(err)
83+ }
84+ req.Header.Set("Content-Type", mw.FormDataContentType())
85+ res, err := cst.Client().Do(req)
86+ if err != nil {
87+ t.Fatal(err)
88+ }
89+ res.Body.Close()
90+ if g, w := res.StatusCode, StatusBadRequest; g != w {
91+ t.Fatalf("Status code mismatch: got %d, want %d", g, w)
92+ }
93+}
94+
95 func TestRedirect_h1(t *testing.T) { testRedirect(t, h1Mode) }
96 func TestRedirect_h2(t *testing.T) { testRedirect(t, h2Mode) }
97 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 @@
1From 5246fa5e75b129a7dbd9722aa4de0cbaf7ceae43 Mon Sep 17 00:00:00 2001
2From: Russ Cox <rsc@golang.org>
3Date: Thu, 3 Dec 2020 09:45:07 -0500
4Subject: [PATCH] mime/multipart: handle ReadForm(math.MaxInt64) better
5
6Returning an error about integer overflow is needlessly pedantic.
7The meaning of ReadForm(MaxInt64) is easily understood
8(accept a lot of data) and can be implemented.
9
10Fixes #40430.
11
12Change-Id: I8a522033dd9a2f9ad31dd2ad82cf08d553736ab9
13Reviewed-on: https://go-review.googlesource.com/c/go/+/275112
14Trust: Russ Cox <rsc@golang.org>
15Run-TryBot: Russ Cox <rsc@golang.org>
16TryBot-Result: Go Bot <gobot@golang.org>
17Reviewed-by: Ian Lance Taylor <iant@golang.org>
18
19Upstream-Status: Backport [https://github.com/golang/go/commit/5246fa5e75b129a7dbd9722aa4de0cbaf7ceae43]
20CVE: CVE-2022-41725 #Dependency Patch3
21Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
22---
23 src/mime/multipart/formdata.go | 8 ++++++--
24 src/mime/multipart/formdata_test.go | 14 +++++---------
25 src/net/http/request_test.go | 2 +-
26 3 files changed, 12 insertions(+), 12 deletions(-)
27
28diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
29index 4eb31012941ac..9c42ea8c023b5 100644
30--- a/src/mime/multipart/formdata.go
31+++ b/src/mime/multipart/formdata.go
32@@ -7,9 +7,9 @@ package multipart
33 import (
34 "bytes"
35 "errors"
36- "fmt"
37 "io"
38 "io/ioutil"
39+ "math"
40 "net/textproto"
41 "os"
42 )
43@@ -43,7 +43,11 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
44 // Reserve an additional 10 MB for non-file parts.
45 maxValueBytes := maxMemory + int64(10<<20)
46 if maxValueBytes <= 0 {
47- return nil, fmt.Errorf("multipart: integer overflow from maxMemory(%d) + 10MiB for non-file parts", maxMemory)
48+ if maxMemory < 0 {
49+ maxValueBytes = 0
50+ } else {
51+ maxValueBytes = math.MaxInt64
52+ }
53 }
54 for {
55 p, err := r.NextPart()
56diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
57index 7112e0d3727fe..e3a3a3eae8e15 100644
58--- a/src/mime/multipart/formdata_test.go
59+++ b/src/mime/multipart/formdata_test.go
60@@ -53,20 +53,16 @@ func TestReadFormWithNamelessFile(t *testing.T) {
61 }
62 }
63
64-// Issue 40430: Ensure that we report integer overflows in additions of maxMemory,
65-// instead of silently and subtly failing without indication.
66+// Issue 40430: Handle ReadForm(math.MaxInt64)
67 func TestReadFormMaxMemoryOverflow(t *testing.T) {
68 b := strings.NewReader(strings.ReplaceAll(messageWithTextContentType, "\n", "\r\n"))
69 r := NewReader(b, boundary)
70 f, err := r.ReadForm(math.MaxInt64)
71- if err == nil {
72- t.Fatal("Unexpected a non-nil error")
73- }
74- if f != nil {
75- t.Fatalf("Unexpected returned a non-nil form: %v\n", f)
76+ if err != nil {
77+ t.Fatalf("ReadForm(MaxInt64): %v", err)
78 }
79- if g, w := err.Error(), "integer overflow from maxMemory"; !strings.Contains(g, w) {
80- t.Errorf(`Error mismatch\n%q\ndid not contain\n%q`, g, w)
81+ if f == nil {
82+ t.Fatal("ReadForm(MaxInt64): missing form")
83 }
84 }
85
86diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
87index 19526b9ad791a..689498e19d5dd 100644
88--- a/src/net/http/request_test.go
89+++ b/src/net/http/request_test.go
90@@ -285,7 +285,7 @@ func TestMaxInt64ForMultipartFormMaxMemoryOverflow(t *testing.T) {
91 t.Fatal(err)
92 }
93 res.Body.Close()
94- if g, w := res.StatusCode, StatusBadRequest; g != w {
95+ if g, w := res.StatusCode, StatusOK; g != w {
96 t.Fatalf("Status code mismatch: got %d, want %d", g, w)
97 }
98 }
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 @@
1From 5c55ac9bf1e5f779220294c843526536605f42ab Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Wed, 25 Jan 2023 09:27:01 -0800
4Subject: [PATCH] [release-branch.go1.19] mime/multipart: limit memory/inode consumption of ReadForm
5
6Reader.ReadForm is documented as storing "up to maxMemory bytes + 10MB"
7in memory. Parsed forms can consume substantially more memory than
8this limit, since ReadForm does not account for map entry overhead
9and MIME headers.
10
11In addition, while the amount of disk memory consumed by ReadForm can
12be constrained by limiting the size of the parsed input, ReadForm will
13create one temporary file per form part stored on disk, potentially
14consuming a large number of inodes.
15
16Update ReadForm's memory accounting to include part names,
17MIME headers, and map entry overhead.
18
19Update ReadForm to store all on-disk file parts in a single
20temporary file.
21
22Files returned by FileHeader.Open are documented as having a concrete
23type of *os.File when a file is stored on disk. The change to use a
24single temporary file for all parts means that this is no longer the
25case when a form contains more than a single file part stored on disk.
26
27The previous behavior of storing each file part in a separate disk
28file may be reenabled with GODEBUG=multipartfiles=distinct.
29
30Update Reader.NextPart and Reader.NextRawPart to set a 10MiB cap
31on the size of MIME headers.
32
33Thanks to Jakob Ackermann (@das7pad) for reporting this issue.
34
35Updates #58006
36Fixes #58362
37Fixes CVE-2022-41725
38
39Change-Id: Ibd780a6c4c83ac8bcfd3cbe344f042e9940f2eab
40Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1714276
41Reviewed-by: Julie Qiu <julieqiu@google.com>
42TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
43Reviewed-by: Roland Shoemaker <bracewell@google.com>
44Run-TryBot: Damien Neil <dneil@google.com>
45(cherry picked from commit ed4664330edcd91b24914c9371c377c132dbce8c)
46Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1728949
47Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
48Run-TryBot: Roland Shoemaker <bracewell@google.com>
49Reviewed-by: Damien Neil <dneil@google.com>
50Reviewed-on: https://go-review.googlesource.com/c/go/+/468116
51TryBot-Result: Gopher Robot <gobot@golang.org>
52Reviewed-by: Than McIntosh <thanm@google.com>
53Run-TryBot: Michael Pratt <mpratt@google.com>
54Auto-Submit: Michael Pratt <mpratt@google.com>
55
56Upstream-Status: Backport [https://github.com/golang/go/commit/5c55ac9bf1e5f779220294c843526536605f42ab]
57CVE: CVE-2022-41725
58Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
59---
60 src/mime/multipart/formdata.go | 132 ++++++++++++++++++++-----
61 src/mime/multipart/formdata_test.go | 140 ++++++++++++++++++++++++++-
62 src/mime/multipart/multipart.go | 25 +++--
63 src/mime/multipart/readmimeheader.go | 14 +++
64 src/net/http/request_test.go | 2 +-
65 src/net/textproto/reader.go | 27 ++++++
66 6 files changed, 303 insertions(+), 37 deletions(-)
67 create mode 100644 src/mime/multipart/readmimeheader.go
68
69diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
70index 9c42ea8..1eeb340 100644
71--- a/src/mime/multipart/formdata.go
72+++ b/src/mime/multipart/formdata.go
73@@ -7,6 +7,7 @@ package multipart
74 import (
75 "bytes"
76 "errors"
77+ "internal/godebug"
78 "io"
79 "io/ioutil"
80 "math"
81@@ -34,23 +35,58 @@ func (r *Reader) ReadForm(maxMemory int64) (*Form, error) {
82
83 func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
84 form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
85+ var (
86+ file *os.File
87+ fileOff int64
88+ )
89+ numDiskFiles := 0
90+ multipartFiles := godebug.Get("multipartfiles")
91+ combineFiles := multipartFiles != "distinct"
92 defer func() {
93+ if file != nil {
94+ if cerr := file.Close(); err == nil {
95+ err = cerr
96+ }
97+ }
98+ if combineFiles && numDiskFiles > 1 {
99+ for _, fhs := range form.File {
100+ for _, fh := range fhs {
101+ fh.tmpshared = true
102+ }
103+ }
104+ }
105 if err != nil {
106 form.RemoveAll()
107+ if file != nil {
108+ os.Remove(file.Name())
109+ }
110 }
111 }()
112
113- // Reserve an additional 10 MB for non-file parts.
114- maxValueBytes := maxMemory + int64(10<<20)
115- if maxValueBytes <= 0 {
116+ // maxFileMemoryBytes is the maximum bytes of file data we will store in memory.
117+ // Data past this limit is written to disk.
118+ // This limit strictly applies to content, not metadata (filenames, MIME headers, etc.),
119+ // since metadata is always stored in memory, not disk.
120+ //
121+ // maxMemoryBytes is the maximum bytes we will store in memory, including file content,
122+ // non-file part values, metdata, and map entry overhead.
123+ //
124+ // We reserve an additional 10 MB in maxMemoryBytes for non-file data.
125+ //
126+ // The relationship between these parameters, as well as the overly-large and
127+ // unconfigurable 10 MB added on to maxMemory, is unfortunate but difficult to change
128+ // within the constraints of the API as documented.
129+ maxFileMemoryBytes := maxMemory
130+ maxMemoryBytes := maxMemory + int64(10<<20)
131+ if maxMemoryBytes <= 0 {
132 if maxMemory < 0 {
133- maxValueBytes = 0
134+ maxMemoryBytes = 0
135 } else {
136- maxValueBytes = math.MaxInt64
137+ maxMemoryBytes = math.MaxInt64
138 }
139 }
140 for {
141- p, err := r.NextPart()
142+ p, err := r.nextPart(false, maxMemoryBytes)
143 if err == io.EOF {
144 break
145 }
146@@ -64,16 +100,27 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
147 }
148 filename := p.FileName()
149
150+ // Multiple values for the same key (one map entry, longer slice) are cheaper
151+ // than the same number of values for different keys (many map entries), but
152+ // using a consistent per-value cost for overhead is simpler.
153+ maxMemoryBytes -= int64(len(name))
154+ maxMemoryBytes -= 100 // map overhead
155+ if maxMemoryBytes < 0 {
156+ // We can't actually take this path, since nextPart would already have
157+ // rejected the MIME headers for being too large. Check anyway.
158+ return nil, ErrMessageTooLarge
159+ }
160+
161 var b bytes.Buffer
162
163 if filename == "" {
164 // value, store as string in memory
165- n, err := io.CopyN(&b, p, maxValueBytes+1)
166+ n, err := io.CopyN(&b, p, maxMemoryBytes+1)
167 if err != nil && err != io.EOF {
168 return nil, err
169 }
170- maxValueBytes -= n
171- if maxValueBytes < 0 {
172+ maxMemoryBytes -= n
173+ if maxMemoryBytes < 0 {
174 return nil, ErrMessageTooLarge
175 }
176 form.Value[name] = append(form.Value[name], b.String())
177@@ -81,35 +128,45 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
178 }
179
180 // file, store in memory or on disk
181+ maxMemoryBytes -= mimeHeaderSize(p.Header)
182+ if maxMemoryBytes < 0 {
183+ return nil, ErrMessageTooLarge
184+ }
185 fh := &FileHeader{
186 Filename: filename,
187 Header: p.Header,
188 }
189- n, err := io.CopyN(&b, p, maxMemory+1)
190+ n, err := io.CopyN(&b, p, maxFileMemoryBytes+1)
191 if err != nil && err != io.EOF {
192 return nil, err
193 }
194- if n > maxMemory {
195- // too big, write to disk and flush buffer
196- file, err := ioutil.TempFile("", "multipart-")
197- if err != nil {
198- return nil, err
199+ if n > maxFileMemoryBytes {
200+ if file == nil {
201+ file, err = ioutil.TempFile(r.tempDir, "multipart-")
202+ if err != nil {
203+ return nil, err
204+ }
205 }
206+ numDiskFiles++
207 size, err := io.Copy(file, io.MultiReader(&b, p))
208- if cerr := file.Close(); err == nil {
209- err = cerr
210- }
211 if err != nil {
212- os.Remove(file.Name())
213 return nil, err
214 }
215 fh.tmpfile = file.Name()
216 fh.Size = size
217+ fh.tmpoff = fileOff
218+ fileOff += size
219+ if !combineFiles {
220+ if err := file.Close(); err != nil {
221+ return nil, err
222+ }
223+ file = nil
224+ }
225 } else {
226 fh.content = b.Bytes()
227 fh.Size = int64(len(fh.content))
228- maxMemory -= n
229- maxValueBytes -= n
230+ maxFileMemoryBytes -= n
231+ maxMemoryBytes -= n
232 }
233 form.File[name] = append(form.File[name], fh)
234 }
235@@ -117,6 +174,17 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
236 return form, nil
237 }
238
239+func mimeHeaderSize(h textproto.MIMEHeader) (size int64) {
240+ for k, vs := range h {
241+ size += int64(len(k))
242+ size += 100 // map entry overhead
243+ for _, v := range vs {
244+ size += int64(len(v))
245+ }
246+ }
247+ return size
248+}
249+
250 // Form is a parsed multipart form.
251 // Its File parts are stored either in memory or on disk,
252 // and are accessible via the *FileHeader's Open method.
253@@ -134,7 +202,7 @@ func (f *Form) RemoveAll() error {
254 for _, fh := range fhs {
255 if fh.tmpfile != "" {
256 e := os.Remove(fh.tmpfile)
257- if e != nil && err == nil {
258+ if e != nil && !errors.Is(e, os.ErrNotExist) && err == nil {
259 err = e
260 }
261 }
262@@ -149,15 +217,25 @@ type FileHeader struct {
263 Header textproto.MIMEHeader
264 Size int64
265
266- content []byte
267- tmpfile string
268+ content []byte
269+ tmpfile string
270+ tmpoff int64
271+ tmpshared bool
272 }
273
274 // Open opens and returns the FileHeader's associated File.
275 func (fh *FileHeader) Open() (File, error) {
276 if b := fh.content; b != nil {
277 r := io.NewSectionReader(bytes.NewReader(b), 0, int64(len(b)))
278- return sectionReadCloser{r}, nil
279+ return sectionReadCloser{r, nil}, nil
280+ }
281+ if fh.tmpshared {
282+ f, err := os.Open(fh.tmpfile)
283+ if err != nil {
284+ return nil, err
285+ }
286+ r := io.NewSectionReader(f, fh.tmpoff, fh.Size)
287+ return sectionReadCloser{r, f}, nil
288 }
289 return os.Open(fh.tmpfile)
290 }
291@@ -176,8 +254,12 @@ type File interface {
292
293 type sectionReadCloser struct {
294 *io.SectionReader
295+ io.Closer
296 }
297
298 func (rc sectionReadCloser) Close() error {
299+ if rc.Closer != nil {
300+ return rc.Closer.Close()
301+ }
302 return nil
303 }
304diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
305index e3a3a3e..5cded71 100644
306--- a/src/mime/multipart/formdata_test.go
307+++ b/src/mime/multipart/formdata_test.go
308@@ -6,8 +6,10 @@ package multipart
309
310 import (
311 "bytes"
312+ "fmt"
313 "io"
314 "math"
315+ "net/textproto"
316 "os"
317 "strings"
318 "testing"
319@@ -208,8 +210,8 @@ Content-Disposition: form-data; name="largetext"
320 maxMemory int64
321 err error
322 }{
323- {"smaller", 50, nil},
324- {"exact-fit", 25, nil},
325+ {"smaller", 50 + int64(len("largetext")) + 100, nil},
326+ {"exact-fit", 25 + int64(len("largetext")) + 100, nil},
327 {"too-large", 0, ErrMessageTooLarge},
328 }
329 for _, tc := range testCases {
330@@ -224,7 +226,7 @@ Content-Disposition: form-data; name="largetext"
331 defer f.RemoveAll()
332 }
333 if tc.err != err {
334- t.Fatalf("ReadForm error - got: %v; expected: %v", tc.err, err)
335+ t.Fatalf("ReadForm error - got: %v; expected: %v", err, tc.err)
336 }
337 if err == nil {
338 if g := f.Value["largetext"][0]; g != largeTextValue {
339@@ -234,3 +236,135 @@ Content-Disposition: form-data; name="largetext"
340 })
341 }
342 }
343+
344+// TestReadForm_MetadataTooLarge verifies that we account for the size of field names,
345+// MIME headers, and map entry overhead while limiting the memory consumption of parsed forms.
346+func TestReadForm_MetadataTooLarge(t *testing.T) {
347+ for _, test := range []struct {
348+ name string
349+ f func(*Writer)
350+ }{{
351+ name: "large name",
352+ f: func(fw *Writer) {
353+ name := strings.Repeat("a", 10<<20)
354+ w, _ := fw.CreateFormField(name)
355+ w.Write([]byte("value"))
356+ },
357+ }, {
358+ name: "large MIME header",
359+ f: func(fw *Writer) {
360+ h := make(textproto.MIMEHeader)
361+ h.Set("Content-Disposition", `form-data; name="a"`)
362+ h.Set("X-Foo", strings.Repeat("a", 10<<20))
363+ w, _ := fw.CreatePart(h)
364+ w.Write([]byte("value"))
365+ },
366+ }, {
367+ name: "many parts",
368+ f: func(fw *Writer) {
369+ for i := 0; i < 110000; i++ {
370+ w, _ := fw.CreateFormField("f")
371+ w.Write([]byte("v"))
372+ }
373+ },
374+ }} {
375+ t.Run(test.name, func(t *testing.T) {
376+ var buf bytes.Buffer
377+ fw := NewWriter(&buf)
378+ test.f(fw)
379+ if err := fw.Close(); err != nil {
380+ t.Fatal(err)
381+ }
382+ fr := NewReader(&buf, fw.Boundary())
383+ _, err := fr.ReadForm(0)
384+ if err != ErrMessageTooLarge {
385+ t.Errorf("fr.ReadForm() = %v, want ErrMessageTooLarge", err)
386+ }
387+ })
388+ }
389+}
390+
391+// TestReadForm_ManyFiles_Combined tests that a multipart form containing many files only
392+// results in a single on-disk file.
393+func TestReadForm_ManyFiles_Combined(t *testing.T) {
394+ const distinct = false
395+ testReadFormManyFiles(t, distinct)
396+}
397+
398+// TestReadForm_ManyFiles_Distinct tests that setting GODEBUG=multipartfiles=distinct
399+// results in every file in a multipart form being placed in a distinct on-disk file.
400+func TestReadForm_ManyFiles_Distinct(t *testing.T) {
401+ t.Setenv("GODEBUG", "multipartfiles=distinct")
402+ const distinct = true
403+ testReadFormManyFiles(t, distinct)
404+}
405+
406+func testReadFormManyFiles(t *testing.T, distinct bool) {
407+ var buf bytes.Buffer
408+ fw := NewWriter(&buf)
409+ const numFiles = 10
410+ for i := 0; i < numFiles; i++ {
411+ name := fmt.Sprint(i)
412+ w, err := fw.CreateFormFile(name, name)
413+ if err != nil {
414+ t.Fatal(err)
415+ }
416+ w.Write([]byte(name))
417+ }
418+ if err := fw.Close(); err != nil {
419+ t.Fatal(err)
420+ }
421+ fr := NewReader(&buf, fw.Boundary())
422+ fr.tempDir = t.TempDir()
423+ form, err := fr.ReadForm(0)
424+ if err != nil {
425+ t.Fatal(err)
426+ }
427+ for i := 0; i < numFiles; i++ {
428+ name := fmt.Sprint(i)
429+ if got := len(form.File[name]); got != 1 {
430+ t.Fatalf("form.File[%q] has %v entries, want 1", name, got)
431+ }
432+ fh := form.File[name][0]
433+ file, err := fh.Open()
434+ if err != nil {
435+ t.Fatalf("form.File[%q].Open() = %v", name, err)
436+ }
437+ if distinct {
438+ if _, ok := file.(*os.File); !ok {
439+ t.Fatalf("form.File[%q].Open: %T, want *os.File", name, file)
440+ }
441+ }
442+ got, err := io.ReadAll(file)
443+ file.Close()
444+ if string(got) != name || err != nil {
445+ t.Fatalf("read form.File[%q]: %q, %v; want %q, nil", name, string(got), err, name)
446+ }
447+ }
448+ dir, err := os.Open(fr.tempDir)
449+ if err != nil {
450+ t.Fatal(err)
451+ }
452+ defer dir.Close()
453+ names, err := dir.Readdirnames(0)
454+ if err != nil {
455+ t.Fatal(err)
456+ }
457+ wantNames := 1
458+ if distinct {
459+ wantNames = numFiles
460+ }
461+ if len(names) != wantNames {
462+ t.Fatalf("temp dir contains %v files; want 1", len(names))
463+ }
464+ if err := form.RemoveAll(); err != nil {
465+ t.Fatalf("form.RemoveAll() = %v", err)
466+ }
467+ names, err = dir.Readdirnames(0)
468+ if err != nil {
469+ t.Fatal(err)
470+ }
471+ if len(names) != 0 {
472+ t.Fatalf("temp dir contains %v files; want 0", len(names))
473+ }
474+}
475diff --git a/src/mime/multipart/multipart.go b/src/mime/multipart/multipart.go
476index 1750300..958cef8 100644
477--- a/src/mime/multipart/multipart.go
478+++ b/src/mime/multipart/multipart.go
479@@ -121,12 +121,12 @@ func (r *stickyErrorReader) Read(p []byte) (n int, _ error) {
480 return n, r.err
481 }
482
483-func newPart(mr *Reader, rawPart bool) (*Part, error) {
484+func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
485 bp := &Part{
486 Header: make(map[string][]string),
487 mr: mr,
488 }
489- if err := bp.populateHeaders(); err != nil {
490+ if err := bp.populateHeaders(maxMIMEHeaderSize); err != nil {
491 return nil, err
492 }
493 bp.r = partReader{bp}
494@@ -142,12 +142,16 @@ func newPart(mr *Reader, rawPart bool) (*Part, error) {
495 return bp, nil
496 }
497
498-func (bp *Part) populateHeaders() error {
499+func (bp *Part) populateHeaders(maxMIMEHeaderSize int64) error {
500 r := textproto.NewReader(bp.mr.bufReader)
501- header, err := r.ReadMIMEHeader()
502+ header, err := readMIMEHeader(r, maxMIMEHeaderSize)
503 if err == nil {
504 bp.Header = header
505 }
506+ // TODO: Add a distinguishable error to net/textproto.
507+ if err != nil && err.Error() == "message too large" {
508+ err = ErrMessageTooLarge
509+ }
510 return err
511 }
512
513@@ -287,6 +291,7 @@ func (p *Part) Close() error {
514 // isn't supported.
515 type Reader struct {
516 bufReader *bufio.Reader
517+ tempDir string // used in tests
518
519 currentPart *Part
520 partsRead int
521@@ -297,6 +302,10 @@ type Reader struct {
522 dashBoundary []byte // "--boundary"
523 }
524
525+// maxMIMEHeaderSize is the maximum size of a MIME header we will parse,
526+// including header keys, values, and map overhead.
527+const maxMIMEHeaderSize = 10 << 20
528+
529 // NextPart returns the next part in the multipart or an error.
530 // When there are no more parts, the error io.EOF is returned.
531 //
532@@ -304,7 +313,7 @@ type Reader struct {
533 // has a value of "quoted-printable", that header is instead
534 // hidden and the body is transparently decoded during Read calls.
535 func (r *Reader) NextPart() (*Part, error) {
536- return r.nextPart(false)
537+ return r.nextPart(false, maxMIMEHeaderSize)
538 }
539
540 // NextRawPart returns the next part in the multipart or an error.
541@@ -313,10 +322,10 @@ func (r *Reader) NextPart() (*Part, error) {
542 // Unlike NextPart, it does not have special handling for
543 // "Content-Transfer-Encoding: quoted-printable".
544 func (r *Reader) NextRawPart() (*Part, error) {
545- return r.nextPart(true)
546+ return r.nextPart(true, maxMIMEHeaderSize)
547 }
548
549-func (r *Reader) nextPart(rawPart bool) (*Part, error) {
550+func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
551 if r.currentPart != nil {
552 r.currentPart.Close()
553 }
554@@ -341,7 +350,7 @@ func (r *Reader) nextPart(rawPart bool) (*Part, error) {
555
556 if r.isBoundaryDelimiterLine(line) {
557 r.partsRead++
558- bp, err := newPart(r, rawPart)
559+ bp, err := newPart(r, rawPart, maxMIMEHeaderSize)
560 if err != nil {
561 return nil, err
562 }
563diff --git a/src/mime/multipart/readmimeheader.go b/src/mime/multipart/readmimeheader.go
564new file mode 100644
565index 0000000..6836928
566--- /dev/null
567+++ b/src/mime/multipart/readmimeheader.go
568@@ -0,0 +1,14 @@
569+// Copyright 2023 The Go Authors. All rights reserved.
570+// Use of this source code is governed by a BSD-style
571+// license that can be found in the LICENSE file.
572+package multipart
573+
574+import (
575+ "net/textproto"
576+ _ "unsafe" // for go:linkname
577+)
578+
579+// readMIMEHeader is defined in package net/textproto.
580+//
581+//go:linkname readMIMEHeader net/textproto.readMIMEHeader
582+func readMIMEHeader(r *textproto.Reader, lim int64) (textproto.MIMEHeader, error)
583diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
584index 94133ee..170d3f5 100644
585--- a/src/net/http/request_test.go
586+++ b/src/net/http/request_test.go
587@@ -962,7 +962,7 @@ func testMissingFile(t *testing.T, req *Request) {
588 t.Errorf("FormFile file = %v, want nil", f)
589 }
590 if fh != nil {
591- t.Errorf("FormFile file header = %q, want nil", fh)
592+ t.Errorf("FormFile file header = %v, want nil", fh)
593 }
594 if err != ErrMissingFile {
595 t.Errorf("FormFile err = %q, want ErrMissingFile", err)
596diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
597index f63f5ec..96553fb 100644
598--- a/src/net/textproto/reader.go
599+++ b/src/net/textproto/reader.go
600@@ -7,9 +7,11 @@ package textproto
601 import (
602 "bufio"
603 "bytes"
604+ "errors"
605 "fmt"
606 "io"
607 "io/ioutil"
608+ "math"
609 "strconv"
610 "strings"
611 "sync"
612@@ -482,6 +484,12 @@ func (r *Reader) ReadDotLines() ([]string, error) {
613 // }
614 //
615 func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
616+ return readMIMEHeader(r, math.MaxInt64)
617+}
618+
619+// readMIMEHeader is a version of ReadMIMEHeader which takes a limit on the header size.
620+// It is called by the mime/multipart package.
621+func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
622 // Avoid lots of small slice allocations later by allocating one
623 // large one ahead of time which we'll cut up into smaller
624 // slices. If this isn't big enough later, we allocate small ones.
625@@ -525,6 +533,15 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
626 continue
627 }
628
629+ // backport 5c55ac9bf1e5f779220294c843526536605f42ab
630+ //
631+ // value is computed as
632+ // value := string(bytes.TrimLeft(v, " \t"))
633+ //
634+ // in the original patch from 1.19. This relies on
635+ // 'v' which does not exist in 1.14. We leave the
636+ // 1.14 method unchanged.
637+
638 // Skip initial spaces in value.
639 i++ // skip colon
640 for i < len(kv) && (kv[i] == ' ' || kv[i] == '\t') {
641@@ -533,6 +550,16 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
642 value := string(kv[i:])
643
644 vv := m[key]
645+ if vv == nil {
646+ lim -= int64(len(key))
647+ lim -= 100 // map entry overhead
648+ }
649+ lim -= int64(len(value))
650+ if lim < 0 {
651+ // TODO: This should be a distinguishable error (ErrMessageTooLarge)
652+ // to allow mime/multipart to detect it.
653+ return m, errors.New("message too large")
654+ }
655 if vv == nil && len(strs) > 0 {
656 // More than likely this will be a single-element key.
657 // Most headers aren't multi-valued.
658--
6592.25.1
660
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 @@
1From d6759e7a059f4208f07aa781402841d7ddaaef96 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Fri, 10 Mar 2023 14:21:05 -0800
4Subject: [PATCH] [release-branch.go1.19] net/textproto: avoid overpredicting
5 the number of MIME header keys
6
7Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802452
8Run-TryBot: Damien Neil <dneil@google.com>
9Reviewed-by: Roland Shoemaker <bracewell@google.com>
10Reviewed-by: Julie Qiu <julieqiu@google.com>
11(cherry picked from commit f739f080a72fd5b06d35c8e244165159645e2ed6)
12Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802393
13Reviewed-by: Damien Neil <dneil@google.com>
14Run-TryBot: Roland Shoemaker <bracewell@google.com>
15Change-Id: I675451438d619a9130360c56daf529559004903f
16Reviewed-on: https://go-review.googlesource.com/c/go/+/481982
17Run-TryBot: Michael Knyszek <mknyszek@google.com>
18TryBot-Result: Gopher Robot <gobot@golang.org>
19Reviewed-by: Matthew Dempsky <mdempsky@google.com>
20Auto-Submit: Michael Knyszek <mknyszek@google.com>
21
22Upstream-Status: Backport [https://github.com/golang/go/commit/d6759e7a059f4208f07aa781402841d7ddaaef96]
23CVE: CVE-2023-24534
24Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
25---
26 src/bytes/bytes.go | 13 +++++++
27 src/net/textproto/reader.go | 31 +++++++++++------
28 src/net/textproto/reader_test.go | 59 ++++++++++++++++++++++++++++++++
29 3 files changed, 92 insertions(+), 11 deletions(-)
30
31diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go
32index e872cc2..1f0d760 100644
33--- a/src/bytes/bytes.go
34+++ b/src/bytes/bytes.go
35@@ -1078,6 +1078,19 @@ func Index(s, sep []byte) int {
36 return -1
37 }
38
39+// Cut slices s around the first instance of sep,
40+// returning the text before and after sep.
41+// The found result reports whether sep appears in s.
42+// If sep does not appear in s, cut returns s, nil, false.
43+//
44+// Cut returns slices of the original slice s, not copies.
45+func Cut(s, sep []byte) (before, after []byte, found bool) {
46+ if i := Index(s, sep); i >= 0 {
47+ return s[:i], s[i+len(sep):], true
48+ }
49+ return s, nil, false
50+}
51+
52 func indexRabinKarp(s, sep []byte) int {
53 // Rabin-Karp search
54 hashsep, pow := hashStr(sep)
55diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
56index a505da9..8d547fe 100644
57--- a/src/net/textproto/reader.go
58+++ b/src/net/textproto/reader.go
59@@ -486,8 +487,11 @@ func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
60 // large one ahead of time which we'll cut up into smaller
61 // slices. If this isn't big enough later, we allocate small ones.
62 var strs []string
63- hint := r.upcomingHeaderNewlines()
64+ hint := r.upcomingHeaderKeys()
65 if hint > 0 {
66+ if hint > 1000 {
67+ hint = 1000 // set a cap to avoid overallocation
68+ }
69 strs = make([]string, hint)
70 }
71
72@@ -562,9 +566,11 @@ func mustHaveFieldNameColon(line []byte) error {
73 return nil
74 }
75
76-// upcomingHeaderNewlines returns an approximation of the number of newlines
77+var nl = []byte("\n")
78+
79+// upcomingHeaderKeys returns an approximation of the number of keys
80 // that will be in this header. If it gets confused, it returns 0.
81-func (r *Reader) upcomingHeaderNewlines() (n int) {
82+func (r *Reader) upcomingHeaderKeys() (n int) {
83 // Try to determine the 'hint' size.
84 r.R.Peek(1) // force a buffer load if empty
85 s := r.R.Buffered()
86@@ -572,17 +578,20 @@ func (r *Reader) upcomingHeaderNewlines() (n int) {
87 return
88 }
89 peek, _ := r.R.Peek(s)
90- for len(peek) > 0 {
91- i := bytes.IndexByte(peek, '\n')
92- if i < 3 {
93- // Not present (-1) or found within the next few bytes,
94- // implying we're at the end ("\r\n\r\n" or "\n\n")
95- return
96+ for len(peek) > 0 && n < 1000 {
97+ var line []byte
98+ line, peek, _ = bytes.Cut(peek, nl)
99+ if len(line) == 0 || (len(line) == 1 && line[0] == '\r') {
100+ // Blank line separating headers from the body.
101+ break
102+ }
103+ if line[0] == ' ' || line[0] == '\t' {
104+ // Folded continuation of the previous line.
105+ continue
106 }
107 n++
108- peek = peek[i+1:]
109 }
110- return
111+ return n
112 }
113
114 // CanonicalMIMEHeaderKey returns the canonical format of the
115diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
116index 3124d43..3ae0de1 100644
117--- a/src/net/textproto/reader_test.go
118+++ b/src/net/textproto/reader_test.go
119@@ -9,6 +9,7 @@ import (
120 "bytes"
121 "io"
122 "reflect"
123+ "runtime"
124 "strings"
125 "testing"
126 )
127@@ -127,6 +128,42 @@ func TestReadMIMEHeaderSingle(t *testing.T) {
128 }
129 }
130
131+// TestReaderUpcomingHeaderKeys is testing an internal function, but it's very
132+// difficult to test well via the external API.
133+func TestReaderUpcomingHeaderKeys(t *testing.T) {
134+ for _, test := range []struct {
135+ input string
136+ want int
137+ }{{
138+ input: "",
139+ want: 0,
140+ }, {
141+ input: "A: v",
142+ want: 1,
143+ }, {
144+ input: "A: v\r\nB: v\r\n",
145+ want: 2,
146+ }, {
147+ input: "A: v\nB: v\n",
148+ want: 2,
149+ }, {
150+ input: "A: v\r\n continued\r\n still continued\r\nB: v\r\n\r\n",
151+ want: 2,
152+ }, {
153+ input: "A: v\r\n\r\nB: v\r\nC: v\r\n",
154+ want: 1,
155+ }, {
156+ input: "A: v" + strings.Repeat("\n", 1000),
157+ want: 1,
158+ }} {
159+ r := reader(test.input)
160+ got := r.upcomingHeaderKeys()
161+ if test.want != got {
162+ t.Fatalf("upcomingHeaderKeys(%q): %v; want %v", test.input, got, test.want)
163+ }
164+ }
165+}
166+
167 func TestReadMIMEHeaderNoKey(t *testing.T) {
168 r := reader(": bar\ntest-1: 1\n\n")
169 m, err := r.ReadMIMEHeader()
170@@ -223,6 +260,28 @@ func TestReadMIMEHeaderTrimContinued(t *testing.T) {
171 }
172 }
173
174+// Test that reading a header doesn't overallocate. Issue 58975.
175+func TestReadMIMEHeaderAllocations(t *testing.T) {
176+ var totalAlloc uint64
177+ const count = 200
178+ for i := 0; i < count; i++ {
179+ r := reader("A: b\r\n\r\n" + strings.Repeat("\n", 4096))
180+ var m1, m2 runtime.MemStats
181+ runtime.ReadMemStats(&m1)
182+ _, err := r.ReadMIMEHeader()
183+ if err != nil {
184+ t.Fatalf("ReadMIMEHeader: %v", err)
185+ }
186+ runtime.ReadMemStats(&m2)
187+ totalAlloc += m2.TotalAlloc - m1.TotalAlloc
188+ }
189+ // 32k is large and we actually allocate substantially less,
190+ // but prior to the fix for #58975 we allocated ~400k in this case.
191+ if got, want := totalAlloc/count, uint64(32768); got > want {
192+ t.Fatalf("ReadMIMEHeader allocated %v bytes, want < %v", got, want)
193+ }
194+}
195+
196 type readResponseTest struct {
197 in string
198 inCode int
199--
2002.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 @@
1From ef41a4e2face45e580c5836eaebd51629fc23f15 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Thu, 16 Mar 2023 14:18:04 -0700
4Subject: [PATCH] [release-branch.go1.19] mime/multipart: avoid excessive copy
5 buffer allocations in ReadForm
6
7When copying form data to disk with io.Copy,
8allocate only one copy buffer and reuse it rather than
9creating two buffers per file (one from io.multiReader.WriteTo,
10and a second one from os.File.ReadFrom).
11
12Thanks to Jakob Ackermann (@das7pad) for reporting this issue.
13
14For CVE-2023-24536
15For #59153
16For #59269
17
18Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802453
19Run-TryBot: Damien Neil <dneil@google.com>
20Reviewed-by: Julie Qiu <julieqiu@google.com>
21Reviewed-by: Roland Shoemaker <bracewell@google.com>
22Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802395
23Run-TryBot: Roland Shoemaker <bracewell@google.com>
24Reviewed-by: Damien Neil <dneil@google.com>
25Change-Id: Ie405470c92abffed3356913b37d813e982c96c8b
26Reviewed-on: https://go-review.googlesource.com/c/go/+/481983
27Run-TryBot: Michael Knyszek <mknyszek@google.com>
28TryBot-Result: Gopher Robot <gobot@golang.org>
29Auto-Submit: Michael Knyszek <mknyszek@google.com>
30Reviewed-by: Matthew Dempsky <mdempsky@google.com>
31
32Upstream-Status: Backport [https://github.com/golang/go/commit/ef41a4e2face45e580c5836eaebd51629fc23f15]
33CVE: CVE-2023-24536
34Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
35---
36 src/mime/multipart/formdata.go | 15 +++++++--
37 src/mime/multipart/formdata_test.go | 49 +++++++++++++++++++++++++++++
38 2 files changed, 61 insertions(+), 3 deletions(-)
39
40diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
41index a7d4ca97f0484..975dcb6b26db4 100644
42--- a/src/mime/multipart/formdata.go
43+++ b/src/mime/multipart/formdata.go
44@@ -84,6 +84,7 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
45 maxMemoryBytes = math.MaxInt64
46 }
47 }
48+ var copyBuf []byte
49 for {
50 p, err := r.nextPart(false, maxMemoryBytes)
51 if err == io.EOF {
52@@ -147,14 +148,22 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
53 }
54 }
55 numDiskFiles++
56- size, err := io.Copy(file, io.MultiReader(&b, p))
57+ if _, err := file.Write(b.Bytes()); err != nil {
58+ return nil, err
59+ }
60+ if copyBuf == nil {
61+ copyBuf = make([]byte, 32*1024) // same buffer size as io.Copy uses
62+ }
63+ // os.File.ReadFrom will allocate its own copy buffer if we let io.Copy use it.
64+ type writerOnly struct{ io.Writer }
65+ remainingSize, err := io.CopyBuffer(writerOnly{file}, p, copyBuf)
66 if err != nil {
67 return nil, err
68 }
69 fh.tmpfile = file.Name()
70- fh.Size = size
71+ fh.Size = int64(b.Len()) + remainingSize
72 fh.tmpoff = fileOff
73- fileOff += size
74+ fileOff += fh.Size
75 if !combineFiles {
76 if err := file.Close(); err != nil {
77 return nil, err
78diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
79index 5cded7170c6b8..f5b56083b2377 100644
80--- a/src/mime/multipart/formdata_test.go
81+++ b/src/mime/multipart/formdata_test.go
82@@ -368,3 +368,52 @@ func testReadFormManyFiles(t *testing.T, distinct bool) {
83 t.Fatalf("temp dir contains %v files; want 0", len(names))
84 }
85 }
86+
87+func BenchmarkReadForm(b *testing.B) {
88+ for _, test := range []struct {
89+ name string
90+ form func(fw *Writer, count int)
91+ }{{
92+ name: "fields",
93+ form: func(fw *Writer, count int) {
94+ for i := 0; i < count; i++ {
95+ w, _ := fw.CreateFormField(fmt.Sprintf("field%v", i))
96+ fmt.Fprintf(w, "value %v", i)
97+ }
98+ },
99+ }, {
100+ name: "files",
101+ form: func(fw *Writer, count int) {
102+ for i := 0; i < count; i++ {
103+ w, _ := fw.CreateFormFile(fmt.Sprintf("field%v", i), fmt.Sprintf("file%v", i))
104+ fmt.Fprintf(w, "value %v", i)
105+ }
106+ },
107+ }} {
108+ b.Run(test.name, func(b *testing.B) {
109+ for _, maxMemory := range []int64{
110+ 0,
111+ 1 << 20,
112+ } {
113+ var buf bytes.Buffer
114+ fw := NewWriter(&buf)
115+ test.form(fw, 10)
116+ if err := fw.Close(); err != nil {
117+ b.Fatal(err)
118+ }
119+ b.Run(fmt.Sprintf("maxMemory=%v", maxMemory), func(b *testing.B) {
120+ b.ReportAllocs()
121+ for i := 0; i < b.N; i++ {
122+ fr := NewReader(bytes.NewReader(buf.Bytes()), fw.Boundary())
123+ form, err := fr.ReadForm(maxMemory)
124+ if err != nil {
125+ b.Fatal(err)
126+ }
127+ form.RemoveAll()
128+ }
129+
130+ })
131+ }
132+ })
133+ }
134+}
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 @@
1From 7a359a651c7ebdb29e0a1c03102fce793e9f58f0 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Thu, 16 Mar 2023 16:56:12 -0700
4Subject: [PATCH] [release-branch.go1.19] net/textproto, mime/multipart:
5 improve accounting of non-file data
6
7For requests containing large numbers of small parts,
8memory consumption of a parsed form could be about 250%
9over the estimated size.
10
11When considering the size of parsed forms, account for the size of
12FileHeader structs and increase the estimate of memory consumed by
13map entries.
14
15Thanks to Jakob Ackermann (@das7pad) for reporting this issue.
16
17For CVE-2023-24536
18For #59153
19For #59269
20
21Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802454
22Run-TryBot: Damien Neil <dneil@google.com>
23Reviewed-by: Roland Shoemaker <bracewell@google.com>
24Reviewed-by: Julie Qiu <julieqiu@google.com>
25Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802396
26Run-TryBot: Roland Shoemaker <bracewell@google.com>
27Reviewed-by: Damien Neil <dneil@google.com>
28Change-Id: I31bc50e9346b4eee6fbe51a18c3c57230cc066db
29Reviewed-on: https://go-review.googlesource.com/c/go/+/481984
30Reviewed-by: Matthew Dempsky <mdempsky@google.com>
31Auto-Submit: Michael Knyszek <mknyszek@google.com>
32TryBot-Result: Gopher Robot <gobot@golang.org>
33Run-TryBot: Michael Knyszek <mknyszek@google.com>
34
35Upstream-Status: Backport [https://github.com/golang/go/commit/7a359a651c7ebdb29e0a1c03102fce793e9f58f0]
36CVE: CVE-2023-24536
37Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
38---
39 src/mime/multipart/formdata.go | 9 +++--
40 src/mime/multipart/formdata_test.go | 55 ++++++++++++-----------------
41 src/net/textproto/reader.go | 8 ++++-
42 3 files changed, 37 insertions(+), 35 deletions(-)
43
44diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
45index 975dcb6b26db4..3f6ff697ca608 100644
46--- a/src/mime/multipart/formdata.go
47+++ b/src/mime/multipart/formdata.go
48@@ -103,8 +103,9 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
49 // Multiple values for the same key (one map entry, longer slice) are cheaper
50 // than the same number of values for different keys (many map entries), but
51 // using a consistent per-value cost for overhead is simpler.
52+ const mapEntryOverhead = 200
53 maxMemoryBytes -= int64(len(name))
54- maxMemoryBytes -= 100 // map overhead
55+ maxMemoryBytes -= mapEntryOverhead
56 if maxMemoryBytes < 0 {
57 // We can't actually take this path, since nextPart would already have
58 // rejected the MIME headers for being too large. Check anyway.
59@@ -128,7 +129,10 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
60 }
61
62 // file, store in memory or on disk
63+ const fileHeaderSize = 100
64 maxMemoryBytes -= mimeHeaderSize(p.Header)
65+ maxMemoryBytes -= mapEntryOverhead
66+ maxMemoryBytes -= fileHeaderSize
67 if maxMemoryBytes < 0 {
68 return nil, ErrMessageTooLarge
69 }
70@@ -183,9 +187,10 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
71 }
72
73 func mimeHeaderSize(h textproto.MIMEHeader) (size int64) {
74+ size = 400
75 for k, vs := range h {
76 size += int64(len(k))
77- size += 100 // map entry overhead
78+ size += 200 // map entry overhead
79 for _, v := range vs {
80 size += int64(len(v))
81 }
82diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
83index f5b56083b2377..8ed26e0c34081 100644
84--- a/src/mime/multipart/formdata_test.go
85+++ b/src/mime/multipart/formdata_test.go
86@@ -192,10 +192,10 @@ func (r *failOnReadAfterErrorReader) Read(p []byte) (n int, err error) {
87 // TestReadForm_NonFileMaxMemory asserts that the ReadForm maxMemory limit is applied
88 // while processing non-file form data as well as file form data.
89 func TestReadForm_NonFileMaxMemory(t *testing.T) {
90- n := 10<<20 + 25
91 if testing.Short() {
92- n = 10<<10 + 25
93+ t.Skip("skipping in -short mode")
94 }
95+ n := 10 << 20
96 largeTextValue := strings.Repeat("1", n)
97 message := `--MyBoundary
98 Content-Disposition: form-data; name="largetext"
99@@ -203,38 +203,29 @@ Content-Disposition: form-data; name="largetext"
100 ` + largeTextValue + `
101 --MyBoundary--
102 `
103-
104 testBody := strings.ReplaceAll(message, "\n", "\r\n")
105- testCases := []struct {
106- name string
107- maxMemory int64
108- err error
109- }{
110- {"smaller", 50 + int64(len("largetext")) + 100, nil},
111- {"exact-fit", 25 + int64(len("largetext")) + 100, nil},
112- {"too-large", 0, ErrMessageTooLarge},
113- }
114- for _, tc := range testCases {
115- t.Run(tc.name, func(t *testing.T) {
116- if tc.maxMemory == 0 && testing.Short() {
117- t.Skip("skipping in -short mode")
118- }
119- b := strings.NewReader(testBody)
120- r := NewReader(b, boundary)
121- f, err := r.ReadForm(tc.maxMemory)
122- if err == nil {
123- defer f.RemoveAll()
124- }
125- if tc.err != err {
126- t.Fatalf("ReadForm error - got: %v; expected: %v", err, tc.err)
127- }
128- if err == nil {
129- if g := f.Value["largetext"][0]; g != largeTextValue {
130- t.Errorf("largetext mismatch: got size: %v, expected size: %v", len(g), len(largeTextValue))
131- }
132- }
133- })
134+ // Try parsing the form with increasing maxMemory values.
135+ // Changes in how we account for non-file form data may cause the exact point
136+ // where we change from rejecting the form as too large to accepting it to vary,
137+ // but we should see both successes and failures.
138+ const failWhenMaxMemoryLessThan = 128
139+ for maxMemory := int64(0); maxMemory < failWhenMaxMemoryLessThan*2; maxMemory += 16 {
140+ b := strings.NewReader(testBody)
141+ r := NewReader(b, boundary)
142+ f, err := r.ReadForm(maxMemory)
143+ if err != nil {
144+ continue
145+ }
146+ if g := f.Value["largetext"][0]; g != largeTextValue {
147+ t.Errorf("largetext mismatch: got size: %v, expected size: %v", len(g), len(largeTextValue))
148+ }
149+ f.RemoveAll()
150+ if maxMemory < failWhenMaxMemoryLessThan {
151+ t.Errorf("ReadForm(%v): no error, expect to hit memory limit when maxMemory < %v", maxMemory, failWhenMaxMemoryLessThan)
152+ }
153+ return
154 }
155+ t.Errorf("ReadForm(x) failed for x < 1024, expect success")
156 }
157
158 // TestReadForm_MetadataTooLarge verifies that we account for the size of field names,
159diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
160index 9a21777df8be0..c1284fde25eb7 100644
161--- a/src/net/textproto/reader.go
162+++ b/src/net/textproto/reader.go
163@@ -503,6 +503,12 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
164
165 m := make(MIMEHeader, hint)
166
167+ // Account for 400 bytes of overhead for the MIMEHeader, plus 200 bytes per entry.
168+ // Benchmarking map creation as of go1.20, a one-entry MIMEHeader is 416 bytes and large
169+ // MIMEHeaders average about 200 bytes per entry.
170+ lim -= 400
171+ const mapEntryOverhead = 200
172+
173 // The first line cannot start with a leading space.
174 if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
175 line, err := r.readLineSlice()
176@@ -538,7 +544,7 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
177 vv := m[key]
178 if vv == nil {
179 lim -= int64(len(key))
180- lim -= 100 // map entry overhead
181+ lim -= mapEntryOverhead
182 }
183 lim -= int64(len(value))
184 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 @@
1From 7917b5f31204528ea72e0629f0b7d52b35b27538 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Mon, 20 Mar 2023 10:43:19 -0700
4Subject: [PATCH] [release-branch.go1.19] mime/multipart: limit parsed mime message sizes
5
6The parsed forms of MIME headers and multipart forms can consume
7substantially more memory than the size of the input data.
8A malicious input containing a very large number of headers or
9form parts can cause excessively large memory allocations.
10
11Set limits on the size of MIME data:
12
13Reader.NextPart and Reader.NextRawPart limit the the number
14of headers in a part to 10000.
15
16Reader.ReadForm limits the total number of headers in all
17FileHeaders to 10000.
18
19Both of these limits may be set with with
20GODEBUG=multipartmaxheaders=<values>.
21
22Reader.ReadForm limits the number of parts in a form to 1000.
23This limit may be set with GODEBUG=multipartmaxparts=<value>.
24
25Thanks for Jakob Ackermann (@das7pad) for reporting this issue.
26
27For CVE-2023-24536
28For #59153
29For #59269
30
31Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802455
32Run-TryBot: Damien Neil <dneil@google.com>
33Reviewed-by: Roland Shoemaker <bracewell@google.com>
34Reviewed-by: Julie Qiu <julieqiu@google.com>
35Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1801087
36Reviewed-by: Damien Neil <dneil@google.com>
37Run-TryBot: Roland Shoemaker <bracewell@google.com>
38Change-Id: If134890d75f0d95c681d67234daf191ba08e6424
39Reviewed-on: https://go-review.googlesource.com/c/go/+/481985
40Run-TryBot: Michael Knyszek <mknyszek@google.com>
41Auto-Submit: Michael Knyszek <mknyszek@google.com>
42TryBot-Result: Gopher Robot <gobot@golang.org>
43Reviewed-by: Matthew Dempsky <mdempsky@google.com>
44
45Upstream-Status: Backport [https://github.com/golang/go/commit/7917b5f31204528ea72e0629f0b7d52b35b27538]
46CVE: CVE-2023-24536
47Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
48---
49 src/mime/multipart/formdata.go | 19 ++++++++-
50 src/mime/multipart/formdata_test.go | 61 ++++++++++++++++++++++++++++
51 src/mime/multipart/multipart.go | 31 ++++++++++----
52 src/mime/multipart/readmimeheader.go | 2 +-
53 src/net/textproto/reader.go | 19 +++++----
54 5 files changed, 115 insertions(+), 17 deletions(-)
55
56diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
57index 216cccb..0b508ae 100644
58--- a/src/mime/multipart/formdata.go
59+++ b/src/mime/multipart/formdata.go
60@@ -13,6 +13,7 @@ import (
61 "math"
62 "net/textproto"
63 "os"
64+ "strconv"
65 )
66
67 // ErrMessageTooLarge is returned by ReadForm if the message form
68@@ -42,6 +43,15 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
69 numDiskFiles := 0
70 multipartFiles := godebug.Get("multipartfiles")
71 combineFiles := multipartFiles != "distinct"
72+ maxParts := 1000
73+ multipartMaxParts := godebug.Get("multipartmaxparts")
74+ if multipartMaxParts != "" {
75+ if v, err := strconv.Atoi(multipartMaxParts); err == nil && v >= 0 {
76+ maxParts = v
77+ }
78+ }
79+ maxHeaders := maxMIMEHeaders()
80+
81 defer func() {
82 if file != nil {
83 if cerr := file.Close(); err == nil {
84@@ -87,13 +97,17 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
85 }
86 var copyBuf []byte
87 for {
88- p, err := r.nextPart(false, maxMemoryBytes)
89+ p, err := r.nextPart(false, maxMemoryBytes, maxHeaders)
90 if err == io.EOF {
91 break
92 }
93 if err != nil {
94 return nil, err
95 }
96+ if maxParts <= 0 {
97+ return nil, ErrMessageTooLarge
98+ }
99+ maxParts--
100
101 name := p.FormName()
102 if name == "" {
103@@ -137,6 +151,9 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
104 if maxMemoryBytes < 0 {
105 return nil, ErrMessageTooLarge
106 }
107+ for _, v := range p.Header {
108+ maxHeaders -= int64(len(v))
109+ }
110 fh := &FileHeader{
111 Filename: filename,
112 Header: p.Header,
113diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
114index 8ed26e0..c78eeb7 100644
115--- a/src/mime/multipart/formdata_test.go
116+++ b/src/mime/multipart/formdata_test.go
117@@ -360,6 +360,67 @@ func testReadFormManyFiles(t *testing.T, distinct bool) {
118 }
119 }
120
121+func TestReadFormLimits(t *testing.T) {
122+ for _, test := range []struct {
123+ values int
124+ files int
125+ extraKeysPerFile int
126+ wantErr error
127+ godebug string
128+ }{
129+ {values: 1000},
130+ {values: 1001, wantErr: ErrMessageTooLarge},
131+ {values: 500, files: 500},
132+ {values: 501, files: 500, wantErr: ErrMessageTooLarge},
133+ {files: 1000},
134+ {files: 1001, wantErr: ErrMessageTooLarge},
135+ {files: 1, extraKeysPerFile: 9998}, // plus Content-Disposition and Content-Type
136+ {files: 1, extraKeysPerFile: 10000, wantErr: ErrMessageTooLarge},
137+ {godebug: "multipartmaxparts=100", values: 100},
138+ {godebug: "multipartmaxparts=100", values: 101, wantErr: ErrMessageTooLarge},
139+ {godebug: "multipartmaxheaders=100", files: 2, extraKeysPerFile: 48},
140+ {godebug: "multipartmaxheaders=100", files: 2, extraKeysPerFile: 50, wantErr: ErrMessageTooLarge},
141+ } {
142+ name := fmt.Sprintf("values=%v/files=%v/extraKeysPerFile=%v", test.values, test.files, test.extraKeysPerFile)
143+ if test.godebug != "" {
144+ name += fmt.Sprintf("/godebug=%v", test.godebug)
145+ }
146+ t.Run(name, func(t *testing.T) {
147+ if test.godebug != "" {
148+ t.Setenv("GODEBUG", test.godebug)
149+ }
150+ var buf bytes.Buffer
151+ fw := NewWriter(&buf)
152+ for i := 0; i < test.values; i++ {
153+ w, _ := fw.CreateFormField(fmt.Sprintf("field%v", i))
154+ fmt.Fprintf(w, "value %v", i)
155+ }
156+ for i := 0; i < test.files; i++ {
157+ h := make(textproto.MIMEHeader)
158+ h.Set("Content-Disposition",
159+ fmt.Sprintf(`form-data; name="file%v"; filename="file%v"`, i, i))
160+ h.Set("Content-Type", "application/octet-stream")
161+ for j := 0; j < test.extraKeysPerFile; j++ {
162+ h.Set(fmt.Sprintf("k%v", j), "v")
163+ }
164+ w, _ := fw.CreatePart(h)
165+ fmt.Fprintf(w, "value %v", i)
166+ }
167+ if err := fw.Close(); err != nil {
168+ t.Fatal(err)
169+ }
170+ fr := NewReader(bytes.NewReader(buf.Bytes()), fw.Boundary())
171+ form, err := fr.ReadForm(1 << 10)
172+ if err == nil {
173+ defer form.RemoveAll()
174+ }
175+ if err != test.wantErr {
176+ t.Errorf("ReadForm = %v, want %v", err, test.wantErr)
177+ }
178+ })
179+ }
180+}
181+
182 func BenchmarkReadForm(b *testing.B) {
183 for _, test := range []struct {
184 name string
185diff --git a/src/mime/multipart/multipart.go b/src/mime/multipart/multipart.go
186index 958cef8..94464a8 100644
187--- a/src/mime/multipart/multipart.go
188+++ b/src/mime/multipart/multipart.go
189@@ -16,11 +16,13 @@ import (
190 "bufio"
191 "bytes"
192 "fmt"
193+ "internal/godebug"
194 "io"
195 "io/ioutil"
196 "mime"
197 "mime/quotedprintable"
198 "net/textproto"
199+ "strconv"
200 "strings"
201 )
202
203@@ -121,12 +123,12 @@ func (r *stickyErrorReader) Read(p []byte) (n int, _ error) {
204 return n, r.err
205 }
206
207-func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
208+func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders int64) (*Part, error) {
209 bp := &Part{
210 Header: make(map[string][]string),
211 mr: mr,
212 }
213- if err := bp.populateHeaders(maxMIMEHeaderSize); err != nil {
214+ if err := bp.populateHeaders(maxMIMEHeaderSize, maxMIMEHeaders); err != nil {
215 return nil, err
216 }
217 bp.r = partReader{bp}
218@@ -142,9 +144,9 @@ func newPart(mr *Reader, rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
219 return bp, nil
220 }
221
222-func (bp *Part) populateHeaders(maxMIMEHeaderSize int64) error {
223+func (bp *Part) populateHeaders(maxMIMEHeaderSize, maxMIMEHeaders int64) error {
224 r := textproto.NewReader(bp.mr.bufReader)
225- header, err := readMIMEHeader(r, maxMIMEHeaderSize)
226+ header, err := readMIMEHeader(r, maxMIMEHeaderSize, maxMIMEHeaders)
227 if err == nil {
228 bp.Header = header
229 }
230@@ -306,6 +308,19 @@ type Reader struct {
231 // including header keys, values, and map overhead.
232 const maxMIMEHeaderSize = 10 << 20
233
234+func maxMIMEHeaders() int64 {
235+ // multipartMaxHeaders is the maximum number of header entries NextPart will return,
236+ // as well as the maximum combined total of header entries Reader.ReadForm will return
237+ // in FileHeaders.
238+ multipartMaxHeaders := godebug.Get("multipartmaxheaders")
239+ if multipartMaxHeaders != "" {
240+ if v, err := strconv.ParseInt(multipartMaxHeaders, 10, 64); err == nil && v >= 0 {
241+ return v
242+ }
243+ }
244+ return 10000
245+}
246+
247 // NextPart returns the next part in the multipart or an error.
248 // When there are no more parts, the error io.EOF is returned.
249 //
250@@ -313,7 +328,7 @@ const maxMIMEHeaderSize = 10 << 20
251 // has a value of "quoted-printable", that header is instead
252 // hidden and the body is transparently decoded during Read calls.
253 func (r *Reader) NextPart() (*Part, error) {
254- return r.nextPart(false, maxMIMEHeaderSize)
255+ return r.nextPart(false, maxMIMEHeaderSize, maxMIMEHeaders())
256 }
257
258 // NextRawPart returns the next part in the multipart or an error.
259@@ -322,10 +337,10 @@ func (r *Reader) NextPart() (*Part, error) {
260 // Unlike NextPart, it does not have special handling for
261 // "Content-Transfer-Encoding: quoted-printable".
262 func (r *Reader) NextRawPart() (*Part, error) {
263- return r.nextPart(true, maxMIMEHeaderSize)
264+ return r.nextPart(true, maxMIMEHeaderSize, maxMIMEHeaders())
265 }
266
267-func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize int64) (*Part, error) {
268+func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize, maxMIMEHeaders int64) (*Part, error) {
269 if r.currentPart != nil {
270 r.currentPart.Close()
271 }
272@@ -350,7 +365,7 @@ func (r *Reader) nextPart(rawPart bool, maxMIMEHeaderSize int64) (*Part, error)
273
274 if r.isBoundaryDelimiterLine(line) {
275 r.partsRead++
276- bp, err := newPart(r, rawPart, maxMIMEHeaderSize)
277+ bp, err := newPart(r, rawPart, maxMIMEHeaderSize, maxMIMEHeaders)
278 if err != nil {
279 return nil, err
280 }
281diff --git a/src/mime/multipart/readmimeheader.go b/src/mime/multipart/readmimeheader.go
282index 6836928..25aa6e2 100644
283--- a/src/mime/multipart/readmimeheader.go
284+++ b/src/mime/multipart/readmimeheader.go
285@@ -11,4 +11,4 @@ import (
286 // readMIMEHeader is defined in package net/textproto.
287 //
288 //go:linkname readMIMEHeader net/textproto.readMIMEHeader
289-func readMIMEHeader(r *textproto.Reader, lim int64) (textproto.MIMEHeader, error)
290+func readMIMEHeader(r *textproto.Reader, maxMemory, maxHeaders int64) (textproto.MIMEHeader, error)
291diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
292index 1c79f0a..ad2d777 100644
293--- a/src/net/textproto/reader.go
294+++ b/src/net/textproto/reader.go
295@@ -484,12 +484,12 @@ func (r *Reader) ReadDotLines() ([]string, error) {
296 // }
297 //
298 func (r *Reader) ReadMIMEHeader() (MIMEHeader, error) {
299- return readMIMEHeader(r, math.MaxInt64)
300+ return readMIMEHeader(r, math.MaxInt64, math.MaxInt64)
301 }
302
303 // readMIMEHeader is a version of ReadMIMEHeader which takes a limit on the header size.
304 // It is called by the mime/multipart package.
305-func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
306+func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) {
307 // Avoid lots of small slice allocations later by allocating one
308 // large one ahead of time which we'll cut up into smaller
309 // slices. If this isn't big enough later, we allocate small ones.
310@@ -507,7 +507,7 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
311 // Account for 400 bytes of overhead for the MIMEHeader, plus 200 bytes per entry.
312 // Benchmarking map creation as of go1.20, a one-entry MIMEHeader is 416 bytes and large
313 // MIMEHeaders average about 200 bytes per entry.
314- lim -= 400
315+ maxMemory -= 400
316 const mapEntryOverhead = 200
317
318 // The first line cannot start with a leading space.
319@@ -539,6 +539,11 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
320 continue
321 }
322
323+ maxHeaders--
324+ if maxHeaders < 0 {
325+ return nil, errors.New("message too large")
326+ }
327+
328 // backport 5c55ac9bf1e5f779220294c843526536605f42ab
329 //
330 // value is computed as
331@@ -557,11 +562,11 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
332
333 vv := m[key]
334 if vv == nil {
335- lim -= int64(len(key))
336- lim -= mapEntryOverhead
337+ maxMemory -= int64(len(key))
338+ maxMemory -= mapEntryOverhead
339 }
340- lim -= int64(len(value))
341- if lim < 0 {
342+ maxMemory -= int64(len(value))
343+ if maxMemory < 0 {
344 // TODO: This should be a distinguishable error (ErrMessageTooLarge)
345 // to allow mime/multipart to detect it.
346 return m, errors.New("message too large")
347--
3482.25.1
349
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 @@
1From bf8c7c575c8a552d9d79deb29e80854dc88528d0 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Mon, 20 Mar 2023 10:43:19 -0700
4Subject: [PATCH] [release-branch.go1.20] mime/multipart: limit parsed mime
5 message sizes
6
7Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802456
8Reviewed-by: Julie Qiu <julieqiu@google.com>
9Reviewed-by: Roland Shoemaker <bracewell@google.com>
10Run-TryBot: Damien Neil <dneil@google.com>
11Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802611
12Reviewed-by: Damien Neil <dneil@google.com>
13Change-Id: Ifdfa192d54f722d781a4d8c5f35b5fb72d122168
14Reviewed-on: https://go-review.googlesource.com/c/go/+/481986
15Reviewed-by: Matthew Dempsky <mdempsky@google.com>
16TryBot-Result: Gopher Robot <gobot@golang.org>
17Run-TryBot: Michael Knyszek <mknyszek@google.com>
18Auto-Submit: Michael Knyszek <mknyszek@google.com>
19
20Upstream-Status: Backport [https://github.com/golang/go/commit/126a1d02da82f93ede7ce0bd8d3c51ef627f2104]
21CVE: CVE-2023-24537
22Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
23---
24 src/go/parser/parser_test.go | 16 ++++++++++++++++
25 src/go/scanner/scanner.go | 5 ++++-
26 2 files changed, 20 insertions(+), 1 deletion(-)
27
28diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go
29index 37a6a2b..714557c 100644
30--- a/src/go/parser/parser_test.go
31+++ b/src/go/parser/parser_test.go
32@@ -738,3 +738,19 @@ func TestScopeDepthLimit(t *testing.T) {
33 }
34 }
35 }
36+
37+// TestIssue59180 tests that line number overflow doesn't cause an infinite loop.
38+func TestIssue59180(t *testing.T) {
39+ testcases := []string{
40+ "package p\n//line :9223372036854775806\n\n//",
41+ "package p\n//line :1:9223372036854775806\n\n//",
42+ "package p\n//line file:9223372036854775806\n\n//",
43+ }
44+
45+ for _, src := range testcases {
46+ _, err := ParseFile(token.NewFileSet(), "", src, ParseComments)
47+ if err == nil {
48+ t.Errorf("ParseFile(%s) succeeded unexpectedly", src)
49+ }
50+ }
51+}
52diff --git a/src/go/scanner/scanner.go b/src/go/scanner/scanner.go
53index 00fe2dc..3159d25 100644
54--- a/src/go/scanner/scanner.go
55+++ b/src/go/scanner/scanner.go
56@@ -246,13 +246,16 @@ func (s *Scanner) updateLineInfo(next, offs int, text []byte) {
57 return
58 }
59
60+ // Put a cap on the maximum size of line and column numbers.
61+ // 30 bits allows for some additional space before wrapping an int32.
62+ const maxLineCol = 1<<30 - 1
63 var line, col int
64 i2, n2, ok2 := trailingDigits(text[:i-1])
65 if ok2 {
66 //line filename:line:col
67 i, i2 = i2, i
68 line, col = n2, n
69- if col == 0 {
70+ if col == 0 || col > maxLineCol {
71 s.error(offs+i2, "invalid column number: "+string(text[i2:]))
72 return
73 }
74--
752.25.1
76
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 @@
1From 8acd01094d9ee17f6e763a61e49a8a808b3a9ddb Mon Sep 17 00:00:00 2001
2From: Brad Fitzpatrick <bradfitz@golang.org>
3Date: Mon, 2 Aug 2021 14:55:51 -0700
4Subject: [PATCH 1/6] net/netip: add new IP address package
5
6Co-authored-by: Alex Willmer <alex@moreati.org.uk> (GitHub @moreati)
7Co-authored-by: Alexander Yastrebov <yastrebov.alex@gmail.com>
8Co-authored-by: David Anderson <dave@natulte.net> (Tailscale CLA)
9Co-authored-by: David Crawshaw <crawshaw@tailscale.com> (Tailscale CLA)
10Co-authored-by: Dmytro Shynkevych <dmytro@tailscale.com> (Tailscale CLA)
11Co-authored-by: Elias Naur <mail@eliasnaur.com>
12Co-authored-by: Joe Tsai <joetsai@digital-static.net> (Tailscale CLA)
13Co-authored-by: Jonathan Yu <jawnsy@cpan.org> (GitHub @jawnsy)
14Co-authored-by: Josh Bleecher Snyder <josharian@gmail.com> (Tailscale CLA)
15Co-authored-by: Maisem Ali <maisem@tailscale.com> (Tailscale CLA)
16Co-authored-by: Manuel Mendez (Go AUTHORS mmendez534@...)
17Co-authored-by: Matt Layher <mdlayher@gmail.com>
18Co-authored-by: Noah Treuhaft <noah.treuhaft@gmail.com> (GitHub @nwt)
19Co-authored-by: Stefan Majer <stefan.majer@gmail.com>
20Co-authored-by: Terin Stock <terinjokes@gmail.com> (Cloudflare CLA)
21Co-authored-by: Tobias Klauser <tklauser@distanz.ch>
22
23Fixes #46518
24
25Change-Id: I0041f9e1115d61fa6e95fcf32b01d9faee708712
26Reviewed-on: https://go-review.googlesource.com/c/go/+/339309
27Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
28TryBot-Result: Go Bot <gobot@golang.org>
29Reviewed-by: Russ Cox <rsc@golang.org>
30Trust: Brad Fitzpatrick <bradfitz@golang.org>
31
32Dependency Patch #1
33
34Upstream-Status: Backport from https://github.com/golang/go/commit/a59e33224e42d60a97fa720a45e1b74eb6aaa3d0
35CVE: CVE-2023-24538
36Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
37---
38 src/internal/godebug/godebug.go | 34 ++++++++++++++++++++++++++++++++++
39 src/internal/godebug/godebug_test.go | 34 ++++++++++++++++++++++++++++++++++
40 2 files changed, 68 insertions(+)
41 create mode 100644 src/internal/godebug/godebug.go
42 create mode 100644 src/internal/godebug/godebug_test.go
43
44diff --git a/src/internal/godebug/godebug.go b/src/internal/godebug/godebug.go
45new file mode 100644
46index 0000000..ac434e5
47--- /dev/null
48+++ b/src/internal/godebug/godebug.go
49@@ -0,0 +1,34 @@
50+// Copyright 2021 The Go Authors. All rights reserved.
51+// Use of this source code is governed by a BSD-style
52+// license that can be found in the LICENSE file.
53+
54+// Package godebug parses the GODEBUG environment variable.
55+package godebug
56+
57+import "os"
58+
59+// Get returns the value for the provided GODEBUG key.
60+func Get(key string) string {
61+ return get(os.Getenv("GODEBUG"), key)
62+}
63+
64+// get returns the value part of key=value in s (a GODEBUG value).
65+func get(s, key string) string {
66+ for i := 0; i < len(s)-len(key)-1; i++ {
67+ if i > 0 && s[i-1] != ',' {
68+ continue
69+ }
70+ afterKey := s[i+len(key):]
71+ if afterKey[0] != '=' || s[i:i+len(key)] != key {
72+ continue
73+ }
74+ val := afterKey[1:]
75+ for i, b := range val {
76+ if b == ',' {
77+ return val[:i]
78+ }
79+ }
80+ return val
81+ }
82+ return ""
83+}
84diff --git a/src/internal/godebug/godebug_test.go b/src/internal/godebug/godebug_test.go
85new file mode 100644
86index 0000000..41b9117
87--- /dev/null
88+++ b/src/internal/godebug/godebug_test.go
89@@ -0,0 +1,34 @@
90+// Copyright 2021 The Go Authors. All rights reserved.
91+// Use of this source code is governed by a BSD-style
92+// license that can be found in the LICENSE file.
93+
94+package godebug
95+
96+import "testing"
97+
98+func TestGet(t *testing.T) {
99+ tests := []struct {
100+ godebug string
101+ key string
102+ want string
103+ }{
104+ {"", "", ""},
105+ {"", "foo", ""},
106+ {"foo=bar", "foo", "bar"},
107+ {"foo=bar,after=x", "foo", "bar"},
108+ {"before=x,foo=bar,after=x", "foo", "bar"},
109+ {"before=x,foo=bar", "foo", "bar"},
110+ {",,,foo=bar,,,", "foo", "bar"},
111+ {"foodecoy=wrong,foo=bar", "foo", "bar"},
112+ {"foo=", "foo", ""},
113+ {"foo", "foo", ""},
114+ {",foo", "foo", ""},
115+ {"foo=bar,baz", "loooooooong", ""},
116+ }
117+ for _, tt := range tests {
118+ got := get(tt.godebug, tt.key)
119+ if got != tt.want {
120+ t.Errorf("get(%q, %q) = %q; want %q", tt.godebug, tt.key, got, tt.want)
121+ }
122+ }
123+}
124--
1252.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 @@
1From 6fc21505614f36178df0dad7034b6b8e3f7588d5 Mon Sep 17 00:00:00 2001
2From: empijei <robclap8@gmail.com>
3Date: Fri, 27 Mar 2020 19:27:55 +0100
4Subject: [PATCH 2/6] html/template,text/template: switch to Unicode escapes
5 for JSON compatibility
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10The existing implementation is not compatible with JSON
11escape as it uses hex escaping.
12Unicode escape, instead, is valid for both JSON and JS.
13This fix avoids creating a separate escaping context for
14scripts of type "application/ld+json" and it is more
15future-proof in case more JSON+JS contexts get added
16to the platform (e.g. import maps).
17
18Fixes #33671
19Fixes #37634
20
21Change-Id: Id6f6524b4abc52e81d9d744d46bbe5bf2e081543
22Reviewed-on: https://go-review.googlesource.com/c/go/+/226097
23Reviewed-by: Carl Johnson <me@carlmjohnson.net>
24Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
25Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
26TryBot-Result: Gobot Gobot <gobot@golang.org>
27
28Dependency Patch #2
29
30Upstream-Status: Backport from https://github.com/golang/go/commit/d4d298040d072ddacea0e0d6b55fb148fff18070
31CVE: CVE-2023-24538
32Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
33---
34 src/html/template/content_test.go | 70 +++++++++++++++++++-------------------
35 src/html/template/escape_test.go | 6 ++--
36 src/html/template/example_test.go | 6 ++--
37 src/html/template/js.go | 70 +++++++++++++++++++++++---------------
38 src/html/template/js_test.go | 68 ++++++++++++++++++------------------
39 src/html/template/template_test.go | 39 +++++++++++++++++++++
40 src/text/template/exec_test.go | 6 ++--
41 src/text/template/funcs.go | 8 ++---
42 8 files changed, 163 insertions(+), 110 deletions(-)
43
44diff --git a/src/html/template/content_test.go b/src/html/template/content_test.go
45index 72d56f5..bd86527 100644
46--- a/src/html/template/content_test.go
47+++ b/src/html/template/content_test.go
48@@ -18,7 +18,7 @@ func TestTypedContent(t *testing.T) {
49 HTML(`Hello, <b>World</b> &amp;tc!`),
50 HTMLAttr(` dir="ltr"`),
51 JS(`c && alert("Hello, World!");`),
52- JSStr(`Hello, World & O'Reilly\x21`),
53+ JSStr(`Hello, World & O'Reilly\u0021`),
54 URL(`greeting=H%69,&addressee=(World)`),
55 Srcset(`greeting=H%69,&addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`),
56 URL(`,foo/,`),
57@@ -70,7 +70,7 @@ func TestTypedContent(t *testing.T) {
58 `Hello, <b>World</b> &amp;tc!`,
59 ` dir=&#34;ltr&#34;`,
60 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
61- `Hello, World &amp; O&#39;Reilly\x21`,
62+ `Hello, World &amp; O&#39;Reilly\u0021`,
63 `greeting=H%69,&amp;addressee=(World)`,
64 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
65 `,foo/,`,
66@@ -100,7 +100,7 @@ func TestTypedContent(t *testing.T) {
67 `Hello,&#32;World&#32;&amp;tc!`,
68 `&#32;dir&#61;&#34;ltr&#34;`,
69 `c&#32;&amp;&amp;&#32;alert(&#34;Hello,&#32;World!&#34;);`,
70- `Hello,&#32;World&#32;&amp;&#32;O&#39;Reilly\x21`,
71+ `Hello,&#32;World&#32;&amp;&#32;O&#39;Reilly\u0021`,
72 `greeting&#61;H%69,&amp;addressee&#61;(World)`,
73 `greeting&#61;H%69,&amp;addressee&#61;(World)&#32;2x,&#32;https://golang.org/favicon.ico&#32;500.5w`,
74 `,foo/,`,
75@@ -115,7 +115,7 @@ func TestTypedContent(t *testing.T) {
76 `Hello, World &amp;tc!`,
77 ` dir=&#34;ltr&#34;`,
78 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
79- `Hello, World &amp; O&#39;Reilly\x21`,
80+ `Hello, World &amp; O&#39;Reilly\u0021`,
81 `greeting=H%69,&amp;addressee=(World)`,
82 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
83 `,foo/,`,
84@@ -130,7 +130,7 @@ func TestTypedContent(t *testing.T) {
85 `Hello, &lt;b&gt;World&lt;/b&gt; &amp;tc!`,
86 ` dir=&#34;ltr&#34;`,
87 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
88- `Hello, World &amp; O&#39;Reilly\x21`,
89+ `Hello, World &amp; O&#39;Reilly\u0021`,
90 `greeting=H%69,&amp;addressee=(World)`,
91 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
92 `,foo/,`,
93@@ -146,7 +146,7 @@ func TestTypedContent(t *testing.T) {
94 // Not escaped.
95 `c && alert("Hello, World!");`,
96 // Escape sequence not over-escaped.
97- `"Hello, World & O'Reilly\x21"`,
98+ `"Hello, World & O'Reilly\u0021"`,
99 `"greeting=H%69,\u0026addressee=(World)"`,
100 `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`,
101 `",foo/,"`,
102@@ -162,7 +162,7 @@ func TestTypedContent(t *testing.T) {
103 // Not JS escaped but HTML escaped.
104 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
105 // Escape sequence not over-escaped.
106- `&#34;Hello, World &amp; O&#39;Reilly\x21&#34;`,
107+ `&#34;Hello, World &amp; O&#39;Reilly\u0021&#34;`,
108 `&#34;greeting=H%69,\u0026addressee=(World)&#34;`,
109 `&#34;greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w&#34;`,
110 `&#34;,foo/,&#34;`,
111@@ -171,30 +171,30 @@ func TestTypedContent(t *testing.T) {
112 {
113 `<script>alert("{{.}}")</script>`,
114 []string{
115- `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
116- `a[href =~ \x22\/\/example.com\x22]#foo`,
117- `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
118- ` dir=\x22ltr\x22`,
119- `c \x26\x26 alert(\x22Hello, World!\x22);`,
120+ `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`,
121+ `a[href =~ \u0022\/\/example.com\u0022]#foo`,
122+ `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`,
123+ ` dir=\u0022ltr\u0022`,
124+ `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`,
125 // Escape sequence not over-escaped.
126- `Hello, World \x26 O\x27Reilly\x21`,
127- `greeting=H%69,\x26addressee=(World)`,
128- `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
129+ `Hello, World \u0026 O\u0027Reilly\u0021`,
130+ `greeting=H%69,\u0026addressee=(World)`,
131+ `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
132 `,foo\/,`,
133 },
134 },
135 {
136 `<script type="text/javascript">alert("{{.}}")</script>`,
137 []string{
138- `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
139- `a[href =~ \x22\/\/example.com\x22]#foo`,
140- `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
141- ` dir=\x22ltr\x22`,
142- `c \x26\x26 alert(\x22Hello, World!\x22);`,
143+ `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`,
144+ `a[href =~ \u0022\/\/example.com\u0022]#foo`,
145+ `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`,
146+ ` dir=\u0022ltr\u0022`,
147+ `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`,
148 // Escape sequence not over-escaped.
149- `Hello, World \x26 O\x27Reilly\x21`,
150- `greeting=H%69,\x26addressee=(World)`,
151- `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
152+ `Hello, World \u0026 O\u0027Reilly\u0021`,
153+ `greeting=H%69,\u0026addressee=(World)`,
154+ `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
155 `,foo\/,`,
156 },
157 },
158@@ -208,7 +208,7 @@ func TestTypedContent(t *testing.T) {
159 // Not escaped.
160 `c && alert("Hello, World!");`,
161 // Escape sequence not over-escaped.
162- `"Hello, World & O'Reilly\x21"`,
163+ `"Hello, World & O'Reilly\u0021"`,
164 `"greeting=H%69,\u0026addressee=(World)"`,
165 `"greeting=H%69,\u0026addressee=(World) 2x, https://golang.org/favicon.ico 500.5w"`,
166 `",foo/,"`,
167@@ -224,7 +224,7 @@ func TestTypedContent(t *testing.T) {
168 `Hello, <b>World</b> &amp;tc!`,
169 ` dir=&#34;ltr&#34;`,
170 `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
171- `Hello, World &amp; O&#39;Reilly\x21`,
172+ `Hello, World &amp; O&#39;Reilly\u0021`,
173 `greeting=H%69,&amp;addressee=(World)`,
174 `greeting=H%69,&amp;addressee=(World) 2x, https://golang.org/favicon.ico 500.5w`,
175 `,foo/,`,
176@@ -233,15 +233,15 @@ func TestTypedContent(t *testing.T) {
177 {
178 `<button onclick='alert("{{.}}")'>`,
179 []string{
180- `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
181- `a[href =~ \x22\/\/example.com\x22]#foo`,
182- `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
183- ` dir=\x22ltr\x22`,
184- `c \x26\x26 alert(\x22Hello, World!\x22);`,
185+ `\u003cb\u003e \u0022foo%\u0022 O\u0027Reilly \u0026bar;`,
186+ `a[href =~ \u0022\/\/example.com\u0022]#foo`,
187+ `Hello, \u003cb\u003eWorld\u003c\/b\u003e \u0026amp;tc!`,
188+ ` dir=\u0022ltr\u0022`,
189+ `c \u0026\u0026 alert(\u0022Hello, World!\u0022);`,
190 // Escape sequence not over-escaped.
191- `Hello, World \x26 O\x27Reilly\x21`,
192- `greeting=H%69,\x26addressee=(World)`,
193- `greeting=H%69,\x26addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
194+ `Hello, World \u0026 O\u0027Reilly\u0021`,
195+ `greeting=H%69,\u0026addressee=(World)`,
196+ `greeting=H%69,\u0026addressee=(World) 2x, https:\/\/golang.org\/favicon.ico 500.5w`,
197 `,foo\/,`,
198 },
199 },
200@@ -253,7 +253,7 @@ func TestTypedContent(t *testing.T) {
201 `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
202 `%20dir%3d%22ltr%22`,
203 `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
204- `Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
205+ `Hello%2c%20World%20%26%20O%27Reilly%5cu0021`,
206 // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is done.
207 `greeting=H%69,&amp;addressee=%28World%29`,
208 `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`,
209@@ -268,7 +268,7 @@ func TestTypedContent(t *testing.T) {
210 `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
211 `%20dir%3d%22ltr%22`,
212 `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
213- `Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
214+ `Hello%2c%20World%20%26%20O%27Reilly%5cu0021`,
215 // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is not done.
216 `greeting=H%69,&addressee=%28World%29`,
217 `greeting%3dH%2569%2c%26addressee%3d%28World%29%202x%2c%20https%3a%2f%2fgolang.org%2ffavicon.ico%20500.5w`,
218diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
219index e72a9ba..c709660 100644
220--- a/src/html/template/escape_test.go
221+++ b/src/html/template/escape_test.go
222@@ -238,7 +238,7 @@ func TestEscape(t *testing.T) {
223 {
224 "jsStr",
225 "<button onclick='alert(&quot;{{.H}}&quot;)'>",
226- `<button onclick='alert(&quot;\x3cHello\x3e&quot;)'>`,
227+ `<button onclick='alert(&quot;\u003cHello\u003e&quot;)'>`,
228 },
229 {
230 "badMarshaler",
231@@ -259,7 +259,7 @@ func TestEscape(t *testing.T) {
232 {
233 "jsRe",
234 `<button onclick='alert(/{{"foo+bar"}}/.test(""))'>`,
235- `<button onclick='alert(/foo\x2bbar/.test(""))'>`,
236+ `<button onclick='alert(/foo\u002bbar/.test(""))'>`,
237 },
238 {
239 "jsReBlank",
240@@ -825,7 +825,7 @@ func TestEscapeSet(t *testing.T) {
241 "main": `<button onclick="title='{{template "helper"}}'; ...">{{template "helper"}}</button>`,
242 "helper": `{{11}} of {{"<100>"}}`,
243 },
244- `<button onclick="title='11 of \x3c100\x3e'; ...">11 of &lt;100&gt;</button>`,
245+ `<button onclick="title='11 of \u003c100\u003e'; ...">11 of &lt;100&gt;</button>`,
246 },
247 // A non-recursive template that ends in a different context.
248 // helper starts in jsCtxRegexp and ends in jsCtxDivOp.
249diff --git a/src/html/template/example_test.go b/src/html/template/example_test.go
250index 9d965f1..6cf936f 100644
251--- a/src/html/template/example_test.go
252+++ b/src/html/template/example_test.go
253@@ -116,9 +116,9 @@ func Example_escape() {
254 // &#34;Fran &amp; Freddie&#39;s Diner&#34; &lt;tasty@example.com&gt;
255 // &#34;Fran &amp; Freddie&#39;s Diner&#34; &lt;tasty@example.com&gt;
256 // &#34;Fran &amp; Freddie&#39;s Diner&#34;32&lt;tasty@example.com&gt;
257- // \"Fran \x26 Freddie\'s Diner\" \x3Ctasty@example.com\x3E
258- // \"Fran \x26 Freddie\'s Diner\" \x3Ctasty@example.com\x3E
259- // \"Fran \x26 Freddie\'s Diner\"32\x3Ctasty@example.com\x3E
260+ // \"Fran \u0026 Freddie\'s Diner\" \u003Ctasty@example.com\u003E
261+ // \"Fran \u0026 Freddie\'s Diner\" \u003Ctasty@example.com\u003E
262+ // \"Fran \u0026 Freddie\'s Diner\"32\u003Ctasty@example.com\u003E
263 // %22Fran+%26+Freddie%27s+Diner%2232%3Ctasty%40example.com%3E
264
265 }
266diff --git a/src/html/template/js.go b/src/html/template/js.go
267index 0e91458..ea9c183 100644
268--- a/src/html/template/js.go
269+++ b/src/html/template/js.go
270@@ -163,7 +163,6 @@ func jsValEscaper(args ...interface{}) string {
271 }
272 // TODO: detect cycles before calling Marshal which loops infinitely on
273 // cyclic data. This may be an unacceptable DoS risk.
274-
275 b, err := json.Marshal(a)
276 if err != nil {
277 // Put a space before comment so that if it is flush against
278@@ -178,8 +177,8 @@ func jsValEscaper(args ...interface{}) string {
279 // TODO: maybe post-process output to prevent it from containing
280 // "<!--", "-->", "<![CDATA[", "]]>", or "</script"
281 // in case custom marshalers produce output containing those.
282-
283- // TODO: Maybe abbreviate \u00ab to \xab to produce more compact output.
284+ // Note: Do not use \x escaping to save bytes because it is not JSON compatible and this escaper
285+ // supports ld+json content-type.
286 if len(b) == 0 {
287 // In, `x=y/{{.}}*z` a json.Marshaler that produces "" should
288 // not cause the output `x=y/*z`.
289@@ -260,6 +259,8 @@ func replace(s string, replacementTable []string) string {
290 r, w = utf8.DecodeRuneInString(s[i:])
291 var repl string
292 switch {
293+ case int(r) < len(lowUnicodeReplacementTable):
294+ repl = lowUnicodeReplacementTable[r]
295 case int(r) < len(replacementTable) && replacementTable[r] != "":
296 repl = replacementTable[r]
297 case r == '\u2028':
298@@ -283,67 +284,80 @@ func replace(s string, replacementTable []string) string {
299 return b.String()
300 }
301
302+var lowUnicodeReplacementTable = []string{
303+ 0: `\u0000`, 1: `\u0001`, 2: `\u0002`, 3: `\u0003`, 4: `\u0004`, 5: `\u0005`, 6: `\u0006`,
304+ '\a': `\u0007`,
305+ '\b': `\u0008`,
306+ '\t': `\t`,
307+ '\n': `\n`,
308+ '\v': `\u000b`, // "\v" == "v" on IE 6.
309+ '\f': `\f`,
310+ '\r': `\r`,
311+ 0xe: `\u000e`, 0xf: `\u000f`, 0x10: `\u0010`, 0x11: `\u0011`, 0x12: `\u0012`, 0x13: `\u0013`,
312+ 0x14: `\u0014`, 0x15: `\u0015`, 0x16: `\u0016`, 0x17: `\u0017`, 0x18: `\u0018`, 0x19: `\u0019`,
313+ 0x1a: `\u001a`, 0x1b: `\u001b`, 0x1c: `\u001c`, 0x1d: `\u001d`, 0x1e: `\u001e`, 0x1f: `\u001f`,
314+}
315+
316 var jsStrReplacementTable = []string{
317- 0: `\0`,
318+ 0: `\u0000`,
319 '\t': `\t`,
320 '\n': `\n`,
321- '\v': `\x0b`, // "\v" == "v" on IE 6.
322+ '\v': `\u000b`, // "\v" == "v" on IE 6.
323 '\f': `\f`,
324 '\r': `\r`,
325 // Encode HTML specials as hex so the output can be embedded
326 // in HTML attributes without further encoding.
327- '"': `\x22`,
328- '&': `\x26`,
329- '\'': `\x27`,
330- '+': `\x2b`,
331+ '"': `\u0022`,
332+ '&': `\u0026`,
333+ '\'': `\u0027`,
334+ '+': `\u002b`,
335 '/': `\/`,
336- '<': `\x3c`,
337- '>': `\x3e`,
338+ '<': `\u003c`,
339+ '>': `\u003e`,
340 '\\': `\\`,
341 }
342
343 // jsStrNormReplacementTable is like jsStrReplacementTable but does not
344 // overencode existing escapes since this table has no entry for `\`.
345 var jsStrNormReplacementTable = []string{
346- 0: `\0`,
347+ 0: `\u0000`,
348 '\t': `\t`,
349 '\n': `\n`,
350- '\v': `\x0b`, // "\v" == "v" on IE 6.
351+ '\v': `\u000b`, // "\v" == "v" on IE 6.
352 '\f': `\f`,
353 '\r': `\r`,
354 // Encode HTML specials as hex so the output can be embedded
355 // in HTML attributes without further encoding.
356- '"': `\x22`,
357- '&': `\x26`,
358- '\'': `\x27`,
359- '+': `\x2b`,
360+ '"': `\u0022`,
361+ '&': `\u0026`,
362+ '\'': `\u0027`,
363+ '+': `\u002b`,
364 '/': `\/`,
365- '<': `\x3c`,
366- '>': `\x3e`,
367+ '<': `\u003c`,
368+ '>': `\u003e`,
369 }
370-
371 var jsRegexpReplacementTable = []string{
372- 0: `\0`,
373+ 0: `\u0000`,
374 '\t': `\t`,
375 '\n': `\n`,
376- '\v': `\x0b`, // "\v" == "v" on IE 6.
377+ '\v': `\u000b`, // "\v" == "v" on IE 6.
378 '\f': `\f`,
379 '\r': `\r`,
380 // Encode HTML specials as hex so the output can be embedded
381 // in HTML attributes without further encoding.
382- '"': `\x22`,
383+ '"': `\u0022`,
384 '$': `\$`,
385- '&': `\x26`,
386- '\'': `\x27`,
387+ '&': `\u0026`,
388+ '\'': `\u0027`,
389 '(': `\(`,
390 ')': `\)`,
391 '*': `\*`,
392- '+': `\x2b`,
393+ '+': `\u002b`,
394 '-': `\-`,
395 '.': `\.`,
396 '/': `\/`,
397- '<': `\x3c`,
398- '>': `\x3e`,
399+ '<': `\u003c`,
400+ '>': `\u003e`,
401 '?': `\?`,
402 '[': `\[`,
403 '\\': `\\`,
404diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go
405index 075adaa..d7ee47b 100644
406--- a/src/html/template/js_test.go
407+++ b/src/html/template/js_test.go
408@@ -137,7 +137,7 @@ func TestJSValEscaper(t *testing.T) {
409 {"foo", `"foo"`},
410 // Newlines.
411 {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
412- // "\v" == "v" on IE 6 so use "\x0b" instead.
413+ // "\v" == "v" on IE 6 so use "\u000b" instead.
414 {"\t\x0b", `"\t\u000b"`},
415 {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
416 {[]interface{}{}, "[]"},
417@@ -173,7 +173,7 @@ func TestJSStrEscaper(t *testing.T) {
418 }{
419 {"", ``},
420 {"foo", `foo`},
421- {"\u0000", `\0`},
422+ {"\u0000", `\u0000`},
423 {"\t", `\t`},
424 {"\n", `\n`},
425 {"\r", `\r`},
426@@ -183,14 +183,14 @@ func TestJSStrEscaper(t *testing.T) {
427 {"\\n", `\\n`},
428 {"foo\r\nbar", `foo\r\nbar`},
429 // Preserve attribute boundaries.
430- {`"`, `\x22`},
431- {`'`, `\x27`},
432+ {`"`, `\u0022`},
433+ {`'`, `\u0027`},
434 // Allow embedding in HTML without further escaping.
435- {`&amp;`, `\x26amp;`},
436+ {`&amp;`, `\u0026amp;`},
437 // Prevent breaking out of text node and element boundaries.
438- {"</script>", `\x3c\/script\x3e`},
439- {"<![CDATA[", `\x3c![CDATA[`},
440- {"]]>", `]]\x3e`},
441+ {"</script>", `\u003c\/script\u003e`},
442+ {"<![CDATA[", `\u003c![CDATA[`},
443+ {"]]>", `]]\u003e`},
444 // https://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span
445 // "The text in style, script, title, and textarea elements
446 // must not have an escaping text span start that is not
447@@ -201,11 +201,11 @@ func TestJSStrEscaper(t *testing.T) {
448 // allow regular text content to be interpreted as script
449 // allowing script execution via a combination of a JS string
450 // injection followed by an HTML text injection.
451- {"<!--", `\x3c!--`},
452- {"-->", `--\x3e`},
453+ {"<!--", `\u003c!--`},
454+ {"-->", `--\u003e`},
455 // From https://code.google.com/p/doctype/wiki/ArticleUtf7
456 {"+ADw-script+AD4-alert(1)+ADw-/script+AD4-",
457- `\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`,
458+ `\u002bADw-script\u002bAD4-alert(1)\u002bADw-\/script\u002bAD4-`,
459 },
460 // Invalid UTF-8 sequence
461 {"foo\xA0bar", "foo\xA0bar"},
462@@ -228,7 +228,7 @@ func TestJSRegexpEscaper(t *testing.T) {
463 }{
464 {"", `(?:)`},
465 {"foo", `foo`},
466- {"\u0000", `\0`},
467+ {"\u0000", `\u0000`},
468 {"\t", `\t`},
469 {"\n", `\n`},
470 {"\r", `\r`},
471@@ -238,19 +238,19 @@ func TestJSRegexpEscaper(t *testing.T) {
472 {"\\n", `\\n`},
473 {"foo\r\nbar", `foo\r\nbar`},
474 // Preserve attribute boundaries.
475- {`"`, `\x22`},
476- {`'`, `\x27`},
477+ {`"`, `\u0022`},
478+ {`'`, `\u0027`},
479 // Allow embedding in HTML without further escaping.
480- {`&amp;`, `\x26amp;`},
481+ {`&amp;`, `\u0026amp;`},
482 // Prevent breaking out of text node and element boundaries.
483- {"</script>", `\x3c\/script\x3e`},
484- {"<![CDATA[", `\x3c!\[CDATA\[`},
485- {"]]>", `\]\]\x3e`},
486+ {"</script>", `\u003c\/script\u003e`},
487+ {"<![CDATA[", `\u003c!\[CDATA\[`},
488+ {"]]>", `\]\]\u003e`},
489 // Escaping text spans.
490- {"<!--", `\x3c!\-\-`},
491- {"-->", `\-\-\x3e`},
492+ {"<!--", `\u003c!\-\-`},
493+ {"-->", `\-\-\u003e`},
494 {"*", `\*`},
495- {"+", `\x2b`},
496+ {"+", `\u002b`},
497 {"?", `\?`},
498 {"[](){}", `\[\]\(\)\{\}`},
499 {"$foo|x.y", `\$foo\|x\.y`},
500@@ -284,27 +284,27 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
501 {
502 "jsStrEscaper",
503 jsStrEscaper,
504- "\\0\x01\x02\x03\x04\x05\x06\x07" +
505- "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
506- "\x10\x11\x12\x13\x14\x15\x16\x17" +
507- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
508- ` !\x22#$%\x26\x27()*\x2b,-.\/` +
509- `0123456789:;\x3c=\x3e?` +
510+ `\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007` +
511+ `\u0008\t\n\u000b\f\r\u000e\u000f` +
512+ `\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017` +
513+ `\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f` +
514+ ` !\u0022#$%\u0026\u0027()*\u002b,-.\/` +
515+ `0123456789:;\u003c=\u003e?` +
516 `@ABCDEFGHIJKLMNO` +
517 `PQRSTUVWXYZ[\\]^_` +
518 "`abcdefghijklmno" +
519- "pqrstuvwxyz{|}~\x7f" +
520+ "pqrstuvwxyz{|}~\u007f" +
521 "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
522 },
523 {
524 "jsRegexpEscaper",
525 jsRegexpEscaper,
526- "\\0\x01\x02\x03\x04\x05\x06\x07" +
527- "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
528- "\x10\x11\x12\x13\x14\x15\x16\x17" +
529- "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
530- ` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` +
531- `0123456789:;\x3c=\x3e\?` +
532+ `\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007` +
533+ `\u0008\t\n\u000b\f\r\u000e\u000f` +
534+ `\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017` +
535+ `\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f` +
536+ ` !\u0022#\$%\u0026\u0027\(\)\*\u002b,\-\.\/` +
537+ `0123456789:;\u003c=\u003e\?` +
538 `@ABCDEFGHIJKLMNO` +
539 `PQRSTUVWXYZ\[\\\]\^_` +
540 "`abcdefghijklmno" +
541diff --git a/src/html/template/template_test.go b/src/html/template/template_test.go
542index 13e6ba4..86bd4db 100644
543--- a/src/html/template/template_test.go
544+++ b/src/html/template/template_test.go
545@@ -6,6 +6,7 @@ package template_test
546
547 import (
548 "bytes"
549+ "encoding/json"
550 . "html/template"
551 "strings"
552 "testing"
553@@ -121,6 +122,44 @@ func TestNumbers(t *testing.T) {
554 c.mustExecute(c.root, nil, "12.34 7.5")
555 }
556
557+func TestStringsInScriptsWithJsonContentTypeAreCorrectlyEscaped(t *testing.T) {
558+ // See #33671 and #37634 for more context on this.
559+ tests := []struct{ name, in string }{
560+ {"empty", ""},
561+ {"invalid", string(rune(-1))},
562+ {"null", "\u0000"},
563+ {"unit separator", "\u001F"},
564+ {"tab", "\t"},
565+ {"gt and lt", "<>"},
566+ {"quotes", `'"`},
567+ {"ASCII letters", "ASCII letters"},
568+ {"Unicode", "ʕ⊙ϖ⊙ʔ"},
569+ {"Pizza", "P"},
570+ }
571+ const (
572+ prefix = `<script type="application/ld+json">`
573+ suffix = `</script>`
574+ templ = prefix + `"{{.}}"` + suffix
575+ )
576+ tpl := Must(New("JS string is JSON string").Parse(templ))
577+ for _, tt := range tests {
578+ t.Run(tt.name, func(t *testing.T) {
579+ var buf bytes.Buffer
580+ if err := tpl.Execute(&buf, tt.in); err != nil {
581+ t.Fatalf("Cannot render template: %v", err)
582+ }
583+ trimmed := bytes.TrimSuffix(bytes.TrimPrefix(buf.Bytes(), []byte(prefix)), []byte(suffix))
584+ var got string
585+ if err := json.Unmarshal(trimmed, &got); err != nil {
586+ t.Fatalf("Cannot parse JS string %q as JSON: %v", trimmed[1:len(trimmed)-1], err)
587+ }
588+ if got != tt.in {
589+ t.Errorf("Serialization changed the string value: got %q want %q", got, tt.in)
590+ }
591+ })
592+ }
593+}
594+
595 type testCase struct {
596 t *testing.T
597 root *Template
598diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go
599index 77294ed..b8a809e 100644
600--- a/src/text/template/exec_test.go
601+++ b/src/text/template/exec_test.go
602@@ -911,9 +911,9 @@ func TestJSEscaping(t *testing.T) {
603 {`Go "jump" \`, `Go \"jump\" \\`},
604 {`Yukihiro says "今日は世界"`, `Yukihiro says \"今日は世界\"`},
605 {"unprintable \uFDFF", `unprintable \uFDFF`},
606- {`<html>`, `\x3Chtml\x3E`},
607- {`no = in attributes`, `no \x3D in attributes`},
608- {`&#x27; does not become HTML entity`, `\x26#x27; does not become HTML entity`},
609+ {`<html>`, `\u003Chtml\u003E`},
610+ {`no = in attributes`, `no \u003D in attributes`},
611+ {`&#x27; does not become HTML entity`, `\u0026#x27; does not become HTML entity`},
612 }
613 for _, tc := range testCases {
614 s := JSEscapeString(tc.in)
615diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go
616index 46125bc..f3de9fb 100644
617--- a/src/text/template/funcs.go
618+++ b/src/text/template/funcs.go
619@@ -640,10 +640,10 @@ var (
620 jsBackslash = []byte(`\\`)
621 jsApos = []byte(`\'`)
622 jsQuot = []byte(`\"`)
623- jsLt = []byte(`\x3C`)
624- jsGt = []byte(`\x3E`)
625- jsAmp = []byte(`\x26`)
626- jsEq = []byte(`\x3D`)
627+ jsLt = []byte(`\u003C`)
628+ jsGt = []byte(`\u003E`)
629+ jsAmp = []byte(`\u0026`)
630+ jsEq = []byte(`\u003D`)
631 )
632
633 // JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
634--
6352.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 @@
1From 7ddce23c7d5b728acf8482f5006497c7b9915f8a Mon Sep 17 00:00:00 2001
2From: Ariel Mashraki <ariel@mashraki.co.il>
3Date: Wed, 22 Apr 2020 22:17:56 +0300
4Subject: [PATCH 3/6] text/template: add CommentNode to template parse tree
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Fixes #34652
10
11Change-Id: Icf6e3eda593fed826736f34f95a9d66f5450cc98
12Reviewed-on: https://go-review.googlesource.com/c/go/+/229398
13Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
14Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
15TryBot-Result: Gobot Gobot <gobot@golang.org>
16
17Dependency Patch #3
18
19Upstream-Status: Backport from https://github.com/golang/go/commit/c8ea03828b0645b1fd5725888e44873b75fcfbb6
20CVE: CVE-2023-24538
21Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
22---
23 api/next.txt | 19 +++++++++++++++++++
24 src/html/template/escape.go | 2 ++
25 src/html/template/template_test.go | 16 ++++++++++++++++
26 src/text/template/exec.go | 1 +
27 src/text/template/parse/lex.go | 8 +++++++-
28 src/text/template/parse/lex_test.go | 7 +++++--
29 src/text/template/parse/node.go | 33 +++++++++++++++++++++++++++++++++
30 src/text/template/parse/parse.go | 22 +++++++++++++++++++---
31 src/text/template/parse/parse_test.go | 25 +++++++++++++++++++++++++
32 9 files changed, 127 insertions(+), 6 deletions(-)
33
34diff --git a/api/next.txt b/api/next.txt
35index e69de29..076f39e 100644
36--- a/api/next.txt
37+++ b/api/next.txt
38@@ -0,0 +1,19 @@
39+pkg unicode, const Version = "13.0.0"
40+pkg unicode, var Chorasmian *RangeTable
41+pkg unicode, var Dives_Akuru *RangeTable
42+pkg unicode, var Khitan_Small_Script *RangeTable
43+pkg unicode, var Yezidi *RangeTable
44+pkg text/template/parse, const NodeComment = 20
45+pkg text/template/parse, const NodeComment NodeType
46+pkg text/template/parse, const ParseComments = 1
47+pkg text/template/parse, const ParseComments Mode
48+pkg text/template/parse, method (*CommentNode) Copy() Node
49+pkg text/template/parse, method (*CommentNode) String() string
50+pkg text/template/parse, method (CommentNode) Position() Pos
51+pkg text/template/parse, method (CommentNode) Type() NodeType
52+pkg text/template/parse, type CommentNode struct
53+pkg text/template/parse, type CommentNode struct, Text string
54+pkg text/template/parse, type CommentNode struct, embedded NodeType
55+pkg text/template/parse, type CommentNode struct, embedded Pos
56+pkg text/template/parse, type Mode uint
57+pkg text/template/parse, type Tree struct, Mode Mode
58diff --git a/src/html/template/escape.go b/src/html/template/escape.go
59index f12dafa..8739735 100644
60--- a/src/html/template/escape.go
61+++ b/src/html/template/escape.go
62@@ -124,6 +124,8 @@ func (e *escaper) escape(c context, n parse.Node) context {
63 switch n := n.(type) {
64 case *parse.ActionNode:
65 return e.escapeAction(c, n)
66+ case *parse.CommentNode:
67+ return c
68 case *parse.IfNode:
69 return e.escapeBranch(c, &n.BranchNode, "if")
70 case *parse.ListNode:
71diff --git a/src/html/template/template_test.go b/src/html/template/template_test.go
72index 86bd4db..1f2c888 100644
73--- a/src/html/template/template_test.go
74+++ b/src/html/template/template_test.go
75@@ -10,6 +10,7 @@ import (
76 . "html/template"
77 "strings"
78 "testing"
79+ "text/template/parse"
80 )
81
82 func TestTemplateClone(t *testing.T) {
83@@ -160,6 +161,21 @@ func TestStringsInScriptsWithJsonContentTypeAreCorrectlyEscaped(t *testing.T) {
84 }
85 }
86
87+func TestSkipEscapeComments(t *testing.T) {
88+ c := newTestCase(t)
89+ tr := parse.New("root")
90+ tr.Mode = parse.ParseComments
91+ newT, err := tr.Parse("{{/* A comment */}}{{ 1 }}{{/* Another comment */}}", "", "", make(map[string]*parse.Tree))
92+ if err != nil {
93+ t.Fatalf("Cannot parse template text: %v", err)
94+ }
95+ c.root, err = c.root.AddParseTree("root", newT)
96+ if err != nil {
97+ t.Fatalf("Cannot add parse tree to template: %v", err)
98+ }
99+ c.mustExecute(c.root, nil, "1")
100+}
101+
102 type testCase struct {
103 t *testing.T
104 root *Template
105diff --git a/src/text/template/exec.go b/src/text/template/exec.go
106index ac3e741..7ac5175 100644
107--- a/src/text/template/exec.go
108+++ b/src/text/template/exec.go
109@@ -256,6 +256,7 @@ func (s *state) walk(dot reflect.Value, node parse.Node) {
110 if len(node.Pipe.Decl) == 0 {
111 s.printValue(node, val)
112 }
113+ case *parse.CommentNode:
114 case *parse.IfNode:
115 s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
116 case *parse.ListNode:
117diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go
118index 30371f2..e41373a 100644
119--- a/src/text/template/parse/lex.go
120+++ b/src/text/template/parse/lex.go
121@@ -41,6 +41,7 @@ const (
122 itemBool // boolean constant
123 itemChar // printable ASCII character; grab bag for comma etc.
124 itemCharConstant // character constant
125+ itemComment // comment text
126 itemComplex // complex constant (1+2i); imaginary is just a number
127 itemAssign // equals ('=') introducing an assignment
128 itemDeclare // colon-equals (':=') introducing a declaration
129@@ -112,6 +113,7 @@ type lexer struct {
130 leftDelim string // start of action
131 rightDelim string // end of action
132 trimRightDelim string // end of action with trim marker
133+ emitComment bool // emit itemComment tokens.
134 pos Pos // current position in the input
135 start Pos // start position of this item
136 width Pos // width of last rune read from input
137@@ -203,7 +205,7 @@ func (l *lexer) drain() {
138 }
139
140 // lex creates a new scanner for the input string.
141-func lex(name, input, left, right string) *lexer {
142+func lex(name, input, left, right string, emitComment bool) *lexer {
143 if left == "" {
144 left = leftDelim
145 }
146@@ -216,6 +218,7 @@ func lex(name, input, left, right string) *lexer {
147 leftDelim: left,
148 rightDelim: right,
149 trimRightDelim: rightTrimMarker + right,
150+ emitComment: emitComment,
151 items: make(chan item),
152 line: 1,
153 startLine: 1,
154@@ -323,6 +326,9 @@ func lexComment(l *lexer) stateFn {
155 if !delim {
156 return l.errorf("comment ends before closing delimiter")
157 }
158+ if l.emitComment {
159+ l.emit(itemComment)
160+ }
161 if trimSpace {
162 l.pos += trimMarkerLen
163 }
164diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go
165index 563c4fc..f6d5f28 100644
166--- a/src/text/template/parse/lex_test.go
167+++ b/src/text/template/parse/lex_test.go
168@@ -15,6 +15,7 @@ var itemName = map[itemType]string{
169 itemBool: "bool",
170 itemChar: "char",
171 itemCharConstant: "charconst",
172+ itemComment: "comment",
173 itemComplex: "complex",
174 itemDeclare: ":=",
175 itemEOF: "EOF",
176@@ -90,6 +91,7 @@ var lexTests = []lexTest{
177 {"text", `now is the time`, []item{mkItem(itemText, "now is the time"), tEOF}},
178 {"text with comment", "hello-{{/* this is a comment */}}-world", []item{
179 mkItem(itemText, "hello-"),
180+ mkItem(itemComment, "/* this is a comment */"),
181 mkItem(itemText, "-world"),
182 tEOF,
183 }},
184@@ -311,6 +313,7 @@ var lexTests = []lexTest{
185 }},
186 {"trimming spaces before and after comment", "hello- {{- /* hello */ -}} -world", []item{
187 mkItem(itemText, "hello-"),
188+ mkItem(itemComment, "/* hello */"),
189 mkItem(itemText, "-world"),
190 tEOF,
191 }},
192@@ -389,7 +392,7 @@ var lexTests = []lexTest{
193
194 // collect gathers the emitted items into a slice.
195 func collect(t *lexTest, left, right string) (items []item) {
196- l := lex(t.name, t.input, left, right)
197+ l := lex(t.name, t.input, left, right, true)
198 for {
199 item := l.nextItem()
200 items = append(items, item)
201@@ -529,7 +532,7 @@ func TestPos(t *testing.T) {
202 func TestShutdown(t *testing.T) {
203 // We need to duplicate template.Parse here to hold on to the lexer.
204 const text = "erroneous{{define}}{{else}}1234"
205- lexer := lex("foo", text, "{{", "}}")
206+ lexer := lex("foo", text, "{{", "}}", false)
207 _, err := New("root").parseLexer(lexer)
208 if err == nil {
209 t.Fatalf("expected error")
210diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go
211index 1c116ea..a9dad5e 100644
212--- a/src/text/template/parse/node.go
213+++ b/src/text/template/parse/node.go
214@@ -70,6 +70,7 @@ const (
215 NodeTemplate // A template invocation action.
216 NodeVariable // A $ variable.
217 NodeWith // A with action.
218+ NodeComment // A comment.
219 )
220
221 // Nodes.
222@@ -149,6 +150,38 @@ func (t *TextNode) Copy() Node {
223 return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)}
224 }
225
226+// CommentNode holds a comment.
227+type CommentNode struct {
228+ NodeType
229+ Pos
230+ tr *Tree
231+ Text string // Comment text.
232+}
233+
234+func (t *Tree) newComment(pos Pos, text string) *CommentNode {
235+ return &CommentNode{tr: t, NodeType: NodeComment, Pos: pos, Text: text}
236+}
237+
238+func (c *CommentNode) String() string {
239+ var sb strings.Builder
240+ c.writeTo(&sb)
241+ return sb.String()
242+}
243+
244+func (c *CommentNode) writeTo(sb *strings.Builder) {
245+ sb.WriteString("{{")
246+ sb.WriteString(c.Text)
247+ sb.WriteString("}}")
248+}
249+
250+func (c *CommentNode) tree() *Tree {
251+ return c.tr
252+}
253+
254+func (c *CommentNode) Copy() Node {
255+ return &CommentNode{tr: c.tr, NodeType: NodeComment, Pos: c.Pos, Text: c.Text}
256+}
257+
258 // PipeNode holds a pipeline with optional declaration
259 type PipeNode struct {
260 NodeType
261diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go
262index c9b80f4..496d8bf 100644
263--- a/src/text/template/parse/parse.go
264+++ b/src/text/template/parse/parse.go
265@@ -21,6 +21,7 @@ type Tree struct {
266 Name string // name of the template represented by the tree.
267 ParseName string // name of the top-level template during parsing, for error messages.
268 Root *ListNode // top-level root of the tree.
269+ Mode Mode // parsing mode.
270 text string // text parsed to create the template (or its parent)
271 // Parsing only; cleared after parse.
272 funcs []map[string]interface{}
273@@ -29,8 +30,16 @@ type Tree struct {
274 peekCount int
275 vars []string // variables defined at the moment.
276 treeSet map[string]*Tree
277+ mode Mode
278 }
279
280+// A mode value is a set of flags (or 0). Modes control parser behavior.
281+type Mode uint
282+
283+const (
284+ ParseComments Mode = 1 << iota // parse comments and add them to AST
285+)
286+
287 // Copy returns a copy of the Tree. Any parsing state is discarded.
288 func (t *Tree) Copy() *Tree {
289 if t == nil {
290@@ -220,7 +229,8 @@ func (t *Tree) stopParse() {
291 func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
292 defer t.recover(&err)
293 t.ParseName = t.Name
294- t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim), treeSet)
295+ emitComment := t.Mode&ParseComments != 0
296+ t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim, emitComment), treeSet)
297 t.text = text
298 t.parse()
299 t.add()
300@@ -240,12 +250,14 @@ func (t *Tree) add() {
301 }
302 }
303
304-// IsEmptyTree reports whether this tree (node) is empty of everything but space.
305+// IsEmptyTree reports whether this tree (node) is empty of everything but space or comments.
306 func IsEmptyTree(n Node) bool {
307 switch n := n.(type) {
308 case nil:
309 return true
310 case *ActionNode:
311+ case *CommentNode:
312+ return true
313 case *IfNode:
314 case *ListNode:
315 for _, node := range n.Nodes {
316@@ -276,6 +288,7 @@ func (t *Tree) parse() {
317 if t.nextNonSpace().typ == itemDefine {
318 newT := New("definition") // name will be updated once we know it.
319 newT.text = t.text
320+ newT.Mode = t.Mode
321 newT.ParseName = t.ParseName
322 newT.startParse(t.funcs, t.lex, t.treeSet)
323 newT.parseDefinition()
324@@ -331,13 +344,15 @@ func (t *Tree) itemList() (list *ListNode, next Node) {
325 }
326
327 // textOrAction:
328-// text | action
329+// text | comment | action
330 func (t *Tree) textOrAction() Node {
331 switch token := t.nextNonSpace(); token.typ {
332 case itemText:
333 return t.newText(token.pos, token.val)
334 case itemLeftDelim:
335 return t.action()
336+ case itemComment:
337+ return t.newComment(token.pos, token.val)
338 default:
339 t.unexpected(token, "input")
340 }
341@@ -539,6 +554,7 @@ func (t *Tree) blockControl() Node {
342
343 block := New(name) // name will be updated once we know it.
344 block.text = t.text
345+ block.Mode = t.Mode
346 block.ParseName = t.ParseName
347 block.startParse(t.funcs, t.lex, t.treeSet)
348 var end Node
349diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go
350index 4e09a78..d9c13c5 100644
351--- a/src/text/template/parse/parse_test.go
352+++ b/src/text/template/parse/parse_test.go
353@@ -348,6 +348,30 @@ func TestParseCopy(t *testing.T) {
354 testParse(true, t)
355 }
356
357+func TestParseWithComments(t *testing.T) {
358+ textFormat = "%q"
359+ defer func() { textFormat = "%s" }()
360+ tests := [...]parseTest{
361+ {"comment", "{{/*\n\n\n*/}}", noError, "{{/*\n\n\n*/}}"},
362+ {"comment trim left", "x \r\n\t{{- /* hi */}}", noError, `"x"{{/* hi */}}`},
363+ {"comment trim right", "{{/* hi */ -}}\n\n\ty", noError, `{{/* hi */}}"y"`},
364+ {"comment trim left and right", "x \r\n\t{{- /* */ -}}\n\n\ty", noError, `"x"{{/* */}}"y"`},
365+ }
366+ for _, test := range tests {
367+ t.Run(test.name, func(t *testing.T) {
368+ tr := New(test.name)
369+ tr.Mode = ParseComments
370+ tmpl, err := tr.Parse(test.input, "", "", make(map[string]*Tree))
371+ if err != nil {
372+ t.Errorf("%q: expected error; got none", test.name)
373+ }
374+ if result := tmpl.Root.String(); result != test.result {
375+ t.Errorf("%s=(%q): got\n\t%v\nexpected\n\t%v", test.name, test.input, result, test.result)
376+ }
377+ })
378+ }
379+}
380+
381 type isEmptyTest struct {
382 name string
383 input string
384@@ -358,6 +382,7 @@ var isEmptyTests = []isEmptyTest{
385 {"empty", ``, true},
386 {"nonempty", `hello`, false},
387 {"spaces only", " \t\n \t\n", true},
388+ {"comment only", "{{/* comment */}}", true},
389 {"definition", `{{define "x"}}something{{end}}`, true},
390 {"definitions and space", "{{define `x`}}something{{end}}\n\n{{define `y`}}something{{end}}\n\n", true},
391 {"definitions and text", "{{define `x`}}something{{end}}\nx\n{{define `y`}}something{{end}}\ny\n", false},
392--
3932.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 @@
1From 760d88497091fb5d6d231a18e6f4e06ecb9af9b2 Mon Sep 17 00:00:00 2001
2From: Russ Cox <rsc@golang.org>
3Date: Thu, 10 Sep 2020 18:53:26 -0400
4Subject: [PATCH 4/6] text/template: allow newlines inside action delimiters
5
6This allows multiline constructs like:
7
8 {{"hello" |
9 printf}}
10
11Now that unclosed actions can span multiple lines,
12track and report the start of the action when reporting errors.
13
14Also clean up a few "unexpected <error message>" to be just "<error message>".
15
16Fixes #29770.
17
18Change-Id: I54c6c016029a8328b7902a4b6d85eab713ec3285
19Reviewed-on: https://go-review.googlesource.com/c/go/+/254257
20Trust: Russ Cox <rsc@golang.org>
21Run-TryBot: Russ Cox <rsc@golang.org>
22TryBot-Result: Go Bot <gobot@golang.org>
23Reviewed-by: Rob Pike <r@golang.org>
24
25Dependency Patch #4
26
27Upstream-Status: Backport from https://github.com/golang/go/commit/9384d34c58099657bb1b133beaf3ff37ada9b017
28CVE: CVE-2023-24538
29Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
30---
31 src/text/template/doc.go | 21 ++++-----
32 src/text/template/exec_test.go | 2 +-
33 src/text/template/parse/lex.go | 84 +++++++++++++++++------------------
34 src/text/template/parse/lex_test.go | 2 +-
35 src/text/template/parse/parse.go | 59 +++++++++++++-----------
36 src/text/template/parse/parse_test.go | 36 ++++++++++++---
37 6 files changed, 117 insertions(+), 87 deletions(-)
38
39diff --git a/src/text/template/doc.go b/src/text/template/doc.go
40index 4b0efd2..7b30294 100644
41--- a/src/text/template/doc.go
42+++ b/src/text/template/doc.go
43@@ -40,16 +40,17 @@ More intricate examples appear below.
44 Text and spaces
45
46 By default, all text between actions is copied verbatim when the template is
47-executed. For example, the string " items are made of " in the example above appears
48-on standard output when the program is run.
49-
50-However, to aid in formatting template source code, if an action's left delimiter
51-(by default "{{") is followed immediately by a minus sign and ASCII space character
52-("{{- "), all trailing white space is trimmed from the immediately preceding text.
53-Similarly, if the right delimiter ("}}") is preceded by a space and minus sign
54-(" -}}"), all leading white space is trimmed from the immediately following text.
55-In these trim markers, the ASCII space must be present; "{{-3}}" parses as an
56-action containing the number -3.
57+executed. For example, the string " items are made of " in the example above
58+appears on standard output when the program is run.
59+
60+However, to aid in formatting template source code, if an action's left
61+delimiter (by default "{{") is followed immediately by a minus sign and white
62+space, all trailing white space is trimmed from the immediately preceding text.
63+Similarly, if the right delimiter ("}}") is preceded by white space and a minus
64+sign, all leading white space is trimmed from the immediately following text.
65+In these trim markers, the white space must be present:
66+"{{- 3}}" is like "{{3}}" but trims the immediately preceding text, while
67+"{{-3}}" parses as an action containing the number -3.
68
69 For instance, when executing the template whose source is
70
71diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go
72index b8a809e..3309b33 100644
73--- a/src/text/template/exec_test.go
74+++ b/src/text/template/exec_test.go
75@@ -1295,7 +1295,7 @@ func TestUnterminatedStringError(t *testing.T) {
76 t.Fatal("expected error")
77 }
78 str := err.Error()
79- if !strings.Contains(str, "X:3: unexpected unterminated raw quoted string") {
80+ if !strings.Contains(str, "X:3: unterminated raw quoted string") {
81 t.Fatalf("unexpected error: %s", str)
82 }
83 }
84diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go
85index e41373a..6784071 100644
86--- a/src/text/template/parse/lex.go
87+++ b/src/text/template/parse/lex.go
88@@ -92,15 +92,14 @@ const eof = -1
89 // If the action begins "{{- " rather than "{{", then all space/tab/newlines
90 // preceding the action are trimmed; conversely if it ends " -}}" the
91 // leading spaces are trimmed. This is done entirely in the lexer; the
92-// parser never sees it happen. We require an ASCII space to be
93-// present to avoid ambiguity with things like "{{-3}}". It reads
94+// parser never sees it happen. We require an ASCII space (' ', \t, \r, \n)
95+// to be present to avoid ambiguity with things like "{{-3}}". It reads
96 // better with the space present anyway. For simplicity, only ASCII
97-// space does the job.
98+// does the job.
99 const (
100- spaceChars = " \t\r\n" // These are the space characters defined by Go itself.
101- leftTrimMarker = "- " // Attached to left delimiter, trims trailing spaces from preceding text.
102- rightTrimMarker = " -" // Attached to right delimiter, trims leading spaces from following text.
103- trimMarkerLen = Pos(len(leftTrimMarker))
104+ spaceChars = " \t\r\n" // These are the space characters defined by Go itself.
105+ trimMarker = '-' // Attached to left/right delimiter, trims trailing spaces from preceding/following text.
106+ trimMarkerLen = Pos(1 + 1) // marker plus space before or after
107 )
108
109 // stateFn represents the state of the scanner as a function that returns the next state.
110@@ -108,19 +107,18 @@ type stateFn func(*lexer) stateFn
111
112 // lexer holds the state of the scanner.
113 type lexer struct {
114- name string // the name of the input; used only for error reports
115- input string // the string being scanned
116- leftDelim string // start of action
117- rightDelim string // end of action
118- trimRightDelim string // end of action with trim marker
119- emitComment bool // emit itemComment tokens.
120- pos Pos // current position in the input
121- start Pos // start position of this item
122- width Pos // width of last rune read from input
123- items chan item // channel of scanned items
124- parenDepth int // nesting depth of ( ) exprs
125- line int // 1+number of newlines seen
126- startLine int // start line of this item
127+ name string // the name of the input; used only for error reports
128+ input string // the string being scanned
129+ leftDelim string // start of action
130+ rightDelim string // end of action
131+ emitComment bool // emit itemComment tokens.
132+ pos Pos // current position in the input
133+ start Pos // start position of this item
134+ width Pos // width of last rune read from input
135+ items chan item // channel of scanned items
136+ parenDepth int // nesting depth of ( ) exprs
137+ line int // 1+number of newlines seen
138+ startLine int // start line of this item
139 }
140
141 // next returns the next rune in the input.
142@@ -213,15 +211,14 @@ func lex(name, input, left, right string, emitComment bool) *lexer {
143 right = rightDelim
144 }
145 l := &lexer{
146- name: name,
147- input: input,
148- leftDelim: left,
149- rightDelim: right,
150- trimRightDelim: rightTrimMarker + right,
151- emitComment: emitComment,
152- items: make(chan item),
153- line: 1,
154- startLine: 1,
155+ name: name,
156+ input: input,
157+ leftDelim: left,
158+ rightDelim: right,
159+ emitComment: emitComment,
160+ items: make(chan item),
161+ line: 1,
162+ startLine: 1,
163 }
164 go l.run()
165 return l
166@@ -251,7 +248,7 @@ func lexText(l *lexer) stateFn {
167 ldn := Pos(len(l.leftDelim))
168 l.pos += Pos(x)
169 trimLength := Pos(0)
170- if strings.HasPrefix(l.input[l.pos+ldn:], leftTrimMarker) {
171+ if hasLeftTrimMarker(l.input[l.pos+ldn:]) {
172 trimLength = rightTrimLength(l.input[l.start:l.pos])
173 }
174 l.pos -= trimLength
175@@ -280,7 +277,7 @@ func rightTrimLength(s string) Pos {
176
177 // atRightDelim reports whether the lexer is at a right delimiter, possibly preceded by a trim marker.
178 func (l *lexer) atRightDelim() (delim, trimSpaces bool) {
179- if strings.HasPrefix(l.input[l.pos:], l.trimRightDelim) { // With trim marker.
180+ if hasRightTrimMarker(l.input[l.pos:]) && strings.HasPrefix(l.input[l.pos+trimMarkerLen:], l.rightDelim) { // With trim marker.
181 return true, true
182 }
183 if strings.HasPrefix(l.input[l.pos:], l.rightDelim) { // Without trim marker.
184@@ -297,7 +294,7 @@ func leftTrimLength(s string) Pos {
185 // lexLeftDelim scans the left delimiter, which is known to be present, possibly with a trim marker.
186 func lexLeftDelim(l *lexer) stateFn {
187 l.pos += Pos(len(l.leftDelim))
188- trimSpace := strings.HasPrefix(l.input[l.pos:], leftTrimMarker)
189+ trimSpace := hasLeftTrimMarker(l.input[l.pos:])
190 afterMarker := Pos(0)
191 if trimSpace {
192 afterMarker = trimMarkerLen
193@@ -342,7 +339,7 @@ func lexComment(l *lexer) stateFn {
194
195 // lexRightDelim scans the right delimiter, which is known to be present, possibly with a trim marker.
196 func lexRightDelim(l *lexer) stateFn {
197- trimSpace := strings.HasPrefix(l.input[l.pos:], rightTrimMarker)
198+ trimSpace := hasRightTrimMarker(l.input[l.pos:])
199 if trimSpace {
200 l.pos += trimMarkerLen
201 l.ignore()
202@@ -369,7 +366,7 @@ func lexInsideAction(l *lexer) stateFn {
203 return l.errorf("unclosed left paren")
204 }
205 switch r := l.next(); {
206- case r == eof || isEndOfLine(r):
207+ case r == eof:
208 return l.errorf("unclosed action")
209 case isSpace(r):
210 l.backup() // Put space back in case we have " -}}".
211@@ -439,7 +436,7 @@ func lexSpace(l *lexer) stateFn {
212 }
213 // Be careful about a trim-marked closing delimiter, which has a minus
214 // after a space. We know there is a space, so check for the '-' that might follow.
215- if strings.HasPrefix(l.input[l.pos-1:], l.trimRightDelim) {
216+ if hasRightTrimMarker(l.input[l.pos-1:]) && strings.HasPrefix(l.input[l.pos-1+trimMarkerLen:], l.rightDelim) {
217 l.backup() // Before the space.
218 if numSpaces == 1 {
219 return lexRightDelim // On the delim, so go right to that.
220@@ -526,7 +523,7 @@ func lexFieldOrVariable(l *lexer, typ itemType) stateFn {
221 // day to implement arithmetic.
222 func (l *lexer) atTerminator() bool {
223 r := l.peek()
224- if isSpace(r) || isEndOfLine(r) {
225+ if isSpace(r) {
226 return true
227 }
228 switch r {
229@@ -657,15 +654,18 @@ Loop:
230
231 // isSpace reports whether r is a space character.
232 func isSpace(r rune) bool {
233- return r == ' ' || r == '\t'
234-}
235-
236-// isEndOfLine reports whether r is an end-of-line character.
237-func isEndOfLine(r rune) bool {
238- return r == '\r' || r == '\n'
239+ return r == ' ' || r == '\t' || r == '\r' || r == '\n'
240 }
241
242 // isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
243 func isAlphaNumeric(r rune) bool {
244 return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
245 }
246+
247+func hasLeftTrimMarker(s string) bool {
248+ return len(s) >= 2 && s[0] == trimMarker && isSpace(rune(s[1]))
249+}
250+
251+func hasRightTrimMarker(s string) bool {
252+ return len(s) >= 2 && isSpace(rune(s[0])) && s[1] == trimMarker
253+}
254diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go
255index f6d5f28..6510eed 100644
256--- a/src/text/template/parse/lex_test.go
257+++ b/src/text/template/parse/lex_test.go
258@@ -323,7 +323,7 @@ var lexTests = []lexTest{
259 tLeft,
260 mkItem(itemError, "unrecognized character in action: U+0001"),
261 }},
262- {"unclosed action", "{{\n}}", []item{
263+ {"unclosed action", "{{", []item{
264 tLeft,
265 mkItem(itemError, "unclosed action"),
266 }},
267diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go
268index 496d8bf..5e6e512 100644
269--- a/src/text/template/parse/parse.go
270+++ b/src/text/template/parse/parse.go
271@@ -24,13 +24,14 @@ type Tree struct {
272 Mode Mode // parsing mode.
273 text string // text parsed to create the template (or its parent)
274 // Parsing only; cleared after parse.
275- funcs []map[string]interface{}
276- lex *lexer
277- token [3]item // three-token lookahead for parser.
278- peekCount int
279- vars []string // variables defined at the moment.
280- treeSet map[string]*Tree
281- mode Mode
282+ funcs []map[string]interface{}
283+ lex *lexer
284+ token [3]item // three-token lookahead for parser.
285+ peekCount int
286+ vars []string // variables defined at the moment.
287+ treeSet map[string]*Tree
288+ actionLine int // line of left delim starting action
289+ mode Mode
290 }
291
292 // A mode value is a set of flags (or 0). Modes control parser behavior.
293@@ -187,6 +188,16 @@ func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
294
295 // unexpected complains about the token and terminates processing.
296 func (t *Tree) unexpected(token item, context string) {
297+ if token.typ == itemError {
298+ extra := ""
299+ if t.actionLine != 0 && t.actionLine != token.line {
300+ extra = fmt.Sprintf(" in action started at %s:%d", t.ParseName, t.actionLine)
301+ if strings.HasSuffix(token.val, " action") {
302+ extra = extra[len(" in action"):] // avoid "action in action"
303+ }
304+ }
305+ t.errorf("%s%s", token, extra)
306+ }
307 t.errorf("unexpected %s in %s", token, context)
308 }
309
310@@ -350,6 +361,8 @@ func (t *Tree) textOrAction() Node {
311 case itemText:
312 return t.newText(token.pos, token.val)
313 case itemLeftDelim:
314+ t.actionLine = token.line
315+ defer t.clearActionLine()
316 return t.action()
317 case itemComment:
318 return t.newComment(token.pos, token.val)
319@@ -359,6 +372,10 @@ func (t *Tree) textOrAction() Node {
320 return nil
321 }
322
323+func (t *Tree) clearActionLine() {
324+ t.actionLine = 0
325+}
326+
327 // Action:
328 // control
329 // command ("|" command)*
330@@ -384,12 +401,12 @@ func (t *Tree) action() (n Node) {
331 t.backup()
332 token := t.peek()
333 // Do not pop variables; they persist until "end".
334- return t.newAction(token.pos, token.line, t.pipeline("command"))
335+ return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim))
336 }
337
338 // Pipeline:
339 // declarations? command ('|' command)*
340-func (t *Tree) pipeline(context string) (pipe *PipeNode) {
341+func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) {
342 token := t.peekNonSpace()
343 pipe = t.newPipeline(token.pos, token.line, nil)
344 // Are there declarations or assignments?
345@@ -430,12 +447,9 @@ decls:
346 }
347 for {
348 switch token := t.nextNonSpace(); token.typ {
349- case itemRightDelim, itemRightParen:
350+ case end:
351 // At this point, the pipeline is complete
352 t.checkPipeline(pipe, context)
353- if token.typ == itemRightParen {
354- t.backup()
355- }
356 return
357 case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
358 itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen:
359@@ -464,7 +478,7 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context string) {
360
361 func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
362 defer t.popVars(len(t.vars))
363- pipe = t.pipeline(context)
364+ pipe = t.pipeline(context, itemRightDelim)
365 var next Node
366 list, next = t.itemList()
367 switch next.Type() {
368@@ -550,7 +564,7 @@ func (t *Tree) blockControl() Node {
369
370 token := t.nextNonSpace()
371 name := t.parseTemplateName(token, context)
372- pipe := t.pipeline(context)
373+ pipe := t.pipeline(context, itemRightDelim)
374
375 block := New(name) // name will be updated once we know it.
376 block.text = t.text
377@@ -580,7 +594,7 @@ func (t *Tree) templateControl() Node {
378 if t.nextNonSpace().typ != itemRightDelim {
379 t.backup()
380 // Do not pop variables; they persist until "end".
381- pipe = t.pipeline(context)
382+ pipe = t.pipeline(context, itemRightDelim)
383 }
384 return t.newTemplate(token.pos, token.line, name, pipe)
385 }
386@@ -614,13 +628,12 @@ func (t *Tree) command() *CommandNode {
387 switch token := t.next(); token.typ {
388 case itemSpace:
389 continue
390- case itemError:
391- t.errorf("%s", token.val)
392 case itemRightDelim, itemRightParen:
393 t.backup()
394 case itemPipe:
395+ // nothing here; break loop below
396 default:
397- t.errorf("unexpected %s in operand", token)
398+ t.unexpected(token, "operand")
399 }
400 break
401 }
402@@ -675,8 +688,6 @@ func (t *Tree) operand() Node {
403 // A nil return means the next item is not a term.
404 func (t *Tree) term() Node {
405 switch token := t.nextNonSpace(); token.typ {
406- case itemError:
407- t.errorf("%s", token.val)
408 case itemIdentifier:
409 if !t.hasFunction(token.val) {
410 t.errorf("function %q not defined", token.val)
411@@ -699,11 +710,7 @@ func (t *Tree) term() Node {
412 }
413 return number
414 case itemLeftParen:
415- pipe := t.pipeline("parenthesized pipeline")
416- if token := t.next(); token.typ != itemRightParen {
417- t.errorf("unclosed right paren: unexpected %s", token)
418- }
419- return pipe
420+ return t.pipeline("parenthesized pipeline", itemRightParen)
421 case itemString, itemRawString:
422 s, err := strconv.Unquote(token.val)
423 if err != nil {
424diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go
425index d9c13c5..220f984 100644
426--- a/src/text/template/parse/parse_test.go
427+++ b/src/text/template/parse/parse_test.go
428@@ -250,6 +250,13 @@ var parseTests = []parseTest{
429 {"comment trim left and right", "x \r\n\t{{- /* */ -}}\n\n\ty", noError, `"x""y"`},
430 {"block definition", `{{block "foo" .}}hello{{end}}`, noError,
431 `{{template "foo" .}}`},
432+
433+ {"newline in assignment", "{{ $x \n := \n 1 \n }}", noError, "{{$x := 1}}"},
434+ {"newline in empty action", "{{\n}}", hasError, "{{\n}}"},
435+ {"newline in pipeline", "{{\n\"x\"\n|\nprintf\n}}", noError, `{{"x" | printf}}`},
436+ {"newline in comment", "{{/*\nhello\n*/}}", noError, ""},
437+ {"newline in comment", "{{-\n/*\nhello\n*/\n-}}", noError, ""},
438+
439 // Errors.
440 {"unclosed action", "hello{{range", hasError, ""},
441 {"unmatched end", "{{end}}", hasError, ""},
442@@ -426,23 +433,38 @@ var errorTests = []parseTest{
443 // Check line numbers are accurate.
444 {"unclosed1",
445 "line1\n{{",
446- hasError, `unclosed1:2: unexpected unclosed action in command`},
447+ hasError, `unclosed1:2: unclosed action`},
448 {"unclosed2",
449 "line1\n{{define `x`}}line2\n{{",
450- hasError, `unclosed2:3: unexpected unclosed action in command`},
451+ hasError, `unclosed2:3: unclosed action`},
452+ {"unclosed3",
453+ "line1\n{{\"x\"\n\"y\"\n",
454+ hasError, `unclosed3:4: unclosed action started at unclosed3:2`},
455+ {"unclosed4",
456+ "{{\n\n\n\n\n",
457+ hasError, `unclosed4:6: unclosed action started at unclosed4:1`},
458+ {"var1",
459+ "line1\n{{\nx\n}}",
460+ hasError, `var1:3: function "x" not defined`},
461 // Specific errors.
462 {"function",
463 "{{foo}}",
464 hasError, `function "foo" not defined`},
465- {"comment",
466+ {"comment1",
467 "{{/*}}",
468- hasError, `unclosed comment`},
469+ hasError, `comment1:1: unclosed comment`},
470+ {"comment2",
471+ "{{/*\nhello\n}}",
472+ hasError, `comment2:1: unclosed comment`},
473 {"lparen",
474 "{{.X (1 2 3}}",
475 hasError, `unclosed left paren`},
476 {"rparen",
477- "{{.X 1 2 3)}}",
478- hasError, `unexpected ")"`},
479+ "{{.X 1 2 3 ) }}",
480+ hasError, `unexpected ")" in command`},
481+ {"rparen2",
482+ "{{(.X 1 2 3",
483+ hasError, `unclosed action`},
484 {"space",
485 "{{`x`3}}",
486 hasError, `in operand`},
487@@ -488,7 +510,7 @@ var errorTests = []parseTest{
488 hasError, `missing value for parenthesized pipeline`},
489 {"multilinerawstring",
490 "{{ $v := `\n` }} {{",
491- hasError, `multilinerawstring:2: unexpected unclosed action`},
492+ hasError, `multilinerawstring:2: unclosed action`},
493 {"rangeundefvar",
494 "{{range $k}}{{end}}",
495 hasError, `undefined variable`},
496--
4972.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 @@
1From e0e6bca6ddc0e6d9fa3a5b644af9b446924fbf83 Mon Sep 17 00:00:00 2001
2From: Russ Cox <rsc@golang.org>
3Date: Thu, 20 May 2021 12:46:33 -0400
4Subject: [PATCH 5/6] html/template, text/template: implement break and
5 continue for range loops
6
7Break and continue for range loops was accepted as a proposal in June 2017.
8It was implemented in CL 66410 (Oct 2017)
9but then rolled back in CL 92155 (Feb 2018)
10because html/template changes had not been implemented.
11
12This CL reimplements break and continue in text/template
13and then adds support for them in html/template as well.
14
15Fixes #20531.
16
17Change-Id: I05330482a976f1c078b4b49c2287bd9031bb7616
18Reviewed-on: https://go-review.googlesource.com/c/go/+/321491
19Trust: Russ Cox <rsc@golang.org>
20Run-TryBot: Russ Cox <rsc@golang.org>
21TryBot-Result: Go Bot <gobot@golang.org>
22Reviewed-by: Rob Pike <r@golang.org>
23
24Dependency Patch #5
25
26Upstream-Status: Backport from https://github.com/golang/go/commit/d0dd26a88c019d54f22463daae81e785f5867565
27CVE: CVE-2023-24538
28Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
29---
30 src/html/template/context.go | 4 ++
31 src/html/template/escape.go | 71 ++++++++++++++++++++++++++++++++++-
32 src/html/template/escape_test.go | 24 ++++++++++++
33 src/text/template/doc.go | 8 ++++
34 src/text/template/exec.go | 24 +++++++++++-
35 src/text/template/exec_test.go | 2 +
36 src/text/template/parse/lex.go | 13 ++++++-
37 src/text/template/parse/lex_test.go | 2 +
38 src/text/template/parse/node.go | 36 ++++++++++++++++++
39 src/text/template/parse/parse.go | 42 ++++++++++++++++++++-
40 src/text/template/parse/parse_test.go | 8 ++++
41 11 files changed, 230 insertions(+), 4 deletions(-)
42
43diff --git a/src/html/template/context.go b/src/html/template/context.go
44index f7d4849..aaa7d08 100644
45--- a/src/html/template/context.go
46+++ b/src/html/template/context.go
47@@ -6,6 +6,7 @@ package template
48
49 import (
50 "fmt"
51+ "text/template/parse"
52 )
53
54 // context describes the state an HTML parser must be in when it reaches the
55@@ -22,6 +23,7 @@ type context struct {
56 jsCtx jsCtx
57 attr attr
58 element element
59+ n parse.Node // for range break/continue
60 err *Error
61 }
62
63@@ -141,6 +143,8 @@ const (
64 // stateError is an infectious error state outside any valid
65 // HTML/CSS/JS construct.
66 stateError
67+ // stateDead marks unreachable code after a {{break}} or {{continue}}.
68+ stateDead
69 )
70
71 // isComment is true for any state that contains content meant for template
72diff --git a/src/html/template/escape.go b/src/html/template/escape.go
73index 8739735..6dea79c 100644
74--- a/src/html/template/escape.go
75+++ b/src/html/template/escape.go
76@@ -97,6 +97,15 @@ type escaper struct {
77 actionNodeEdits map[*parse.ActionNode][]string
78 templateNodeEdits map[*parse.TemplateNode]string
79 textNodeEdits map[*parse.TextNode][]byte
80+ // rangeContext holds context about the current range loop.
81+ rangeContext *rangeContext
82+}
83+
84+// rangeContext holds information about the current range loop.
85+type rangeContext struct {
86+ outer *rangeContext // outer loop
87+ breaks []context // context at each break action
88+ continues []context // context at each continue action
89 }
90
91 // makeEscaper creates a blank escaper for the given set.
92@@ -109,6 +118,7 @@ func makeEscaper(n *nameSpace) escaper {
93 map[*parse.ActionNode][]string{},
94 map[*parse.TemplateNode]string{},
95 map[*parse.TextNode][]byte{},
96+ nil,
97 }
98 }
99
100@@ -124,8 +134,16 @@ func (e *escaper) escape(c context, n parse.Node) context {
101 switch n := n.(type) {
102 case *parse.ActionNode:
103 return e.escapeAction(c, n)
104+ case *parse.BreakNode:
105+ c.n = n
106+ e.rangeContext.breaks = append(e.rangeContext.breaks, c)
107+ return context{state: stateDead}
108 case *parse.CommentNode:
109 return c
110+ case *parse.ContinueNode:
111+ c.n = n
112+ e.rangeContext.continues = append(e.rangeContext.breaks, c)
113+ return context{state: stateDead}
114 case *parse.IfNode:
115 return e.escapeBranch(c, &n.BranchNode, "if")
116 case *parse.ListNode:
117@@ -427,6 +445,12 @@ func join(a, b context, node parse.Node, nodeName string) context {
118 if b.state == stateError {
119 return b
120 }
121+ if a.state == stateDead {
122+ return b
123+ }
124+ if b.state == stateDead {
125+ return a
126+ }
127 if a.eq(b) {
128 return a
129 }
130@@ -466,14 +490,27 @@ func join(a, b context, node parse.Node, nodeName string) context {
131
132 // escapeBranch escapes a branch template node: "if", "range" and "with".
133 func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context {
134+ if nodeName == "range" {
135+ e.rangeContext = &rangeContext{outer: e.rangeContext}
136+ }
137 c0 := e.escapeList(c, n.List)
138- if nodeName == "range" && c0.state != stateError {
139+ if nodeName == "range" {
140+ if c0.state != stateError {
141+ c0 = joinRange(c0, e.rangeContext)
142+ }
143+ e.rangeContext = e.rangeContext.outer
144+ if c0.state == stateError {
145+ return c0
146+ }
147+
148 // The "true" branch of a "range" node can execute multiple times.
149 // We check that executing n.List once results in the same context
150 // as executing n.List twice.
151+ e.rangeContext = &rangeContext{outer: e.rangeContext}
152 c1, _ := e.escapeListConditionally(c0, n.List, nil)
153 c0 = join(c0, c1, n, nodeName)
154 if c0.state == stateError {
155+ e.rangeContext = e.rangeContext.outer
156 // Make clear that this is a problem on loop re-entry
157 // since developers tend to overlook that branch when
158 // debugging templates.
159@@ -481,11 +518,39 @@ func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string)
160 c0.err.Description = "on range loop re-entry: " + c0.err.Description
161 return c0
162 }
163+ c0 = joinRange(c0, e.rangeContext)
164+ e.rangeContext = e.rangeContext.outer
165+ if c0.state == stateError {
166+ return c0
167+ }
168 }
169 c1 := e.escapeList(c, n.ElseList)
170 return join(c0, c1, n, nodeName)
171 }
172
173+func joinRange(c0 context, rc *rangeContext) context {
174+ // Merge contexts at break and continue statements into overall body context.
175+ // In theory we could treat breaks differently from continues, but for now it is
176+ // enough to treat them both as going back to the start of the loop (which may then stop).
177+ for _, c := range rc.breaks {
178+ c0 = join(c0, c, c.n, "range")
179+ if c0.state == stateError {
180+ c0.err.Line = c.n.(*parse.BreakNode).Line
181+ c0.err.Description = "at range loop break: " + c0.err.Description
182+ return c0
183+ }
184+ }
185+ for _, c := range rc.continues {
186+ c0 = join(c0, c, c.n, "range")
187+ if c0.state == stateError {
188+ c0.err.Line = c.n.(*parse.ContinueNode).Line
189+ c0.err.Description = "at range loop continue: " + c0.err.Description
190+ return c0
191+ }
192+ }
193+ return c0
194+}
195+
196 // escapeList escapes a list template node.
197 func (e *escaper) escapeList(c context, n *parse.ListNode) context {
198 if n == nil {
199@@ -493,6 +558,9 @@ func (e *escaper) escapeList(c context, n *parse.ListNode) context {
200 }
201 for _, m := range n.Nodes {
202 c = e.escape(c, m)
203+ if c.state == stateDead {
204+ break
205+ }
206 }
207 return c
208 }
209@@ -503,6 +571,7 @@ func (e *escaper) escapeList(c context, n *parse.ListNode) context {
210 // which is the same as whether e was updated.
211 func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) {
212 e1 := makeEscaper(e.ns)
213+ e1.rangeContext = e.rangeContext
214 // Make type inferences available to f.
215 for k, v := range e.output {
216 e1.output[k] = v
217diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
218index c709660..fa2b84a 100644
219--- a/src/html/template/escape_test.go
220+++ b/src/html/template/escape_test.go
221@@ -920,6 +920,22 @@ func TestErrors(t *testing.T) {
222 "<a href='/foo?{{range .Items}}&{{.K}}={{.V}}{{end}}'>",
223 "",
224 },
225+ {
226+ "{{range .Items}}<a{{if .X}}{{end}}>{{end}}",
227+ "",
228+ },
229+ {
230+ "{{range .Items}}<a{{if .X}}{{end}}>{{continue}}{{end}}",
231+ "",
232+ },
233+ {
234+ "{{range .Items}}<a{{if .X}}{{end}}>{{break}}{{end}}",
235+ "",
236+ },
237+ {
238+ "{{range .Items}}<a{{if .X}}{{end}}>{{if .X}}{{break}}{{end}}{{end}}",
239+ "",
240+ },
241 // Error cases.
242 {
243 "{{if .Cond}}<a{{end}}",
244@@ -956,6 +972,14 @@ func TestErrors(t *testing.T) {
245 "z:2:8: on range loop re-entry: {{range}} branches",
246 },
247 {
248+ "{{range .Items}}<a{{if .X}}{{break}}{{end}}>{{end}}",
249+ "z:1:29: at range loop break: {{range}} branches end in different contexts",
250+ },
251+ {
252+ "{{range .Items}}<a{{if .X}}{{continue}}{{end}}>{{end}}",
253+ "z:1:29: at range loop continue: {{range}} branches end in different contexts",
254+ },
255+ {
256 "<a b=1 c={{.H}}",
257 "z: ends in a non-text context: {stateAttr delimSpaceOrTagEnd",
258 },
259diff --git a/src/text/template/doc.go b/src/text/template/doc.go
260index 7b30294..0228b15 100644
261--- a/src/text/template/doc.go
262+++ b/src/text/template/doc.go
263@@ -112,6 +112,14 @@ data, defined in detail in the corresponding sections that follow.
264 T0 is executed; otherwise, dot is set to the successive elements
265 of the array, slice, or map and T1 is executed.
266
267+ {{break}}
268+ The innermost {{range pipeline}} loop is ended early, stopping the
269+ current iteration and bypassing all remaining iterations.
270+
271+ {{continue}}
272+ The current iteration of the innermost {{range pipeline}} loop is
273+ stopped, and the loop starts the next iteration.
274+
275 {{template "name"}}
276 The template with the specified name is executed with nil data.
277
278diff --git a/src/text/template/exec.go b/src/text/template/exec.go
279index 7ac5175..6cb140a 100644
280--- a/src/text/template/exec.go
281+++ b/src/text/template/exec.go
282@@ -5,6 +5,7 @@
283 package template
284
285 import (
286+ "errors"
287 "fmt"
288 "internal/fmtsort"
289 "io"
290@@ -244,6 +245,12 @@ func (t *Template) DefinedTemplates() string {
291 return b.String()
292 }
293
294+// Sentinel errors for use with panic to signal early exits from range loops.
295+var (
296+ walkBreak = errors.New("break")
297+ walkContinue = errors.New("continue")
298+)
299+
300 // Walk functions step through the major pieces of the template structure,
301 // generating output as they go.
302 func (s *state) walk(dot reflect.Value, node parse.Node) {
303@@ -256,7 +263,11 @@ func (s *state) walk(dot reflect.Value, node parse.Node) {
304 if len(node.Pipe.Decl) == 0 {
305 s.printValue(node, val)
306 }
307+ case *parse.BreakNode:
308+ panic(walkBreak)
309 case *parse.CommentNode:
310+ case *parse.ContinueNode:
311+ panic(walkContinue)
312 case *parse.IfNode:
313 s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
314 case *parse.ListNode:
315@@ -335,6 +346,11 @@ func isTrue(val reflect.Value) (truth, ok bool) {
316
317 func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
318 s.at(r)
319+ defer func() {
320+ if r := recover(); r != nil && r != walkBreak {
321+ panic(r)
322+ }
323+ }()
324 defer s.pop(s.mark())
325 val, _ := indirect(s.evalPipeline(dot, r.Pipe))
326 // mark top of stack before any variables in the body are pushed.
327@@ -348,8 +364,14 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
328 if len(r.Pipe.Decl) > 1 {
329 s.setTopVar(2, index)
330 }
331+ defer s.pop(mark)
332+ defer func() {
333+ // Consume panic(walkContinue)
334+ if r := recover(); r != nil && r != walkContinue {
335+ panic(r)
336+ }
337+ }()
338 s.walk(elem, r.List)
339- s.pop(mark)
340 }
341 switch val.Kind() {
342 case reflect.Array, reflect.Slice:
343diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go
344index 3309b33..a639f44 100644
345--- a/src/text/template/exec_test.go
346+++ b/src/text/template/exec_test.go
347@@ -563,6 +563,8 @@ var execTests = []execTest{
348 {"range empty no else", "{{range .SIEmpty}}-{{.}}-{{end}}", "", tVal, true},
349 {"range []int else", "{{range .SI}}-{{.}}-{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true},
350 {"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
351+ {"range []int break else", "{{range .SI}}-{{.}}-{{break}}NOTREACHED{{else}}EMPTY{{end}}", "-3-", tVal, true},
352+ {"range []int continue else", "{{range .SI}}-{{.}}-{{continue}}NOTREACHED{{else}}EMPTY{{end}}", "-3--4--5-", tVal, true},
353 {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true},
354 {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true},
355 {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true},
356diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go
357index 6784071..95e3377 100644
358--- a/src/text/template/parse/lex.go
359+++ b/src/text/template/parse/lex.go
360@@ -62,6 +62,8 @@ const (
361 // Keywords appear after all the rest.
362 itemKeyword // used only to delimit the keywords
363 itemBlock // block keyword
364+ itemBreak // break keyword
365+ itemContinue // continue keyword
366 itemDot // the cursor, spelled '.'
367 itemDefine // define keyword
368 itemElse // else keyword
369@@ -76,6 +78,8 @@ const (
370 var key = map[string]itemType{
371 ".": itemDot,
372 "block": itemBlock,
373+ "break": itemBreak,
374+ "continue": itemContinue,
375 "define": itemDefine,
376 "else": itemElse,
377 "end": itemEnd,
378@@ -119,6 +123,8 @@ type lexer struct {
379 parenDepth int // nesting depth of ( ) exprs
380 line int // 1+number of newlines seen
381 startLine int // start line of this item
382+ breakOK bool // break keyword allowed
383+ continueOK bool // continue keyword allowed
384 }
385
386 // next returns the next rune in the input.
387@@ -461,7 +467,12 @@ Loop:
388 }
389 switch {
390 case key[word] > itemKeyword:
391- l.emit(key[word])
392+ item := key[word]
393+ if item == itemBreak && !l.breakOK || item == itemContinue && !l.continueOK {
394+ l.emit(itemIdentifier)
395+ } else {
396+ l.emit(item)
397+ }
398 case word[0] == '.':
399 l.emit(itemField)
400 case word == "true", word == "false":
401diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go
402index 6510eed..df6aabf 100644
403--- a/src/text/template/parse/lex_test.go
404+++ b/src/text/template/parse/lex_test.go
405@@ -35,6 +35,8 @@ var itemName = map[itemType]string{
406 // keywords
407 itemDot: ".",
408 itemBlock: "block",
409+ itemBreak: "break",
410+ itemContinue: "continue",
411 itemDefine: "define",
412 itemElse: "else",
413 itemIf: "if",
414diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go
415index a9dad5e..c398da0 100644
416--- a/src/text/template/parse/node.go
417+++ b/src/text/template/parse/node.go
418@@ -71,6 +71,8 @@ const (
419 NodeVariable // A $ variable.
420 NodeWith // A with action.
421 NodeComment // A comment.
422+ NodeBreak // A break action.
423+ NodeContinue // A continue action.
424 )
425
426 // Nodes.
427@@ -907,6 +909,40 @@ func (i *IfNode) Copy() Node {
428 return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
429 }
430
431+// BreakNode represents a {{break}} action.
432+type BreakNode struct {
433+ tr *Tree
434+ NodeType
435+ Pos
436+ Line int
437+}
438+
439+func (t *Tree) newBreak(pos Pos, line int) *BreakNode {
440+ return &BreakNode{tr: t, NodeType: NodeBreak, Pos: pos, Line: line}
441+}
442+
443+func (b *BreakNode) Copy() Node { return b.tr.newBreak(b.Pos, b.Line) }
444+func (b *BreakNode) String() string { return "{{break}}" }
445+func (b *BreakNode) tree() *Tree { return b.tr }
446+func (b *BreakNode) writeTo(sb *strings.Builder) { sb.WriteString("{{break}}") }
447+
448+// ContinueNode represents a {{continue}} action.
449+type ContinueNode struct {
450+ tr *Tree
451+ NodeType
452+ Pos
453+ Line int
454+}
455+
456+func (t *Tree) newContinue(pos Pos, line int) *ContinueNode {
457+ return &ContinueNode{tr: t, NodeType: NodeContinue, Pos: pos, Line: line}
458+}
459+
460+func (c *ContinueNode) Copy() Node { return c.tr.newContinue(c.Pos, c.Line) }
461+func (c *ContinueNode) String() string { return "{{continue}}" }
462+func (c *ContinueNode) tree() *Tree { return c.tr }
463+func (c *ContinueNode) writeTo(sb *strings.Builder) { sb.WriteString("{{continue}}") }
464+
465 // RangeNode represents a {{range}} action and its commands.
466 type RangeNode struct {
467 BranchNode
468diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go
469index 5e6e512..7f78b56 100644
470--- a/src/text/template/parse/parse.go
471+++ b/src/text/template/parse/parse.go
472@@ -31,6 +31,7 @@ type Tree struct {
473 vars []string // variables defined at the moment.
474 treeSet map[string]*Tree
475 actionLine int // line of left delim starting action
476+ rangeDepth int
477 mode Mode
478 }
479
480@@ -223,6 +224,8 @@ func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer, treeSet ma
481 t.vars = []string{"$"}
482 t.funcs = funcs
483 t.treeSet = treeSet
484+ lex.breakOK = !t.hasFunction("break")
485+ lex.continueOK = !t.hasFunction("continue")
486 }
487
488 // stopParse terminates parsing.
489@@ -385,6 +388,10 @@ func (t *Tree) action() (n Node) {
490 switch token := t.nextNonSpace(); token.typ {
491 case itemBlock:
492 return t.blockControl()
493+ case itemBreak:
494+ return t.breakControl(token.pos, token.line)
495+ case itemContinue:
496+ return t.continueControl(token.pos, token.line)
497 case itemElse:
498 return t.elseControl()
499 case itemEnd:
500@@ -404,6 +411,32 @@ func (t *Tree) action() (n Node) {
501 return t.newAction(token.pos, token.line, t.pipeline("command", itemRightDelim))
502 }
503
504+// Break:
505+// {{break}}
506+// Break keyword is past.
507+func (t *Tree) breakControl(pos Pos, line int) Node {
508+ if token := t.next(); token.typ != itemRightDelim {
509+ t.unexpected(token, "in {{break}}")
510+ }
511+ if t.rangeDepth == 0 {
512+ t.errorf("{{break}} outside {{range}}")
513+ }
514+ return t.newBreak(pos, line)
515+}
516+
517+// Continue:
518+// {{continue}}
519+// Continue keyword is past.
520+func (t *Tree) continueControl(pos Pos, line int) Node {
521+ if token := t.next(); token.typ != itemRightDelim {
522+ t.unexpected(token, "in {{continue}}")
523+ }
524+ if t.rangeDepth == 0 {
525+ t.errorf("{{continue}} outside {{range}}")
526+ }
527+ return t.newContinue(pos, line)
528+}
529+
530 // Pipeline:
531 // declarations? command ('|' command)*
532 func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) {
533@@ -479,8 +512,14 @@ func (t *Tree) checkPipeline(pipe *PipeNode, context string) {
534 func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
535 defer t.popVars(len(t.vars))
536 pipe = t.pipeline(context, itemRightDelim)
537+ if context == "range" {
538+ t.rangeDepth++
539+ }
540 var next Node
541 list, next = t.itemList()
542+ if context == "range" {
543+ t.rangeDepth--
544+ }
545 switch next.Type() {
546 case nodeEnd: //done
547 case nodeElse:
548@@ -522,7 +561,8 @@ func (t *Tree) ifControl() Node {
549 // {{range pipeline}} itemList {{else}} itemList {{end}}
550 // Range keyword is past.
551 func (t *Tree) rangeControl() Node {
552- return t.newRange(t.parseControl(false, "range"))
553+ r := t.newRange(t.parseControl(false, "range"))
554+ return r
555 }
556
557 // With:
558diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go
559index 220f984..ba45636 100644
560--- a/src/text/template/parse/parse_test.go
561+++ b/src/text/template/parse/parse_test.go
562@@ -230,6 +230,10 @@ var parseTests = []parseTest{
563 `{{range $x := .SI}}{{.}}{{end}}`},
564 {"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
565 `{{range $x, $y := .SI}}{{.}}{{end}}`},
566+ {"range with break", "{{range .SI}}{{.}}{{break}}{{end}}", noError,
567+ `{{range .SI}}{{.}}{{break}}{{end}}`},
568+ {"range with continue", "{{range .SI}}{{.}}{{continue}}{{end}}", noError,
569+ `{{range .SI}}{{.}}{{continue}}{{end}}`},
570 {"constants", "{{range .SI 1 -3.2i true false 'a' nil}}{{end}}", noError,
571 `{{range .SI 1 -3.2i true false 'a' nil}}{{end}}`},
572 {"template", "{{template `x`}}", noError,
573@@ -279,6 +283,10 @@ var parseTests = []parseTest{
574 {"adjacent args", "{{printf 3`x`}}", hasError, ""},
575 {"adjacent args with .", "{{printf `x`.}}", hasError, ""},
576 {"extra end after if", "{{if .X}}a{{else if .Y}}b{{end}}{{end}}", hasError, ""},
577+ {"break outside range", "{{range .}}{{end}} {{break}}", hasError, ""},
578+ {"continue outside range", "{{range .}}{{end}} {{continue}}", hasError, ""},
579+ {"break in range else", "{{range .}}{{else}}{{break}}{{end}}", hasError, ""},
580+ {"continue in range else", "{{range .}}{{else}}{{continue}}{{end}}", hasError, ""},
581 // Other kinds of assignments and operators aren't available yet.
582 {"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
583 {"bug0b", "{{$x += 1}}{{$x}}", hasError, ""},
584--
5852.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 @@
1From 16f4882984569f179d73967c9eee679bb9b098c5 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Mon, 20 Mar 2023 11:01:13 -0700
4Subject: [PATCH 6/6] html/template: disallow actions in JS template literals
5
6ECMAScript 6 introduced template literals[0][1] which are delimited with
7backticks. These need to be escaped in a similar fashion to the
8delimiters for other string literals. Additionally template literals can
9contain special syntax for string interpolation.
10
11There is no clear way to allow safe insertion of actions within JS
12template literals, as handling (JS) string interpolation inside of these
13literals is rather complex. As such we've chosen to simply disallow
14template actions within these template literals.
15
16A new error code is added for this parsing failure case, errJsTmplLit,
17but it is unexported as it is not backwards compatible with other minor
18release versions to introduce an API change in a minor release. We will
19export this code in the next major release.
20
21The previous behavior (with the cavet that backticks are now escaped
22properly) can be re-enabled with GODEBUG=jstmpllitinterp=1.
23
24This change subsumes CL471455.
25
26Thanks to Sohom Datta, Manipal Institute of Technology, for reporting
27this issue.
28
29Fixes CVE-2023-24538
30For #59234
31Fixes #59271
32
33[0] https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-template-literals
34[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
35
36Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802457
37Reviewed-by: Damien Neil <dneil@google.com>
38Run-TryBot: Damien Neil <dneil@google.com>
39Reviewed-by: Julie Qiu <julieqiu@google.com>
40Reviewed-by: Roland Shoemaker <bracewell@google.com>
41Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802612
42Run-TryBot: Roland Shoemaker <bracewell@google.com>
43Change-Id: Ic7f10595615f2b2740d9c85ad7ef40dc0e78c04c
44Reviewed-on: https://go-review.googlesource.com/c/go/+/481987
45Auto-Submit: Michael Knyszek <mknyszek@google.com>
46TryBot-Result: Gopher Robot <gobot@golang.org>
47Run-TryBot: Michael Knyszek <mknyszek@google.com>
48Reviewed-by: Matthew Dempsky <mdempsky@google.com>
49
50Upstream-Status: Backport from https://github.com/golang/go/commit/b1e3ecfa06b67014429a197ec5e134ce4303ad9b
51CVE: CVE-2023-24538
52Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
53---
54 src/html/template/context.go | 2 ++
55 src/html/template/error.go | 13 ++++++++
56 src/html/template/escape.go | 11 +++++++
57 src/html/template/escape_test.go | 66 ++++++++++++++++++++++-----------------
58 src/html/template/js.go | 2 ++
59 src/html/template/js_test.go | 2 +-
60 src/html/template/jsctx_string.go | 9 ++++++
61 src/html/template/state_string.go | 37 ++++++++++++++++++++--
62 src/html/template/transition.go | 7 ++++-
63 9 files changed, 116 insertions(+), 33 deletions(-)
64
65diff --git a/src/html/template/context.go b/src/html/template/context.go
66index f7d4849..0b65313 100644
67--- a/src/html/template/context.go
68+++ b/src/html/template/context.go
69@@ -116,6 +116,8 @@ const (
70 stateJSDqStr
71 // stateJSSqStr occurs inside a JavaScript single quoted string.
72 stateJSSqStr
73+ // stateJSBqStr occurs inside a JavaScript back quoted string.
74+ stateJSBqStr
75 // stateJSRegexp occurs inside a JavaScript regexp literal.
76 stateJSRegexp
77 // stateJSBlockCmt occurs inside a JavaScript /* block comment */.
78diff --git a/src/html/template/error.go b/src/html/template/error.go
79index 0e52706..fd26b64 100644
80--- a/src/html/template/error.go
81+++ b/src/html/template/error.go
82@@ -211,6 +211,19 @@ const (
83 // pipeline occurs in an unquoted attribute value context, "html" is
84 // disallowed. Avoid using "html" and "urlquery" entirely in new templates.
85 ErrPredefinedEscaper
86+
87+ // errJSTmplLit: "... appears in a JS template literal"
88+ // Example:
89+ // <script>var tmpl = `{{.Interp}`</script>
90+ // Discussion:
91+ // Package html/template does not support actions inside of JS template
92+ // literals.
93+ //
94+ // TODO(rolandshoemaker): we cannot add this as an exported error in a minor
95+ // release, since it is backwards incompatible with the other minor
96+ // releases. As such we need to leave it unexported, and then we'll add it
97+ // in the next major release.
98+ errJSTmplLit
99 )
100
101 func (e *Error) Error() string {
102diff --git a/src/html/template/escape.go b/src/html/template/escape.go
103index f12dafa..29ca5b3 100644
104--- a/src/html/template/escape.go
105+++ b/src/html/template/escape.go
106@@ -8,6 +8,7 @@ import (
107 "bytes"
108 "fmt"
109 "html"
110+ "internal/godebug"
111 "io"
112 "text/template"
113 "text/template/parse"
114@@ -203,6 +204,16 @@ func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
115 c.jsCtx = jsCtxDivOp
116 case stateJSDqStr, stateJSSqStr:
117 s = append(s, "_html_template_jsstrescaper")
118+ case stateJSBqStr:
119+ debugAllowActionJSTmpl := godebug.Get("jstmpllitinterp")
120+ if debugAllowActionJSTmpl == "1" {
121+ s = append(s, "_html_template_jsstrescaper")
122+ } else {
123+ return context{
124+ state: stateError,
125+ err: errorf(errJSTmplLit, n, n.Line, "%s appears in a JS template literal", n),
126+ }
127+ }
128 case stateJSRegexp:
129 s = append(s, "_html_template_jsregexpescaper")
130 case stateCSS:
131diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
132index fa2b84a..1b150e9 100644
133--- a/src/html/template/escape_test.go
134+++ b/src/html/template/escape_test.go
135@@ -681,35 +681,31 @@ func TestEscape(t *testing.T) {
136 }
137
138 for _, test := range tests {
139- tmpl := New(test.name)
140- tmpl = Must(tmpl.Parse(test.input))
141- // Check for bug 6459: Tree field was not set in Parse.
142- if tmpl.Tree != tmpl.text.Tree {
143- t.Errorf("%s: tree not set properly", test.name)
144- continue
145- }
146- b := new(bytes.Buffer)
147- if err := tmpl.Execute(b, data); err != nil {
148- t.Errorf("%s: template execution failed: %s", test.name, err)
149- continue
150- }
151- if w, g := test.output, b.String(); w != g {
152- t.Errorf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
153- continue
154- }
155- b.Reset()
156- if err := tmpl.Execute(b, pdata); err != nil {
157- t.Errorf("%s: template execution failed for pointer: %s", test.name, err)
158- continue
159- }
160- if w, g := test.output, b.String(); w != g {
161- t.Errorf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g)
162- continue
163- }
164- if tmpl.Tree != tmpl.text.Tree {
165- t.Errorf("%s: tree mismatch", test.name)
166- continue
167- }
168+ t.Run(test.name, func(t *testing.T) {
169+ tmpl := New(test.name)
170+ tmpl = Must(tmpl.Parse(test.input))
171+ // Check for bug 6459: Tree field was not set in Parse.
172+ if tmpl.Tree != tmpl.text.Tree {
173+ t.Fatalf("%s: tree not set properly", test.name)
174+ }
175+ b := new(strings.Builder)
176+ if err := tmpl.Execute(b, data); err != nil {
177+ t.Fatalf("%s: template execution failed: %s", test.name, err)
178+ }
179+ if w, g := test.output, b.String(); w != g {
180+ t.Fatalf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
181+ }
182+ b.Reset()
183+ if err := tmpl.Execute(b, pdata); err != nil {
184+ t.Fatalf("%s: template execution failed for pointer: %s", test.name, err)
185+ }
186+ if w, g := test.output, b.String(); w != g {
187+ t.Fatalf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g)
188+ }
189+ if tmpl.Tree != tmpl.text.Tree {
190+ t.Fatalf("%s: tree mismatch", test.name)
191+ }
192+ })
193 }
194 }
195
196@@ -936,6 +932,10 @@ func TestErrors(t *testing.T) {
197 "{{range .Items}}<a{{if .X}}{{end}}>{{if .X}}{{break}}{{end}}{{end}}",
198 "",
199 },
200+ {
201+ "<script>var a = `${a+b}`</script>`",
202+ "",
203+ },
204 // Error cases.
205 {
206 "{{if .Cond}}<a{{end}}",
207@@ -1082,6 +1082,10 @@ func TestErrors(t *testing.T) {
208 // html is allowed since it is the last command in the pipeline, but urlquery is not.
209 `predefined escaper "urlquery" disallowed in template`,
210 },
211+ {
212+ "<script>var tmpl = `asd {{.}}`;</script>",
213+ `{{.}} appears in a JS template literal`,
214+ },
215 }
216 for _, test := range tests {
217 buf := new(bytes.Buffer)
218@@ -1304,6 +1308,10 @@ func TestEscapeText(t *testing.T) {
219 context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
220 },
221 {
222+ "<a onclick=\"`foo",
223+ context{state: stateJSBqStr, delim: delimDoubleQuote, attr: attrScript},
224+ },
225+ {
226 `<A ONCLICK="'`,
227 context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
228 },
229diff --git a/src/html/template/js.go b/src/html/template/js.go
230index ea9c183..b888eaf 100644
231--- a/src/html/template/js.go
232+++ b/src/html/template/js.go
233@@ -308,6 +308,7 @@ var jsStrReplacementTable = []string{
234 // Encode HTML specials as hex so the output can be embedded
235 // in HTML attributes without further encoding.
236 '"': `\u0022`,
237+ '`': `\u0060`,
238 '&': `\u0026`,
239 '\'': `\u0027`,
240 '+': `\u002b`,
241@@ -331,6 +332,7 @@ var jsStrNormReplacementTable = []string{
242 '"': `\u0022`,
243 '&': `\u0026`,
244 '\'': `\u0027`,
245+ '`': `\u0060`,
246 '+': `\u002b`,
247 '/': `\/`,
248 '<': `\u003c`,
249diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go
250index d7ee47b..7d963ae 100644
251--- a/src/html/template/js_test.go
252+++ b/src/html/template/js_test.go
253@@ -292,7 +292,7 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
254 `0123456789:;\u003c=\u003e?` +
255 `@ABCDEFGHIJKLMNO` +
256 `PQRSTUVWXYZ[\\]^_` +
257- "`abcdefghijklmno" +
258+ "\\u0060abcdefghijklmno" +
259 "pqrstuvwxyz{|}~\u007f" +
260 "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
261 },
262diff --git a/src/html/template/jsctx_string.go b/src/html/template/jsctx_string.go
263index dd1d87e..2394893 100644
264--- a/src/html/template/jsctx_string.go
265+++ b/src/html/template/jsctx_string.go
266@@ -4,6 +4,15 @@ package template
267
268 import "strconv"
269
270+func _() {
271+ // An "invalid array index" compiler error signifies that the constant values have changed.
272+ // Re-run the stringer command to generate them again.
273+ var x [1]struct{}
274+ _ = x[jsCtxRegexp-0]
275+ _ = x[jsCtxDivOp-1]
276+ _ = x[jsCtxUnknown-2]
277+}
278+
279 const _jsCtx_name = "jsCtxRegexpjsCtxDivOpjsCtxUnknown"
280
281 var _jsCtx_index = [...]uint8{0, 11, 21, 33}
282diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go
283index 05104be..6fb1a6e 100644
284--- a/src/html/template/state_string.go
285+++ b/src/html/template/state_string.go
286@@ -4,9 +4,42 @@ package template
287
288 import "strconv"
289
290-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateError"
291+func _() {
292+ // An "invalid array index" compiler error signifies that the constant values have changed.
293+ // Re-run the stringer command to generate them again.
294+ var x [1]struct{}
295+ _ = x[stateText-0]
296+ _ = x[stateTag-1]
297+ _ = x[stateAttrName-2]
298+ _ = x[stateAfterName-3]
299+ _ = x[stateBeforeValue-4]
300+ _ = x[stateHTMLCmt-5]
301+ _ = x[stateRCDATA-6]
302+ _ = x[stateAttr-7]
303+ _ = x[stateURL-8]
304+ _ = x[stateSrcset-9]
305+ _ = x[stateJS-10]
306+ _ = x[stateJSDqStr-11]
307+ _ = x[stateJSSqStr-12]
308+ _ = x[stateJSBqStr-13]
309+ _ = x[stateJSRegexp-14]
310+ _ = x[stateJSBlockCmt-15]
311+ _ = x[stateJSLineCmt-16]
312+ _ = x[stateCSS-17]
313+ _ = x[stateCSSDqStr-18]
314+ _ = x[stateCSSSqStr-19]
315+ _ = x[stateCSSDqURL-20]
316+ _ = x[stateCSSSqURL-21]
317+ _ = x[stateCSSURL-22]
318+ _ = x[stateCSSBlockCmt-23]
319+ _ = x[stateCSSLineCmt-24]
320+ _ = x[stateError-25]
321+ _ = x[stateDead-26]
322+}
323+
324+const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
325
326-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 155, 170, 184, 192, 205, 218, 231, 244, 255, 271, 286, 296}
327+var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 204, 217, 230, 243, 256, 267, 283, 298, 308, 317}
328
329 func (i state) String() string {
330 if i >= state(len(_state_index)-1) {
331diff --git a/src/html/template/transition.go b/src/html/template/transition.go
332index 06df679..92eb351 100644
333--- a/src/html/template/transition.go
334+++ b/src/html/template/transition.go
335@@ -27,6 +27,7 @@ var transitionFunc = [...]func(context, []byte) (context, int){
336 stateJS: tJS,
337 stateJSDqStr: tJSDelimited,
338 stateJSSqStr: tJSDelimited,
339+ stateJSBqStr: tJSDelimited,
340 stateJSRegexp: tJSDelimited,
341 stateJSBlockCmt: tBlockCmt,
342 stateJSLineCmt: tLineCmt,
343@@ -262,7 +263,7 @@ func tURL(c context, s []byte) (context, int) {
344
345 // tJS is the context transition function for the JS state.
346 func tJS(c context, s []byte) (context, int) {
347- i := bytes.IndexAny(s, `"'/`)
348+ i := bytes.IndexAny(s, "\"`'/")
349 if i == -1 {
350 // Entire input is non string, comment, regexp tokens.
351 c.jsCtx = nextJSCtx(s, c.jsCtx)
352@@ -274,6 +275,8 @@ func tJS(c context, s []byte) (context, int) {
353 c.state, c.jsCtx = stateJSDqStr, jsCtxRegexp
354 case '\'':
355 c.state, c.jsCtx = stateJSSqStr, jsCtxRegexp
356+ case '`':
357+ c.state, c.jsCtx = stateJSBqStr, jsCtxRegexp
358 case '/':
359 switch {
360 case i+1 < len(s) && s[i+1] == '/':
361@@ -303,6 +306,8 @@ func tJSDelimited(c context, s []byte) (context, int) {
362 switch c.state {
363 case stateJSSqStr:
364 specials = `\'`
365+ case stateJSBqStr:
366+ specials = "`\\"
367 case stateJSRegexp:
368 specials = `\/[]`
369 }
370--
3712.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 @@
1From 8673ca81e5340b87709db2d9749c92a3bf925df1 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Thu, 13 Apr 2023 15:40:44 -0700
4Subject: [PATCH] html/template: disallow angle brackets in CSS values
5
6Angle brackets should not appear in CSS contexts, as they may affect
7token boundaries (such as closing a <style> tag, resulting in
8injection). Instead emit filterFailsafe, matching the behavior for other
9dangerous characters.
10
11Thanks to Juho Nurminen of Mattermost for reporting this issue.
12
13Fixes #59720
14Fixes CVE-2023-24539
15
16Change-Id: Iccc659c9a18415992b0c05c178792228e3a7bae4
17Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1826636
18Reviewed-by: Julie Qiu <julieqiu@google.com>
19Run-TryBot: Roland Shoemaker <bracewell@google.com>
20Reviewed-by: Damien Neil <dneil@google.com>
21Reviewed-on: https://go-review.googlesource.com/c/go/+/491615
22Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
23Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
24Run-TryBot: Carlos Amedee <carlos@golang.org>
25TryBot-Result: Gopher Robot <gobot@golang.org>
26
27Upstream-Status: Backport from [https://github.com/golang/go/commit/8673ca81e5340b87709db2d9749c92a3bf925df1]
28CVE: CVE-2023-24539
29Signed-off-by: Ashish Sharma <asharma@mvista.com>
30---
31 src/html/template/css.go | 2 +-
32 src/html/template/css_test.go | 2 ++
33 2 files changed, 3 insertions(+), 1 deletion(-)
34
35diff --git a/src/html/template/css.go b/src/html/template/css.go
36index 890a0c6b227fe..f650d8b3e843a 100644
37--- a/src/html/template/css.go
38+++ b/src/html/template/css.go
39@@ -238,7 +238,7 @@ func cssValueFilter(args ...any) string {
40 // inside a string that might embed JavaScript source.
41 for i, c := range b {
42 switch c {
43- case 0, '"', '\'', '(', ')', '/', ';', '@', '[', '\\', ']', '`', '{', '}':
44+ case 0, '"', '\'', '(', ')', '/', ';', '@', '[', '\\', ']', '`', '{', '}', '<', '>':
45 return filterFailsafe
46 case '-':
47 // Disallow <!-- or -->.
48diff --git a/src/html/template/css_test.go b/src/html/template/css_test.go
49index a735638b0314f..2b76256a766e9 100644
50--- a/src/html/template/css_test.go
51+++ b/src/html/template/css_test.go
52@@ -231,6 +231,8 @@ func TestCSSValueFilter(t *testing.T) {
53 {`-exp\000052 ession(alert(1337))`, "ZgotmplZ"},
54 {`-expre\0000073sion`, "-expre\x073sion"},
55 {`@import url evil.css`, "ZgotmplZ"},
56+ {"<", "ZgotmplZ"},
57+ {">", "ZgotmplZ"},
58 }
59 for _, test := range tests {
60 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 @@
1From ce7bd33345416e6d8cac901792060591cafc2797 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Tue, 11 Apr 2023 16:27:43 +0100
4Subject: [PATCH] [release-branch.go1.19] html/template: handle all JS
5 whitespace characters
6
7Rather than just a small set. Character class as defined by \s [0].
8
9Thanks to Juho Nurminen of Mattermost for reporting this.
10
11For #59721
12Fixes #59813
13Fixes CVE-2023-24540
14
15[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
16
17Change-Id: I56d4fa1ef08125b417106ee7dbfb5b0923b901ba
18Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1821459
19Reviewed-by: Julie Qiu <julieqiu@google.com>
20Run-TryBot: Roland Shoemaker <bracewell@google.com>
21Reviewed-by: Damien Neil <dneil@google.com>
22Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1851497
23Run-TryBot: Damien Neil <dneil@google.com>
24Reviewed-by: Roland Shoemaker <bracewell@google.com>
25Reviewed-on: https://go-review.googlesource.com/c/go/+/491355
26Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
27Reviewed-by: Carlos Amedee <carlos@golang.org>
28TryBot-Bypass: Carlos Amedee <carlos@golang.org>
29Run-TryBot: Carlos Amedee <carlos@golang.org>
30
31Upstream-Status: Backport [https://github.com/golang/go/commit/ce7bd33345416e6d8cac901792060591cafc2797]
32CVE: CVE-2023-24540
33Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
34---
35 src/html/template/js.go | 8 +++++++-
36 src/html/template/js_test.go | 11 +++++++----
37 2 files changed, 14 insertions(+), 5 deletions(-)
38
39diff --git a/src/html/template/js.go b/src/html/template/js.go
40index fe7054efe5cd8..4e05c1455723f 100644
41--- a/src/html/template/js.go
42+++ b/src/html/template/js.go
43@@ -13,6 +13,11 @@ import (
44 "unicode/utf8"
45 )
46
47+// jsWhitespace contains all of the JS whitespace characters, as defined
48+// by the \s character class.
49+// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Character_classes.
50+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"
51+
52 // nextJSCtx returns the context that determines whether a slash after the
53 // given run of tokens starts a regular expression instead of a division
54 // operator: / or /=.
55@@ -26,7 +31,8 @@ import (
56 // JavaScript 2.0 lexical grammar and requires one token of lookbehind:
57 // https://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html
58 func nextJSCtx(s []byte, preceding jsCtx) jsCtx {
59- s = bytes.TrimRight(s, "\t\n\f\r \u2028\u2029")
60+ // Trim all JS whitespace characters
61+ s = bytes.TrimRight(s, jsWhitespace)
62 if len(s) == 0 {
63 return preceding
64 }
65diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go
66index e07c695f7a77d..e52180cc113b5 100644
67--- a/src/html/template/js_test.go
68+++ b/src/html/template/js_test.go
69@@ -81,14 +81,17 @@ func TestNextJsCtx(t *testing.T) {
70 {jsCtxDivOp, "0"},
71 // Dots that are part of a number are div preceders.
72 {jsCtxDivOp, "0."},
73+ // Some JS interpreters treat NBSP as a normal space, so
74+ // we must too in order to properly escape things.
75+ {jsCtxRegexp, "=\u00A0"},
76 }
77
78 for _, test := range tests {
79- if nextJSCtx([]byte(test.s), jsCtxRegexp) != test.jsCtx {
80- t.Errorf("want %s got %q", test.jsCtx, test.s)
81+ if ctx := nextJSCtx([]byte(test.s), jsCtxRegexp); ctx != test.jsCtx {
82+ t.Errorf("%q: want %s got %s", test.s, test.jsCtx, ctx)
83 }
84- if nextJSCtx([]byte(test.s), jsCtxDivOp) != test.jsCtx {
85- t.Errorf("want %s got %q", test.jsCtx, test.s)
86+ if ctx := nextJSCtx([]byte(test.s), jsCtxDivOp); ctx != test.jsCtx {
87+ t.Errorf("%q: want %s got %s", test.s, test.jsCtx, ctx)
88 }
89 }
90
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 @@
1From 0d347544cbca0f42b160424f6bc2458ebcc7b3fc Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Thu, 13 Apr 2023 14:01:50 -0700
4Subject: [PATCH] html/template: emit filterFailsafe for empty unquoted attr
5 value
6
7An unquoted action used as an attribute value can result in unsafe
8behavior if it is empty, as HTML normalization will result in unexpected
9attributes, and may allow attribute injection. If executing a template
10results in a empty unquoted attribute value, emit filterFailsafe
11instead.
12
13Thanks to Juho Nurminen of Mattermost for reporting this issue.
14
15Fixes #59722
16Fixes CVE-2023-29400
17
18Change-Id: Ia38d1b536ae2b4af5323a6c6d861e3c057c2570a
19Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1826631
20Reviewed-by: Julie Qiu <julieqiu@google.com>
21Run-TryBot: Roland Shoemaker <bracewell@google.com>
22Reviewed-by: Damien Neil <dneil@google.com>
23Reviewed-on: https://go-review.googlesource.com/c/go/+/491617
24Run-TryBot: Carlos Amedee <carlos@golang.org>
25Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
26Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
27TryBot-Result: Gopher Robot <gobot@golang.org>
28
29Upstream-Status: Backport from [https://github.com/golang/go/commit/0d347544cbca0f42b160424f6bc2458ebcc7b3fc]
30CVE: CVE-2023-29400
31Signed-off-by: Ashish Sharma <asharma@mvista.com>
32---
33 src/html/template/escape.go | 5 ++---
34 src/html/template/escape_test.go | 15 +++++++++++++++
35 src/html/template/html.go | 3 +++
36 3 files changed, 20 insertions(+), 3 deletions(-)
37
38diff --git a/src/html/template/escape.go b/src/html/template/escape.go
39index 4ba1d6b31897e..a62ef159f0dcd 100644
40--- a/src/html/template/escape.go
41+++ b/src/html/template/escape.go
42@@ -382,9 +382,8 @@ func normalizeEscFn(e string) string {
43 // for all x.
44 var redundantFuncs = map[string]map[string]bool{
45 "_html_template_commentescaper": {
46- "_html_template_attrescaper": true,
47- "_html_template_nospaceescaper": true,
48- "_html_template_htmlescaper": true,
49+ "_html_template_attrescaper": true,
50+ "_html_template_htmlescaper": true,
51 },
52 "_html_template_cssescaper": {
53 "_html_template_attrescaper": true,
54diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
55index 3dd212bac9406..f8b2b448f2dfa 100644
56--- a/src/html/template/escape_test.go
57+++ b/src/html/template/escape_test.go
58@@ -678,6 +678,21 @@ func TestEscape(t *testing.T) {
59 `<img srcset={{",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"}}>`,
60 `<img srcset=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,>`,
61 },
62+ {
63+ "unquoted empty attribute value (plaintext)",
64+ "<p name={{.U}}>",
65+ "<p name=ZgotmplZ>",
66+ },
67+ {
68+ "unquoted empty attribute value (url)",
69+ "<p href={{.U}}>",
70+ "<p href=ZgotmplZ>",
71+ },
72+ {
73+ "quoted empty attribute value",
74+ "<p name=\"{{.U}}\">",
75+ "<p name=\"\">",
76+ },
77 }
78
79 for _, test := range tests {
80diff --git a/src/html/template/html.go b/src/html/template/html.go
81index bcca0b51a0ef9..a181699a5bda8 100644
82--- a/src/html/template/html.go
83+++ b/src/html/template/html.go
84@@ -14,6 +14,9 @@ import (
85 // htmlNospaceEscaper escapes for inclusion in unquoted attribute values.
86 func htmlNospaceEscaper(args ...interface{}) string {
87 s, t := stringify(args...)
88+ if s == "" {
89+ return filterFailsafe
90+ }
91 if t == contentTypeHTML {
92 return htmlReplacer(stripTags(s), htmlNospaceNormReplacementTable, false)
93 }
94
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 @@
1rom c160b49b6d328c86bd76ca2fff9009a71347333f Mon Sep 17 00:00:00 2001
2From: "Bryan C. Mills" <bcmills@google.com>
3Date: Fri, 12 May 2023 14:15:16 -0400
4Subject: [PATCH] [release-branch.go1.19] cmd/go: disallow package directories
5 containing newlines
6
7Directory or file paths containing newlines may cause tools (such as
8cmd/cgo) that emit "//line" or "#line" -directives to write part of
9the path into non-comment lines in generated source code. If those
10lines contain valid Go code, it may be injected into the resulting
11binary.
12
13(Note that Go import paths and file paths within module zip files
14already could not contain newlines.)
15
16Thanks to Juho Nurminen of Mattermost for reporting this issue.
17
18Updates #60167.
19Fixes #60515.
20Fixes CVE-2023-29402.
21
22Change-Id: If55d0400c02beb7a5da5eceac60f1abeac99f064
23Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1882606
24Reviewed-by: Roland Shoemaker <bracewell@google.com>
25Run-TryBot: Roland Shoemaker <bracewell@google.com>
26Reviewed-by: Russ Cox <rsc@google.com>
27Reviewed-by: Damien Neil <dneil@google.com>
28(cherry picked from commit 41f9046495564fc728d6f98384ab7276450ac7e2)
29Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1902229
30Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1904343
31Reviewed-by: Michael Knyszek <mknyszek@google.com>
32Reviewed-by: Bryan Mills <bcmills@google.com>
33Reviewed-on: https://go-review.googlesource.com/c/go/+/501218
34Run-TryBot: David Chase <drchase@google.com>
35Auto-Submit: Michael Knyszek <mknyszek@google.com>
36TryBot-Result: Gopher Robot <gobot@golang.org>
37
38Upstream-Status: Backport [https://github.com/golang/go/commit/c160b49b6d328c86bd76ca2fff9009a71347333f]
39CVE: CVE-2023-29402
40Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
41---
42 src/cmd/go/internal/load/pkg.go | 4 +
43 src/cmd/go/internal/work/exec.go | 6 ++
44 src/cmd/go/script_test.go | 1 +
45 .../go/testdata/script/build_cwd_newline.txt | 100 ++++++++++++++++++
46 4 files changed, 111 insertions(+)
47 create mode 100644 src/cmd/go/testdata/script/build_cwd_newline.txt
48
49diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
50index 369a79b..d2b63b0 100644
51--- a/src/cmd/go/internal/load/pkg.go
52+++ b/src/cmd/go/internal/load/pkg.go
53@@ -1697,6 +1697,10 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
54 setError(ImportErrorf(p.ImportPath, "invalid import path %q", p.ImportPath))
55 return
56 }
57+ if strings.ContainsAny(p.Dir, "\r\n") {
58+ setError(fmt.Errorf("invalid package directory %q", p.Dir))
59+ return
60+ }
61
62 // Build list of imported packages and full dependency list.
63 imports := make([]*Package, 0, len(p.Imports))
64diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
65index 9a9650b..050b785 100644
66--- a/src/cmd/go/internal/work/exec.go
67+++ b/src/cmd/go/internal/work/exec.go
68@@ -458,6 +458,12 @@ func (b *Builder) build(a *Action) (err error) {
69 b.Print(a.Package.ImportPath + "\n")
70 }
71
72+ if p.Error != nil {
73+ // Don't try to build anything for packages with errors. There may be a
74+ // problem with the inputs that makes the package unsafe to build.
75+ return p.Error
76+ }
77+
78 if a.Package.BinaryOnly {
79 p.Stale = true
80 p.StaleReason = "binary-only packages are no longer supported"
81diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go
82index ec498bb..a1398ad 100644
83--- a/src/cmd/go/script_test.go
84+++ b/src/cmd/go/script_test.go
85@@ -123,6 +123,7 @@ func (ts *testScript) setup() {
86 "devnull=" + os.DevNull,
87 "goversion=" + goVersion(ts),
88 ":=" + string(os.PathListSeparator),
89+ "newline=\n",
90 }
91
92 if runtime.GOOS == "plan9" {
93diff --git a/src/cmd/go/testdata/script/build_cwd_newline.txt b/src/cmd/go/testdata/script/build_cwd_newline.txt
94new file mode 100644
95index 0000000..61c6966
96--- /dev/null
97+++ b/src/cmd/go/testdata/script/build_cwd_newline.txt
98@@ -0,0 +1,100 @@
99+[windows] skip 'filesystem normalizes / to \'
100+[plan9] skip 'filesystem disallows \n in paths'
101+
102+# If the directory path containing a package to be built includes a newline,
103+# the go command should refuse to even try to build the package.
104+
105+env DIR=$WORK${/}${newline}'package main'${newline}'func main() { panic("uh-oh")'${newline}'/*'
106+
107+mkdir $DIR
108+cd $DIR
109+exec pwd
110+cp $WORK/go.mod ./go.mod
111+cp $WORK/main.go ./main.go
112+cp $WORK/main_test.go ./main_test.go
113+
114+! go build -o $devnull .
115+stderr 'package example: invalid package directory .*uh-oh'
116+
117+! go build -o $devnull main.go
118+stderr 'package command-line-arguments: invalid package directory .*uh-oh'
119+
120+! go run .
121+stderr 'package example: invalid package directory .*uh-oh'
122+
123+! go run main.go
124+stderr 'package command-line-arguments: invalid package directory .*uh-oh'
125+
126+! go test .
127+stderr 'package example: invalid package directory .*uh-oh'
128+
129+! go test -v main.go main_test.go
130+stderr 'package command-line-arguments: invalid package directory .*uh-oh'
131+
132+
133+# Since we do preserve $PWD (or set it appropriately) for commands, and we do
134+# not resolve symlinks unnecessarily, referring to the contents of the unsafe
135+# directory via a safe symlink should be ok, and should not inject the data from
136+# the symlink target path.
137+
138+[!symlink] stop 'remainder of test checks symlink behavior'
139+[short] stop 'links and runs binaries'
140+
141+symlink $WORK${/}link -> $DIR
142+
143+go run $WORK${/}link${/}main.go
144+! stdout panic
145+! stderr panic
146+stderr '^ok$'
147+
148+go test -v $WORK${/}link${/}main.go $WORK${/}link${/}main_test.go
149+! stdout panic
150+! stderr panic
151+stdout '^ok$' # 'go test' combines the test's stdout into stderr
152+
153+cd $WORK/link
154+
155+! go run $DIR${/}main.go
156+stderr 'package command-line-arguments: invalid package directory .*uh-oh'
157+
158+go run .
159+! stdout panic
160+! stderr panic
161+stderr '^ok$'
162+
163+go run main.go
164+! stdout panic
165+! stderr panic
166+stderr '^ok$'
167+
168+go test -v
169+! stdout panic
170+! stderr panic
171+stdout '^ok$' # 'go test' combines the test's stdout into stderr
172+
173+go test -v .
174+! stdout panic
175+! stderr panic
176+stdout '^ok$' # 'go test' combines the test's stdout into stderr
177+
178+
179+-- $WORK/go.mod --
180+module example
181+go 1.19
182+-- $WORK/main.go --
183+package main
184+
185+import "C"
186+
187+func main() {
188+ /* nothing here */
189+ println("ok")
190+}
191+-- $WORK/main_test.go --
192+package main
193+
194+import "testing"
195+
196+func TestMain(*testing.M) {
197+ main()
198+}
199--
2002.25.1
201
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 @@
1From bf3c8ce03e175e870763901a3850bca01381a828 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Fri, 5 May 2023 13:10:34 -0700
4Subject: [PATCH] [release-branch.go1.19] cmd/go: enforce flags with
5 non-optional arguments
6
7Enforce that linker flags which expect arguments get them, otherwise it
8may be possible to smuggle unexpected flags through as the linker can
9consume what looks like a flag as an argument to a preceding flag (i.e.
10"-Wl,-O -Wl,-R,-bad-flag" is interpreted as "-O=-R -bad-flag"). Also be
11somewhat more restrictive in the general format of some flags.
12
13Thanks to Juho Nurminen of Mattermost for reporting this issue.
14
15Updates #60305
16Fixes #60511
17Fixes CVE-2023-29404
18
19Change-Id: Icdffef2c0f644da50261cace6f43742783931cff
20Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1876275
21Reviewed-by: Ian Lance Taylor <iant@google.com>
22Reviewed-by: Damien Neil <dneil@google.com>
23(cherry picked from commit 896779503cf754cbdac24b61d4cc953b50fe2dde)
24Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1902225
25Run-TryBot: Roland Shoemaker <bracewell@google.com>
26Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1904342
27Reviewed-by: Michael Knyszek <mknyszek@google.com>
28Reviewed-on: https://go-review.googlesource.com/c/go/+/501217
29Auto-Submit: Michael Knyszek <mknyszek@google.com>
30Run-TryBot: David Chase <drchase@google.com>
31TryBot-Bypass: Michael Knyszek <mknyszek@google.com>
32
33Upstream-Status: Backport [https://github.com/golang/go/commit/bf3c8ce03e175e870763901a3850bca01381a828]
34CVE: CVE-2023-29404
35Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
36---
37 src/cmd/go/internal/work/security.go | 6 +++---
38 src/cmd/go/internal/work/security_test.go | 5 +++++
39 2 files changed, 8 insertions(+), 3 deletions(-)
40
41diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go
42index a823b20..8acb6dc 100644
43--- a/src/cmd/go/internal/work/security.go
44+++ b/src/cmd/go/internal/work/security.go
45@@ -177,17 +177,17 @@ var validLinkerFlags = []*lazyregexp.Regexp{
46 re(`-Wl,-Bdynamic`),
47 re(`-Wl,-berok`),
48 re(`-Wl,-Bstatic`),
49- re(`-WL,-O([^@,\-][^,]*)?`),
50+ re(`-Wl,-O[0-9]+`),
51 re(`-Wl,-d[ny]`),
52 re(`-Wl,--disable-new-dtags`),
53- re(`-Wl,-e[=,][a-zA-Z0-9]*`),
54+ re(`-Wl,-e[=,][a-zA-Z0-9]+`),
55 re(`-Wl,--enable-new-dtags`),
56 re(`-Wl,--end-group`),
57 re(`-Wl,--(no-)?export-dynamic`),
58 re(`-Wl,-framework,[^,@\-][^,]+`),
59 re(`-Wl,-headerpad_max_install_names`),
60 re(`-Wl,--no-undefined`),
61- re(`-Wl,-R([^@\-][^,@]*$)`),
62+ re(`-Wl,-R,?([^@\-,][^,@]*$)`),
63 re(`-Wl,--just-symbols[=,]([^,@\-][^,@]+)`),
64 re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]+)`),
65 re(`-Wl,-s`),
66diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go
67index bd707ff..7b0b7d3 100644
68--- a/src/cmd/go/internal/work/security_test.go
69+++ b/src/cmd/go/internal/work/security_test.go
70@@ -220,6 +220,11 @@ var badLinkerFlags = [][]string{
71 {"-Wl,-R,@foo"},
72 {"-Wl,--just-symbols,@foo"},
73 {"../x.o"},
74+ {"-Wl,-R,"},
75+ {"-Wl,-O"},
76+ {"-Wl,-e="},
77+ {"-Wl,-e,"},
78+ {"-Wl,-R,-flag"},
79 }
80
81 func TestCheckLinkerFlags(t *testing.T) {
82--
832.25.1
84
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 @@
1From fa60c381ed06c12f9c27a7b50ca44c5f84f7f0f4 Mon Sep 17 00:00:00 2001
2From: Ian Lance Taylor <iant@golang.org>
3Date: Thu, 4 May 2023 14:06:39 -0700
4Subject: [PATCH] [release-branch.go1.20] cmd/go,cmd/cgo: in _cgo_flags use one
5 line per flag
6
7The flags that we recorded in _cgo_flags did not use any quoting,
8so a flag containing embedded spaces was mishandled.
9Change the _cgo_flags format to put each flag on a separate line.
10That is a simple format that does not require any quoting.
11
12As far as I can tell only cmd/go uses _cgo_flags, and it is only
13used for gccgo. If this patch doesn't cause any trouble, then
14in the next release we can change to only using _cgo_flags for gccgo.
15
16Thanks to Juho Nurminen of Mattermost for reporting this issue.
17
18Updates #60306
19Fixes #60514
20Fixes CVE-2023-29405
21
22Change-Id: I36b6e188a44c80d7b9573efa577c386770bd2ba3
23Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1875094
24Reviewed-by: Damien Neil <dneil@google.com>
25Reviewed-by: Roland Shoemaker <bracewell@google.com>
26(cherry picked from commit bcdfcadd5612212089d958bc352a6f6c90742dcc)
27Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1902228
28Run-TryBot: Roland Shoemaker <bracewell@google.com>
29TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
30Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1904345
31Reviewed-by: Michael Knyszek <mknyszek@google.com>
32Reviewed-on: https://go-review.googlesource.com/c/go/+/501220
33TryBot-Result: Gopher Robot <gobot@golang.org>
34Run-TryBot: David Chase <drchase@google.com>
35Auto-Submit: Michael Knyszek <mknyszek@google.com>
36---
37Upstream-Status: Backport [https://github.com/golang/go/commit/fa60c381ed06c12f9c27a7b50ca44c5f84f7f0f4]
38CVE: CVE-2023-29405
39Signed-off-by: Ashish Sharma <asharma@mvista.com>
40
41 src/cmd/cgo/out.go | 4 +++-
42 src/cmd/go/internal/work/gccgo.go | 14 ++++++-------
43 .../go/testdata/script/gccgo_link_ldflags.txt | 20 +++++++++++++++++++
44 3 files changed, 29 insertions(+), 9 deletions(-)
45 create mode 100644 src/cmd/go/testdata/script/gccgo_link_ldflags.txt
46
47diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
48index d26f9e76a374a..d0c6fe3d4c2c2 100644
49--- a/src/cmd/cgo/out.go
50+++ b/src/cmd/cgo/out.go
51@@ -47,7 +47,9 @@ func (p *Package) writeDefs() {
52
53 fflg := creat(*objDir + "_cgo_flags")
54 for k, v := range p.CgoFlags {
55- fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
56+ for _, arg := range v {
57+ fmt.Fprintf(fflg, "_CGO_%s=%s\n", arg)
58+ }
59 if k == "LDFLAGS" && !*gccgo {
60 for _, arg := range v {
61 fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
62diff --git a/src/cmd/go/internal/work/gccgo.go b/src/cmd/go/internal/work/gccgo.go
63index 08a4c2d8166c7..a048b7f4eecef 100644
64--- a/src/cmd/go/internal/work/gccgo.go
65+++ b/src/cmd/go/internal/work/gccgo.go
66@@ -280,14 +280,12 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
67 const ldflagsPrefix = "_CGO_LDFLAGS="
68 for _, line := range strings.Split(string(flags), "\n") {
69 if strings.HasPrefix(line, ldflagsPrefix) {
70- newFlags := strings.Fields(line[len(ldflagsPrefix):])
71- for _, flag := range newFlags {
72- // Every _cgo_flags file has -g and -O2 in _CGO_LDFLAGS
73- // but they don't mean anything to the linker so filter
74- // them out.
75- if flag != "-g" && !strings.HasPrefix(flag, "-O") {
76- cgoldflags = append(cgoldflags, flag)
77- }
78+ flag := line[len(ldflagsPrefix):]
79+ // Every _cgo_flags file has -g and -O2 in _CGO_LDFLAGS
80+ // but they don't mean anything to the linker so filter
81+ // them out.
82+ if flag != "-g" && !strings.HasPrefix(flag, "-O") {
83+ cgoldflags = append(cgoldflags, flag)
84 }
85 }
86 }
87diff --git a/src/cmd/go/testdata/script/gccgo_link_ldflags.txt b/src/cmd/go/testdata/script/gccgo_link_ldflags.txt
88new file mode 100644
89index 0000000000000..4e91ae56505b6
90--- /dev/null
91+++ b/src/cmd/go/testdata/script/gccgo_link_ldflags.txt
92@@ -0,0 +1,20 @@
93+# Test that #cgo LDFLAGS are properly quoted.
94+# The #cgo LDFLAGS below should pass a string with spaces to -L,
95+# as though searching a directory with a space in its name.
96+# It should not pass --nosuchoption to the external linker.
97+
98+[!cgo] skip
99+
100+go build
101+
102+[!exec:gccgo] skip
103+
104+go build -compiler gccgo
105+
106+-- go.mod --
107+module m
108+-- cgo.go --
109+package main
110+// #cgo LDFLAGS: -L "./ -Wl,--nosuchoption"
111+import "C"
112+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 @@
1From 1008486a9ff979dbd21c7466eeb6abf378f9c637 Mon Sep 17 00:00:00 2001
2From: Ian Lance Taylor <iant@golang.org>
3Date: Tue, 6 Jun 2023 12:51:17 -0700
4Subject: [PATCH] [release-branch.go1.20] cmd/cgo: correct _cgo_flags output
5
6For #60306
7For #60514
8
9Change-Id: I3f5d14aee7d7195030e8872e42b1d97aa11d3582
10Reviewed-on: https://go-review.googlesource.com/c/go/+/501298
11Run-TryBot: Ian Lance Taylor <iant@golang.org>
12TryBot-Result: Gopher Robot <gobot@golang.org>
13Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
14Reviewed-by: David Chase <drchase@google.com>
15Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
16---
17
18Upstream-Status: Backport [https://github.com/golang/go/commit/1008486a9ff979dbd21c7466eeb6abf378f9c637]
19CVE: CVE-2023-29405
20Signed-off-by: Ashish Sharma <asharma@mvista.com>
21
22
23 src/cmd/cgo/out.go | 2 +-
24 1 file changed, 1 insertion(+), 1 deletion(-)
25
26diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
27index d0c6fe3d4c2c2..a48f52105628a 100644
28--- a/src/cmd/cgo/out.go
29+++ b/src/cmd/cgo/out.go
30@@ -48,7 +48,7 @@ func (p *Package) writeDefs() {
31 fflg := creat(*objDir + "_cgo_flags")
32 for k, v := range p.CgoFlags {
33 for _, arg := range v {
34- fmt.Fprintf(fflg, "_CGO_%s=%s\n", arg)
35+ fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, arg)
36 }
37 if k == "LDFLAGS" && !*gccgo {
38 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 @@
1From 5fa6923b1ea891400153d04ddf1545e23b40041b Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Wed, 28 Jun 2023 13:20:08 -0700
4Subject: [PATCH] [release-branch.go1.19] net/http: validate Host header before
5 sending
6
7Verify that the Host header we send is valid.
8Avoids surprising behavior such as a Host of "go.dev\r\nX-Evil:oops"
9adding an X-Evil header to HTTP/1 requests.
10
11Add a test, skip the test for HTTP/2. HTTP/2 is not vulnerable to
12header injection in the way HTTP/1 is, but x/net/http2 doesn't validate
13the header and will go into a retry loop when the server rejects it.
14CL 506995 adds the necessary validation to x/net/http2.
15
16Updates #60374
17Fixes #61075
18For CVE-2023-29406
19
20Change-Id: I05cb6866a9bead043101954dfded199258c6dd04
21Reviewed-on: https://go-review.googlesource.com/c/go/+/506996
22Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
23TryBot-Result: Gopher Robot <gobot@golang.org>
24Run-TryBot: Damien Neil <dneil@google.com>
25(cherry picked from commit 499458f7ca04087958987a33c2703c3ef03e27e2)
26Reviewed-on: https://go-review.googlesource.com/c/go/+/507358
27Run-TryBot: Tatiana Bradley <tatianabradley@google.com>
28Reviewed-by: Roland Shoemaker <roland@golang.org>
29
30Upstream-Status: Backport [https://github.com/golang/go/commit/5fa6923b1ea891400153d04ddf1545e23b40041b]
31CVE: CVE-2023-29406
32Signed-off-by: Vivek Kumbhar <vkumbhar@mvista.com>
33---
34 src/net/http/http_test.go | 29 ---------------------
35 src/net/http/request.go | 47 ++++++++--------------------------
36 src/net/http/request_test.go | 11 ++------
37 src/net/http/transport_test.go | 18 +++++++++++++
38 4 files changed, 31 insertions(+), 74 deletions(-)
39
40diff --git a/src/net/http/http_test.go b/src/net/http/http_test.go
41index f4ea52d..ea38cb4 100644
42--- a/src/net/http/http_test.go
43+++ b/src/net/http/http_test.go
44@@ -49,35 +49,6 @@ func TestForeachHeaderElement(t *testing.T) {
45 }
46 }
47
48-func TestCleanHost(t *testing.T) {
49- tests := []struct {
50- in, want string
51- }{
52- {"www.google.com", "www.google.com"},
53- {"www.google.com foo", "www.google.com"},
54- {"www.google.com/foo", "www.google.com"},
55- {" first character is a space", ""},
56- {"[1::6]:8080", "[1::6]:8080"},
57-
58- // Punycode:
59- {"гофер.рф/foo", "xn--c1ae0ajs.xn--p1ai"},
60- {"bücher.de", "xn--bcher-kva.de"},
61- {"bücher.de:8080", "xn--bcher-kva.de:8080"},
62- // Verify we convert to lowercase before punycode:
63- {"BÜCHER.de", "xn--bcher-kva.de"},
64- {"BÜCHER.de:8080", "xn--bcher-kva.de:8080"},
65- // Verify we normalize to NFC before punycode:
66- {"gophér.nfc", "xn--gophr-esa.nfc"}, // NFC input; no work needed
67- {"goph\u0065\u0301r.nfd", "xn--gophr-esa.nfd"}, // NFD input
68- }
69- for _, tt := range tests {
70- got := cleanHost(tt.in)
71- if tt.want != got {
72- t.Errorf("cleanHost(%q) = %q, want %q", tt.in, got, tt.want)
73- }
74- }
75-}
76-
77 // Test that cmd/go doesn't link in the HTTP server.
78 //
79 // This catches accidental dependencies between the HTTP transport and
80diff --git a/src/net/http/request.go b/src/net/http/request.go
81index cb2edd2..2706300 100644
82--- a/src/net/http/request.go
83+++ b/src/net/http/request.go
84@@ -18,7 +18,6 @@ import (
85 "io/ioutil"
86 "mime"
87 "mime/multipart"
88- "net"
89 "net/http/httptrace"
90 "net/textproto"
91 "net/url"
92@@ -26,7 +25,8 @@ import (
93 "strconv"
94 "strings"
95 "sync"
96-
97+
98+ "golang.org/x/net/http/httpguts"
99 "golang.org/x/net/idna"
100 )
101
102@@ -557,12 +557,19 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
103 // is not given, use the host from the request URL.
104 //
105 // Clean the host, in case it arrives with unexpected stuff in it.
106- host := cleanHost(r.Host)
107+ host := r.Host
108 if host == "" {
109 if r.URL == nil {
110 return errMissingHost
111 }
112- host = cleanHost(r.URL.Host)
113+ host = r.URL.Host
114+ }
115+ host, err = httpguts.PunycodeHostPort(host)
116+ if err != nil {
117+ return err
118+ }
119+ if !httpguts.ValidHostHeader(host) {
120+ return errors.New("http: invalid Host header")
121 }
122
123 // According to RFC 6874, an HTTP client, proxy, or other
124@@ -717,38 +724,6 @@ func idnaASCII(v string) (string, error) {
125 return idna.Lookup.ToASCII(v)
126 }
127
128-// cleanHost cleans up the host sent in request's Host header.
129-//
130-// It both strips anything after '/' or ' ', and puts the value
131-// into Punycode form, if necessary.
132-//
133-// Ideally we'd clean the Host header according to the spec:
134-// https://tools.ietf.org/html/rfc7230#section-5.4 (Host = uri-host [ ":" port ]")
135-// https://tools.ietf.org/html/rfc7230#section-2.7 (uri-host -> rfc3986's host)
136-// https://tools.ietf.org/html/rfc3986#section-3.2.2 (definition of host)
137-// But practically, what we are trying to avoid is the situation in
138-// issue 11206, where a malformed Host header used in the proxy context
139-// would create a bad request. So it is enough to just truncate at the
140-// first offending character.
141-func cleanHost(in string) string {
142- if i := strings.IndexAny(in, " /"); i != -1 {
143- in = in[:i]
144- }
145- host, port, err := net.SplitHostPort(in)
146- if err != nil { // input was just a host
147- a, err := idnaASCII(in)
148- if err != nil {
149- return in // garbage in, garbage out
150- }
151- return a
152- }
153- a, err := idnaASCII(host)
154- if err != nil {
155- return in // garbage in, garbage out
156- }
157- return net.JoinHostPort(a, port)
158-}
159-
160 // removeZone removes IPv6 zone identifier from host.
161 // E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"
162 func removeZone(host string) string {
163diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
164index 461d66e..0d417ff 100644
165--- a/src/net/http/request_test.go
166+++ b/src/net/http/request_test.go
167@@ -676,15 +676,8 @@ func TestRequestBadHost(t *testing.T) {
168 }
169 req.Host = "foo.com with spaces"
170 req.URL.Host = "foo.com with spaces"
171- req.Write(logWrites{t, &got})
172- want := []string{
173- "GET /after HTTP/1.1\r\n",
174- "Host: foo.com\r\n",
175- "User-Agent: " + DefaultUserAgent + "\r\n",
176- "\r\n",
177- }
178- if !reflect.DeepEqual(got, want) {
179- t.Errorf("Writes = %q\n Want = %q", got, want)
180+ if err := req.Write(logWrites{t, &got}); err == nil {
181+ t.Errorf("Writing request with invalid Host: succeded, want error")
182 }
183 }
184
185diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
186index fa0c370..0afb6b9 100644
187--- a/src/net/http/transport_test.go
188+++ b/src/net/http/transport_test.go
189@@ -6249,3 +6249,21 @@ func TestIssue32441(t *testing.T) {
190 t.Error(err)
191 }
192 }
193+
194+func TestRequestSanitization(t *testing.T) {
195+ setParallel(t)
196+ defer afterTest(t)
197+
198+ ts := newClientServerTest(t, h1Mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
199+ if h, ok := req.Header["X-Evil"]; ok {
200+ t.Errorf("request has X-Evil header: %q", h)
201+ }
202+ })).ts
203+ defer ts.Close()
204+ req, _ := NewRequest("GET", ts.URL, nil)
205+ req.Host = "go.dev\r\nX-Evil:evil"
206+ resp, _ := ts.Client().Do(req)
207+ if resp != nil {
208+ resp.Body.Close()
209+ }
210+}
211--
2122.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 @@
1From c08a5fa413a34111c9a37fd9e545de27ab0978b1 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Wed, 19 Jul 2023 10:30:46 -0700
4Subject: [PATCH] [release-branch.go1.19] net/http: permit requests with
5 invalid Host headers
6
7Historically, the Transport has silently truncated invalid
8Host headers at the first '/' or ' ' character. CL 506996 changed
9this behavior to reject invalid Host headers entirely.
10Unfortunately, Docker appears to rely on the previous behavior.
11
12When sending a HTTP/1 request with an invalid Host, send an empty
13Host header. This is safer than truncation: If you care about the
14Host, then you should get the one you set; if you don't care,
15then an empty Host should be fine.
16
17Continue to fully validate Host headers sent to a proxy,
18since proxies generally can't productively forward requests
19without a Host.
20
21For #60374
22Fixes #61431
23Fixes #61825
24
25Change-Id: If170c7dd860aa20eb58fe32990fc93af832742b6
26Reviewed-on: https://go-review.googlesource.com/c/go/+/511155
27TryBot-Result: Gopher Robot <gobot@golang.org>
28Reviewed-by: Roland Shoemaker <roland@golang.org>
29Run-TryBot: Damien Neil <dneil@google.com>
30(cherry picked from commit b9153f6ef338baee5fe02a867c8fbc83a8b29dd1)
31Reviewed-on: https://go-review.googlesource.com/c/go/+/518855
32Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
33Run-TryBot: Roland Shoemaker <roland@golang.org>
34Reviewed-by: Russ Cox <rsc@golang.org>
35
36Upstream-Status: Backport [https://github.com/golang/go/commit/c08a5fa413a34111c9a37fd9e545de27ab0978b1]
37CVE: CVE-2023-29406
38Signed-off-by: Ming Liu <liu.ming50@gmail.com>
39---
40 src/net/http/request.go | 23 ++++++++++++++++++++++-
41 src/net/http/request_test.go | 17 ++++++++++++-----
42 2 files changed, 34 insertions(+), 6 deletions(-)
43
44diff --git a/src/net/http/request.go b/src/net/http/request.go
45index 3100037386..91cb8a66b9 100644
46--- a/src/net/http/request.go
47+++ b/src/net/http/request.go
48@@ -582,8 +582,29 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
49 if err != nil {
50 return err
51 }
52+ // Validate that the Host header is a valid header in general,
53+ // but don't validate the host itself. This is sufficient to avoid
54+ // header or request smuggling via the Host field.
55+ // The server can (and will, if it's a net/http server) reject
56+ // the request if it doesn't consider the host valid.
57 if !httpguts.ValidHostHeader(host) {
58- return errors.New("http: invalid Host header")
59+ // Historically, we would truncate the Host header after '/' or ' '.
60+ // Some users have relied on this truncation to convert a network
61+ // address such as Unix domain socket path into a valid, ignored
62+ // Host header (see https://go.dev/issue/61431).
63+ //
64+ // We don't preserve the truncation, because sending an altered
65+ // header field opens a smuggling vector. Instead, zero out the
66+ // Host header entirely if it isn't valid. (An empty Host is valid;
67+ // see RFC 9112 Section 3.2.)
68+ //
69+ // Return an error if we're sending to a proxy, since the proxy
70+ // probably can't do anything useful with an empty Host header.
71+ if !usingProxy {
72+ host = ""
73+ } else {
74+ return errors.New("http: invalid Host header")
75+ }
76 }
77
78 // According to RFC 6874, an HTTP client, proxy, or other
79diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
80index fddc85d6a9..dd1e2dc2a1 100644
81--- a/src/net/http/request_test.go
82+++ b/src/net/http/request_test.go
83@@ -770,16 +770,23 @@ func TestRequestWriteBufferedWriter(t *testing.T) {
84 }
85 }
86
87-func TestRequestBadHost(t *testing.T) {
88+func TestRequestBadHostHeader(t *testing.T) {
89 got := []string{}
90 req, err := NewRequest("GET", "http://foo/after", nil)
91 if err != nil {
92 t.Fatal(err)
93 }
94- req.Host = "foo.com with spaces"
95- req.URL.Host = "foo.com with spaces"
96- if err := req.Write(logWrites{t, &got}); err == nil {
97- t.Errorf("Writing request with invalid Host: succeded, want error")
98+ req.Host = "foo.com\nnewline"
99+ req.URL.Host = "foo.com\nnewline"
100+ req.Write(logWrites{t, &got})
101+ want := []string{
102+ "GET /after HTTP/1.1\r\n",
103+ "Host: \r\n",
104+ "User-Agent: " + DefaultUserAgent + "\r\n",
105+ "\r\n",
106+ }
107+ if !reflect.DeepEqual(got, want) {
108+ t.Errorf("Writes = %q\n Want = %q", got, want)
109 }
110 }
111
112--
1132.34.1
114
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 @@
1From 2300f7ef07718f6be4d8aa8486c7de99836e233f Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Wed, 7 Jun 2023 15:27:13 -0700
4Subject: [PATCH] [release-branch.go1.19] crypto/tls: restrict RSA keys in
5 certificates to <= 8192 bits
6
7Extremely large RSA keys in certificate chains can cause a client/server
8to expend significant CPU time verifying signatures. Limit this by
9restricting the size of RSA keys transmitted during handshakes to <=
108192 bits.
11
12Based on a survey of publicly trusted RSA keys, there are currently only
13three certificates in circulation with keys larger than this, and all
14three appear to be test certificates that are not actively deployed. It
15is possible there are larger keys in use in private PKIs, but we target
16the web PKI, so causing breakage here in the interests of increasing the
17default safety of users of crypto/tls seems reasonable.
18
19Thanks to Mateusz Poliwczak for reporting this issue.
20
21Updates #61460
22Fixes #61579
23Fixes CVE-2023-29409
24
25Change-Id: Ie35038515a649199a36a12fc2c5df3af855dca6c
26Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1912161
27Reviewed-by: Damien Neil <dneil@google.com>
28Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
29Run-TryBot: Roland Shoemaker <bracewell@google.com>
30(cherry picked from commit d865c715d92887361e4bd5596e19e513f27781b7)
31Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1965487
32Reviewed-on: https://go-review.googlesource.com/c/go/+/514915
33Run-TryBot: David Chase <drchase@google.com>
34Reviewed-by: Matthew Dempsky <mdempsky@google.com>
35TryBot-Bypass: David Chase <drchase@google.com>
36
37Upstream-Status: Backport [https://github.com/golang/go/commit/2300f7ef07718f6be4d8aa8486c7de99836e233f]
38CVE: CVE-2023-29409
39Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
40---
41 src/crypto/tls/handshake_client.go | 8 +++
42 src/crypto/tls/handshake_client_test.go | 78 +++++++++++++++++++++++++
43 src/crypto/tls/handshake_server.go | 4 ++
44 3 files changed, 90 insertions(+)
45
46diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
47index 4fb528c..ba33ea1 100644
48--- a/src/crypto/tls/handshake_client.go
49+++ b/src/crypto/tls/handshake_client.go
50@@ -788,6 +788,10 @@ func (hs *clientHandshakeState) sendFinished(out []byte) error {
51 return nil
52 }
53
54+// maxRSAKeySize is the maximum RSA key size in bits that we are willing
55+// to verify the signatures of during a TLS handshake.
56+const maxRSAKeySize = 8192
57+
58 // verifyServerCertificate parses and verifies the provided chain, setting
59 // c.verifiedChains and c.peerCertificates or sending the appropriate alert.
60 func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
61@@ -798,6 +802,10 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
62 c.sendAlert(alertBadCertificate)
63 return errors.New("tls: failed to parse certificate from server: " + err.Error())
64 }
65+ if cert.PublicKeyAlgorithm == x509.RSA && cert.PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
66+ c.sendAlert(alertBadCertificate)
67+ return fmt.Errorf("tls: server sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
68+ }
69 certs[i] = cert
70 }
71
72diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go
73index 6bd3c37..8d20b2b 100644
74--- a/src/crypto/tls/handshake_client_test.go
75+++ b/src/crypto/tls/handshake_client_test.go
76@@ -1984,3 +1984,81 @@ func TestCloseClientConnectionOnIdleServer(t *testing.T) {
77 t.Errorf("Error expected, but no error returned")
78 }
79 }
80+
81+// discardConn wraps a net.Conn but discards all writes, but reports that they happened.
82+type discardConn struct {
83+ net.Conn
84+}
85+
86+func (dc *discardConn) Write(data []byte) (int, error) {
87+ return len(data), nil
88+}
89+
90+// largeRSAKeyCertPEM contains a 8193 bit RSA key
91+const largeRSAKeyCertPEM = `-----BEGIN CERTIFICATE-----
92+MIIInjCCBIWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwd0ZXN0
93+aW5nMB4XDTIzMDYwNzIxMjMzNloXDTIzMDYwNzIzMjMzNlowEjEQMA4GA1UEAxMH
94+dGVzdGluZzCCBCIwDQYJKoZIhvcNAQEBBQADggQPADCCBAoCggQBAWdHsf6Rh2Ca
95+n2SQwn4t4OQrOjbLLdGE1pM6TBKKrHUFy62uEL8atNjlcfXIsa4aEu3xNGiqxqur
96+ZectlkZbm0FkaaQ1Wr9oikDY3KfjuaXdPdO/XC/h8AKNxlDOylyXwUSK/CuYb+1j
97+gy8yF5QFvVfwW/xwTlHmhUeSkVSQPosfQ6yXNNsmMzkd+ZPWLrfq4R+wiNtwYGu0
98+WSBcI/M9o8/vrNLnIppoiBJJ13j9CR1ToEAzOFh9wwRWLY10oZhoh1ONN1KQURx4
99+qedzvvP2DSjZbUccdvl2rBGvZpzfOiFdm1FCnxB0c72Cqx+GTHXBFf8bsa7KHky9
100+sNO1GUanbq17WoDNgwbY6H51bfShqv0CErxatwWox3we4EcAmFHPVTCYL1oWVMGo
101+a3Eth91NZj+b/nGhF9lhHKGzXSv9brmLLkfvM1jA6XhNhA7BQ5Vz67lj2j3XfXdh
102+t/BU5pBXbL4Ut4mIhT1YnKXAjX2/LF5RHQTE8Vwkx5JAEKZyUEGOReD/B+7GOrLp
103+HduMT9vZAc5aR2k9I8qq1zBAzsL69lyQNAPaDYd1BIAjUety9gAYaSQffCgAgpRO
104+Gt+DYvxS+7AT/yEd5h74MU2AH7KrAkbXOtlwupiGwhMVTstncDJWXMJqbBhyHPF8
105+3UmZH0hbL4PYmzSj9LDWQQXI2tv6vrCpfts3Cqhqxz9vRpgY7t1Wu6l/r+KxYYz3
106+1pcGpPvRmPh0DJm7cPTiXqPnZcPt+ulSaSdlxmd19OnvG5awp0fXhxryZVwuiT8G
107+VDkhyARrxYrdjlINsZJZbQjO0t8ketXAELJOnbFXXzeCOosyOHkLwsqOO96AVJA8
108+45ZVL5m95ClGy0RSrjVIkXsxTAMVG6SPAqKwk6vmTdRGuSPS4rhgckPVDHmccmuq
109+dfnT2YkX+wB2/M3oCgU+s30fAHGkbGZ0pCdNbFYFZLiH0iiMbTDl/0L/z7IdK0nH
110+GLHVE7apPraKC6xl6rPWsD2iSfrmtIPQa0+rqbIVvKP5JdfJ8J4alI+OxFw/znQe
111+V0/Rez0j22Fe119LZFFSXhRv+ZSvcq20xDwh00mzcumPWpYuCVPozA18yIhC9tNn
112+ALHndz0tDseIdy9vC71jQWy9iwri3ueN0DekMMF8JGzI1Z6BAFzgyAx3DkHtwHg7
113+B7qD0jPG5hJ5+yt323fYgJsuEAYoZ8/jzZ01pkX8bt+UsVN0DGnSGsI2ktnIIk3J
114+l+8krjmUy6EaW79nITwoOqaeHOIp8m3UkjEcoKOYrzHRKqRy+A09rY+m/cAQaafW
115+4xp0Zv7qZPLwnu0jsqB4jD8Ll9yPB02ndsoV6U5PeHzTkVhPml19jKUAwFfs7TJg
116+kXy+/xFhYVUCAwEAATANBgkqhkiG9w0BAQsFAAOCBAIAAQnZY77pMNeypfpba2WK
117+aDasT7dk2JqP0eukJCVPTN24Zca+xJNPdzuBATm/8SdZK9lddIbjSnWRsKvTnO2r
118+/rYdlPf3jM5uuJtb8+Uwwe1s+gszelGS9G/lzzq+ehWicRIq2PFcs8o3iQMfENiv
119+qILJ+xjcrvms5ZPDNahWkfRx3KCg8Q+/at2n5p7XYjMPYiLKHnDC+RE2b1qT20IZ
120+FhuK/fTWLmKbfYFNNga6GC4qcaZJ7x0pbm4SDTYp0tkhzcHzwKhidfNB5J2vNz6l
121+Ur6wiYwamFTLqcOwWo7rdvI+sSn05WQBv0QZlzFX+OAu0l7WQ7yU+noOxBhjvHds
122+14+r9qcQZg2q9kG+evopYZqYXRUNNlZKo9MRBXhfrISulFAc5lRFQIXMXnglvAu+
123+Ipz2gomEAOcOPNNVldhKAU94GAMJd/KfN0ZP7gX3YvPzuYU6XDhag5RTohXLm18w
124+5AF+ES3DOQ6ixu3DTf0D+6qrDuK+prdX8ivcdTQVNOQ+MIZeGSc6NWWOTaMGJ3lg
125+aZIxJUGdo6E7GBGiC1YTjgFKFbHzek1LRTh/LX3vbSudxwaG0HQxwsU9T4DWiMqa
126+Fkf2KteLEUA6HrR+0XlAZrhwoqAmrJ+8lCFX3V0gE9lpENfVHlFXDGyx10DpTB28
127+DdjnY3F7EPWNzwf9P3oNT69CKW3Bk6VVr3ROOJtDxVu1ioWo3TaXltQ0VOnap2Pu
128+sa5wfrpfwBDuAS9JCDg4ttNp2nW3F7tgXC6xPqw5pvGwUppEw9XNrqV8TZrxduuv
129+rQ3NyZ7KSzIpmFlD3UwV/fGfz3UQmHS6Ng1evrUID9DjfYNfRqSGIGjDfxGtYD+j
130+Z1gLJZuhjJpNtwBkKRtlNtrCWCJK2hidK/foxwD7kwAPo2I9FjpltxCRywZUs07X
131+KwXTfBR9v6ij1LV6K58hFS+8ezZyZ05CeVBFkMQdclTOSfuPxlMkQOtjp8QWDj+F
132+j/MYziT5KBkHvcbrjdRtUJIAi4N7zCsPZtjik918AK1WBNRVqPbrgq/XSEXMfuvs
133+6JbfK0B76vdBDRtJFC1JsvnIrGbUztxXzyQwFLaR/AjVJqpVlysLWzPKWVX6/+SJ
134+u1NQOl2E8P6ycyBsuGnO89p0S4F8cMRcI2X1XQsZ7/q0NBrOMaEp5T3SrWo9GiQ3
135+o2SBdbs3Y6MBPBtTu977Z/0RO63J3M5i2tjUiDfrFy7+VRLKr7qQ7JibohyB8QaR
136+9tedgjn2f+of7PnP/PEl1cCphUZeHM7QKUMPT8dbqwmKtlYY43EHXcvNOT5IBk3X
137+9lwJoZk/B2i+ZMRNSP34ztAwtxmasPt6RAWGQpWCn9qmttAHAnMfDqe7F7jVR6rS
138+u58=
139+-----END CERTIFICATE-----`
140+
141+func TestHandshakeRSATooBig(t *testing.T) {
142+ testCert, _ := pem.Decode([]byte(largeRSAKeyCertPEM))
143+
144+ c := &Conn{conn: &discardConn{}, config: testConfig.Clone()}
145+
146+ expectedErr := "tls: server sent certificate containing RSA key larger than 8192 bits"
147+ err := c.verifyServerCertificate([][]byte{testCert.Bytes})
148+ if err == nil || err.Error() != expectedErr {
149+ t.Errorf("Conn.verifyServerCertificate unexpected error: want %q, got %q", expectedErr, err)
150+ }
151+
152+ expectedErr = "tls: client sent certificate containing RSA key larger than 8192 bits"
153+ err = c.processCertsFromClient(Certificate{Certificate: [][]byte{testCert.Bytes}})
154+ if err == nil || err.Error() != expectedErr {
155+ t.Errorf("Conn.processCertsFromClient unexpected error: want %q, got %q", expectedErr, err)
156+ }
157+}
158diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
159index b16415a..2e36840 100644
160--- a/src/crypto/tls/handshake_server.go
161+++ b/src/crypto/tls/handshake_server.go
162@@ -738,6 +738,10 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
163 c.sendAlert(alertBadCertificate)
164 return errors.New("tls: failed to parse client certificate: " + err.Error())
165 }
166+ if certs[i].PublicKeyAlgorithm == x509.RSA && certs[i].PublicKey.(*rsa.PublicKey).N.BitLen() > maxRSAKeySize {
167+ c.sendAlert(alertBadCertificate)
168+ return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", maxRSAKeySize)
169+ }
170 }
171
172 if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) {
173--
1742.25.1
175
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 @@
1From 023b542edf38e2a1f87fcefb9f75ff2f99401b4c Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Thu, 3 Aug 2023 12:24:13 -0700
4Subject: [PATCH] [release-branch.go1.20] html/template: support HTML-like
5 comments in script contexts
6
7Per Appendix B.1.1 of the ECMAScript specification, support HTML-like
8comments in script contexts. Also per section 12.5, support hashbang
9comments. This brings our parsing in-line with how browsers treat these
10comment types.
11
12Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
13reporting this issue.
14
15Fixes #62196
16Fixes #62395
17Fixes CVE-2023-39318
18
19Change-Id: Id512702c5de3ae46cf648e268cb10e1eb392a181
20Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976593
21Run-TryBot: Roland Shoemaker <bracewell@google.com>
22Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
23Reviewed-by: Damien Neil <dneil@google.com>
24Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
25Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014620
26Reviewed-on: https://go-review.googlesource.com/c/go/+/526098
27Run-TryBot: Cherry Mui <cherryyz@google.com>
28TryBot-Result: Gopher Robot <gobot@golang.org>
29
30Upstream-Status: Backport from [https://github.com/golang/go/commit/023b542edf38e2a1f87fcefb9f75ff2f99401b4c]
31CVE: CVE-2023-39318
32Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
33---
34 src/html/template/context.go | 6 ++-
35 src/html/template/escape.go | 5 +-
36 src/html/template/escape_test.go | 10 ++++
37 src/html/template/state_string.go | 26 +++++-----
38 src/html/template/transition.go | 80 ++++++++++++++++++++-----------
39 5 files changed, 84 insertions(+), 43 deletions(-)
40
41diff --git a/src/html/template/context.go b/src/html/template/context.go
42index 0b65313..4eb7891 100644
43--- a/src/html/template/context.go
44+++ b/src/html/template/context.go
45@@ -124,6 +124,10 @@ const (
46 stateJSBlockCmt
47 // stateJSLineCmt occurs inside a JavaScript // line comment.
48 stateJSLineCmt
49+ // stateJSHTMLOpenCmt occurs inside a JavaScript <!-- HTML-like comment.
50+ stateJSHTMLOpenCmt
51+ // stateJSHTMLCloseCmt occurs inside a JavaScript --> HTML-like comment.
52+ stateJSHTMLCloseCmt
53 // stateCSS occurs inside a <style> element or style attribute.
54 stateCSS
55 // stateCSSDqStr occurs inside a CSS double quoted string.
56@@ -149,7 +153,7 @@ const (
57 // authors & maintainers, not for end-users or machines.
58 func isComment(s state) bool {
59 switch s {
60- case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateCSSBlockCmt, stateCSSLineCmt:
61+ case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt, stateCSSBlockCmt, stateCSSLineCmt:
62 return true
63 }
64 return false
65diff --git a/src/html/template/escape.go b/src/html/template/escape.go
66index 435f912..ad2ec69 100644
67--- a/src/html/template/escape.go
68+++ b/src/html/template/escape.go
69@@ -698,9 +698,12 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
70 if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
71 // Preserve the portion between written and the comment start.
72 cs := i1 - 2
73- if c1.state == stateHTMLCmt {
74+ if c1.state == stateHTMLCmt || c1.state == stateJSHTMLOpenCmt {
75 // "<!--" instead of "/*" or "//"
76 cs -= 2
77+ } else if c1.state == stateJSHTMLCloseCmt {
78+ // "-->" instead of "/*" or "//"
79+ cs -= 1
80 }
81 b.Write(s[written:cs])
82 written = i1
83diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
84index f550691..5f41e52 100644
85--- a/src/html/template/escape_test.go
86+++ b/src/html/template/escape_test.go
87@@ -503,6 +503,16 @@ func TestEscape(t *testing.T) {
88 "<script>var a/*b*///c\nd</script>",
89 "<script>var a \nd</script>",
90 },
91+ {
92+ "JS HTML-like comments",
93+ "<script>before <!-- beep\nbetween\nbefore-->boop\n</script>",
94+ "<script>before \nbetween\nbefore\n</script>",
95+ },
96+ {
97+ "JS hashbang comment",
98+ "<script>#! beep\n</script>",
99+ "<script>\n</script>",
100+ },
101 {
102 "CSS comments",
103 "<style>p// paragraph\n" +
104diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go
105index 05104be..b5cfe70 100644
106--- a/src/html/template/state_string.go
107+++ b/src/html/template/state_string.go
108@@ -25,21 +25,23 @@ func _() {
109 _ = x[stateJSRegexp-14]
110 _ = x[stateJSBlockCmt-15]
111 _ = x[stateJSLineCmt-16]
112- _ = x[stateCSS-17]
113- _ = x[stateCSSDqStr-18]
114- _ = x[stateCSSSqStr-19]
115- _ = x[stateCSSDqURL-20]
116- _ = x[stateCSSSqURL-21]
117- _ = x[stateCSSURL-22]
118- _ = x[stateCSSBlockCmt-23]
119- _ = x[stateCSSLineCmt-24]
120- _ = x[stateError-25]
121- _ = x[stateDead-26]
122+ _ = x[stateJSHTMLOpenCmt-17]
123+ _ = x[stateJSHTMLCloseCmt-18]
124+ _ = x[stateCSS-19]
125+ _ = x[stateCSSDqStr-20]
126+ _ = x[stateCSSSqStr-21]
127+ _ = x[stateCSSDqURL-22]
128+ _ = x[stateCSSSqURL-23]
129+ _ = x[stateCSSURL-24]
130+ _ = x[stateCSSBlockCmt-25]
131+ _ = x[stateCSSLineCmt-26]
132+ _ = x[stateError-27]
133+ _ = x[stateDead-28]
134 }
135
136-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
137+const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
138
139-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 204, 217, 230, 243, 256, 267, 283, 298, 308, 317}
140+var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 214, 233, 241, 254, 267, 280, 293, 304, 320, 335, 345, 354}
141
142 func (i state) String() string {
143 if i >= state(len(_state_index)-1) {
144diff --git a/src/html/template/transition.go b/src/html/template/transition.go
145index 92eb351..12aa4c4 100644
146--- a/src/html/template/transition.go
147+++ b/src/html/template/transition.go
148@@ -14,32 +14,34 @@ import (
149 // the updated context and the number of bytes consumed from the front of the
150 // input.
151 var transitionFunc = [...]func(context, []byte) (context, int){
152- stateText: tText,
153- stateTag: tTag,
154- stateAttrName: tAttrName,
155- stateAfterName: tAfterName,
156- stateBeforeValue: tBeforeValue,
157- stateHTMLCmt: tHTMLCmt,
158- stateRCDATA: tSpecialTagEnd,
159- stateAttr: tAttr,
160- stateURL: tURL,
161- stateSrcset: tURL,
162- stateJS: tJS,
163- stateJSDqStr: tJSDelimited,
164- stateJSSqStr: tJSDelimited,
165- stateJSBqStr: tJSDelimited,
166- stateJSRegexp: tJSDelimited,
167- stateJSBlockCmt: tBlockCmt,
168- stateJSLineCmt: tLineCmt,
169- stateCSS: tCSS,
170- stateCSSDqStr: tCSSStr,
171- stateCSSSqStr: tCSSStr,
172- stateCSSDqURL: tCSSStr,
173- stateCSSSqURL: tCSSStr,
174- stateCSSURL: tCSSStr,
175- stateCSSBlockCmt: tBlockCmt,
176- stateCSSLineCmt: tLineCmt,
177- stateError: tError,
178+ stateText: tText,
179+ stateTag: tTag,
180+ stateAttrName: tAttrName,
181+ stateAfterName: tAfterName,
182+ stateBeforeValue: tBeforeValue,
183+ stateHTMLCmt: tHTMLCmt,
184+ stateRCDATA: tSpecialTagEnd,
185+ stateAttr: tAttr,
186+ stateURL: tURL,
187+ stateSrcset: tURL,
188+ stateJS: tJS,
189+ stateJSDqStr: tJSDelimited,
190+ stateJSSqStr: tJSDelimited,
191+ stateJSBqStr: tJSDelimited,
192+ stateJSRegexp: tJSDelimited,
193+ stateJSBlockCmt: tBlockCmt,
194+ stateJSLineCmt: tLineCmt,
195+ stateJSHTMLOpenCmt: tLineCmt,
196+ stateJSHTMLCloseCmt: tLineCmt,
197+ stateCSS: tCSS,
198+ stateCSSDqStr: tCSSStr,
199+ stateCSSSqStr: tCSSStr,
200+ stateCSSDqURL: tCSSStr,
201+ stateCSSSqURL: tCSSStr,
202+ stateCSSURL: tCSSStr,
203+ stateCSSBlockCmt: tBlockCmt,
204+ stateCSSLineCmt: tLineCmt,
205+ stateError: tError,
206 }
207
208 var commentStart = []byte("<!--")
209@@ -263,7 +265,7 @@ func tURL(c context, s []byte) (context, int) {
210
211 // tJS is the context transition function for the JS state.
212 func tJS(c context, s []byte) (context, int) {
213- i := bytes.IndexAny(s, "\"`'/")
214+ i := bytes.IndexAny(s, "\"`'/<-#")
215 if i == -1 {
216 // Entire input is non string, comment, regexp tokens.
217 c.jsCtx = nextJSCtx(s, c.jsCtx)
218@@ -293,6 +295,26 @@ func tJS(c context, s []byte) (context, int) {
219 err: errorf(ErrSlashAmbig, nil, 0, "'/' could start a division or regexp: %.32q", s[i:]),
220 }, len(s)
221 }
222+ // ECMAScript supports HTML style comments for legacy reasons, see Appendix
223+ // B.1.1 "HTML-like Comments". The handling of these comments is somewhat
224+ // confusing. Multi-line comments are not supported, i.e. anything on lines
225+ // between the opening and closing tokens is not considered a comment, but
226+ // anything following the opening or closing token, on the same line, is
227+ // ignored. As such we simply treat any line prefixed with "<!--" or "-->"
228+ // as if it were actually prefixed with "//" and move on.
229+ case '<':
230+ if i+3 < len(s) && bytes.Equal(commentStart, s[i:i+4]) {
231+ c.state, i = stateJSHTMLOpenCmt, i+3
232+ }
233+ case '-':
234+ if i+2 < len(s) && bytes.Equal(commentEnd, s[i:i+3]) {
235+ c.state, i = stateJSHTMLCloseCmt, i+2
236+ }
237+ // ECMAScript also supports "hashbang" comment lines, see Section 12.5.
238+ case '#':
239+ if i+1 < len(s) && s[i+1] == '!' {
240+ c.state, i = stateJSLineCmt, i+1
241+ }
242 default:
243 panic("unreachable")
244 }
245@@ -372,12 +394,12 @@ func tBlockCmt(c context, s []byte) (context, int) {
246 return c, i + 2
247 }
248
249-// tLineCmt is the context transition function for //comment states.
250+// tLineCmt is the context transition function for //comment states, and the JS HTML-like comment state.
251 func tLineCmt(c context, s []byte) (context, int) {
252 var lineTerminators string
253 var endState state
254 switch c.state {
255- case stateJSLineCmt:
256+ case stateJSLineCmt, stateJSHTMLOpenCmt, stateJSHTMLCloseCmt:
257 lineTerminators, endState = "\n\r\u2028\u2029", stateJS
258 case stateCSSLineCmt:
259 lineTerminators, endState = "\n\f\r", stateCSS
260--
2612.24.4
262
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 @@
1From 2070531d2f53df88e312edace6c8dfc9686ab2f5 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Thu, 3 Aug 2023 12:28:28 -0700
4Subject: [PATCH] [release-branch.go1.20] html/template: properly handle
5 special tags within the script context
6
7The HTML specification has incredibly complex rules for how to handle
8"<!--", "<script", and "</script" when they appear within literals in
9the script context. Rather than attempting to apply these restrictions
10(which require a significantly more complex state machine) we apply
11the workaround suggested in section 4.12.1.3 of the HTML specification [1].
12
13More precisely, when "<!--", "<script", and "</script" appear within
14literals (strings and regular expressions, ignoring comments since we
15already elide their content) we replace the "<" with "\x3C". This avoids
16the unintuitive behavior that using these tags within literals can cause,
17by simply preventing the rendered content from triggering it. This may
18break some correct usages of these tags, but on balance is more likely
19to prevent XSS attacks where users are unknowingly either closing or not
20closing the script blocks where they think they are.
21
22Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
23reporting this issue.
24
25Fixes #62197
26Fixes #62397
27Fixes CVE-2023-39319
28
29[1] https://html.spec.whatwg.org/#restrictions-for-contents-of-script-elements
30
31Change-Id: Iab57b0532694827e3eddf57a7497ba1fab1746dc
32Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976594
33Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
34Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
35Reviewed-by: Damien Neil <dneil@google.com>
36Run-TryBot: Roland Shoemaker <bracewell@google.com>
37Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014621
38TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
39Reviewed-on: https://go-review.googlesource.com/c/go/+/526099
40TryBot-Result: Gopher Robot <gobot@golang.org>
41Run-TryBot: Cherry Mui <cherryyz@google.com>
42
43Upstream-Status: Backport from [https://github.com/golang/go/commit/2070531d2f53df88e312edace6c8dfc9686ab2f5]
44CVE: CVE-2023-39319
45Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
46---
47 src/html/template/context.go | 14 ++++++++++
48 src/html/template/escape.go | 26 ++++++++++++++++++
49 src/html/template/escape_test.go | 47 +++++++++++++++++++++++++++++++-
50 src/html/template/transition.go | 15 ++++++++++
51 4 files changed, 101 insertions(+), 1 deletion(-)
52
53diff --git a/src/html/template/context.go b/src/html/template/context.go
54index 4eb7891..feb6517 100644
55--- a/src/html/template/context.go
56+++ b/src/html/template/context.go
57@@ -168,6 +168,20 @@ func isInTag(s state) bool {
58 return false
59 }
60
61+// isInScriptLiteral returns true if s is one of the literal states within a
62+// <script> tag, and as such occurances of "<!--", "<script", and "</script"
63+// need to be treated specially.
64+func isInScriptLiteral(s state) bool {
65+ // Ignore the comment states (stateJSBlockCmt, stateJSLineCmt,
66+ // stateJSHTMLOpenCmt, stateJSHTMLCloseCmt) because their content is already
67+ // omitted from the output.
68+ switch s {
69+ case stateJSDqStr, stateJSSqStr, stateJSBqStr, stateJSRegexp:
70+ return true
71+ }
72+ return false
73+}
74+
75 // delim is the delimiter that will end the current HTML attribute.
76 type delim uint8
77
78diff --git a/src/html/template/escape.go b/src/html/template/escape.go
79index ad2ec69..de8cf6f 100644
80--- a/src/html/template/escape.go
81+++ b/src/html/template/escape.go
82@@ -10,6 +10,7 @@ import (
83 "html"
84 "internal/godebug"
85 "io"
86+ "regexp"
87 "text/template"
88 "text/template/parse"
89 )
90@@ -650,6 +651,26 @@ var delimEnds = [...]string{
91 delimSpaceOrTagEnd: " \t\n\f\r>",
92 }
93
94+var (
95+ // Per WHATWG HTML specification, section 4.12.1.3, there are extremely
96+ // complicated rules for how to handle the set of opening tags <!--,
97+ // <script, and </script when they appear in JS literals (i.e. strings,
98+ // regexs, and comments). The specification suggests a simple solution,
99+ // rather than implementing the arcane ABNF, which involves simply escaping
100+ // the opening bracket with \x3C. We use the below regex for this, since it
101+ // makes doing the case-insensitive find-replace much simpler.
102+ specialScriptTagRE = regexp.MustCompile("(?i)<(script|/script|!--)")
103+ specialScriptTagReplacement = []byte("\\x3C$1")
104+)
105+
106+func containsSpecialScriptTag(s []byte) bool {
107+ return specialScriptTagRE.Match(s)
108+}
109+
110+func escapeSpecialScriptTags(s []byte) []byte {
111+ return specialScriptTagRE.ReplaceAll(s, specialScriptTagReplacement)
112+}
113+
114 var doctypeBytes = []byte("<!DOCTYPE")
115
116 // escapeText escapes a text template node.
117@@ -708,6 +729,11 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
118 b.Write(s[written:cs])
119 written = i1
120 }
121+ if isInScriptLiteral(c.state) && containsSpecialScriptTag(s[i:i1]) {
122+ b.Write(s[written:i])
123+ b.Write(escapeSpecialScriptTags(s[i:i1]))
124+ written = i1
125+ }
126 if i == i1 && c.state == c1.state {
127 panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
128 }
129diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
130index 5f41e52..0cacb20 100644
131--- a/src/html/template/escape_test.go
132+++ b/src/html/template/escape_test.go
133@@ -513,6 +513,21 @@ func TestEscape(t *testing.T) {
134 "<script>#! beep\n</script>",
135 "<script>\n</script>",
136 },
137+ {
138+ "Special tags in <script> string literals",
139+ `<script>var a = "asd < 123 <!-- 456 < fgh <script jkl < 789 </script"</script>`,
140+ `<script>var a = "asd < 123 \x3C!-- 456 < fgh \x3Cscript jkl < 789 \x3C/script"</script>`,
141+ },
142+ {
143+ "Special tags in <script> string literals (mixed case)",
144+ `<script>var a = "<!-- <ScripT </ScripT"</script>`,
145+ `<script>var a = "\x3C!-- \x3CScripT \x3C/ScripT"</script>`,
146+ },
147+ {
148+ "Special tags in <script> regex literals (mixed case)",
149+ `<script>var a = /<!-- <ScripT </ScripT/</script>`,
150+ `<script>var a = /\x3C!-- \x3CScripT \x3C/ScripT/</script>`,
151+ },
152 {
153 "CSS comments",
154 "<style>p// paragraph\n" +
155@@ -1501,8 +1516,38 @@ func TestEscapeText(t *testing.T) {
156 context{state: stateJS, element: elementScript},
157 },
158 {
159+ // <script and </script tags are escaped, so </script> should not
160+ // cause us to exit the JS state.
161 `<script>document.write("<script>alert(1)</script>");`,
162- context{state: stateText},
163+ context{state: stateJS, element: elementScript},
164+ },
165+ {
166+ `<script>document.write("<script>`,
167+ context{state: stateJSDqStr, element: elementScript},
168+ },
169+ {
170+ `<script>document.write("<script>alert(1)</script>`,
171+ context{state: stateJSDqStr, element: elementScript},
172+ },
173+ {
174+ `<script>document.write("<script>alert(1)<!--`,
175+ context{state: stateJSDqStr, element: elementScript},
176+ },
177+ {
178+ `<script>document.write("<script>alert(1)</Script>");`,
179+ context{state: stateJS, element: elementScript},
180+ },
181+ {
182+ `<script>document.write("<!--");`,
183+ context{state: stateJS, element: elementScript},
184+ },
185+ {
186+ `<script>let a = /</script`,
187+ context{state: stateJSRegexp, element: elementScript},
188+ },
189+ {
190+ `<script>let a = /</script/`,
191+ context{state: stateJS, element: elementScript, jsCtx: jsCtxDivOp},
192 },
193 {
194 `<script type="text/template">`,
195diff --git a/src/html/template/transition.go b/src/html/template/transition.go
196index 12aa4c4..3d2a37c 100644
197--- a/src/html/template/transition.go
198+++ b/src/html/template/transition.go
199@@ -214,6 +214,11 @@ var (
200 // element states.
201 func tSpecialTagEnd(c context, s []byte) (context, int) {
202 if c.element != elementNone {
203+ // script end tags ("</script") within script literals are ignored, so that
204+ // we can properly escape them.
205+ if c.element == elementScript && (isInScriptLiteral(c.state) || isComment(c.state)) {
206+ return c, len(s)
207+ }
208 if i := indexTagEnd(s, specialTagEndMarkers[c.element]); i != -1 {
209 return context{}, i
210 }
211@@ -353,6 +358,16 @@ func tJSDelimited(c context, s []byte) (context, int) {
212 inCharset = true
213 case ']':
214 inCharset = false
215+ case '/':
216+ // If "</script" appears in a regex literal, the '/' should not
217+ // close the regex literal, and it will later be escaped to
218+ // "\x3C/script" in escapeText.
219+ if i > 0 && i+7 <= len(s) && bytes.Compare(bytes.ToLower(s[i-1:i+7]), []byte("</script")) == 0 {
220+ i++
221+ } else if !inCharset {
222+ c.state, c.jsCtx = stateJS, jsCtxDivOp
223+ return c, i + 1
224+ }
225 default:
226 // end delimiter
227 if !inCharset {
228--
2292.24.4
230
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 @@
1From 6446af942e2e2b161c4ec1b60d9703a2b55dc4dd Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Tue, 7 Nov 2023 10:47:56 -0800
4Subject: [PATCH] [release-branch.go1.20] net/http: limit chunked data overhead
5
6The chunked transfer encoding adds some overhead to
7the content transferred. When writing one byte per
8chunk, for example, there are five bytes of overhead
9per byte of data transferred: "1\r\nX\r\n" to send "X".
10
11Chunks may include "chunk extensions",
12which we skip over and do not use.
13For example: "1;chunk extension here\r\nX\r\n".
14
15A malicious sender can use chunk extensions to add
16about 4k of overhead per byte of data.
17(The maximum chunk header line size we will accept.)
18
19Track the amount of overhead read in chunked data,
20and produce an error if it seems excessive.
21
22Updates #64433
23Fixes #64434
24Fixes CVE-2023-39326
25
26Change-Id: I40f8d70eb6f9575fb43f506eb19132ccedafcf39
27Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2076135
28Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
29Reviewed-by: Roland Shoemaker <bracewell@google.com>
30(cherry picked from commit 3473ae72ee66c60744665a24b2fde143e8964d4f)
31Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2095407
32Run-TryBot: Roland Shoemaker <bracewell@google.com>
33TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
34Reviewed-by: Damien Neil <dneil@google.com>
35Reviewed-on: https://go-review.googlesource.com/c/go/+/547355
36Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
37LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
38
39Upstream-Status: Backport [https://github.com/golang/go/commit/6446af942e2e2b161c4ec1b60d9703a2b55dc4dd]
40CVE: CVE-2023-39326
41Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
42---
43 src/net/http/internal/chunked.go | 36 +++++++++++++---
44 src/net/http/internal/chunked_test.go | 59 +++++++++++++++++++++++++++
45 2 files changed, 89 insertions(+), 6 deletions(-)
46
47diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go
48index f06e572..ddbaacb 100644
49--- a/src/net/http/internal/chunked.go
50+++ b/src/net/http/internal/chunked.go
51@@ -39,7 +39,8 @@ type chunkedReader struct {
52 n uint64 // unread bytes in chunk
53 err error
54 buf [2]byte
55- checkEnd bool // whether need to check for \r\n chunk footer
56+ checkEnd bool // whether need to check for \r\n chunk footer
57+ excess int64 // "excessive" chunk overhead, for malicious sender detection
58 }
59
60 func (cr *chunkedReader) beginChunk() {
61@@ -49,10 +50,38 @@ func (cr *chunkedReader) beginChunk() {
62 if cr.err != nil {
63 return
64 }
65+ cr.excess += int64(len(line)) + 2 // header, plus \r\n after the chunk data
66+ line = trimTrailingWhitespace(line)
67+ line, cr.err = removeChunkExtension(line)
68+ if cr.err != nil {
69+ return
70+ }
71 cr.n, cr.err = parseHexUint(line)
72 if cr.err != nil {
73 return
74 }
75+ // A sender who sends one byte per chunk will send 5 bytes of overhead
76+ // for every byte of data. ("1\r\nX\r\n" to send "X".)
77+ // We want to allow this, since streaming a byte at a time can be legitimate.
78+ //
79+ // A sender can use chunk extensions to add arbitrary amounts of additional
80+ // data per byte read. ("1;very long extension\r\nX\r\n" to send "X".)
81+ // We don't want to disallow extensions (although we discard them),
82+ // but we also don't want to allow a sender to reduce the signal/noise ratio
83+ // arbitrarily.
84+ //
85+ // We track the amount of excess overhead read,
86+ // and produce an error if it grows too large.
87+ //
88+ // Currently, we say that we're willing to accept 16 bytes of overhead per chunk,
89+ // plus twice the amount of real data in the chunk.
90+ cr.excess -= 16 + (2 * int64(cr.n))
91+ if cr.excess < 0 {
92+ cr.excess = 0
93+ }
94+ if cr.excess > 16*1024 {
95+ cr.err = errors.New("chunked encoding contains too much non-data")
96+ }
97 if cr.n == 0 {
98 cr.err = io.EOF
99 }
100@@ -133,11 +162,6 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) {
101 if len(p) >= maxLineLength {
102 return nil, ErrLineTooLong
103 }
104- p = trimTrailingWhitespace(p)
105- p, err = removeChunkExtension(p)
106- if err != nil {
107- return nil, err
108- }
109 return p, nil
110 }
111
112diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go
113index d067165..b20747d 100644
114--- a/src/net/http/internal/chunked_test.go
115+++ b/src/net/http/internal/chunked_test.go
116@@ -212,3 +212,62 @@ func TestChunkReadPartial(t *testing.T) {
117 }
118
119 }
120+
121+func TestChunkReaderTooMuchOverhead(t *testing.T) {
122+ // If the sender is sending 100x as many chunk header bytes as chunk data,
123+ // we should reject the stream at some point.
124+ chunk := []byte("1;")
125+ for i := 0; i < 100; i++ {
126+ chunk = append(chunk, 'a') // chunk extension
127+ }
128+ chunk = append(chunk, "\r\nX\r\n"...)
129+ const bodylen = 1 << 20
130+ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) {
131+ if i < bodylen {
132+ return chunk, nil
133+ }
134+ return []byte("0\r\n"), nil
135+ }})
136+ _, err := io.ReadAll(r)
137+ if err == nil {
138+ t.Fatalf("successfully read body with excessive overhead; want error")
139+ }
140+}
141+
142+func TestChunkReaderByteAtATime(t *testing.T) {
143+ // Sending one byte per chunk should not trip the excess-overhead detection.
144+ const bodylen = 1 << 20
145+ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) {
146+ if i < bodylen {
147+ return []byte("1\r\nX\r\n"), nil
148+ }
149+ return []byte("0\r\n"), nil
150+ }})
151+ got, err := io.ReadAll(r)
152+ if err != nil {
153+ t.Errorf("unexpected error: %v", err)
154+ }
155+ if len(got) != bodylen {
156+ t.Errorf("read %v bytes, want %v", len(got), bodylen)
157+ }
158+}
159+
160+type funcReader struct {
161+ f func(iteration int) ([]byte, error)
162+ i int
163+ b []byte
164+ err error
165+}
166+
167+func (r *funcReader) Read(p []byte) (n int, err error) {
168+ if len(r.b) == 0 && r.err == nil {
169+ r.b, r.err = r.f(r.i)
170+ r.i++
171+ }
172+ n = copy(p, r.b)
173+ r.b = r.b[n:]
174+ if len(r.b) > 0 {
175+ return n, nil
176+ }
177+ return n, r.err
178+}
179--
1802.25.1
181
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 @@
1From 9baafabac9a84813a336f068862207d2bb06d255 Mon Sep 17 00:00:00 2001
2From: Filippo Valsorda <filippo@golang.org>
3Date: Wed, 1 Apr 2020 17:25:40 -0400
4Subject: [PATCH] crypto/rsa: refactor RSA-PSS signing and verification
5
6Cleaned up for readability and consistency.
7
8There is one tiny behavioral change: when PSSSaltLengthEqualsHash is
9used and both hash and opts.Hash were set, hash.Size() was used for the
10salt length instead of opts.Hash.Size(). That's clearly wrong because
11opts.Hash is documented to override hash.
12
13Change-Id: I3e25dad933961eac827c6d2e3bbfe45fc5a6fb0e
14Reviewed-on: https://go-review.googlesource.com/c/go/+/226937
15Run-TryBot: Filippo Valsorda <filippo@golang.org>
16TryBot-Result: Gobot Gobot <gobot@golang.org>
17Reviewed-by: Katie Hockman <katie@golang.org>
18
19Upstream-Status: Backport [https://github.com/golang/go/commit/9baafabac9a84813a336f068862207d2bb06d255]
20CVE: CVE-2023-45287 #Dependency Patch1
21Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
22---
23 src/crypto/rsa/pss.go | 173 ++++++++++++++++++++++--------------------
24 src/crypto/rsa/rsa.go | 9 ++-
25 2 files changed, 96 insertions(+), 86 deletions(-)
26
27diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
28index 3ff0c2f4d0076..f9844d87329a8 100644
29--- a/src/crypto/rsa/pss.go
30+++ b/src/crypto/rsa/pss.go
31@@ -4,9 +4,7 @@
32
33 package rsa
34
35-// This file implements the PSS signature scheme [1].
36-//
37-// [1] https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf
38+// This file implements the RSASSA-PSS signature scheme according to RFC 8017.
39
40 import (
41 "bytes"
42@@ -17,8 +15,22 @@ import (
43 "math/big"
44 )
45
46+// Per RFC 8017, Section 9.1
47+//
48+// EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc
49+//
50+// where
51+//
52+// DB = PS || 0x01 || salt
53+//
54+// and PS can be empty so
55+//
56+// emLen = dbLen + hLen + 1 = psLen + sLen + hLen + 2
57+//
58+
59 func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
60- // See [1], section 9.1.1
61+ // See RFC 8017, Section 9.1.1.
62+
63 hLen := hash.Size()
64 sLen := len(salt)
65 emLen := (emBits + 7) / 8
66@@ -30,7 +42,7 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
67 // 2. Let mHash = Hash(M), an octet string of length hLen.
68
69 if len(mHash) != hLen {
70- return nil, errors.New("crypto/rsa: input must be hashed message")
71+ return nil, errors.New("crypto/rsa: input must be hashed with given hash")
72 }
73
74 // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop.
75@@ -40,8 +52,9 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
76 }
77
78 em := make([]byte, emLen)
79- db := em[:emLen-sLen-hLen-2+1+sLen]
80- h := em[emLen-sLen-hLen-2+1+sLen : emLen-1]
81+ psLen := emLen - sLen - hLen - 2
82+ db := em[:psLen+1+sLen]
83+ h := em[psLen+1+sLen : emLen-1]
84
85 // 4. Generate a random octet string salt of length sLen; if sLen = 0,
86 // then salt is the empty string.
87@@ -69,8 +82,8 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
88 // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length
89 // emLen - hLen - 1.
90
91- db[emLen-sLen-hLen-2] = 0x01
92- copy(db[emLen-sLen-hLen-1:], salt)
93+ db[psLen] = 0x01
94+ copy(db[psLen+1:], salt)
95
96 // 9. Let dbMask = MGF(H, emLen - hLen - 1).
97 //
98@@ -81,47 +94,57 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
99 // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in
100 // maskedDB to zero.
101
102- db[0] &= (0xFF >> uint(8*emLen-emBits))
103+ db[0] &= 0xff >> (8*emLen - emBits)
104
105 // 12. Let EM = maskedDB || H || 0xbc.
106- em[emLen-1] = 0xBC
107+ em[emLen-1] = 0xbc
108
109 // 13. Output EM.
110 return em, nil
111 }
112
113 func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
114+ // See RFC 8017, Section 9.1.2.
115+
116+ hLen := hash.Size()
117+ if sLen == PSSSaltLengthEqualsHash {
118+ sLen = hLen
119+ }
120+ emLen := (emBits + 7) / 8
121+ if emLen != len(em) {
122+ return errors.New("rsa: internal error: inconsistent length")
123+ }
124+
125 // 1. If the length of M is greater than the input limitation for the
126 // hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
127 // and stop.
128 //
129 // 2. Let mHash = Hash(M), an octet string of length hLen.
130- hLen := hash.Size()
131 if hLen != len(mHash) {
132 return ErrVerification
133 }
134
135 // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop.
136- emLen := (emBits + 7) / 8
137 if emLen < hLen+sLen+2 {
138 return ErrVerification
139 }
140
141 // 4. If the rightmost octet of EM does not have hexadecimal value
142 // 0xbc, output "inconsistent" and stop.
143- if em[len(em)-1] != 0xBC {
144+ if em[emLen-1] != 0xbc {
145 return ErrVerification
146 }
147
148 // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
149 // let H be the next hLen octets.
150 db := em[:emLen-hLen-1]
151- h := em[emLen-hLen-1 : len(em)-1]
152+ h := em[emLen-hLen-1 : emLen-1]
153
154 // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in
155 // maskedDB are not all equal to zero, output "inconsistent" and
156 // stop.
157- if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 {
158+ var bitMask byte = 0xff >> (8*emLen - emBits)
159+ if em[0] & ^bitMask != 0 {
160 return ErrVerification
161 }
162
163@@ -132,37 +155,30 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
164
165 // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
166 // to zero.
167- db[0] &= (0xFF >> uint(8*emLen-emBits))
168+ db[0] &= bitMask
169
170+ // If we don't know the salt length, look for the 0x01 delimiter.
171 if sLen == PSSSaltLengthAuto {
172- FindSaltLength:
173- for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- {
174- switch db[emLen-hLen-sLen-2] {
175- case 1:
176- break FindSaltLength
177- case 0:
178- continue
179- default:
180- return ErrVerification
181- }
182- }
183- if sLen < 0 {
184+ psLen := bytes.IndexByte(db, 0x01)
185+ if psLen < 0 {
186 return ErrVerification
187 }
188- } else {
189- // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
190- // or if the octet at position emLen - hLen - sLen - 1 (the leftmost
191- // position is "position 1") does not have hexadecimal value 0x01,
192- // output "inconsistent" and stop.
193- for _, e := range db[:emLen-hLen-sLen-2] {
194- if e != 0x00 {
195- return ErrVerification
196- }
197- }
198- if db[emLen-hLen-sLen-2] != 0x01 {
199+ sLen = len(db) - psLen - 1
200+ }
201+
202+ // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
203+ // or if the octet at position emLen - hLen - sLen - 1 (the leftmost
204+ // position is "position 1") does not have hexadecimal value 0x01,
205+ // output "inconsistent" and stop.
206+ psLen := emLen - hLen - sLen - 2
207+ for _, e := range db[:psLen] {
208+ if e != 0x00 {
209 return ErrVerification
210 }
211 }
212+ if db[psLen] != 0x01 {
213+ return ErrVerification
214+ }
215
216 // 11. Let salt be the last sLen octets of DB.
217 salt := db[len(db)-sLen:]
218@@ -181,19 +197,19 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
219 h0 := hash.Sum(nil)
220
221 // 14. If H = H', output "consistent." Otherwise, output "inconsistent."
222- if !bytes.Equal(h0, h) {
223+ if !bytes.Equal(h0, h) { // TODO: constant time?
224 return ErrVerification
225 }
226 return nil
227 }
228
229-// signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt.
230+// signPSSWithSalt calculates the signature of hashed using PSS with specified salt.
231 // Note that hashed must be the result of hashing the input message using the
232 // given hash function. salt is a random sequence of bytes whose length will be
233 // later used to verify the signature.
234 func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
235- nBits := priv.N.BitLen()
236- em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New())
237+ emBits := priv.N.BitLen() - 1
238+ em, err := emsaPSSEncode(hashed, emBits, salt, hash.New())
239 if err != nil {
240 return
241 }
242@@ -202,7 +218,7 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed,
243 if err != nil {
244 return
245 }
246- s = make([]byte, (nBits+7)/8)
247+ s = make([]byte, priv.Size())
248 copyWithLeftPad(s, c.Bytes())
249 return
250 }
251@@ -223,16 +239,15 @@ type PSSOptions struct {
252 // PSSSaltLength constants.
253 SaltLength int
254
255- // Hash, if not zero, overrides the hash function passed to SignPSS.
256- // This is the only way to specify the hash function when using the
257- // crypto.Signer interface.
258+ // Hash is the hash function used to generate the message digest. If not
259+ // zero, it overrides the hash function passed to SignPSS. It's required
260+ // when using PrivateKey.Sign.
261 Hash crypto.Hash
262 }
263
264-// HashFunc returns pssOpts.Hash so that PSSOptions implements
265-// crypto.SignerOpts.
266-func (pssOpts *PSSOptions) HashFunc() crypto.Hash {
267- return pssOpts.Hash
268+// HashFunc returns opts.Hash so that PSSOptions implements crypto.SignerOpts.
269+func (opts *PSSOptions) HashFunc() crypto.Hash {
270+ return opts.Hash
271 }
272
273 func (opts *PSSOptions) saltLength() int {
274@@ -242,56 +257,50 @@ func (opts *PSSOptions) saltLength() int {
275 return opts.SaltLength
276 }
277
278-// SignPSS calculates the signature of hashed using RSASSA-PSS [1].
279-// Note that hashed must be the result of hashing the input message using the
280-// given hash function. The opts argument may be nil, in which case sensible
281-// defaults are used.
282-func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) ([]byte, error) {
283+// SignPSS calculates the signature of digest using PSS.
284+//
285+// digest must be the result of hashing the input message using the given hash
286+// function. The opts argument may be nil, in which case sensible defaults are
287+// used. If opts.Hash is set, it overrides hash.
288+func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) {
289+ if opts != nil && opts.Hash != 0 {
290+ hash = opts.Hash
291+ }
292+
293 saltLength := opts.saltLength()
294 switch saltLength {
295 case PSSSaltLengthAuto:
296- saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size()
297+ saltLength = priv.Size() - 2 - hash.Size()
298 case PSSSaltLengthEqualsHash:
299 saltLength = hash.Size()
300 }
301
302- if opts != nil && opts.Hash != 0 {
303- hash = opts.Hash
304- }
305-
306 salt := make([]byte, saltLength)
307 if _, err := io.ReadFull(rand, salt); err != nil {
308 return nil, err
309 }
310- return signPSSWithSalt(rand, priv, hash, hashed, salt)
311+ return signPSSWithSalt(rand, priv, hash, digest, salt)
312 }
313
314 // VerifyPSS verifies a PSS signature.
315-// hashed is the result of hashing the input message using the given hash
316-// function and sig is the signature. A valid signature is indicated by
317-// returning a nil error. The opts argument may be nil, in which case sensible
318-// defaults are used.
319-func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error {
320- return verifyPSS(pub, hash, hashed, sig, opts.saltLength())
321-}
322-
323-// verifyPSS verifies a PSS signature with the given salt length.
324-func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
325- nBits := pub.N.BitLen()
326- if len(sig) != (nBits+7)/8 {
327+//
328+// A valid signature is indicated by returning a nil error. digest must be the
329+// result of hashing the input message using the given hash function. The opts
330+// argument may be nil, in which case sensible defaults are used. opts.Hash is
331+// ignored.
332+func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error {
333+ if len(sig) != pub.Size() {
334 return ErrVerification
335 }
336 s := new(big.Int).SetBytes(sig)
337 m := encrypt(new(big.Int), pub, s)
338- emBits := nBits - 1
339+ emBits := pub.N.BitLen() - 1
340 emLen := (emBits + 7) / 8
341- if emLen < len(m.Bytes()) {
342+ emBytes := m.Bytes()
343+ if emLen < len(emBytes) {
344 return ErrVerification
345 }
346 em := make([]byte, emLen)
347- copyWithLeftPad(em, m.Bytes())
348- if saltLen == PSSSaltLengthEqualsHash {
349- saltLen = hash.Size()
350- }
351- return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New())
352+ copyWithLeftPad(em, emBytes)
353+ return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New())
354 }
355diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
356index 5a42990640164..b4bfa13defbdf 100644
357--- a/src/crypto/rsa/rsa.go
358+++ b/src/crypto/rsa/rsa.go
359@@ -2,7 +2,7 @@
360 // Use of this source code is governed by a BSD-style
361 // license that can be found in the LICENSE file.
362
363-// Package rsa implements RSA encryption as specified in PKCS#1.
364+// Package rsa implements RSA encryption as specified in PKCS#1 and RFC 8017.
365 //
366 // RSA is a single, fundamental operation that is used in this package to
367 // implement either public-key encryption or public-key signatures.
368@@ -10,13 +10,13 @@
369 // The original specification for encryption and signatures with RSA is PKCS#1
370 // and the terms "RSA encryption" and "RSA signatures" by default refer to
371 // PKCS#1 version 1.5. However, that specification has flaws and new designs
372-// should use version two, usually called by just OAEP and PSS, where
373+// should use version 2, usually called by just OAEP and PSS, where
374 // possible.
375 //
376 // Two sets of interfaces are included in this package. When a more abstract
377 // interface isn't necessary, there are functions for encrypting/decrypting
378 // with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract
379-// over the public-key primitive, the PrivateKey struct implements the
380+// over the public key primitive, the PrivateKey type implements the
381 // Decrypter and Signer interfaces from the crypto package.
382 //
383 // The RSA operations in this package are not implemented using constant-time algorithms.
384@@ -111,7 +111,8 @@ func (priv *PrivateKey) Public() crypto.PublicKey {
385
386 // Sign signs digest with priv, reading randomness from rand. If opts is a
387 // *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will
388-// be used.
389+// be used. digest must be the result of hashing the input message using
390+// opts.HashFunc().
391 //
392 // This method implements crypto.Signer, which is an interface to support keys
393 // 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 @@
1From c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3 Mon Sep 17 00:00:00 2001
2From: Filippo Valsorda <filippo@golang.org>
3Date: Mon, 27 Apr 2020 21:52:38 -0400
4Subject: [PATCH] math/big: add (*Int).FillBytes
5
6Replaced almost every use of Bytes with FillBytes.
7
8Note that the approved proposal was for
9
10 func (*Int) FillBytes(buf []byte)
11
12while this implements
13
14 func (*Int) FillBytes(buf []byte) []byte
15
16because the latter was far nicer to use in all callsites.
17
18Fixes #35833
19
20Change-Id: Ia912df123e5d79b763845312ea3d9a8051343c0a
21Reviewed-on: https://go-review.googlesource.com/c/go/+/230397
22Reviewed-by: Robert Griesemer <gri@golang.org>
23
24Upstream-Status: Backport [https://github.com/golang/go/commit/c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3]
25CVE: CVE-2023-45287 #Dependency Patch2
26Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
27---
28 src/crypto/elliptic/elliptic.go | 13 ++++----
29 src/crypto/rsa/pkcs1v15.go | 20 +++---------
30 src/crypto/rsa/pss.go | 17 +++++------
31 src/crypto/rsa/rsa.go | 32 +++----------------
32 src/crypto/tls/key_schedule.go | 7 ++---
33 src/crypto/x509/sec1.go | 7 ++---
34 src/math/big/int.go | 15 +++++++++
35 src/math/big/int_test.go | 54 +++++++++++++++++++++++++++++++++
36 src/math/big/nat.go | 15 ++++++---
37 9 files changed, 106 insertions(+), 74 deletions(-)
38
39diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go
40index e2f71cdb63bab..bd5168c5fd842 100644
41--- a/src/crypto/elliptic/elliptic.go
42+++ b/src/crypto/elliptic/elliptic.go
43@@ -277,7 +277,7 @@ var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
44 func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) {
45 N := curve.Params().N
46 bitSize := N.BitLen()
47- byteLen := (bitSize + 7) >> 3
48+ byteLen := (bitSize + 7) / 8
49 priv = make([]byte, byteLen)
50
51 for x == nil {
52@@ -304,15 +304,14 @@ func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err e
53
54 // Marshal converts a point into the uncompressed form specified in section 4.3.6 of ANSI X9.62.
55 func Marshal(curve Curve, x, y *big.Int) []byte {
56- byteLen := (curve.Params().BitSize + 7) >> 3
57+ byteLen := (curve.Params().BitSize + 7) / 8
58
59 ret := make([]byte, 1+2*byteLen)
60 ret[0] = 4 // uncompressed point
61
62- xBytes := x.Bytes()
63- copy(ret[1+byteLen-len(xBytes):], xBytes)
64- yBytes := y.Bytes()
65- copy(ret[1+2*byteLen-len(yBytes):], yBytes)
66+ x.FillBytes(ret[1 : 1+byteLen])
67+ y.FillBytes(ret[1+byteLen : 1+2*byteLen])
68+
69 return ret
70 }
71
72@@ -320,7 +319,7 @@ func Marshal(curve Curve, x, y *big.Int) []byte {
73 // It is an error if the point is not in uncompressed form or is not on the curve.
74 // On error, x = nil.
75 func Unmarshal(curve Curve, data []byte) (x, y *big.Int) {
76- byteLen := (curve.Params().BitSize + 7) >> 3
77+ byteLen := (curve.Params().BitSize + 7) / 8
78 if len(data) != 1+2*byteLen {
79 return
80 }
81diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go
82index 499242ffc5b57..3208119ae1ff4 100644
83--- a/src/crypto/rsa/pkcs1v15.go
84+++ b/src/crypto/rsa/pkcs1v15.go
85@@ -61,8 +61,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)
86 m := new(big.Int).SetBytes(em)
87 c := encrypt(new(big.Int), pub, m)
88
89- copyWithLeftPad(em, c.Bytes())
90- return em, nil
91+ return c.FillBytes(em), nil
92 }
93
94 // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
95@@ -150,7 +149,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
96 return
97 }
98
99- em = leftPad(m.Bytes(), k)
100+ em = m.FillBytes(make([]byte, k))
101 firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
102 secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
103
104@@ -256,8 +255,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
105 return nil, err
106 }
107
108- copyWithLeftPad(em, c.Bytes())
109- return em, nil
110+ return c.FillBytes(em), nil
111 }
112
113 // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
114@@ -286,7 +284,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
115
116 c := new(big.Int).SetBytes(sig)
117 m := encrypt(new(big.Int), pub, c)
118- em := leftPad(m.Bytes(), k)
119+ em := m.FillBytes(make([]byte, k))
120 // EM = 0x00 || 0x01 || PS || 0x00 || T
121
122 ok := subtle.ConstantTimeByteEq(em[0], 0)
123@@ -323,13 +321,3 @@ func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte,
124 }
125 return
126 }
127-
128-// copyWithLeftPad copies src to the end of dest, padding with zero bytes as
129-// needed.
130-func copyWithLeftPad(dest, src []byte) {
131- numPaddingBytes := len(dest) - len(src)
132- for i := 0; i < numPaddingBytes; i++ {
133- dest[i] = 0
134- }
135- copy(dest[numPaddingBytes:], src)
136-}
137diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
138index f9844d87329a8..b2adbedb28fa8 100644
139--- a/src/crypto/rsa/pss.go
140+++ b/src/crypto/rsa/pss.go
141@@ -207,20 +207,19 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
142 // Note that hashed must be the result of hashing the input message using the
143 // given hash function. salt is a random sequence of bytes whose length will be
144 // later used to verify the signature.
145-func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
146+func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) {
147 emBits := priv.N.BitLen() - 1
148 em, err := emsaPSSEncode(hashed, emBits, salt, hash.New())
149 if err != nil {
150- return
151+ return nil, err
152 }
153 m := new(big.Int).SetBytes(em)
154 c, err := decryptAndCheck(rand, priv, m)
155 if err != nil {
156- return
157+ return nil, err
158 }
159- s = make([]byte, priv.Size())
160- copyWithLeftPad(s, c.Bytes())
161- return
162+ s := make([]byte, priv.Size())
163+ return c.FillBytes(s), nil
164 }
165
166 const (
167@@ -296,11 +295,9 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts
168 m := encrypt(new(big.Int), pub, s)
169 emBits := pub.N.BitLen() - 1
170 emLen := (emBits + 7) / 8
171- emBytes := m.Bytes()
172- if emLen < len(emBytes) {
173+ if m.BitLen() > emLen*8 {
174 return ErrVerification
175 }
176- em := make([]byte, emLen)
177- copyWithLeftPad(em, emBytes)
178+ em := m.FillBytes(make([]byte, emLen))
179 return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New())
180 }
181diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
182index b4bfa13defbdf..28eb5926c1a54 100644
183--- a/src/crypto/rsa/rsa.go
184+++ b/src/crypto/rsa/rsa.go
185@@ -416,16 +416,9 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
186 m := new(big.Int)
187 m.SetBytes(em)
188 c := encrypt(new(big.Int), pub, m)
189- out := c.Bytes()
190
191- if len(out) < k {
192- // If the output is too small, we need to left-pad with zeros.
193- t := make([]byte, k)
194- copy(t[k-len(out):], out)
195- out = t
196- }
197-
198- return out, nil
199+ out := make([]byte, k)
200+ return c.FillBytes(out), nil
201 }
202
203 // ErrDecryption represents a failure to decrypt a message.
204@@ -597,12 +590,9 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
205 lHash := hash.Sum(nil)
206 hash.Reset()
207
208- // Converting the plaintext number to bytes will strip any
209- // leading zeros so we may have to left pad. We do this unconditionally
210- // to avoid leaking timing information. (Although we still probably
211- // leak the number of leading zeros. It's not clear that we can do
212- // anything about this.)
213- em := leftPad(m.Bytes(), k)
214+ // We probably leak the number of leading zeros.
215+ // It's not clear that we can do anything about this.
216+ em := m.FillBytes(make([]byte, k))
217
218 firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
219
220@@ -643,15 +633,3 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
221
222 return rest[index+1:], nil
223 }
224-
225-// leftPad returns a new slice of length size. The contents of input are right
226-// aligned in the new slice.
227-func leftPad(input []byte, size int) (out []byte) {
228- n := len(input)
229- if n > size {
230- n = size
231- }
232- out = make([]byte, size)
233- copy(out[len(out)-n:], input)
234- return
235-}
236diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go
237index 2aab323202f7d..314016979afb8 100644
238--- a/src/crypto/tls/key_schedule.go
239+++ b/src/crypto/tls/key_schedule.go
240@@ -173,11 +173,8 @@ func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte {
241 }
242
243 xShared, _ := curve.ScalarMult(x, y, p.privateKey)
244- sharedKey := make([]byte, (curve.Params().BitSize+7)>>3)
245- xBytes := xShared.Bytes()
246- copy(sharedKey[len(sharedKey)-len(xBytes):], xBytes)
247-
248- return sharedKey
249+ sharedKey := make([]byte, (curve.Params().BitSize+7)/8)
250+ return xShared.FillBytes(sharedKey)
251 }
252
253 type x25519Parameters struct {
254diff --git a/src/crypto/x509/sec1.go b/src/crypto/x509/sec1.go
255index 0bfb90cd5464a..52c108ff1d624 100644
256--- a/src/crypto/x509/sec1.go
257+++ b/src/crypto/x509/sec1.go
258@@ -52,13 +52,10 @@ func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
259 // marshalECPrivateKey marshals an EC private key into ASN.1, DER format and
260 // sets the curve ID to the given OID, or omits it if OID is nil.
261 func marshalECPrivateKeyWithOID(key *ecdsa.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) {
262- privateKeyBytes := key.D.Bytes()
263- paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
264- copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
265-
266+ privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
267 return asn1.Marshal(ecPrivateKey{
268 Version: 1,
269- PrivateKey: paddedPrivateKey,
270+ PrivateKey: key.D.FillBytes(privateKey),
271 NamedCurveOID: oid,
272 PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
273 })
274diff --git a/src/math/big/int.go b/src/math/big/int.go
275index 8816cf5266cc4..65f32487b58c0 100644
276--- a/src/math/big/int.go
277+++ b/src/math/big/int.go
278@@ -447,11 +447,26 @@ func (z *Int) SetBytes(buf []byte) *Int {
279 }
280
281 // Bytes returns the absolute value of x as a big-endian byte slice.
282+//
283+// To use a fixed length slice, or a preallocated one, use FillBytes.
284 func (x *Int) Bytes() []byte {
285 buf := make([]byte, len(x.abs)*_S)
286 return buf[x.abs.bytes(buf):]
287 }
288
289+// FillBytes sets buf to the absolute value of x, storing it as a zero-extended
290+// big-endian byte slice, and returns buf.
291+//
292+// If the absolute value of x doesn't fit in buf, FillBytes will panic.
293+func (x *Int) FillBytes(buf []byte) []byte {
294+ // Clear whole buffer. (This gets optimized into a memclr.)
295+ for i := range buf {
296+ buf[i] = 0
297+ }
298+ x.abs.bytes(buf)
299+ return buf
300+}
301+
302 // BitLen returns the length of the absolute value of x in bits.
303 // The bit length of 0 is 0.
304 func (x *Int) BitLen() int {
305diff --git a/src/math/big/int_test.go b/src/math/big/int_test.go
306index e3a1587b3f0ad..3c8557323a032 100644
307--- a/src/math/big/int_test.go
308+++ b/src/math/big/int_test.go
309@@ -1840,3 +1840,57 @@ func BenchmarkDiv(b *testing.B) {
310 })
311 }
312 }
313+
314+func TestFillBytes(t *testing.T) {
315+ checkResult := func(t *testing.T, buf []byte, want *Int) {
316+ t.Helper()
317+ got := new(Int).SetBytes(buf)
318+ if got.CmpAbs(want) != 0 {
319+ t.Errorf("got 0x%x, want 0x%x: %x", got, want, buf)
320+ }
321+ }
322+ panics := func(f func()) (panic bool) {
323+ defer func() { panic = recover() != nil }()
324+ f()
325+ return
326+ }
327+
328+ for _, n := range []string{
329+ "0",
330+ "1000",
331+ "0xffffffff",
332+ "-0xffffffff",
333+ "0xffffffffffffffff",
334+ "0x10000000000000000",
335+ "0xabababababababababababababababababababababababababa",
336+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
337+ } {
338+ t.Run(n, func(t *testing.T) {
339+ t.Logf(n)
340+ x, ok := new(Int).SetString(n, 0)
341+ if !ok {
342+ panic("invalid test entry")
343+ }
344+
345+ // Perfectly sized buffer.
346+ byteLen := (x.BitLen() + 7) / 8
347+ buf := make([]byte, byteLen)
348+ checkResult(t, x.FillBytes(buf), x)
349+
350+ // Way larger, checking all bytes get zeroed.
351+ buf = make([]byte, 100)
352+ for i := range buf {
353+ buf[i] = 0xff
354+ }
355+ checkResult(t, x.FillBytes(buf), x)
356+
357+ // Too small.
358+ if byteLen > 0 {
359+ buf = make([]byte, byteLen-1)
360+ if !panics(func() { x.FillBytes(buf) }) {
361+ t.Errorf("expected panic for small buffer and value %x", x)
362+ }
363+ }
364+ })
365+ }
366+}
367diff --git a/src/math/big/nat.go b/src/math/big/nat.go
368index c31ec5156b81d..6a3989bf9d82b 100644
369--- a/src/math/big/nat.go
370+++ b/src/math/big/nat.go
371@@ -1476,19 +1476,26 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
372 }
373
374 // bytes writes the value of z into buf using big-endian encoding.
375-// len(buf) must be >= len(z)*_S. The value of z is encoded in the
376-// slice buf[i:]. The number i of unused bytes at the beginning of
377-// buf is returned as result.
378+// The value of z is encoded in the slice buf[i:]. If the value of z
379+// cannot be represented in buf, bytes panics. The number i of unused
380+// bytes at the beginning of buf is returned as result.
381 func (z nat) bytes(buf []byte) (i int) {
382 i = len(buf)
383 for _, d := range z {
384 for j := 0; j < _S; j++ {
385 i--
386- buf[i] = byte(d)
387+ if i >= 0 {
388+ buf[i] = byte(d)
389+ } else if byte(d) != 0 {
390+ panic("math/big: buffer too small to fit value")
391+ }
392 d >>= 8
393 }
394 }
395
396+ if i < 0 {
397+ i = 0
398+ }
399 for i < len(buf) && buf[i] == 0 {
400 i++
401 }
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 @@
1From 8f676144ad7b7c91adb0c6e1ec89aaa6283c6807 Mon Sep 17 00:00:00 2001
2From: Himanshu Kishna Srivastava <28himanshu@gmail.com>
3Date: Tue, 16 Mar 2021 22:37:46 +0530
4Subject: [PATCH] crypto/rsa: fix salt length calculation with
5 PSSSaltLengthAuto
6
7When PSSSaltLength is set, the maximum salt length must equal:
8
9 (modulus_key_size - 1 + 7)/8 - hash_length - 2
10and for example, with a 4096 bit modulus key, and a SHA-1 hash,
11it should be:
12
13 (4096 -1 + 7)/8 - 20 - 2 = 490
14Previously we'd encounter this error:
15
16 crypto/rsa: key size too small for PSS signature
17
18Fixes #42741
19
20Change-Id: I18bb82c41c511d564b3f4c443f4b3a38ab010ac5
21Reviewed-on: https://go-review.googlesource.com/c/go/+/302230
22Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
23Reviewed-by: Filippo Valsorda <filippo@golang.org>
24Trust: Emmanuel Odeke <emmanuel@orijtech.com>
25Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
26TryBot-Result: Go Bot <gobot@golang.org>
27
28Upstream-Status: Backport [https://github.com/golang/go/commit/8f676144ad7b7c91adb0c6e1ec89aaa6283c6807]
29CVE: CVE-2023-45287 #Dependency Patch3
30Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
31---
32 src/crypto/rsa/pss.go | 2 +-
33 src/crypto/rsa/pss_test.go | 20 +++++++++++++++++++-
34 2 files changed, 20 insertions(+), 2 deletions(-)
35
36diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
37index b2adbedb28fa8..814522de8181f 100644
38--- a/src/crypto/rsa/pss.go
39+++ b/src/crypto/rsa/pss.go
40@@ -269,7 +269,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
41 saltLength := opts.saltLength()
42 switch saltLength {
43 case PSSSaltLengthAuto:
44- saltLength = priv.Size() - 2 - hash.Size()
45+ saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size()
46 case PSSSaltLengthEqualsHash:
47 saltLength = hash.Size()
48 }
49diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go
50index dfa8d8bb5ad02..c3a6d468497cd 100644
51--- a/src/crypto/rsa/pss_test.go
52+++ b/src/crypto/rsa/pss_test.go
53@@ -12,7 +12,7 @@ import (
54 _ "crypto/md5"
55 "crypto/rand"
56 "crypto/sha1"
57- _ "crypto/sha256"
58+ "crypto/sha256"
59 "encoding/hex"
60 "math/big"
61 "os"
62@@ -233,6 +233,24 @@ func TestPSSSigning(t *testing.T) {
63 }
64 }
65
66+func TestSignWithPSSSaltLengthAuto(t *testing.T) {
67+ key, err := GenerateKey(rand.Reader, 513)
68+ if err != nil {
69+ t.Fatal(err)
70+ }
71+ digest := sha256.Sum256([]byte("message"))
72+ signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{
73+ SaltLength: PSSSaltLengthAuto,
74+ Hash: crypto.SHA256,
75+ })
76+ if err != nil {
77+ t.Fatal(err)
78+ }
79+ if len(signature) == 0 {
80+ t.Fatal("empty signature returned")
81+ }
82+}
83+
84 func bigFromHex(hex string) *big.Int {
85 n, ok := new(big.Int).SetString(hex, 16)
86 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 @@
1From 8a81fdf165facdcefa06531de5af98a4db343035 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?L=C3=BAc=C3=A1s=20Meier?= <cronokirby@gmail.com>
3Date: Tue, 8 Jun 2021 21:36:06 +0200
4Subject: [PATCH] crypto/rsa: replace big.Int for encryption and decryption
5
6Infamously, big.Int does not provide constant-time arithmetic, making
7its use in cryptographic code quite tricky. RSA uses big.Int
8pervasively, in its public API, for key generation, precomputation, and
9for encryption and decryption. This is a known problem. One mitigation,
10blinding, is already in place during decryption. This helps mitigate the
11very leaky exponentiation operation. Because big.Int is fundamentally
12not constant-time, it's unfortunately difficult to guarantee that
13mitigations like these are completely effective.
14
15This patch removes the use of big.Int for encryption and decryption,
16replacing it with an internal nat type instead. Signing and verification
17are also affected, because they depend on encryption and decryption.
18
19Overall, this patch degrades performance by 55% for private key
20operations, and 4-5x for (much faster) public key operations.
21(Signatures do both, so the slowdown is worse than decryption.)
22
23name old time/op new time/op delta
24DecryptPKCS1v15/2048-8 1.50ms ± 0% 2.34ms ± 0% +56.44% (p=0.000 n=8+10)
25DecryptPKCS1v15/3072-8 4.40ms ± 0% 6.79ms ± 0% +54.33% (p=0.000 n=10+9)
26DecryptPKCS1v15/4096-8 9.31ms ± 0% 15.14ms ± 0% +62.60% (p=0.000 n=10+10)
27EncryptPKCS1v15/2048-8 8.16µs ± 0% 355.58µs ± 0% +4258.90% (p=0.000 n=10+9)
28DecryptOAEP/2048-8 1.50ms ± 0% 2.34ms ± 0% +55.68% (p=0.000 n=10+9)
29EncryptOAEP/2048-8 8.51µs ± 0% 355.95µs ± 0% +4082.75% (p=0.000 n=10+9)
30SignPKCS1v15/2048-8 1.51ms ± 0% 2.69ms ± 0% +77.94% (p=0.000 n=10+10)
31VerifyPKCS1v15/2048-8 7.25µs ± 0% 354.34µs ± 0% +4789.52% (p=0.000 n=9+9)
32SignPSS/2048-8 1.51ms ± 0% 2.70ms ± 0% +78.80% (p=0.000 n=9+10)
33VerifyPSS/2048-8 8.27µs ± 1% 355.65µs ± 0% +4199.39% (p=0.000 n=10+10)
34
35Keep in mind that this is without any assembly at all, and that further
36improvements are likely possible. I think having a review of the logic
37and the cryptography would be a good idea at this stage, before we
38complicate the code too much through optimization.
39
40The bulk of the work is in nat.go. This introduces two new types: nat,
41representing natural numbers, and modulus, representing moduli used in
42modular arithmetic.
43
44A nat has an "announced size", which may be larger than its "true size",
45the number of bits needed to represent this number. Operations on a nat
46will only ever leak its announced size, never its true size, or other
47information about its value. The size of a nat is always clear based on
48how its value is set. For example, x.mod(y, m) will make the announced
49size of x match that of m, since x is reduced modulo m.
50
51Operations assume that the announced size of the operands match what's
52expected (with a few exceptions). For example, x.modAdd(y, m) assumes
53that x and y have the same announced size as m, and that they're reduced
54modulo m.
55
56Nats are represented over unsatured bits.UintSize - 1 bit limbs. This
57means that we can't reuse the assembly routines for big.Int, which use
58saturated bits.UintSize limbs. The advantage of unsaturated limbs is
59that it makes Montgomery multiplication faster, by needing fewer
60registers in a hot loop. This makes exponentiation faster, which
61consists of many Montgomery multiplications.
62
63Moduli use nat internally. Unlike nat, the true size of a modulus always
64matches its announced size. When creating a modulus, any zero padding is
65removed. Moduli will also precompute constants when created, which is
66another reason why having a separate type is desirable.
67
68Updates #20654
69
70Co-authored-by: Filippo Valsorda <filippo@golang.org>
71Change-Id: I73b61f87d58ab912e80a9644e255d552cbadcced
72Reviewed-on: https://go-review.googlesource.com/c/go/+/326012
73Run-TryBot: Filippo Valsorda <filippo@golang.org>
74TryBot-Result: Gopher Robot <gobot@golang.org>
75Reviewed-by: Roland Shoemaker <roland@golang.org>
76Reviewed-by: Joedian Reid <joedian@golang.org>
77
78Upstream-Status: Backport [https://github.com/golang/go/commit/8a81fdf165facdcefa06531de5af98a4db343035]
79CVE: CVE-2023-45287
80Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
81---
82 src/crypto/rsa/example_test.go | 21 +-
83 src/crypto/rsa/nat.go | 626 +++++++++++++++++++++++++++++++++
84 src/crypto/rsa/nat_test.go | 384 ++++++++++++++++++++
85 src/crypto/rsa/pkcs1v15.go | 47 +--
86 src/crypto/rsa/pss.go | 50 ++-
87 src/crypto/rsa/pss_test.go | 10 +-
88 src/crypto/rsa/rsa.go | 174 ++++-----
89 7 files changed, 1143 insertions(+), 169 deletions(-)
90 create mode 100644 src/crypto/rsa/nat.go
91 create mode 100644 src/crypto/rsa/nat_test.go
92
93diff --git a/src/crypto/rsa/example_test.go b/src/crypto/rsa/example_test.go
94index 1435b70..1963609 100644
95--- a/src/crypto/rsa/example_test.go
96+++ b/src/crypto/rsa/example_test.go
97@@ -12,7 +12,6 @@ import (
98 "crypto/sha256"
99 "encoding/hex"
100 "fmt"
101- "io"
102 "os"
103 )
104
105@@ -36,21 +35,17 @@ import (
106 // a buffer that contains a random key. Thus, if the RSA result isn't
107 // well-formed, the implementation uses a random key in constant time.
108 func ExampleDecryptPKCS1v15SessionKey() {
109- // crypto/rand.Reader is a good source of entropy for blinding the RSA
110- // operation.
111- rng := rand.Reader
112-
113 // The hybrid scheme should use at least a 16-byte symmetric key. Here
114 // we read the random key that will be used if the RSA decryption isn't
115 // well-formed.
116 key := make([]byte, 32)
117- if _, err := io.ReadFull(rng, key); err != nil {
118+ if _, err := rand.Read(key); err != nil {
119 panic("RNG failure")
120 }
121
122 rsaCiphertext, _ := hex.DecodeString("aabbccddeeff")
123
124- if err := DecryptPKCS1v15SessionKey(rng, rsaPrivateKey, rsaCiphertext, key); err != nil {
125+ if err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, rsaCiphertext, key); err != nil {
126 // Any errors that result will be “public” – meaning that they
127 // can be determined without any secret information. (For
128 // instance, if the length of key is impossible given the RSA
129@@ -86,10 +81,6 @@ func ExampleDecryptPKCS1v15SessionKey() {
130 }
131
132 func ExampleSignPKCS1v15() {
133- // crypto/rand.Reader is a good source of entropy for blinding the RSA
134- // operation.
135- rng := rand.Reader
136-
137 message := []byte("message to be signed")
138
139 // Only small messages can be signed directly; thus the hash of a
140@@ -99,7 +90,7 @@ func ExampleSignPKCS1v15() {
141 // of writing (2016).
142 hashed := sha256.Sum256(message)
143
144- signature, err := SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA256, hashed[:])
145+ signature, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA256, hashed[:])
146 if err != nil {
147 fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err)
148 return
149@@ -151,11 +142,7 @@ func ExampleDecryptOAEP() {
150 ciphertext, _ := hex.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc54d2cb80c08fcd19dacbc265ee1c6014616b0e04ea0328c2a04e73460")
151 label := []byte("orders")
152
153- // crypto/rand.Reader is a good source of entropy for blinding the RSA
154- // operation.
155- rng := rand.Reader
156-
157- plaintext, err := DecryptOAEP(sha256.New(), rng, test2048Key, ciphertext, label)
158+ plaintext, err := DecryptOAEP(sha256.New(), nil, test2048Key, ciphertext, label)
159 if err != nil {
160 fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
161 return
162diff --git a/src/crypto/rsa/nat.go b/src/crypto/rsa/nat.go
163new file mode 100644
164index 0000000..da521c2
165--- /dev/null
166+++ b/src/crypto/rsa/nat.go
167@@ -0,0 +1,626 @@
168+// Copyright 2021 The Go Authors. All rights reserved.
169+// Use of this source code is governed by a BSD-style
170+// license that can be found in the LICENSE file.
171+
172+package rsa
173+
174+import (
175+ "math/big"
176+ "math/bits"
177+)
178+
179+const (
180+ // _W is the number of bits we use for our limbs.
181+ _W = bits.UintSize - 1
182+ // _MASK selects _W bits from a full machine word.
183+ _MASK = (1 << _W) - 1
184+)
185+
186+// choice represents a constant-time boolean. The value of choice is always
187+// either 1 or 0. We use an int instead of bool in order to make decisions in
188+// constant time by turning it into a mask.
189+type choice uint
190+
191+func not(c choice) choice { return 1 ^ c }
192+
193+const yes = choice(1)
194+const no = choice(0)
195+
196+// ctSelect returns x if on == 1, and y if on == 0. The execution time of this
197+// function does not depend on its inputs. If on is any value besides 1 or 0,
198+// the result is undefined.
199+func ctSelect(on choice, x, y uint) uint {
200+ // When on == 1, mask is 0b111..., otherwise mask is 0b000...
201+ mask := -uint(on)
202+ // When mask is all zeros, we just have y, otherwise, y cancels with itself.
203+ return y ^ (mask & (y ^ x))
204+}
205+
206+// ctEq returns 1 if x == y, and 0 otherwise. The execution time of this
207+// function does not depend on its inputs.
208+func ctEq(x, y uint) choice {
209+ // If x != y, then either x - y or y - x will generate a carry.
210+ _, c1 := bits.Sub(x, y, 0)
211+ _, c2 := bits.Sub(y, x, 0)
212+ return not(choice(c1 | c2))
213+}
214+
215+// ctGeq returns 1 if x >= y, and 0 otherwise. The execution time of this
216+// function does not depend on its inputs.
217+func ctGeq(x, y uint) choice {
218+ // If x < y, then x - y generates a carry.
219+ _, carry := bits.Sub(x, y, 0)
220+ return not(choice(carry))
221+}
222+
223+// nat represents an arbitrary natural number
224+//
225+// Each nat has an announced length, which is the number of limbs it has stored.
226+// Operations on this number are allowed to leak this length, but will not leak
227+// any information about the values contained in those limbs.
228+type nat struct {
229+ // limbs is a little-endian representation in base 2^W with
230+ // W = bits.UintSize - 1. The top bit is always unset between operations.
231+ //
232+ // The top bit is left unset to optimize Montgomery multiplication, in the
233+ // inner loop of exponentiation. Using fully saturated limbs would leave us
234+ // working with 129-bit numbers on 64-bit platforms, wasting a lot of space,
235+ // and thus time.
236+ limbs []uint
237+}
238+
239+// expand expands x to n limbs, leaving its value unchanged.
240+func (x *nat) expand(n int) *nat {
241+ for len(x.limbs) > n {
242+ if x.limbs[len(x.limbs)-1] != 0 {
243+ panic("rsa: internal error: shrinking nat")
244+ }
245+ x.limbs = x.limbs[:len(x.limbs)-1]
246+ }
247+ if cap(x.limbs) < n {
248+ newLimbs := make([]uint, n)
249+ copy(newLimbs, x.limbs)
250+ x.limbs = newLimbs
251+ return x
252+ }
253+ extraLimbs := x.limbs[len(x.limbs):n]
254+ for i := range extraLimbs {
255+ extraLimbs[i] = 0
256+ }
257+ x.limbs = x.limbs[:n]
258+ return x
259+}
260+
261+// reset returns a zero nat of n limbs, reusing x's storage if n <= cap(x.limbs).
262+func (x *nat) reset(n int) *nat {
263+ if cap(x.limbs) < n {
264+ x.limbs = make([]uint, n)
265+ return x
266+ }
267+ for i := range x.limbs {
268+ x.limbs[i] = 0
269+ }
270+ x.limbs = x.limbs[:n]
271+ return x
272+}
273+
274+// clone returns a new nat, with the same value and announced length as x.
275+func (x *nat) clone() *nat {
276+ out := &nat{make([]uint, len(x.limbs))}
277+ copy(out.limbs, x.limbs)
278+ return out
279+}
280+
281+// natFromBig creates a new natural number from a big.Int.
282+//
283+// The announced length of the resulting nat is based on the actual bit size of
284+// the input, ignoring leading zeroes.
285+func natFromBig(x *big.Int) *nat {
286+ xLimbs := x.Bits()
287+ bitSize := bigBitLen(x)
288+ requiredLimbs := (bitSize + _W - 1) / _W
289+
290+ out := &nat{make([]uint, requiredLimbs)}
291+ outI := 0
292+ shift := 0
293+ for i := range xLimbs {
294+ xi := uint(xLimbs[i])
295+ out.limbs[outI] |= (xi << shift) & _MASK
296+ outI++
297+ if outI == requiredLimbs {
298+ return out
299+ }
300+ out.limbs[outI] = xi >> (_W - shift)
301+ shift++ // this assumes bits.UintSize - _W = 1
302+ if shift == _W {
303+ shift = 0
304+ outI++
305+ }
306+ }
307+ return out
308+}
309+
310+// fillBytes sets bytes to x as a zero-extended big-endian byte slice.
311+//
312+// If bytes is not long enough to contain the number or at least len(x.limbs)-1
313+// limbs, or has zero length, fillBytes will panic.
314+func (x *nat) fillBytes(bytes []byte) []byte {
315+ if len(bytes) == 0 {
316+ panic("nat: fillBytes invoked with too small buffer")
317+ }
318+ for i := range bytes {
319+ bytes[i] = 0
320+ }
321+ shift := 0
322+ outI := len(bytes) - 1
323+ for i, limb := range x.limbs {
324+ remainingBits := _W
325+ for remainingBits >= 8 {
326+ bytes[outI] |= byte(limb) << shift
327+ consumed := 8 - shift
328+ limb >>= consumed
329+ remainingBits -= consumed
330+ shift = 0
331+ outI--
332+ if outI < 0 {
333+ if limb != 0 || i < len(x.limbs)-1 {
334+ panic("nat: fillBytes invoked with too small buffer")
335+ }
336+ return bytes
337+ }
338+ }
339+ bytes[outI] = byte(limb)
340+ shift = remainingBits
341+ }
342+ return bytes
343+}
344+
345+// natFromBytes converts a slice of big-endian bytes into a nat.
346+//
347+// The announced length of the output depends on the length of bytes. Unlike
348+// big.Int, creating a nat will not remove leading zeros.
349+func natFromBytes(bytes []byte) *nat {
350+ bitSize := len(bytes) * 8
351+ requiredLimbs := (bitSize + _W - 1) / _W
352+
353+ out := &nat{make([]uint, requiredLimbs)}
354+ outI := 0
355+ shift := 0
356+ for i := len(bytes) - 1; i >= 0; i-- {
357+ bi := bytes[i]
358+ out.limbs[outI] |= uint(bi) << shift
359+ shift += 8
360+ if shift >= _W {
361+ shift -= _W
362+ out.limbs[outI] &= _MASK
363+ outI++
364+ if shift > 0 {
365+ out.limbs[outI] = uint(bi) >> (8 - shift)
366+ }
367+ }
368+ }
369+ return out
370+}
371+
372+// cmpEq returns 1 if x == y, and 0 otherwise.
373+//
374+// Both operands must have the same announced length.
375+func (x *nat) cmpEq(y *nat) choice {
376+ // Eliminate bounds checks in the loop.
377+ size := len(x.limbs)
378+ xLimbs := x.limbs[:size]
379+ yLimbs := y.limbs[:size]
380+
381+ equal := yes
382+ for i := 0; i < size; i++ {
383+ equal &= ctEq(xLimbs[i], yLimbs[i])
384+ }
385+ return equal
386+}
387+
388+// cmpGeq returns 1 if x >= y, and 0 otherwise.
389+//
390+// Both operands must have the same announced length.
391+func (x *nat) cmpGeq(y *nat) choice {
392+ // Eliminate bounds checks in the loop.
393+ size := len(x.limbs)
394+ xLimbs := x.limbs[:size]
395+ yLimbs := y.limbs[:size]
396+
397+ var c uint
398+ for i := 0; i < size; i++ {
399+ c = (xLimbs[i] - yLimbs[i] - c) >> _W
400+ }
401+ // If there was a carry, then subtracting y underflowed, so
402+ // x is not greater than or equal to y.
403+ return not(choice(c))
404+}
405+
406+// assign sets x <- y if on == 1, and does nothing otherwise.
407+//
408+// Both operands must have the same announced length.
409+func (x *nat) assign(on choice, y *nat) *nat {
410+ // Eliminate bounds checks in the loop.
411+ size := len(x.limbs)
412+ xLimbs := x.limbs[:size]
413+ yLimbs := y.limbs[:size]
414+
415+ for i := 0; i < size; i++ {
416+ xLimbs[i] = ctSelect(on, yLimbs[i], xLimbs[i])
417+ }
418+ return x
419+}
420+
421+// add computes x += y if on == 1, and does nothing otherwise. It returns the
422+// carry of the addition regardless of on.
423+//
424+// Both operands must have the same announced length.
425+func (x *nat) add(on choice, y *nat) (c uint) {
426+ // Eliminate bounds checks in the loop.
427+ size := len(x.limbs)
428+ xLimbs := x.limbs[:size]
429+ yLimbs := y.limbs[:size]
430+
431+ for i := 0; i < size; i++ {
432+ res := xLimbs[i] + yLimbs[i] + c
433+ xLimbs[i] = ctSelect(on, res&_MASK, xLimbs[i])
434+ c = res >> _W
435+ }
436+ return
437+}
438+
439+// sub computes x -= y if on == 1, and does nothing otherwise. It returns the
440+// borrow of the subtraction regardless of on.
441+//
442+// Both operands must have the same announced length.
443+func (x *nat) sub(on choice, y *nat) (c uint) {
444+ // Eliminate bounds checks in the loop.
445+ size := len(x.limbs)
446+ xLimbs := x.limbs[:size]
447+ yLimbs := y.limbs[:size]
448+
449+ for i := 0; i < size; i++ {
450+ res := xLimbs[i] - yLimbs[i] - c
451+ xLimbs[i] = ctSelect(on, res&_MASK, xLimbs[i])
452+ c = res >> _W
453+ }
454+ return
455+}
456+
457+// modulus is used for modular arithmetic, precomputing relevant constants.
458+//
459+// Moduli are assumed to be odd numbers. Moduli can also leak the exact
460+// number of bits needed to store their value, and are stored without padding.
461+//
462+// Their actual value is still kept secret.
463+type modulus struct {
464+ // The underlying natural number for this modulus.
465+ //
466+ // This will be stored without any padding, and shouldn't alias with any
467+ // other natural number being used.
468+ nat *nat
469+ leading int // number of leading zeros in the modulus
470+ m0inv uint // -nat.limbs[0]⁻¹ mod _W
471+}
472+
473+// minusInverseModW computes -x⁻¹ mod _W with x odd.
474+//
475+// This operation is used to precompute a constant involved in Montgomery
476+// multiplication.
477+func minusInverseModW(x uint) uint {
478+ // Every iteration of this loop doubles the least-significant bits of
479+ // correct inverse in y. The first three bits are already correct (1⁻¹ = 1,
480+ // 3⁻¹ = 3, 5⁻¹ = 5, and 7⁻¹ = 7 mod 8), so doubling five times is enough
481+ // for 61 bits (and wastes only one iteration for 31 bits).
482+ //
483+ // See https://crypto.stackexchange.com/a/47496.
484+ y := x
485+ for i := 0; i < 5; i++ {
486+ y = y * (2 - x*y)
487+ }
488+ return (1 << _W) - (y & _MASK)
489+}
490+
491+// modulusFromNat creates a new modulus from a nat.
492+//
493+// The nat should be odd, nonzero, and the number of significant bits in the
494+// number should be leakable. The nat shouldn't be reused.
495+func modulusFromNat(nat *nat) *modulus {
496+ m := &modulus{}
497+ m.nat = nat
498+ size := len(m.nat.limbs)
499+ for m.nat.limbs[size-1] == 0 {
500+ size--
501+ }
502+ m.nat.limbs = m.nat.limbs[:size]
503+ m.leading = _W - bitLen(m.nat.limbs[size-1])
504+ m.m0inv = minusInverseModW(m.nat.limbs[0])
505+ return m
506+}
507+
508+// bitLen is a version of bits.Len that only leaks the bit length of n, but not
509+// its value. bits.Len and bits.LeadingZeros use a lookup table for the
510+// low-order bits on some architectures.
511+func bitLen(n uint) int {
512+ var len int
513+ // We assume, here and elsewhere, that comparison to zero is constant time
514+ // with respect to different non-zero values.
515+ for n != 0 {
516+ len++
517+ n >>= 1
518+ }
519+ return len
520+}
521+
522+// bigBitLen is a version of big.Int.BitLen that only leaks the bit length of x,
523+// but not its value. big.Int.BitLen uses bits.Len.
524+func bigBitLen(x *big.Int) int {
525+ xLimbs := x.Bits()
526+ fullLimbs := len(xLimbs) - 1
527+ topLimb := uint(xLimbs[len(xLimbs)-1])
528+ return fullLimbs*bits.UintSize + bitLen(topLimb)
529+}
530+
531+// modulusSize returns the size of m in bytes.
532+func modulusSize(m *modulus) int {
533+ bits := len(m.nat.limbs)*_W - int(m.leading)
534+ return (bits + 7) / 8
535+}
536+
537+// shiftIn calculates x = x << _W + y mod m.
538+//
539+// This assumes that x is already reduced mod m, and that y < 2^_W.
540+func (x *nat) shiftIn(y uint, m *modulus) *nat {
541+ d := new(nat).resetFor(m)
542+
543+ // Eliminate bounds checks in the loop.
544+ size := len(m.nat.limbs)
545+ xLimbs := x.limbs[:size]
546+ dLimbs := d.limbs[:size]
547+ mLimbs := m.nat.limbs[:size]
548+
549+ // Each iteration of this loop computes x = 2x + b mod m, where b is a bit
550+ // from y. Effectively, it left-shifts x and adds y one bit at a time,
551+ // reducing it every time.
552+ //
553+ // To do the reduction, each iteration computes both 2x + b and 2x + b - m.
554+ // The next iteration (and finally the return line) will use either result
555+ // based on whether the subtraction underflowed.
556+ needSubtraction := no
557+ for i := _W - 1; i >= 0; i-- {
558+ carry := (y >> i) & 1
559+ var borrow uint
560+ for i := 0; i < size; i++ {
561+ l := ctSelect(needSubtraction, dLimbs[i], xLimbs[i])
562+
563+ res := l<<1 + carry
564+ xLimbs[i] = res & _MASK
565+ carry = res >> _W
566+
567+ res = xLimbs[i] - mLimbs[i] - borrow
568+ dLimbs[i] = res & _MASK
569+ borrow = res >> _W
570+ }
571+ // See modAdd for how carry (aka overflow), borrow (aka underflow), and
572+ // needSubtraction relate.
573+ needSubtraction = ctEq(carry, borrow)
574+ }
575+ return x.assign(needSubtraction, d)
576+}
577+
578+// mod calculates out = x mod m.
579+//
580+// This works regardless how large the value of x is.
581+//
582+// The output will be resized to the size of m and overwritten.
583+func (out *nat) mod(x *nat, m *modulus) *nat {
584+ out.resetFor(m)
585+ // Working our way from the most significant to the least significant limb,
586+ // we can insert each limb at the least significant position, shifting all
587+ // previous limbs left by _W. This way each limb will get shifted by the
588+ // correct number of bits. We can insert at least N - 1 limbs without
589+ // overflowing m. After that, we need to reduce every time we shift.
590+ i := len(x.limbs) - 1
591+ // For the first N - 1 limbs we can skip the actual shifting and position
592+ // them at the shifted position, which starts at min(N - 2, i).
593+ start := len(m.nat.limbs) - 2
594+ if i < start {
595+ start = i
596+ }
597+ for j := start; j >= 0; j-- {
598+ out.limbs[j] = x.limbs[i]
599+ i--
600+ }
601+ // We shift in the remaining limbs, reducing modulo m each time.
602+ for i >= 0 {
603+ out.shiftIn(x.limbs[i], m)
604+ i--
605+ }
606+ return out
607+}
608+
609+// expandFor ensures out has the right size to work with operations modulo m.
610+//
611+// This assumes that out has as many or fewer limbs than m, or that the extra
612+// limbs are all zero (which may happen when decoding a value that has leading
613+// zeroes in its bytes representation that spill over the limb threshold).
614+func (out *nat) expandFor(m *modulus) *nat {
615+ return out.expand(len(m.nat.limbs))
616+}
617+
618+// resetFor ensures out has the right size to work with operations modulo m.
619+//
620+// out is zeroed and may start at any size.
621+func (out *nat) resetFor(m *modulus) *nat {
622+ return out.reset(len(m.nat.limbs))
623+}
624+
625+// modSub computes x = x - y mod m.
626+//
627+// The length of both operands must be the same as the modulus. Both operands
628+// must already be reduced modulo m.
629+func (x *nat) modSub(y *nat, m *modulus) *nat {
630+ underflow := x.sub(yes, y)
631+ // If the subtraction underflowed, add m.
632+ x.add(choice(underflow), m.nat)
633+ return x
634+}
635+
636+// modAdd computes x = x + y mod m.
637+//
638+// The length of both operands must be the same as the modulus. Both operands
639+// must already be reduced modulo m.
640+func (x *nat) modAdd(y *nat, m *modulus) *nat {
641+ overflow := x.add(yes, y)
642+ underflow := not(x.cmpGeq(m.nat)) // x < m
643+
644+ // Three cases are possible:
645+ //
646+ // - overflow = 0, underflow = 0
647+ //
648+ // In this case, addition fits in our limbs, but we can still subtract away
649+ // m without an underflow, so we need to perform the subtraction to reduce
650+ // our result.
651+ //
652+ // - overflow = 0, underflow = 1
653+ //
654+ // The addition fits in our limbs, but we can't subtract m without
655+ // underflowing. The result is already reduced.
656+ //
657+ // - overflow = 1, underflow = 1
658+ //
659+ // The addition does not fit in our limbs, and the subtraction's borrow
660+ // would cancel out with the addition's carry. We need to subtract m to
661+ // reduce our result.
662+ //
663+ // The overflow = 1, underflow = 0 case is not possible, because y is at
664+ // most m - 1, and if adding m - 1 overflows, then subtracting m must
665+ // necessarily underflow.
666+ needSubtraction := ctEq(overflow, uint(underflow))
667+
668+ x.sub(needSubtraction, m.nat)
669+ return x
670+}
671+
672+// montgomeryRepresentation calculates x = x * R mod m, with R = 2^(_W * n) and
673+// n = len(m.nat.limbs).
674+//
675+// Faster Montgomery multiplication replaces standard modular multiplication for
676+// numbers in this representation.
677+//
678+// This assumes that x is already reduced mod m.
679+func (x *nat) montgomeryRepresentation(m *modulus) *nat {
680+ for i := 0; i < len(m.nat.limbs); i++ {
681+ x.shiftIn(0, m) // x = x * 2^_W mod m
682+ }
683+ return x
684+}
685+
686+// montgomeryMul calculates d = a * b / R mod m, with R = 2^(_W * n) and
687+// n = len(m.nat.limbs), using the Montgomery Multiplication technique.
688+//
689+// All inputs should be the same length, not aliasing d, and already
690+// reduced modulo m. d will be resized to the size of m and overwritten.
691+func (d *nat) montgomeryMul(a *nat, b *nat, m *modulus) *nat {
692+ // See https://bearssl.org/bigint.html#montgomery-reduction-and-multiplication
693+ // for a description of the algorithm.
694+
695+ // Eliminate bounds checks in the loop.
696+ size := len(m.nat.limbs)
697+ aLimbs := a.limbs[:size]
698+ bLimbs := b.limbs[:size]
699+ dLimbs := d.resetFor(m).limbs[:size]
700+ mLimbs := m.nat.limbs[:size]
701+
702+ var overflow uint
703+ for i := 0; i < size; i++ {
704+ f := ((dLimbs[0] + aLimbs[i]*bLimbs[0]) * m.m0inv) & _MASK
705+ carry := uint(0)
706+ for j := 0; j < size; j++ {
707+ // z = d[j] + a[i] * b[j] + f * m[j] + carry <= 2^(2W+1) - 2^(W+1) + 2^W
708+ hi, lo := bits.Mul(aLimbs[i], bLimbs[j])
709+ z_lo, c := bits.Add(dLimbs[j], lo, 0)
710+ z_hi, _ := bits.Add(0, hi, c)
711+ hi, lo = bits.Mul(f, mLimbs[j])
712+ z_lo, c = bits.Add(z_lo, lo, 0)
713+ z_hi, _ = bits.Add(z_hi, hi, c)
714+ z_lo, c = bits.Add(z_lo, carry, 0)
715+ z_hi, _ = bits.Add(z_hi, 0, c)
716+ if j > 0 {
717+ dLimbs[j-1] = z_lo & _MASK
718+ }
719+ carry = z_hi<<1 | z_lo>>_W // carry <= 2^(W+1) - 2
720+ }
721+ z := overflow + carry // z <= 2^(W+1) - 1
722+ dLimbs[size-1] = z & _MASK
723+ overflow = z >> _W // overflow <= 1
724+ }
725+ // See modAdd for how overflow, underflow, and needSubtraction relate.
726+ underflow := not(d.cmpGeq(m.nat)) // d < m
727+ needSubtraction := ctEq(overflow, uint(underflow))
728+ d.sub(needSubtraction, m.nat)
729+
730+ return d
731+}
732+
733+// modMul calculates x *= y mod m.
734+//
735+// x and y must already be reduced modulo m, they must share its announced
736+// length, and they may not alias.
737+func (x *nat) modMul(y *nat, m *modulus) *nat {
738+ // A Montgomery multiplication by a value out of the Montgomery domain
739+ // takes the result out of Montgomery representation.
740+ xR := x.clone().montgomeryRepresentation(m) // xR = x * R mod m
741+ return x.montgomeryMul(xR, y, m) // x = xR * y / R mod m
742+}
743+
744+// exp calculates out = x^e mod m.
745+//
746+// The exponent e is represented in big-endian order. The output will be resized
747+// to the size of m and overwritten. x must already be reduced modulo m.
748+func (out *nat) exp(x *nat, e []byte, m *modulus) *nat {
749+ // We use a 4 bit window. For our RSA workload, 4 bit windows are faster
750+ // than 2 bit windows, but use an extra 12 nats worth of scratch space.
751+ // Using bit sizes that don't divide 8 are more complex to implement.
752+ table := make([]*nat, (1<<4)-1) // table[i] = x ^ (i+1)
753+ table[0] = x.clone().montgomeryRepresentation(m)
754+ for i := 1; i < len(table); i++ {
755+ table[i] = new(nat).expandFor(m)
756+ table[i].montgomeryMul(table[i-1], table[0], m)
757+ }
758+
759+ out.resetFor(m)
760+ out.limbs[0] = 1
761+ out.montgomeryRepresentation(m)
762+ t0 := new(nat).expandFor(m)
763+ t1 := new(nat).expandFor(m)
764+ for _, b := range e {
765+ for _, j := range []int{4, 0} {
766+ // Square four times.
767+ t1.montgomeryMul(out, out, m)
768+ out.montgomeryMul(t1, t1, m)
769+ t1.montgomeryMul(out, out, m)
770+ out.montgomeryMul(t1, t1, m)
771+
772+ // Select x^k in constant time from the table.
773+ k := uint((b >> j) & 0b1111)
774+ for i := range table {
775+ t0.assign(ctEq(k, uint(i+1)), table[i])
776+ }
777+
778+ // Multiply by x^k, discarding the result if k = 0.
779+ t1.montgomeryMul(out, t0, m)
780+ out.assign(not(ctEq(k, 0)), t1)
781+ }
782+ }
783+
784+ // By Montgomery multiplying with 1 not in Montgomery representation, we
785+ // convert out back from Montgomery representation, because it works out to
786+ // dividing by R.
787+ t0.assign(yes, out)
788+ t1.resetFor(m)
789+ t1.limbs[0] = 1
790+ out.montgomeryMul(t0, t1, m)
791+
792+ return out
793+}
794diff --git a/src/crypto/rsa/nat_test.go b/src/crypto/rsa/nat_test.go
795new file mode 100644
796index 0000000..3e6eb10
797--- /dev/null
798+++ b/src/crypto/rsa/nat_test.go
799@@ -0,0 +1,384 @@
800+// Copyright 2021 The Go Authors. All rights reserved.
801+// Use of this source code is governed by a BSD-style
802+// license that can be found in the LICENSE file.
803+
804+package rsa
805+
806+import (
807+ "bytes"
808+ "math/big"
809+ "math/bits"
810+ "math/rand"
811+ "reflect"
812+ "testing"
813+ "testing/quick"
814+)
815+
816+// Generate generates an even nat. It's used by testing/quick to produce random
817+// *nat values for quick.Check invocations.
818+func (*nat) Generate(r *rand.Rand, size int) reflect.Value {
819+ limbs := make([]uint, size)
820+ for i := 0; i < size; i++ {
821+ limbs[i] = uint(r.Uint64()) & ((1 << _W) - 2)
822+ }
823+ return reflect.ValueOf(&nat{limbs})
824+}
825+
826+func testModAddCommutative(a *nat, b *nat) bool {
827+ mLimbs := make([]uint, len(a.limbs))
828+ for i := 0; i < len(mLimbs); i++ {
829+ mLimbs[i] = _MASK
830+ }
831+ m := modulusFromNat(&nat{mLimbs})
832+ aPlusB := a.clone()
833+ aPlusB.modAdd(b, m)
834+ bPlusA := b.clone()
835+ bPlusA.modAdd(a, m)
836+ return aPlusB.cmpEq(bPlusA) == 1
837+}
838+
839+func TestModAddCommutative(t *testing.T) {
840+ err := quick.Check(testModAddCommutative, &quick.Config{})
841+ if err != nil {
842+ t.Error(err)
843+ }
844+}
845+
846+func testModSubThenAddIdentity(a *nat, b *nat) bool {
847+ mLimbs := make([]uint, len(a.limbs))
848+ for i := 0; i < len(mLimbs); i++ {
849+ mLimbs[i] = _MASK
850+ }
851+ m := modulusFromNat(&nat{mLimbs})
852+ original := a.clone()
853+ a.modSub(b, m)
854+ a.modAdd(b, m)
855+ return a.cmpEq(original) == 1
856+}
857+
858+func TestModSubThenAddIdentity(t *testing.T) {
859+ err := quick.Check(testModSubThenAddIdentity, &quick.Config{})
860+ if err != nil {
861+ t.Error(err)
862+ }
863+}
864+
865+func testMontgomeryRoundtrip(a *nat) bool {
866+ one := &nat{make([]uint, len(a.limbs))}
867+ one.limbs[0] = 1
868+ aPlusOne := a.clone()
869+ aPlusOne.add(1, one)
870+ m := modulusFromNat(aPlusOne)
871+ monty := a.clone()
872+ monty.montgomeryRepresentation(m)
873+ aAgain := monty.clone()
874+ aAgain.montgomeryMul(monty, one, m)
875+ return a.cmpEq(aAgain) == 1
876+}
877+
878+func TestMontgomeryRoundtrip(t *testing.T) {
879+ err := quick.Check(testMontgomeryRoundtrip, &quick.Config{})
880+ if err != nil {
881+ t.Error(err)
882+ }
883+}
884+
885+func TestFromBig(t *testing.T) {
886+ expected := []byte{0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
887+ theBig := new(big.Int).SetBytes(expected)
888+ actual := natFromBig(theBig).fillBytes(make([]byte, len(expected)))
889+ if !bytes.Equal(actual, expected) {
890+ t.Errorf("%+x != %+x", actual, expected)
891+ }
892+}
893+
894+func TestFillBytes(t *testing.T) {
895+ xBytes := []byte{0xAA, 0xFF, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}
896+ x := natFromBytes(xBytes)
897+ for l := 20; l >= len(xBytes); l-- {
898+ buf := make([]byte, l)
899+ rand.Read(buf)
900+ actual := x.fillBytes(buf)
901+ expected := make([]byte, l)
902+ copy(expected[l-len(xBytes):], xBytes)
903+ if !bytes.Equal(actual, expected) {
904+ t.Errorf("%d: %+v != %+v", l, actual, expected)
905+ }
906+ }
907+ for l := len(xBytes) - 1; l >= 0; l-- {
908+ (func() {
909+ defer func() {
910+ if recover() == nil {
911+ t.Errorf("%d: expected panic", l)
912+ }
913+ }()
914+ x.fillBytes(make([]byte, l))
915+ })()
916+ }
917+}
918+
919+func TestFromBytes(t *testing.T) {
920+ f := func(xBytes []byte) bool {
921+ if len(xBytes) == 0 {
922+ return true
923+ }
924+ actual := natFromBytes(xBytes).fillBytes(make([]byte, len(xBytes)))
925+ if !bytes.Equal(actual, xBytes) {
926+ t.Errorf("%+x != %+x", actual, xBytes)
927+ return false
928+ }
929+ return true
930+ }
931+
932+ err := quick.Check(f, &quick.Config{})
933+ if err != nil {
934+ t.Error(err)
935+ }
936+
937+ f([]byte{0xFF, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
938+ f(bytes.Repeat([]byte{0xFF}, _W))
939+}
940+
941+func TestShiftIn(t *testing.T) {
942+ if bits.UintSize != 64 {
943+ t.Skip("examples are only valid in 64 bit")
944+ }
945+ examples := []struct {
946+ m, x, expected []byte
947+ y uint64
948+ }{{
949+ m: []byte{13},
950+ x: []byte{0},
951+ y: 0x7FFF_FFFF_FFFF_FFFF,
952+ expected: []byte{7},
953+ }, {
954+ m: []byte{13},
955+ x: []byte{7},
956+ y: 0x7FFF_FFFF_FFFF_FFFF,
957+ expected: []byte{11},
958+ }, {
959+ m: []byte{0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d},
960+ x: make([]byte, 9),
961+ y: 0x7FFF_FFFF_FFFF_FFFF,
962+ expected: []byte{0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
963+ }, {
964+ m: []byte{0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d},
965+ x: []byte{0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
966+ y: 0,
967+ expected: []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08},
968+ }}
969+
970+ for i, tt := range examples {
971+ m := modulusFromNat(natFromBytes(tt.m))
972+ got := natFromBytes(tt.x).expandFor(m).shiftIn(uint(tt.y), m)
973+ if got.cmpEq(natFromBytes(tt.expected).expandFor(m)) != 1 {
974+ t.Errorf("%d: got %x, expected %x", i, got, tt.expected)
975+ }
976+ }
977+}
978+
979+func TestModulusAndNatSizes(t *testing.T) {
980+ // These are 126 bit (2 * _W on 64-bit architectures) values, serialized as
981+ // 128 bits worth of bytes. If leading zeroes are stripped, they fit in two
982+ // limbs, if they are not, they fit in three. This can be a problem because
983+ // modulus strips leading zeroes and nat does not.
984+ m := modulusFromNat(natFromBytes([]byte{
985+ 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
986+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}))
987+ x := natFromBytes([]byte{
988+ 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
989+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe})
990+ x.expandFor(m) // must not panic for shrinking
991+}
992+
993+func TestExpand(t *testing.T) {
994+ sliced := []uint{1, 2, 3, 4}
995+ examples := []struct {
996+ in []uint
997+ n int
998+ out []uint
999+ }{{
1000+ []uint{1, 2},
1001+ 4,
1002+ []uint{1, 2, 0, 0},
1003+ }, {
1004+ sliced[:2],
1005+ 4,
1006+ []uint{1, 2, 0, 0},
1007+ }, {
1008+ []uint{1, 2},
1009+ 2,
1010+ []uint{1, 2},
1011+ }, {
1012+ []uint{1, 2, 0},
1013+ 2,
1014+ []uint{1, 2},
1015+ }}
1016+
1017+ for i, tt := range examples {
1018+ got := (&nat{tt.in}).expand(tt.n)
1019+ if len(got.limbs) != len(tt.out) || got.cmpEq(&nat{tt.out}) != 1 {
1020+ t.Errorf("%d: got %x, expected %x", i, got, tt.out)
1021+ }
1022+ }
1023+}
1024+
1025+func TestMod(t *testing.T) {
1026+ m := modulusFromNat(natFromBytes([]byte{0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d}))
1027+ x := natFromBytes([]byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})
1028+ out := new(nat)
1029+ out.mod(x, m)
1030+ expected := natFromBytes([]byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09})
1031+ if out.cmpEq(expected) != 1 {
1032+ t.Errorf("%+v != %+v", out, expected)
1033+ }
1034+}
1035+
1036+func TestModSub(t *testing.T) {
1037+ m := modulusFromNat(&nat{[]uint{13}})
1038+ x := &nat{[]uint{6}}
1039+ y := &nat{[]uint{7}}
1040+ x.modSub(y, m)
1041+ expected := &nat{[]uint{12}}
1042+ if x.cmpEq(expected) != 1 {
1043+ t.Errorf("%+v != %+v", x, expected)
1044+ }
1045+ x.modSub(y, m)
1046+ expected = &nat{[]uint{5}}
1047+ if x.cmpEq(expected) != 1 {
1048+ t.Errorf("%+v != %+v", x, expected)
1049+ }
1050+}
1051+
1052+func TestModAdd(t *testing.T) {
1053+ m := modulusFromNat(&nat{[]uint{13}})
1054+ x := &nat{[]uint{6}}
1055+ y := &nat{[]uint{7}}
1056+ x.modAdd(y, m)
1057+ expected := &nat{[]uint{0}}
1058+ if x.cmpEq(expected) != 1 {
1059+ t.Errorf("%+v != %+v", x, expected)
1060+ }
1061+ x.modAdd(y, m)
1062+ expected = &nat{[]uint{7}}
1063+ if x.cmpEq(expected) != 1 {
1064+ t.Errorf("%+v != %+v", x, expected)
1065+ }
1066+}
1067+
1068+func TestExp(t *testing.T) {
1069+ m := modulusFromNat(&nat{[]uint{13}})
1070+ x := &nat{[]uint{3}}
1071+ out := &nat{[]uint{0}}
1072+ out.exp(x, []byte{12}, m)
1073+ expected := &nat{[]uint{1}}
1074+ if out.cmpEq(expected) != 1 {
1075+ t.Errorf("%+v != %+v", out, expected)
1076+ }
1077+}
1078+
1079+func makeBenchmarkModulus() *modulus {
1080+ m := make([]uint, 32)
1081+ for i := 0; i < 32; i++ {
1082+ m[i] = _MASK
1083+ }
1084+ return modulusFromNat(&nat{limbs: m})
1085+}
1086+
1087+func makeBenchmarkValue() *nat {
1088+ x := make([]uint, 32)
1089+ for i := 0; i < 32; i++ {
1090+ x[i] = _MASK - 1
1091+ }
1092+ return &nat{limbs: x}
1093+}
1094+
1095+func makeBenchmarkExponent() []byte {
1096+ e := make([]byte, 256)
1097+ for i := 0; i < 32; i++ {
1098+ e[i] = 0xFF
1099+ }
1100+ return e
1101+}
1102+
1103+func BenchmarkModAdd(b *testing.B) {
1104+ x := makeBenchmarkValue()
1105+ y := makeBenchmarkValue()
1106+ m := makeBenchmarkModulus()
1107+
1108+ b.ResetTimer()
1109+ for i := 0; i < b.N; i++ {
1110+ x.modAdd(y, m)
1111+ }
1112+}
1113+
1114+func BenchmarkModSub(b *testing.B) {
1115+ x := makeBenchmarkValue()
1116+ y := makeBenchmarkValue()
1117+ m := makeBenchmarkModulus()
1118+
1119+ b.ResetTimer()
1120+ for i := 0; i < b.N; i++ {
1121+ x.modSub(y, m)
1122+ }
1123+}
1124+
1125+func BenchmarkMontgomeryRepr(b *testing.B) {
1126+ x := makeBenchmarkValue()
1127+ m := makeBenchmarkModulus()
1128+
1129+ b.ResetTimer()
1130+ for i := 0; i < b.N; i++ {
1131+ x.montgomeryRepresentation(m)
1132+ }
1133+}
1134+
1135+func BenchmarkMontgomeryMul(b *testing.B) {
1136+ x := makeBenchmarkValue()
1137+ y := makeBenchmarkValue()
1138+ out := makeBenchmarkValue()
1139+ m := makeBenchmarkModulus()
1140+
1141+ b.ResetTimer()
1142+ for i := 0; i < b.N; i++ {
1143+ out.montgomeryMul(x, y, m)
1144+ }
1145+}
1146+
1147+func BenchmarkModMul(b *testing.B) {
1148+ x := makeBenchmarkValue()
1149+ y := makeBenchmarkValue()
1150+ m := makeBenchmarkModulus()
1151+
1152+ b.ResetTimer()
1153+ for i := 0; i < b.N; i++ {
1154+ x.modMul(y, m)
1155+ }
1156+}
1157+
1158+func BenchmarkExpBig(b *testing.B) {
1159+ out := new(big.Int)
1160+ exponentBytes := makeBenchmarkExponent()
1161+ x := new(big.Int).SetBytes(exponentBytes)
1162+ e := new(big.Int).SetBytes(exponentBytes)
1163+ n := new(big.Int).SetBytes(exponentBytes)
1164+ one := new(big.Int).SetUint64(1)
1165+ n.Add(n, one)
1166+
1167+ b.ResetTimer()
1168+ for i := 0; i < b.N; i++ {
1169+ out.Exp(x, e, n)
1170+ }
1171+}
1172+
1173+func BenchmarkExp(b *testing.B) {
1174+ x := makeBenchmarkValue()
1175+ e := makeBenchmarkExponent()
1176+ out := makeBenchmarkValue()
1177+ m := makeBenchmarkModulus()
1178+
1179+ b.ResetTimer()
1180+ for i := 0; i < b.N; i++ {
1181+ out.exp(x, e, m)
1182+ }
1183+}
1184diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go
1185index a216be3..ce89f92 100644
1186--- a/src/crypto/rsa/pkcs1v15.go
1187+++ b/src/crypto/rsa/pkcs1v15.go
1188@@ -9,7 +9,6 @@ import (
1189 "crypto/subtle"
1190 "errors"
1191 "io"
1192- "math/big"
1193
1194 "crypto/internal/randutil"
1195 )
1196@@ -58,14 +57,11 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)
1197 em[len(em)-len(msg)-1] = 0
1198 copy(mm, msg)
1199
1200- m := new(big.Int).SetBytes(em)
1201- c := encrypt(new(big.Int), pub, m)
1202-
1203- return c.FillBytes(em), nil
1204+ return encrypt(pub, em), nil
1205 }
1206
1207 // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
1208-// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
1209+// The rand parameter is legacy and ignored, and it can be as nil.
1210 //
1211 // Note that whether this function returns an error or not discloses secret
1212 // information. If an attacker can cause this function to run repeatedly and
1213@@ -76,7 +72,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byt
1214 if err := checkPub(&priv.PublicKey); err != nil {
1215 return nil, err
1216 }
1217- valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext)
1218+ valid, out, index, err := decryptPKCS1v15(priv, ciphertext)
1219 if err != nil {
1220 return nil, err
1221 }
1222@@ -87,7 +83,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byt
1223 }
1224
1225 // DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5.
1226-// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
1227+// The rand parameter is legacy and ignored, and it can be as nil.
1228 // It returns an error if the ciphertext is the wrong length or if the
1229 // ciphertext is greater than the public modulus. Otherwise, no error is
1230 // returned. If the padding is valid, the resulting plaintext message is copied
1231@@ -114,7 +110,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by
1232 return ErrDecryption
1233 }
1234
1235- valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext)
1236+ valid, em, index, err := decryptPKCS1v15(priv, ciphertext)
1237 if err != nil {
1238 return err
1239 }
1240@@ -130,26 +126,24 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by
1241 return nil
1242 }
1243
1244-// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if
1245-// rand is not nil. It returns one or zero in valid that indicates whether the
1246-// plaintext was correctly structured. In either case, the plaintext is
1247-// returned in em so that it may be read independently of whether it was valid
1248-// in order to maintain constant memory access patterns. If the plaintext was
1249-// valid then index contains the index of the original message in em.
1250-func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
1251+// decryptPKCS1v15 decrypts ciphertext using priv. It returns one or zero in
1252+// valid that indicates whether the plaintext was correctly structured.
1253+// In either case, the plaintext is returned in em so that it may be read
1254+// independently of whether it was valid in order to maintain constant memory
1255+// access patterns. If the plaintext was valid then index contains the index of
1256+// the original message in em, to allow constant time padding removal.
1257+func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) {
1258 k := priv.Size()
1259 if k < 11 {
1260 err = ErrDecryption
1261 return
1262 }
1263
1264- c := new(big.Int).SetBytes(ciphertext)
1265- m, err := decrypt(rand, priv, c)
1266+ em, err = decrypt(priv, ciphertext)
1267 if err != nil {
1268 return
1269 }
1270
1271- em = m.FillBytes(make([]byte, k))
1272 firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
1273 secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
1274
1275@@ -221,8 +215,7 @@ var hashPrefixes = map[crypto.Hash][]byte{
1276 // function. If hash is zero, hashed is signed directly. This isn't
1277 // advisable except for interoperability.
1278 //
1279-// If rand is not nil then RSA blinding will be used to avoid timing
1280-// side-channel attacks.
1281+// The rand parameter is legacy and ignored, and it can be as nil.
1282 //
1283 // This function is deterministic. Thus, if the set of possible
1284 // messages is small, an attacker may be able to build a map from
1285@@ -249,13 +242,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
1286 copy(em[k-tLen:k-hashLen], prefix)
1287 copy(em[k-hashLen:k], hashed)
1288
1289- m := new(big.Int).SetBytes(em)
1290- c, err := decryptAndCheck(rand, priv, m)
1291- if err != nil {
1292- return nil, err
1293- }
1294-
1295- return c.FillBytes(em), nil
1296+ return decryptAndCheck(priv, em)
1297 }
1298
1299 // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
1300@@ -275,9 +262,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
1301 return ErrVerification
1302 }
1303
1304- c := new(big.Int).SetBytes(sig)
1305- m := encrypt(new(big.Int), pub, c)
1306- em := m.FillBytes(make([]byte, k))
1307+ em := encrypt(pub, sig)
1308 // EM = 0x00 || 0x01 || PS || 0x00 || T
1309
1310 ok := subtle.ConstantTimeByteEq(em[0], 0)
1311diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
1312index 814522d..eaba4be 100644
1313--- a/src/crypto/rsa/pss.go
1314+++ b/src/crypto/rsa/pss.go
1315@@ -12,7 +12,6 @@ import (
1316 "errors"
1317 "hash"
1318 "io"
1319- "math/big"
1320 )
1321
1322 // Per RFC 8017, Section 9.1
1323@@ -207,19 +206,27 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
1324 // Note that hashed must be the result of hashing the input message using the
1325 // given hash function. salt is a random sequence of bytes whose length will be
1326 // later used to verify the signature.
1327-func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) {
1328- emBits := priv.N.BitLen() - 1
1329+func signPSSWithSalt(priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) {
1330+ emBits := bigBitLen(priv.N) - 1
1331 em, err := emsaPSSEncode(hashed, emBits, salt, hash.New())
1332 if err != nil {
1333 return nil, err
1334 }
1335- m := new(big.Int).SetBytes(em)
1336- c, err := decryptAndCheck(rand, priv, m)
1337- if err != nil {
1338- return nil, err
1339+
1340+ // RFC 8017: "Note that the octet length of EM will be one less than k if
1341+ // modBits - 1 is divisible by 8 and equal to k otherwise, where k is the
1342+ // length in octets of the RSA modulus n."
1343+ //
1344+ // This is extremely annoying, as all other encrypt and decrypt inputs are
1345+ // always the exact same size as the modulus. Since it only happens for
1346+ // weird modulus sizes, fix it by padding inefficiently.
1347+ if emLen, k := len(em), priv.Size(); emLen < k {
1348+ emNew := make([]byte, k)
1349+ copy(emNew[k-emLen:], em)
1350+ em = emNew
1351 }
1352- s := make([]byte, priv.Size())
1353- return c.FillBytes(s), nil
1354+
1355+ return decryptAndCheck(priv, em)
1356 }
1357
1358 const (
1359@@ -269,7 +276,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
1360 saltLength := opts.saltLength()
1361 switch saltLength {
1362 case PSSSaltLengthAuto:
1363- saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size()
1364+ saltLength = (bigBitLen(priv.N)-1+7)/8 - 2 - hash.Size()
1365 case PSSSaltLengthEqualsHash:
1366 saltLength = hash.Size()
1367 }
1368@@ -278,7 +285,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
1369 if _, err := io.ReadFull(rand, salt); err != nil {
1370 return nil, err
1371 }
1372- return signPSSWithSalt(rand, priv, hash, digest, salt)
1373+ return signPSSWithSalt(priv, hash, digest, salt)
1374 }
1375
1376 // VerifyPSS verifies a PSS signature.
1377@@ -291,13 +298,22 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts
1378 if len(sig) != pub.Size() {
1379 return ErrVerification
1380 }
1381- s := new(big.Int).SetBytes(sig)
1382- m := encrypt(new(big.Int), pub, s)
1383- emBits := pub.N.BitLen() - 1
1384+
1385+ emBits := bigBitLen(pub.N) - 1
1386 emLen := (emBits + 7) / 8
1387- if m.BitLen() > emLen*8 {
1388- return ErrVerification
1389+ em := encrypt(pub, sig)
1390+
1391+ // Like in signPSSWithSalt, deal with mismatches between emLen and the size
1392+ // of the modulus. The spec would have us wire emLen into the encoding
1393+ // function, but we'd rather always encode to the size of the modulus and
1394+ // then strip leading zeroes if necessary. This only happens for weird
1395+ // modulus sizes anyway.
1396+ for len(em) > emLen && len(em) > 0 {
1397+ if em[0] != 0 {
1398+ return ErrVerification
1399+ }
1400+ em = em[1:]
1401 }
1402- em := m.FillBytes(make([]byte, emLen))
1403+
1404 return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New())
1405 }
1406diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go
1407index c3a6d46..d018b43 100644
1408--- a/src/crypto/rsa/pss_test.go
1409+++ b/src/crypto/rsa/pss_test.go
1410@@ -233,7 +233,10 @@ func TestPSSSigning(t *testing.T) {
1411 }
1412 }
1413
1414-func TestSignWithPSSSaltLengthAuto(t *testing.T) {
1415+func TestPSS513(t *testing.T) {
1416+ // See Issue 42741, and separately, RFC 8017: "Note that the octet length of
1417+ // EM will be one less than k if modBits - 1 is divisible by 8 and equal to
1418+ // k otherwise, where k is the length in octets of the RSA modulus n."
1419 key, err := GenerateKey(rand.Reader, 513)
1420 if err != nil {
1421 t.Fatal(err)
1422@@ -246,8 +249,9 @@ func TestSignWithPSSSaltLengthAuto(t *testing.T) {
1423 if err != nil {
1424 t.Fatal(err)
1425 }
1426- if len(signature) == 0 {
1427- t.Fatal("empty signature returned")
1428+ err = VerifyPSS(&key.PublicKey, crypto.SHA256, digest[:], signature, nil)
1429+ if err != nil {
1430+ t.Error(err)
1431 }
1432 }
1433
1434diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
1435index 5a00ed2..29d9d31 100644
1436--- a/src/crypto/rsa/rsa.go
1437+++ b/src/crypto/rsa/rsa.go
1438@@ -19,13 +19,17 @@
1439 // over the public key primitive, the PrivateKey type implements the
1440 // Decrypter and Signer interfaces from the crypto package.
1441 //
1442-// The RSA operations in this package are not implemented using constant-time algorithms.
1443+// Operations in this package are implemented using constant-time algorithms,
1444+// except for [GenerateKey], [PrivateKey.Precompute], and [PrivateKey.Validate].
1445+// Every other operation only leaks the bit size of the involved values, which
1446+// all depend on the selected key size.
1447 package rsa
1448
1449 import (
1450 "crypto"
1451 "crypto/rand"
1452 "crypto/subtle"
1453+ "encoding/binary"
1454 "errors"
1455 "hash"
1456 "io"
1457@@ -35,7 +39,6 @@ import (
1458 "crypto/internal/randutil"
1459 )
1460
1461-var bigZero = big.NewInt(0)
1462 var bigOne = big.NewInt(1)
1463
1464 // A PublicKey represents the public part of an RSA key.
1465@@ -47,7 +50,7 @@ type PublicKey struct {
1466 // Size returns the modulus size in bytes. Raw signatures and ciphertexts
1467 // for or by this public key will have the same size.
1468 func (pub *PublicKey) Size() int {
1469- return (pub.N.BitLen() + 7) / 8
1470+ return (bigBitLen(pub.N) + 7) / 8
1471 }
1472
1473 // OAEPOptions is an interface for passing options to OAEP decryption using the
1474@@ -351,10 +354,19 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) {
1475 // too large for the size of the public key.
1476 var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size")
1477
1478-func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
1479- e := big.NewInt(int64(pub.E))
1480- c.Exp(m, e, pub.N)
1481- return c
1482+func encrypt(pub *PublicKey, plaintext []byte) []byte {
1483+
1484+ N := modulusFromNat(natFromBig(pub.N))
1485+ m := natFromBytes(plaintext).expandFor(N)
1486+
1487+ e := make([]byte, 8)
1488+ binary.BigEndian.PutUint64(e, uint64(pub.E))
1489+ for len(e) > 1 && e[0] == 0 {
1490+ e = e[1:]
1491+ }
1492+
1493+ out := make([]byte, modulusSize(N))
1494+ return new(nat).exp(m, e, N).fillBytes(out)
1495 }
1496
1497 // EncryptOAEP encrypts the given message with RSA-OAEP.
1498@@ -404,12 +416,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
1499 mgf1XOR(db, hash, seed)
1500 mgf1XOR(seed, hash, db)
1501
1502- m := new(big.Int)
1503- m.SetBytes(em)
1504- c := encrypt(new(big.Int), pub, m)
1505-
1506- out := make([]byte, k)
1507- return c.FillBytes(out), nil
1508+ return encrypt(pub, em), nil
1509 }
1510
1511 // ErrDecryption represents a failure to decrypt a message.
1512@@ -451,98 +458,71 @@ func (priv *PrivateKey) Precompute() {
1513 }
1514 }
1515
1516-// decrypt performs an RSA decryption, resulting in a plaintext integer. If a
1517-// random source is given, RSA blinding is used.
1518-func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
1519- // TODO(agl): can we get away with reusing blinds?
1520- if c.Cmp(priv.N) > 0 {
1521- err = ErrDecryption
1522- return
1523+// decrypt performs an RSA decryption of ciphertext into out.
1524+func decrypt(priv *PrivateKey, ciphertext []byte) ([]byte, error) {
1525+
1526+ N := modulusFromNat(natFromBig(priv.N))
1527+ c := natFromBytes(ciphertext).expandFor(N)
1528+ if c.cmpGeq(N.nat) == 1 {
1529+ return nil, ErrDecryption
1530 }
1531 if priv.N.Sign() == 0 {
1532 return nil, ErrDecryption
1533 }
1534
1535- var ir *big.Int
1536- if random != nil {
1537- randutil.MaybeReadByte(random)
1538-
1539- // Blinding enabled. Blinding involves multiplying c by r^e.
1540- // Then the decryption operation performs (m^e * r^e)^d mod n
1541- // which equals mr mod n. The factor of r can then be removed
1542- // by multiplying by the multiplicative inverse of r.
1543-
1544- var r *big.Int
1545- ir = new(big.Int)
1546- for {
1547- r, err = rand.Int(random, priv.N)
1548- if err != nil {
1549- return
1550- }
1551- if r.Cmp(bigZero) == 0 {
1552- r = bigOne
1553- }
1554- ok := ir.ModInverse(r, priv.N)
1555- if ok != nil {
1556- break
1557- }
1558- }
1559- bigE := big.NewInt(int64(priv.E))
1560- rpowe := new(big.Int).Exp(r, bigE, priv.N) // N != 0
1561- cCopy := new(big.Int).Set(c)
1562- cCopy.Mul(cCopy, rpowe)
1563- cCopy.Mod(cCopy, priv.N)
1564- c = cCopy
1565- }
1566-
1567+ // Note that because our private decryption exponents are stored as big.Int,
1568+ // we potentially leak the exact number of bits of these exponents. This
1569+ // isn't great, but should be fine.
1570 if priv.Precomputed.Dp == nil {
1571- m = new(big.Int).Exp(c, priv.D, priv.N)
1572- } else {
1573- // We have the precalculated values needed for the CRT.
1574- m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0])
1575- m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1])
1576- m.Sub(m, m2)
1577- if m.Sign() < 0 {
1578- m.Add(m, priv.Primes[0])
1579- }
1580- m.Mul(m, priv.Precomputed.Qinv)
1581- m.Mod(m, priv.Primes[0])
1582- m.Mul(m, priv.Primes[1])
1583- m.Add(m, m2)
1584-
1585- for i, values := range priv.Precomputed.CRTValues {
1586- prime := priv.Primes[2+i]
1587- m2.Exp(c, values.Exp, prime)
1588- m2.Sub(m2, m)
1589- m2.Mul(m2, values.Coeff)
1590- m2.Mod(m2, prime)
1591- if m2.Sign() < 0 {
1592- m2.Add(m2, prime)
1593- }
1594- m2.Mul(m2, values.R)
1595- m.Add(m, m2)
1596- }
1597- }
1598-
1599- if ir != nil {
1600- // Unblind.
1601- m.Mul(m, ir)
1602- m.Mod(m, priv.N)
1603- }
1604-
1605- return
1606+ out := make([]byte, modulusSize(N))
1607+ return new(nat).exp(c, priv.D.Bytes(), N).fillBytes(out), nil
1608+ }
1609+
1610+ t0 := new(nat)
1611+ P := modulusFromNat(natFromBig(priv.Primes[0]))
1612+ Q := modulusFromNat(natFromBig(priv.Primes[1]))
1613+ // m = c ^ Dp mod p
1614+ m := new(nat).exp(t0.mod(c, P), priv.Precomputed.Dp.Bytes(), P)
1615+ // m2 = c ^ Dq mod q
1616+ m2 := new(nat).exp(t0.mod(c, Q), priv.Precomputed.Dq.Bytes(), Q)
1617+ // m = m - m2 mod p
1618+ m.modSub(t0.mod(m2, P), P)
1619+ // m = m * Qinv mod p
1620+ m.modMul(natFromBig(priv.Precomputed.Qinv).expandFor(P), P)
1621+ // m = m * q mod N
1622+ m.expandFor(N).modMul(t0.mod(Q.nat, N), N)
1623+ // m = m + m2 mod N
1624+ m.modAdd(m2.expandFor(N), N)
1625+
1626+ for i, values := range priv.Precomputed.CRTValues {
1627+ p := modulusFromNat(natFromBig(priv.Primes[2+i]))
1628+ // m2 = c ^ Exp mod p
1629+ m2.exp(t0.mod(c, p), values.Exp.Bytes(), p)
1630+ // m2 = m2 - m mod p
1631+ m2.modSub(t0.mod(m, p), p)
1632+ // m2 = m2 * Coeff mod p
1633+ m2.modMul(natFromBig(values.Coeff).expandFor(p), p)
1634+ // m2 = m2 * R mod N
1635+ R := natFromBig(values.R).expandFor(N)
1636+ m2.expandFor(N).modMul(R, N)
1637+ // m = m + m2 mod N
1638+ m.modAdd(m2, N)
1639+ }
1640+
1641+ out := make([]byte, modulusSize(N))
1642+ return m.fillBytes(out), nil
1643 }
1644
1645-func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
1646- m, err = decrypt(random, priv, c)
1647+func decryptAndCheck(priv *PrivateKey, ciphertext []byte) (m []byte, err error) {
1648+ m, err = decrypt(priv, ciphertext)
1649 if err != nil {
1650 return nil, err
1651 }
1652
1653 // In order to defend against errors in the CRT computation, m^e is
1654 // calculated, which should match the original ciphertext.
1655- check := encrypt(new(big.Int), &priv.PublicKey, m)
1656- if c.Cmp(check) != 0 {
1657+ check := encrypt(&priv.PublicKey, m)
1658+ if subtle.ConstantTimeCompare(ciphertext, check) != 1 {
1659 return nil, errors.New("rsa: internal error")
1660 }
1661 return m, nil
1662@@ -554,9 +534,7 @@ func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int
1663 // Encryption and decryption of a given message must use the same hash function
1664 // and sha256.New() is a reasonable choice.
1665 //
1666-// The random parameter, if not nil, is used to blind the private-key operation
1667-// and avoid timing side-channel attacks. Blinding is purely internal to this
1668-// function – the random data need not match that used when encrypting.
1669+// The random parameter is legacy and ignored, and it can be as nil.
1670 //
1671 // The label parameter must match the value given when encrypting. See
1672 // EncryptOAEP for details.
1673@@ -570,9 +548,7 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
1674 return nil, ErrDecryption
1675 }
1676
1677- c := new(big.Int).SetBytes(ciphertext)
1678-
1679- m, err := decrypt(random, priv, c)
1680+ em, err := decrypt(priv, ciphertext)
1681 if err != nil {
1682 return nil, err
1683 }
1684@@ -581,10 +557,6 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
1685 lHash := hash.Sum(nil)
1686 hash.Reset()
1687
1688- // We probably leak the number of leading zeros.
1689- // It's not clear that we can do anything about this.
1690- em := m.FillBytes(make([]byte, k))
1691-
1692 firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
1693
1694 seed := em[1 : hash.Size()+1]
1695--
16962.25.1
1697
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 @@
1From 20586c0dbe03d144f914155f879fa5ee287591a1 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Thu, 11 Jan 2024 11:31:57 -0800
4Subject: [PATCH] [release-branch.go1.21] net/http, net/http/cookiejar: avoid
5 subdomain matches on IPv6 zones
6
7When deciding whether to forward cookies or sensitive headers
8across a redirect, do not attempt to interpret an IPv6 address
9as a domain name.
10
11Avoids a case where a maliciously-crafted redirect to an
12IPv6 address with a scoped addressing zone could be
13misinterpreted as a within-domain redirect. For example,
14we could interpret "::1%.www.example.com" as a subdomain
15of "www.example.com".
16
17Thanks to Juho Nurminen of Mattermost for reporting this issue.
18
19Fixes CVE-2023-45289
20Fixes #65385
21For #65065
22
23Change-Id: I8f463f59f0e700c8a18733d2b264a8bcb3a19599
24Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2131938
25Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
26Reviewed-by: Roland Shoemaker <bracewell@google.com>
27Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173775
28Reviewed-by: Carlos Amedee <amedee@google.com>
29Reviewed-on: https://go-review.googlesource.com/c/go/+/569239
30Reviewed-by: Carlos Amedee <carlos@golang.org>
31Auto-Submit: Michael Knyszek <mknyszek@google.com>
32TryBot-Bypass: Michael Knyszek <mknyszek@google.com>
33
34Upstream-Status: Backport [https://github.com/golang/go/commit/20586c0dbe03d144f914155f879fa5ee287591a1]
35CVE: CVE-2023-45289
36Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
37---
38 src/net/http/client.go | 6 ++++++
39 src/net/http/client_test.go | 1 +
40 src/net/http/cookiejar/jar.go | 7 +++++++
41 src/net/http/cookiejar/jar_test.go | 10 ++++++++++
42 4 files changed, 24 insertions(+)
43
44diff --git a/src/net/http/client.go b/src/net/http/client.go
45index a496f1c..2031834 100644
46--- a/src/net/http/client.go
47+++ b/src/net/http/client.go
48@@ -973,6 +973,12 @@ func isDomainOrSubdomain(sub, parent string) bool {
49 if sub == parent {
50 return true
51 }
52+ // If sub contains a :, it's probably an IPv6 address (and is definitely not a hostname).
53+ // Don't check the suffix in this case, to avoid matching the contents of a IPv6 zone.
54+ // For example, "::1%.www.example.com" is not a subdomain of "www.example.com".
55+ if strings.ContainsAny(sub, ":%") {
56+ return false
57+ }
58 // If sub is "foo.example.com" and parent is "example.com",
59 // that means sub must end in "."+parent.
60 // Do it without allocating.
61diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
62index 2b4f53f..442fe35 100644
63--- a/src/net/http/client_test.go
64+++ b/src/net/http/client_test.go
65@@ -1703,6 +1703,7 @@ func TestShouldCopyHeaderOnRedirect(t *testing.T) {
66 {"cookie2", "http://foo.com/", "http://bar.com/", false},
67 {"authorization", "http://foo.com/", "http://bar.com/", false},
68 {"www-authenticate", "http://foo.com/", "http://bar.com/", false},
69+ {"authorization", "http://foo.com/", "http://[::1%25.foo.com]/", false},
70
71 // But subdomains should work:
72 {"www-authenticate", "http://foo.com/", "http://foo.com/", true},
73diff --git a/src/net/http/cookiejar/jar.go b/src/net/http/cookiejar/jar.go
74index 9f19917..18cbfc2 100644
75--- a/src/net/http/cookiejar/jar.go
76+++ b/src/net/http/cookiejar/jar.go
77@@ -356,6 +356,13 @@ func jarKey(host string, psl PublicSuffixList) string {
78
79 // isIP reports whether host is an IP address.
80 func isIP(host string) bool {
81+ if strings.ContainsAny(host, ":%") {
82+ // Probable IPv6 address.
83+ // Hostnames can't contain : or %, so this is definitely not a valid host.
84+ // Treating it as an IP is the more conservative option, and avoids the risk
85+ // of interpeting ::1%.www.example.com as a subtomain of www.example.com.
86+ return true
87+ }
88 return net.ParseIP(host) != nil
89 }
90
91diff --git a/src/net/http/cookiejar/jar_test.go b/src/net/http/cookiejar/jar_test.go
92index 47fb1ab..fd8d40e 100644
93--- a/src/net/http/cookiejar/jar_test.go
94+++ b/src/net/http/cookiejar/jar_test.go
95@@ -251,6 +251,7 @@ var isIPTests = map[string]bool{
96 "127.0.0.1": true,
97 "1.2.3.4": true,
98 "2001:4860:0:2001::68": true,
99+ "::1%zone": true,
100 "example.com": false,
101 "1.1.1.300": false,
102 "www.foo.bar.net": false,
103@@ -613,6 +614,15 @@ var basicsTests = [...]jarTest{
104 {"http://www.host.test:1234/", "a=1"},
105 },
106 },
107+ {
108+ "IPv6 zone is not treated as a host.",
109+ "https://example.com/",
110+ []string{"a=1"},
111+ "a=1",
112+ []query{
113+ {"https://[::1%25.example.com]:80/", ""},
114+ },
115+ },
116 }
117
118 func TestBasics(t *testing.T) {
119--
1202.25.1
121
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 @@
1From bf80213b121074f4ad9b449410a4d13bae5e9be0 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com>
3Date: Tue, 16 Jan 2024 15:37:52 -0800
4Subject: [PATCH] [release-branch.go1.21] net/textproto, mime/multipart: avoid
5 unbounded read in MIME header
6
7mime/multipart.Reader.ReadForm allows specifying the maximum amount
8of memory that will be consumed by the form. While this limit is
9correctly applied to the parsed form data structure, it was not
10being applied to individual header lines in a form.
11
12For example, when presented with a form containing a header line
13that never ends, ReadForm will continue to read the line until it
14runs out of memory.
15
16Limit the amount of data consumed when reading a header.
17
18Fixes CVE-2023-45290
19Fixes #65389
20For #65383
21
22Change-Id: I7f9264d25752009e95f6b2c80e3d76aaf321d658
23Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2134435
24Reviewed-by: Roland Shoemaker <bracewell@google.com>
25Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
26Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173776
27Reviewed-by: Carlos Amedee <amedee@google.com>
28Reviewed-on: https://go-review.googlesource.com/c/go/+/569240
29Auto-Submit: Michael Knyszek <mknyszek@google.com>
30LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
31Reviewed-by: Carlos Amedee <carlos@golang.org>
32
33Upstream-Status: Backport [https://github.com/golang/go/commit/bf80213b121074f4ad9b449410a4d13bae5e9be0]
34CVE: CVE-2023-45290
35Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
36---
37 src/mime/multipart/formdata_test.go | 42 +++++++++++++++++++++++++
38 src/net/textproto/reader.go | 48 ++++++++++++++++++++---------
39 src/net/textproto/reader_test.go | 12 ++++++++
40 3 files changed, 87 insertions(+), 15 deletions(-)
41
42diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
43index c78eeb7..f729da6 100644
44--- a/src/mime/multipart/formdata_test.go
45+++ b/src/mime/multipart/formdata_test.go
46@@ -421,6 +421,48 @@ func TestReadFormLimits(t *testing.T) {
47 }
48 }
49
50+func TestReadFormEndlessHeaderLine(t *testing.T) {
51+ for _, test := range []struct {
52+ name string
53+ prefix string
54+ }{{
55+ name: "name",
56+ prefix: "X-",
57+ }, {
58+ name: "value",
59+ prefix: "X-Header: ",
60+ }, {
61+ name: "continuation",
62+ prefix: "X-Header: foo\r\n ",
63+ }} {
64+ t.Run(test.name, func(t *testing.T) {
65+ const eol = "\r\n"
66+ s := `--boundary` + eol
67+ s += `Content-Disposition: form-data; name="a"` + eol
68+ s += `Content-Type: text/plain` + eol
69+ s += test.prefix
70+ fr := io.MultiReader(
71+ strings.NewReader(s),
72+ neverendingReader('X'),
73+ )
74+ r := NewReader(fr, "boundary")
75+ _, err := r.ReadForm(1 << 20)
76+ if err != ErrMessageTooLarge {
77+ t.Fatalf("ReadForm(1 << 20): %v, want ErrMessageTooLarge", err)
78+ }
79+ })
80+ }
81+}
82+
83+type neverendingReader byte
84+
85+func (r neverendingReader) Read(p []byte) (n int, err error) {
86+ for i := range p {
87+ p[i] = byte(r)
88+ }
89+ return len(p), nil
90+}
91+
92 func BenchmarkReadForm(b *testing.B) {
93 for _, test := range []struct {
94 name string
95diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
96index ad2d777..cea6613 100644
97--- a/src/net/textproto/reader.go
98+++ b/src/net/textproto/reader.go
99@@ -17,6 +17,10 @@ import (
100 "sync"
101 )
102
103+// TODO: This should be a distinguishable error (ErrMessageTooLarge)
104+// to allow mime/multipart to detect it.
105+var errMessageTooLarge = errors.New("message too large")
106+
107 // A Reader implements convenience methods for reading requests
108 // or responses from a text protocol network connection.
109 type Reader struct {
110@@ -38,13 +42,13 @@ func NewReader(r *bufio.Reader) *Reader {
111 // ReadLine reads a single line from r,
112 // eliding the final \n or \r\n from the returned string.
113 func (r *Reader) ReadLine() (string, error) {
114- line, err := r.readLineSlice()
115+ line, err := r.readLineSlice(-1)
116 return string(line), err
117 }
118
119 // ReadLineBytes is like ReadLine but returns a []byte instead of a string.
120 func (r *Reader) ReadLineBytes() ([]byte, error) {
121- line, err := r.readLineSlice()
122+ line, err := r.readLineSlice(-1)
123 if line != nil {
124 buf := make([]byte, len(line))
125 copy(buf, line)
126@@ -53,7 +57,10 @@ func (r *Reader) ReadLineBytes() ([]byte, error) {
127 return line, err
128 }
129
130-func (r *Reader) readLineSlice() ([]byte, error) {
131+// readLineSlice reads a single line from r,
132+// up to lim bytes long (or unlimited if lim is less than 0),
133+// eliding the final \r or \r\n from the returned string.
134+func (r *Reader) readLineSlice(lim int64) ([]byte, error) {
135 r.closeDot()
136 var line []byte
137 for {
138@@ -61,6 +68,9 @@ func (r *Reader) readLineSlice() ([]byte, error) {
139 if err != nil {
140 return nil, err
141 }
142+ if lim >= 0 && int64(len(line))+int64(len(l)) > lim {
143+ return nil, errMessageTooLarge
144+ }
145 // Avoid the copy if the first call produced a full line.
146 if line == nil && !more {
147 return l, nil
148@@ -93,7 +103,7 @@ func (r *Reader) readLineSlice() ([]byte, error) {
149 // A line consisting of only white space is never continued.
150 //
151 func (r *Reader) ReadContinuedLine() (string, error) {
152- line, err := r.readContinuedLineSlice(noValidation)
153+ line, err := r.readContinuedLineSlice(-1, noValidation)
154 return string(line), err
155 }
156
157@@ -114,7 +124,7 @@ func trim(s []byte) []byte {
158 // ReadContinuedLineBytes is like ReadContinuedLine but
159 // returns a []byte instead of a string.
160 func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
161- line, err := r.readContinuedLineSlice(noValidation)
162+ line, err := r.readContinuedLineSlice(-1, noValidation)
163 if line != nil {
164 buf := make([]byte, len(line))
165 copy(buf, line)
166@@ -127,13 +137,14 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) {
167 // returning a byte slice with all lines. The validateFirstLine function
168 // is run on the first read line, and if it returns an error then this
169 // error is returned from readContinuedLineSlice.
170-func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([]byte, error) {
171+// It reads up to lim bytes of data (or unlimited if lim is less than 0).
172+func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) {
173 if validateFirstLine == nil {
174 return nil, fmt.Errorf("missing validateFirstLine func")
175 }
176
177 // Read the first line.
178- line, err := r.readLineSlice()
179+ line, err := r.readLineSlice(lim)
180 if err != nil {
181 return nil, err
182 }
183@@ -161,13 +172,21 @@ func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([
184 // copy the slice into buf.
185 r.buf = append(r.buf[:0], trim(line)...)
186
187+ if lim < 0 {
188+ lim = math.MaxInt64
189+ }
190+ lim -= int64(len(r.buf))
191+
192 // Read continuation lines.
193 for r.skipSpace() > 0 {
194- line, err := r.readLineSlice()
195+ r.buf = append(r.buf, ' ')
196+ if int64(len(r.buf)) >= lim {
197+ return nil, errMessageTooLarge
198+ }
199+ line, err := r.readLineSlice(lim - int64(len(r.buf)))
200 if err != nil {
201 break
202 }
203- r.buf = append(r.buf, ' ')
204 r.buf = append(r.buf, trim(line)...)
205 }
206 return r.buf, nil
207@@ -512,7 +531,8 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
208
209 // The first line cannot start with a leading space.
210 if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
211- line, err := r.readLineSlice()
212+ const errorLimit = 80 // arbitrary limit on how much of the line we'll quote
213+ line, err := r.readLineSlice(errorLimit)
214 if err != nil {
215 return m, err
216 }
217@@ -520,7 +540,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
218 }
219
220 for {
221- kv, err := r.readContinuedLineSlice(mustHaveFieldNameColon)
222+ kv, err := r.readContinuedLineSlice(maxMemory, mustHaveFieldNameColon)
223 if len(kv) == 0 {
224 return m, err
225 }
226@@ -541,7 +561,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
227
228 maxHeaders--
229 if maxHeaders < 0 {
230- return nil, errors.New("message too large")
231+ return nil, errMessageTooLarge
232 }
233
234 // backport 5c55ac9bf1e5f779220294c843526536605f42ab
235@@ -567,9 +587,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error)
236 }
237 maxMemory -= int64(len(value))
238 if maxMemory < 0 {
239- // TODO: This should be a distinguishable error (ErrMessageTooLarge)
240- // to allow mime/multipart to detect it.
241- return m, errors.New("message too large")
242+ return m, errMessageTooLarge
243 }
244 if vv == nil && len(strs) > 0 {
245 // More than likely this will be a single-element key.
246diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
247index 3ae0de1..db1ed91 100644
248--- a/src/net/textproto/reader_test.go
249+++ b/src/net/textproto/reader_test.go
250@@ -34,6 +34,18 @@ func TestReadLine(t *testing.T) {
251 }
252 }
253
254+func TestReadLineLongLine(t *testing.T) {
255+ line := strings.Repeat("12345", 10000)
256+ r := reader(line + "\r\n")
257+ s, err := r.ReadLine()
258+ if err != nil {
259+ t.Fatalf("Line 1: %v", err)
260+ }
261+ if s != line {
262+ t.Fatalf("%v-byte line does not match expected %v-byte line", len(s), len(line))
263+ }
264+}
265+
266 func TestReadContinuedLine(t *testing.T) {
267 r := reader("line1\nline\n 2\nline3\n")
268 s, err := r.ReadContinuedLine()
269--
2702.25.1
271
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 @@
1From 5330cd225ba54c7dc78c1b46dcdf61a4671a632c Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Wed, 10 Jan 2024 11:02:14 -0800
4Subject: [PATCH] [release-branch.go1.22] net/mail: properly handle special
5 characters in phrase and obs-phrase
6
7Fixes a couple of misalignments with RFC 5322 which introduce
8significant diffs between (mostly) conformant parsers.
9
10This change reverts the changes made in CL50911, which allowed certain
11special RFC 5322 characters to appear unquoted in the "phrase" syntax.
12It is unclear why this change was made in the first place, and created
13a divergence from comformant parsers. In particular this resulted in
14treating comments in display names incorrectly.
15
16Additionally properly handle trailing malformed comments in the group
17syntax.
18
19For #65083
20Fixed #65849
21
22Change-Id: I00dddc044c6ae3381154e43236632604c390f672
23Reviewed-on: https://go-review.googlesource.com/c/go/+/555596
24Reviewed-by: Damien Neil <dneil@google.com>
25LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
26Reviewed-on: https://go-review.googlesource.com/c/go/+/566215
27Reviewed-by: Carlos Amedee <carlos@golang.org>
28
29Upstream-Status: Backport [https://github.com/golang/go/commit/5330cd225ba54c7dc78c1b46dcdf61a4671a632c]
30CVE: CVE-2024-24784
31Signed-off-by: Ashish Sharma <asharma@mvista.com>
32
33 src/net/mail/message.go | 30 +++++++++++++++------------
34 src/net/mail/message_test.go | 40 ++++++++++++++++++++++++++----------
35 2 files changed, 46 insertions(+), 24 deletions(-)
36
37diff --git a/src/net/mail/message.go b/src/net/mail/message.go
38index af516fc30f470..fc2a9e46f811b 100644
39--- a/src/net/mail/message.go
40+++ b/src/net/mail/message.go
41@@ -280,7 +280,7 @@ func (a *Address) String() string {
42 // Add quotes if needed
43 quoteLocal := false
44 for i, r := range local {
45- if isAtext(r, false, false) {
46+ if isAtext(r, false) {
47 continue
48 }
49 if r == '.' {
50@@ -444,7 +444,7 @@ func (p *addrParser) parseAddress(handleGroup bool) ([]*Address, error) {
51 if !p.consume('<') {
52 atext := true
53 for _, r := range displayName {
54- if !isAtext(r, true, false) {
55+ if !isAtext(r, true) {
56 atext = false
57 break
58 }
59@@ -479,7 +479,9 @@ func (p *addrParser) consumeGroupList() ([]*Address, error) {
60 // handle empty group.
61 p.skipSpace()
62 if p.consume(';') {
63- p.skipCFWS()
64+ if !p.skipCFWS() {
65+ return nil, errors.New("mail: misformatted parenthetical comment")
66+ }
67 return group, nil
68 }
69
70@@ -496,7 +498,9 @@ func (p *addrParser) consumeGroupList() ([]*Address, error) {
71 return nil, errors.New("mail: misformatted parenthetical comment")
72 }
73 if p.consume(';') {
74- p.skipCFWS()
75+ if !p.skipCFWS() {
76+ return nil, errors.New("mail: misformatted parenthetical comment")
77+ }
78 break
79 }
80 if !p.consume(',') {
81@@ -566,6 +570,12 @@ func (p *addrParser) consumePhrase() (phrase string, err error) {
82 var words []string
83 var isPrevEncoded bool
84 for {
85+ // obs-phrase allows CFWS after one word
86+ if len(words) > 0 {
87+ if !p.skipCFWS() {
88+ return "", errors.New("mail: misformatted parenthetical comment")
89+ }
90+ }
91 // word = atom / quoted-string
92 var word string
93 p.skipSpace()
94@@ -661,7 +671,6 @@ Loop:
95 // If dot is true, consumeAtom parses an RFC 5322 dot-atom instead.
96 // If permissive is true, consumeAtom will not fail on:
97 // - leading/trailing/double dots in the atom (see golang.org/issue/4938)
98-// - special characters (RFC 5322 3.2.3) except '<', '>', ':' and '"' (see golang.org/issue/21018)
99 func (p *addrParser) consumeAtom(dot bool, permissive bool) (atom string, err error) {
100 i := 0
101
102@@ -672,7 +681,7 @@ Loop:
103 case size == 1 && r == utf8.RuneError:
104 return "", fmt.Errorf("mail: invalid utf-8 in address: %q", p.s)
105
106- case size == 0 || !isAtext(r, dot, permissive):
107+ case size == 0 || !isAtext(r, dot):
108 break Loop
109
110 default:
111@@ -850,18 +859,13 @@ func (e charsetError) Error() string {
112
113 // isAtext reports whether r is an RFC 5322 atext character.
114 // If dot is true, period is included.
115-// If permissive is true, RFC 5322 3.2.3 specials is included,
116-// except '<', '>', ':' and '"'.
117-func isAtext(r rune, dot, permissive bool) bool {
118+func isAtext(r rune, dot bool) bool {
119 switch r {
120 case '.':
121 return dot
122
123 // RFC 5322 3.2.3. specials
124- case '(', ')', '[', ']', ';', '@', '\\', ',':
125- return permissive
126-
127- case '<', '>', '"', ':':
128+ case '(', ')', '<', '>', '[', ']', ':', ';', '@', '\\', ',', '"': // RFC 5322 3.2.3. specials
129 return false
130 }
131 return isVchar(r)
132diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go
133index 1e1bb4092f659..1f2f62afbf406 100644
134--- a/src/net/mail/message_test.go
135+++ b/src/net/mail/message_test.go
136@@ -385,8 +385,11 @@ func TestAddressParsingError(t *testing.T) {
137 13: {"group not closed: null@example.com", "expected comma"},
138 14: {"group: first@example.com, second@example.com;", "group with multiple addresses"},
139 15: {"john.doe", "missing '@' or angle-addr"},
140- 16: {"john.doe@", "no angle-addr"},
141+ 16: {"john.doe@", "missing '@' or angle-addr"},
142 17: {"John Doe@foo.bar", "no angle-addr"},
143+ 18: {" group: null@example.com; (asd", "misformatted parenthetical comment"},
144+ 19: {" group: ; (asd", "misformatted parenthetical comment"},
145+ 20: {`(John) Doe <jdoe@machine.example>`, "missing word in phrase:"},
146 }
147
148 for i, tc := range mustErrTestCases {
149@@ -436,24 +439,19 @@ func TestAddressParsing(t *testing.T) {
150 Address: "john.q.public@example.com",
151 }},
152 },
153- {
154- `"John (middle) Doe" <jdoe@machine.example>`,
155- []*Address{{
156- Name: "John (middle) Doe",
157- Address: "jdoe@machine.example",
158- }},
159- },
160+ // Comment in display name
161 {
162 `John (middle) Doe <jdoe@machine.example>`,
163 []*Address{{
164- Name: "John (middle) Doe",
165+ Name: "John Doe",
166 Address: "jdoe@machine.example",
167 }},
168 },
169+ // Display name is quoted string, so comment is not a comment
170 {
171- `John !@M@! Doe <jdoe@machine.example>`,
172+ `"John (middle) Doe" <jdoe@machine.example>`,
173 []*Address{{
174- Name: "John !@M@! Doe",
175+ Name: "John (middle) Doe",
176 Address: "jdoe@machine.example",
177 }},
178 },
179@@ -788,6 +786,26 @@ func TestAddressParsing(t *testing.T) {
180 },
181 },
182 },
183+ // Comment in group display name
184+ {
185+ `group (comment:): a@example.com, b@example.com;`,
186+ []*Address{
187+ {
188+ Address: "a@example.com",
189+ },
190+ {
191+ Address: "b@example.com",
192+ },
193+ },
194+ },
195+ {
196+ `x(:"):"@a.example;("@b.example;`,
197+ []*Address{
198+ {
199+ Address: `@a.example;(@b.example`,
200+ },
201+ },
202+ },
203 }
204 for _, test := range tests {
205 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 @@
1From 3643147a29352ca2894fd5d0d2069bc4b4335a7e Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <roland@golang.org>
3Date: Wed, 14 Feb 2024 17:18:36 -0800
4Subject: [PATCH] [release-branch.go1.21] html/template: escape additional
5 tokens in MarshalJSON errors
6
7Escape "</script" and "<!--" in errors returned from MarshalJSON errors
8when attempting to marshal types in script blocks. This prevents any
9user controlled content from prematurely terminating the script block.
10
11Updates #65697
12Fixes #65968
13
14Change-Id: Icf0e26c54ea7d9c1deed0bff11b6506c99ddef1b
15Reviewed-on: https://go-review.googlesource.com/c/go/+/564196
16LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
17Reviewed-by: Damien Neil <dneil@google.com>
18(cherry picked from commit ccbc725f2d678255df1bd326fa511a492aa3a0aa)
19Reviewed-on: https://go-review.googlesource.com/c/go/+/567515
20Reviewed-by: Carlos Amedee <carlos@golang.org>
21
22Upstream-Status: Backport [https://github.com/golang/go/commit/3643147a29352ca2894fd5d0d2069bc4b4335a7e]
23CVE: CVE-2024-24785
24Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
25---
26 src/html/template/js.go | 22 ++++++++-
27 src/html/template/js_test.go | 96 ++++++++++++++++++++----------------
28 2 files changed, 74 insertions(+), 44 deletions(-)
29
30diff --git a/src/html/template/js.go b/src/html/template/js.go
31index 35994f0..4d3b25d 100644
32--- a/src/html/template/js.go
33+++ b/src/html/template/js.go
34@@ -171,13 +171,31 @@ func jsValEscaper(args ...interface{}) string {
35 // cyclic data. This may be an unacceptable DoS risk.
36 b, err := json.Marshal(a)
37 if err != nil {
38- // Put a space before comment so that if it is flush against
39+ // While the standard JSON marshaller does not include user controlled
40+ // information in the error message, if a type has a MarshalJSON method,
41+ // the content of the error message is not guaranteed. Since we insert
42+ // the error into the template, as part of a comment, we attempt to
43+ // prevent the error from either terminating the comment, or the script
44+ // block itself.
45+ //
46+ // In particular we:
47+ // * replace "*/" comment end tokens with "* /", which does not
48+ // terminate the comment
49+ // * replace "</script" with "\x3C/script", and "<!--" with
50+ // "\x3C!--", which prevents confusing script block termination
51+ // semantics
52+ //
53+ // We also put a space before the comment so that if it is flush against
54 // a division operator it is not turned into a line comment:
55 // x/{{y}}
56 // turning into
57 // x//* error marshaling y:
58 // second line of error message */null
59- return fmt.Sprintf(" /* %s */null ", strings.ReplaceAll(err.Error(), "*/", "* /"))
60+ errStr := err.Error()
61+ errStr = strings.ReplaceAll(errStr, "*/", "* /")
62+ errStr = strings.ReplaceAll(errStr, "</script", `\x3C/script`)
63+ errStr = strings.ReplaceAll(errStr, "<!--", `\x3C!--`)
64+ return fmt.Sprintf(" /* %s */null ", errStr)
65 }
66
67 // TODO: maybe post-process output to prevent it from containing
68diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go
69index de9ef28..3fc3baf 100644
70--- a/src/html/template/js_test.go
71+++ b/src/html/template/js_test.go
72@@ -5,6 +5,7 @@
73 package template
74
75 import (
76+ "errors"
77 "bytes"
78 "math"
79 "strings"
80@@ -104,61 +105,72 @@ func TestNextJsCtx(t *testing.T) {
81 }
82 }
83
84+type jsonErrType struct{}
85+
86+func (e *jsonErrType) MarshalJSON() ([]byte, error) {
87+ return nil, errors.New("beep */ boop </script blip <!--")
88+}
89+
90 func TestJSValEscaper(t *testing.T) {
91 tests := []struct {
92- x interface{}
93- js string
94+ x interface{}
95+ js string
96+ skipNest bool
97 }{
98- {int(42), " 42 "},
99- {uint(42), " 42 "},
100- {int16(42), " 42 "},
101- {uint16(42), " 42 "},
102- {int32(-42), " -42 "},
103- {uint32(42), " 42 "},
104- {int16(-42), " -42 "},
105- {uint16(42), " 42 "},
106- {int64(-42), " -42 "},
107- {uint64(42), " 42 "},
108- {uint64(1) << 53, " 9007199254740992 "},
109+ {int(42), " 42 ", false},
110+ {uint(42), " 42 ", false},
111+ {int16(42), " 42 ", false},
112+ {uint16(42), " 42 ", false},
113+ {int32(-42), " -42 ", false},
114+ {uint32(42), " 42 ", false},
115+ {int16(-42), " -42 ", false},
116+ {uint16(42), " 42 ", false},
117+ {int64(-42), " -42 ", false},
118+ {uint64(42), " 42 ", false},
119+ {uint64(1) << 53, " 9007199254740992 ", false},
120 // ulp(1 << 53) > 1 so this loses precision in JS
121 // but it is still a representable integer literal.
122- {uint64(1)<<53 + 1, " 9007199254740993 "},
123- {float32(1.0), " 1 "},
124- {float32(-1.0), " -1 "},
125- {float32(0.5), " 0.5 "},
126- {float32(-0.5), " -0.5 "},
127- {float32(1.0) / float32(256), " 0.00390625 "},
128- {float32(0), " 0 "},
129- {math.Copysign(0, -1), " -0 "},
130- {float64(1.0), " 1 "},
131- {float64(-1.0), " -1 "},
132- {float64(0.5), " 0.5 "},
133- {float64(-0.5), " -0.5 "},
134- {float64(0), " 0 "},
135- {math.Copysign(0, -1), " -0 "},
136- {"", `""`},
137- {"foo", `"foo"`},
138+ {uint64(1)<<53 + 1, " 9007199254740993 ", false},
139+ {float32(1.0), " 1 ", false},
140+ {float32(-1.0), " -1 ", false},
141+ {float32(0.5), " 0.5 ", false},
142+ {float32(-0.5), " -0.5 ", false},
143+ {float32(1.0) / float32(256), " 0.00390625 ", false},
144+ {float32(0), " 0 ", false},
145+ {math.Copysign(0, -1), " -0 ", false},
146+ {float64(1.0), " 1 ", false},
147+ {float64(-1.0), " -1 ", false},
148+ {float64(0.5), " 0.5 ", false},
149+ {float64(-0.5), " -0.5 ", false},
150+ {float64(0), " 0 ", false},
151+ {math.Copysign(0, -1), " -0 ", false},
152+ {"", `""`, false},
153+ {"foo", `"foo"`, false},
154 // Newlines.
155- {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
156+ {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`, false},
157 // "\v" == "v" on IE 6 so use "\u000b" instead.
158- {"\t\x0b", `"\t\u000b"`},
159- {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
160- {[]interface{}{}, "[]"},
161- {[]interface{}{42, "foo", nil}, `[42,"foo",null]`},
162- {[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`},
163- {"<!--", `"\u003c!--"`},
164- {"-->", `"--\u003e"`},
165- {"<![CDATA[", `"\u003c![CDATA["`},
166- {"]]>", `"]]\u003e"`},
167- {"</script", `"\u003c/script"`},
168- {"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E"
169- {nil, " null "},
170+ {"\t\x0b", `"\t\u000b"`, false},
171+ {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`, false},
172+ {[]interface{}{}, "[]", false},
173+ {[]interface{}{42, "foo", nil}, `[42,"foo",null]`, false},
174+ {[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`, false},
175+ {"<!--", `"\u003c!--"`, false},
176+ {"-->", `"--\u003e"`, false},
177+ {"<![CDATA[", `"\u003c![CDATA["`, false},
178+ {"]]>", `"]]\u003e"`, false},
179+ {"</script", `"\u003c/script"`, false},
180+ {"\U0001D11E", "\"\U0001D11E\"", false}, // or "\uD834\uDD1E"
181+ {nil, " null ", false},
182+ {&jsonErrType{}, " /* json: error calling MarshalJSON for type *template.jsonErrType: beep * / boop \\x3C/script blip \\x3C!-- */null ", true},
183 }
184
185 for _, test := range tests {
186 if js := jsValEscaper(test.x); js != test.js {
187 t.Errorf("%+v: want\n\t%q\ngot\n\t%q", test.x, test.js, js)
188 }
189+ if test.skipNest {
190+ continue
191+ }
192 // Make sure that escaping corner cases are not broken
193 // by nesting.
194 a := []interface{}{test.x}
195--
1962.25.1
197