summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVijay Anusuri <vanusuri@mvista.com>2024-03-27 08:49:54 +0530
committerSteve Sakoman <steve@sakoman.com>2024-04-05 06:34:42 -0700
commit869db167b1c71e036a70565dc73cef6b002d6d22 (patch)
treebeddf64378f6a00277f36d517b674febb0f69032
parente555aefeef5e87927560aa941bb937511425f7a6 (diff)
downloadpoky-869db167b1c71e036a70565dc73cef6b002d6d22.tar.gz
go: Fix for CVE-2023-45289 CVE-2023-45290 & CVE-2024-24785
Upstream-Status: Backport [https://github.com/golang/go/commit/20586c0dbe03d144f914155f879fa5ee287591a1 & https://github.com/golang/go/commit/bf80213b121074f4ad9b449410a4d13bae5e9be0 & https://github.com/golang/go/commit/3643147a29352ca2894fd5d0d2069bc4b4335a7e] (From OE-Core rev: 2bc50dccff15b9c4ad815092ef20caa3ef06864c) Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-devtools/go/go-1.14.inc3
-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-24785.patch197
4 files changed, 592 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14.inc b/meta/recipes-devtools/go/go-1.14.inc
index 4fbf9d7590..69b65f3eb2 100644
--- a/meta/recipes-devtools/go/go-1.14.inc
+++ b/meta/recipes-devtools/go/go-1.14.inc
@@ -88,6 +88,9 @@ SRC_URI += "\
88 file://CVE-2023-45287-pre2.patch \ 88 file://CVE-2023-45287-pre2.patch \
89 file://CVE-2023-45287-pre3.patch \ 89 file://CVE-2023-45287-pre3.patch \
90 file://CVE-2023-45287.patch \ 90 file://CVE-2023-45287.patch \
91 file://CVE-2023-45289.patch \
92 file://CVE-2023-45290.patch \
93 file://CVE-2024-24785.patch \
91" 94"
92 95
93SRC_URI_append_libc-musl = " file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch" 96SRC_URI_append_libc-musl = " file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch"
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-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