diff options
| author | Hitendra Prajapati <hprajapati@mvista.com> | 2024-03-07 11:14:43 +0530 |
|---|---|---|
| committer | Steve Sakoman <steve@sakoman.com> | 2024-03-12 04:06:19 -1000 |
| commit | ae66c42f9ea2cf1283fef982efb998910de6e2fc (patch) | |
| tree | 64ac3cd8903aa161bfd43138284646be743d8e99 /meta/recipes-devtools | |
| parent | fadcdfdd67a06f4c67d44cb543fbf8b7c756de37 (diff) | |
| download | poky-ae66c42f9ea2cf1283fef982efb998910de6e2fc.tar.gz | |
golang: Fix CVE-2023-45289 & CVE-2023-45290
Backport fixes for:
CVE-2023-45289 - Upstream-Status: Backport from https://github.com/golang/go/commit/3a855208e3efed2e9d7c20ad023f1fa78afcc0be
CVE-2023-45290 - Upstream-Status: Backport from https://github.com/golang/go/commit/041a47712e765e94f86d841c3110c840e76d8f82
(From OE-Core rev: e5aae8a371717215a7d78459788ad67dfaefe37e)
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta/recipes-devtools')
| -rw-r--r-- | meta/recipes-devtools/go/go-1.17.13.inc | 2 | ||||
| -rw-r--r-- | meta/recipes-devtools/go/go-1.21/CVE-2023-45289.patch | 121 | ||||
| -rw-r--r-- | meta/recipes-devtools/go/go-1.21/CVE-2023-45290.patch | 270 |
3 files changed, 393 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.17.13.inc b/meta/recipes-devtools/go/go-1.17.13.inc index c02da60f68..e635445579 100644 --- a/meta/recipes-devtools/go/go-1.17.13.inc +++ b/meta/recipes-devtools/go/go-1.17.13.inc | |||
| @@ -51,6 +51,8 @@ SRC_URI += "\ | |||
| 51 | file://CVE-2023-39326.patch \ | 51 | file://CVE-2023-39326.patch \ |
| 52 | file://CVE-2023-45285.patch \ | 52 | file://CVE-2023-45285.patch \ |
| 53 | file://CVE-2023-45287.patch \ | 53 | file://CVE-2023-45287.patch \ |
| 54 | file://CVE-2023-45289.patch \ | ||
| 55 | file://CVE-2023-45290.patch \ | ||
| 54 | " | 56 | " |
| 55 | SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd" | 57 | SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd" |
| 56 | 58 | ||
diff --git a/meta/recipes-devtools/go/go-1.21/CVE-2023-45289.patch b/meta/recipes-devtools/go/go-1.21/CVE-2023-45289.patch new file mode 100644 index 0000000000..f8ac64472f --- /dev/null +++ b/meta/recipes-devtools/go/go-1.21/CVE-2023-45289.patch | |||
| @@ -0,0 +1,121 @@ | |||
| 1 | From 3a855208e3efed2e9d7c20ad023f1fa78afcc0be Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Damien Neil <dneil@google.com> | ||
| 3 | Date: Thu, 11 Jan 2024 11:31:57 -0800 | ||
| 4 | Subject: [PATCH] [release-branch.go1.22] net/http, net/http/cookiejar: avoid | ||
| 5 | subdomain matches on IPv6 zones | ||
| 6 | |||
| 7 | When deciding whether to forward cookies or sensitive headers | ||
| 8 | across a redirect, do not attempt to interpret an IPv6 address | ||
| 9 | as a domain name. | ||
| 10 | |||
| 11 | Avoids a case where a maliciously-crafted redirect to an | ||
| 12 | IPv6 address with a scoped addressing zone could be | ||
| 13 | misinterpreted as a within-domain redirect. For example, | ||
| 14 | we could interpret "::1%.www.example.com" as a subdomain | ||
| 15 | of "www.example.com". | ||
| 16 | |||
| 17 | Thanks to Juho Nurminen of Mattermost for reporting this issue. | ||
| 18 | |||
| 19 | Fixes CVE-2023-45289 | ||
| 20 | Fixes #65859 | ||
| 21 | For #65065 | ||
| 22 | |||
| 23 | Change-Id: I8f463f59f0e700c8a18733d2b264a8bcb3a19599 | ||
| 24 | Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2131938 | ||
| 25 | Reviewed-by: Tatiana Bradley <tatianabradley@google.com> | ||
| 26 | Reviewed-by: Roland Shoemaker <bracewell@google.com> | ||
| 27 | Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2174344 | ||
| 28 | Reviewed-by: Carlos Amedee <amedee@google.com> | ||
| 29 | Reviewed-on: https://go-review.googlesource.com/c/go/+/569236 | ||
| 30 | Reviewed-by: Carlos Amedee <carlos@golang.org> | ||
| 31 | LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> | ||
| 32 | Auto-Submit: Michael Knyszek <mknyszek@google.com> | ||
| 33 | |||
| 34 | Upstream-Status: Backport [https://github.com/golang/go/commit/3a855208e3efed2e9d7c20ad023f1fa78afcc0be] | ||
| 35 | CVE: CVE-2023-45289 | ||
| 36 | Signed-off-by: Hitendra Prajapati <hprajapati@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 | |||
| 44 | diff --git a/src/net/http/client.go b/src/net/http/client.go | ||
| 45 | index 22db96b..b2dd445 100644 | ||
| 46 | --- a/src/net/http/client.go | ||
| 47 | +++ b/src/net/http/client.go | ||
| 48 | @@ -1015,6 +1015,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. | ||
| 61 | diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go | ||
| 62 | index 9788c7a..7a0aa53 100644 | ||
| 63 | --- a/src/net/http/client_test.go | ||
| 64 | +++ b/src/net/http/client_test.go | ||
| 65 | @@ -1729,6 +1729,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}, | ||
| 73 | diff --git a/src/net/http/cookiejar/jar.go b/src/net/http/cookiejar/jar.go | ||
| 74 | index e6583da..f2cf9c2 100644 | ||
| 75 | --- a/src/net/http/cookiejar/jar.go | ||
| 76 | +++ b/src/net/http/cookiejar/jar.go | ||
| 77 | @@ -362,6 +362,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 | |||
| 91 | diff --git a/src/net/http/cookiejar/jar_test.go b/src/net/http/cookiejar/jar_test.go | ||
| 92 | index 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 | -- | ||
| 120 | 2.25.1 | ||
| 121 | |||
diff --git a/meta/recipes-devtools/go/go-1.21/CVE-2023-45290.patch b/meta/recipes-devtools/go/go-1.21/CVE-2023-45290.patch new file mode 100644 index 0000000000..81f2123f34 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.21/CVE-2023-45290.patch | |||
| @@ -0,0 +1,270 @@ | |||
| 1 | From 041a47712e765e94f86d841c3110c840e76d8f82 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Damien Neil <dneil@google.com> | ||
| 3 | Date: Tue, 16 Jan 2024 15:37:52 -0800 | ||
| 4 | Subject: [PATCH] [release-branch.go1.22] net/textproto, mime/multipart: avoid | ||
| 5 | unbounded read in MIME header | ||
| 6 | |||
| 7 | mime/multipart.Reader.ReadForm allows specifying the maximum amount | ||
| 8 | of memory that will be consumed by the form. While this limit is | ||
| 9 | correctly applied to the parsed form data structure, it was not | ||
| 10 | being applied to individual header lines in a form. | ||
| 11 | |||
| 12 | For example, when presented with a form containing a header line | ||
| 13 | that never ends, ReadForm will continue to read the line until it | ||
| 14 | runs out of memory. | ||
| 15 | |||
| 16 | Limit the amount of data consumed when reading a header. | ||
| 17 | |||
| 18 | Fixes CVE-2023-45290 | ||
| 19 | Fixes #65850 | ||
| 20 | For #65383 | ||
| 21 | |||
| 22 | Change-Id: I7f9264d25752009e95f6b2c80e3d76aaf321d658 | ||
| 23 | Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2134435 | ||
| 24 | Reviewed-by: Roland Shoemaker <bracewell@google.com> | ||
| 25 | Reviewed-by: Tatiana Bradley <tatianabradley@google.com> | ||
| 26 | Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2174345 | ||
| 27 | Reviewed-by: Carlos Amedee <amedee@google.com> | ||
| 28 | Reviewed-on: https://go-review.googlesource.com/c/go/+/569237 | ||
| 29 | Reviewed-by: Carlos Amedee <carlos@golang.org> | ||
| 30 | LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> | ||
| 31 | Auto-Submit: Michael Knyszek <mknyszek@google.com> | ||
| 32 | |||
| 33 | Upstream-Status: Backport [https://github.com/golang/go/commit/041a47712e765e94f86d841c3110c840e76d8f82] | ||
| 34 | CVE: CVE-2023-45290 | ||
| 35 | Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>--- | ||
| 36 | src/mime/multipart/formdata_test.go | 42 +++++++++++++++++++++++++ | ||
| 37 | src/net/textproto/reader.go | 48 ++++++++++++++++++++--------- | ||
| 38 | src/net/textproto/reader_test.go | 12 ++++++++ | ||
| 39 | 3 files changed, 87 insertions(+), 15 deletions(-) | ||
| 40 | |||
| 41 | diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go | ||
| 42 | index c78eeb7..f729da6 100644 | ||
| 43 | --- a/src/mime/multipart/formdata_test.go | ||
| 44 | +++ b/src/mime/multipart/formdata_test.go | ||
| 45 | @@ -421,6 +421,48 @@ func TestReadFormLimits(t *testing.T) { | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | +func TestReadFormEndlessHeaderLine(t *testing.T) { | ||
| 50 | + for _, test := range []struct { | ||
| 51 | + name string | ||
| 52 | + prefix string | ||
| 53 | + }{{ | ||
| 54 | + name: "name", | ||
| 55 | + prefix: "X-", | ||
| 56 | + }, { | ||
| 57 | + name: "value", | ||
| 58 | + prefix: "X-Header: ", | ||
| 59 | + }, { | ||
| 60 | + name: "continuation", | ||
| 61 | + prefix: "X-Header: foo\r\n ", | ||
| 62 | + }} { | ||
| 63 | + t.Run(test.name, func(t *testing.T) { | ||
| 64 | + const eol = "\r\n" | ||
| 65 | + s := `--boundary` + eol | ||
| 66 | + s += `Content-Disposition: form-data; name="a"` + eol | ||
| 67 | + s += `Content-Type: text/plain` + eol | ||
| 68 | + s += test.prefix | ||
| 69 | + fr := io.MultiReader( | ||
| 70 | + strings.NewReader(s), | ||
| 71 | + neverendingReader('X'), | ||
| 72 | + ) | ||
| 73 | + r := NewReader(fr, "boundary") | ||
| 74 | + _, err := r.ReadForm(1 << 20) | ||
| 75 | + if err != ErrMessageTooLarge { | ||
| 76 | + t.Fatalf("ReadForm(1 << 20): %v, want ErrMessageTooLarge", err) | ||
| 77 | + } | ||
| 78 | + }) | ||
| 79 | + } | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +type neverendingReader byte | ||
| 83 | + | ||
| 84 | +func (r neverendingReader) Read(p []byte) (n int, err error) { | ||
| 85 | + for i := range p { | ||
| 86 | + p[i] = byte(r) | ||
| 87 | + } | ||
| 88 | + return len(p), nil | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | func BenchmarkReadForm(b *testing.B) { | ||
| 92 | for _, test := range []struct { | ||
| 93 | name string | ||
| 94 | diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go | ||
| 95 | index c6569c8..3ac4d4d 100644 | ||
| 96 | --- a/src/net/textproto/reader.go | ||
| 97 | +++ b/src/net/textproto/reader.go | ||
| 98 | @@ -16,6 +16,10 @@ import ( | ||
| 99 | "sync" | ||
| 100 | ) | ||
| 101 | |||
| 102 | +// TODO: This should be a distinguishable error (ErrMessageTooLarge) | ||
| 103 | +// to allow mime/multipart to detect it. | ||
| 104 | +var errMessageTooLarge = errors.New("message too large") | ||
| 105 | + | ||
| 106 | // A Reader implements convenience methods for reading requests | ||
| 107 | // or responses from a text protocol network connection. | ||
| 108 | type Reader struct { | ||
| 109 | @@ -37,13 +41,13 @@ func NewReader(r *bufio.Reader) *Reader { | ||
| 110 | // ReadLine reads a single line from r, | ||
| 111 | // eliding the final \n or \r\n from the returned string. | ||
| 112 | func (r *Reader) ReadLine() (string, error) { | ||
| 113 | - line, err := r.readLineSlice() | ||
| 114 | + line, err := r.readLineSlice(-1) | ||
| 115 | return string(line), err | ||
| 116 | } | ||
| 117 | |||
| 118 | // ReadLineBytes is like ReadLine but returns a []byte instead of a string. | ||
| 119 | func (r *Reader) ReadLineBytes() ([]byte, error) { | ||
| 120 | - line, err := r.readLineSlice() | ||
| 121 | + line, err := r.readLineSlice(-1) | ||
| 122 | if line != nil { | ||
| 123 | buf := make([]byte, len(line)) | ||
| 124 | copy(buf, line) | ||
| 125 | @@ -52,7 +56,10 @@ func (r *Reader) ReadLineBytes() ([]byte, error) { | ||
| 126 | return line, err | ||
| 127 | } | ||
| 128 | |||
| 129 | -func (r *Reader) readLineSlice() ([]byte, error) { | ||
| 130 | +// readLineSlice reads a single line from r, | ||
| 131 | +// up to lim bytes long (or unlimited if lim is less than 0), | ||
| 132 | +// eliding the final \r or \r\n from the returned string. | ||
| 133 | +func (r *Reader) readLineSlice(lim int64) ([]byte, error) { | ||
| 134 | r.closeDot() | ||
| 135 | var line []byte | ||
| 136 | for { | ||
| 137 | @@ -60,6 +67,9 @@ func (r *Reader) readLineSlice() ([]byte, error) { | ||
| 138 | if err != nil { | ||
| 139 | return nil, err | ||
| 140 | } | ||
| 141 | + if lim >= 0 && int64(len(line))+int64(len(l)) > lim { | ||
| 142 | + return nil, errMessageTooLarge | ||
| 143 | + } | ||
| 144 | // Avoid the copy if the first call produced a full line. | ||
| 145 | if line == nil && !more { | ||
| 146 | return l, nil | ||
| 147 | @@ -92,7 +102,7 @@ func (r *Reader) readLineSlice() ([]byte, error) { | ||
| 148 | // Empty lines are never continued. | ||
| 149 | // | ||
| 150 | func (r *Reader) ReadContinuedLine() (string, error) { | ||
| 151 | - line, err := r.readContinuedLineSlice(noValidation) | ||
| 152 | + line, err := r.readContinuedLineSlice(-1, noValidation) | ||
| 153 | return string(line), err | ||
| 154 | } | ||
| 155 | |||
| 156 | @@ -113,7 +123,7 @@ func trim(s []byte) []byte { | ||
| 157 | // ReadContinuedLineBytes is like ReadContinuedLine but | ||
| 158 | // returns a []byte instead of a string. | ||
| 159 | func (r *Reader) ReadContinuedLineBytes() ([]byte, error) { | ||
| 160 | - line, err := r.readContinuedLineSlice(noValidation) | ||
| 161 | + line, err := r.readContinuedLineSlice(-1, noValidation) | ||
| 162 | if line != nil { | ||
| 163 | buf := make([]byte, len(line)) | ||
| 164 | copy(buf, line) | ||
| 165 | @@ -126,13 +136,14 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) { | ||
| 166 | // returning a byte slice with all lines. The validateFirstLine function | ||
| 167 | // is run on the first read line, and if it returns an error then this | ||
| 168 | // error is returned from readContinuedLineSlice. | ||
| 169 | -func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([]byte, error) { | ||
| 170 | +// It reads up to lim bytes of data (or unlimited if lim is less than 0). | ||
| 171 | +func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) { | ||
| 172 | if validateFirstLine == nil { | ||
| 173 | return nil, fmt.Errorf("missing validateFirstLine func") | ||
| 174 | } | ||
| 175 | |||
| 176 | // Read the first line. | ||
| 177 | - line, err := r.readLineSlice() | ||
| 178 | + line, err := r.readLineSlice(lim) | ||
| 179 | if err != nil { | ||
| 180 | return nil, err | ||
| 181 | } | ||
| 182 | @@ -160,13 +171,21 @@ func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([ | ||
| 183 | // copy the slice into buf. | ||
| 184 | r.buf = append(r.buf[:0], trim(line)...) | ||
| 185 | |||
| 186 | + if lim < 0 { | ||
| 187 | + lim = math.MaxInt64 | ||
| 188 | + } | ||
| 189 | + lim -= int64(len(r.buf)) | ||
| 190 | + | ||
| 191 | // Read continuation lines. | ||
| 192 | for r.skipSpace() > 0 { | ||
| 193 | - line, err := r.readLineSlice() | ||
| 194 | + r.buf = append(r.buf, ' ') | ||
| 195 | + if int64(len(r.buf)) >= lim { | ||
| 196 | + return nil, errMessageTooLarge | ||
| 197 | + } | ||
| 198 | + line, err := r.readLineSlice(lim - int64(len(r.buf))) | ||
| 199 | if err != nil { | ||
| 200 | break | ||
| 201 | } | ||
| 202 | - r.buf = append(r.buf, ' ') | ||
| 203 | r.buf = append(r.buf, trim(line)...) | ||
| 204 | } | ||
| 205 | return r.buf, nil | ||
| 206 | @@ -511,7 +530,8 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) | ||
| 207 | |||
| 208 | // The first line cannot start with a leading space. | ||
| 209 | if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') { | ||
| 210 | - line, err := r.readLineSlice() | ||
| 211 | + const errorLimit = 80 // arbitrary limit on how much of the line we'll quote | ||
| 212 | + line, err := r.readLineSlice(errorLimit) | ||
| 213 | if err != nil { | ||
| 214 | return m, err | ||
| 215 | } | ||
| 216 | @@ -519,7 +539,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) | ||
| 217 | } | ||
| 218 | |||
| 219 | for { | ||
| 220 | - kv, err := r.readContinuedLineSlice(mustHaveFieldNameColon) | ||
| 221 | + kv, err := r.readContinuedLineSlice(maxMemory, mustHaveFieldNameColon) | ||
| 222 | if len(kv) == 0 { | ||
| 223 | return m, err | ||
| 224 | } | ||
| 225 | @@ -540,7 +560,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) | ||
| 226 | |||
| 227 | maxHeaders-- | ||
| 228 | if maxHeaders < 0 { | ||
| 229 | - return nil, errors.New("message too large") | ||
| 230 | + return nil, errMessageTooLarge | ||
| 231 | } | ||
| 232 | |||
| 233 | // backport 5c55ac9bf1e5f779220294c843526536605f42ab | ||
| 234 | @@ -567,9 +587,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) | ||
| 235 | } | ||
| 236 | maxMemory -= int64(len(value)) | ||
| 237 | if maxMemory < 0 { | ||
| 238 | - // TODO: This should be a distinguishable error (ErrMessageTooLarge) | ||
| 239 | - // to allow mime/multipart to detect it. | ||
| 240 | - return m, errors.New("message too large") | ||
| 241 | + return m, errMessageTooLarge | ||
| 242 | } | ||
| 243 | if vv == nil && len(strs) > 0 { | ||
| 244 | // More than likely this will be a single-element key. | ||
| 245 | diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go | ||
| 246 | index 3ae0de1..db1ed91 100644 | ||
| 247 | --- a/src/net/textproto/reader_test.go | ||
| 248 | +++ b/src/net/textproto/reader_test.go | ||
| 249 | @@ -34,6 +34,18 @@ func TestReadLine(t *testing.T) { | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | +func TestReadLineLongLine(t *testing.T) { | ||
| 254 | + line := strings.Repeat("12345", 10000) | ||
| 255 | + r := reader(line + "\r\n") | ||
| 256 | + s, err := r.ReadLine() | ||
| 257 | + if err != nil { | ||
| 258 | + t.Fatalf("Line 1: %v", err) | ||
| 259 | + } | ||
| 260 | + if s != line { | ||
| 261 | + t.Fatalf("%v-byte line does not match expected %v-byte line", len(s), len(line)) | ||
| 262 | + } | ||
| 263 | +} | ||
| 264 | + | ||
| 265 | func TestReadContinuedLine(t *testing.T) { | ||
| 266 | r := reader("line1\nline\n 2\nline3\n") | ||
| 267 | s, err := r.ReadContinuedLine() | ||
| 268 | -- | ||
| 269 | 2.25.1 | ||
| 270 | |||
