diff --git a/backport-0001-release-branch.go1.21-crypto-x509-make-sure-pub-key-.patch b/backport-0001-release-branch.go1.21-crypto-x509-make-sure-pub-key-.patch deleted file mode 100644 index 7ee3178954539d2f4be6d3d16c008c9137cca16a..0000000000000000000000000000000000000000 --- a/backport-0001-release-branch.go1.21-crypto-x509-make-sure-pub-key-.patch +++ /dev/null @@ -1,78 +0,0 @@ -From 5dfc2e6c42724349a9e9ecbcc69be920c18d90e9 Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Thu, 18 Jan 2024 12:51:13 -0800 -Subject: [PATCH 1/4] [release-branch.go1.21] crypto/x509: make sure pub key is - non-nil before interface conversion - -alreadyInChain assumes all keys fit a interface which contains the -Equal method (which they do), but this ignores that certificates may -have a nil key when PublicKeyAlgorithm is UnknownPublicKeyAlgorithm. In -this case alreadyInChain panics. - -Check that the key is non-nil as part of considerCandidate (we are never -going to build a chain containing UnknownPublicKeyAlgorithm anyway). - -For #65390 -Fixes #65392 -Fixes CVE-2024-24783 - -Change-Id: Ibdccc0a487e3368b6812be35daad2512220243f3 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2137282 -Reviewed-by: Damien Neil -Run-TryBot: Roland Shoemaker -Reviewed-by: Tatiana Bradley -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173774 -Reviewed-by: Roland Shoemaker -Reviewed-by: Carlos Amedee -Reviewed-on: https://go-review.googlesource.com/c/go/+/569238 -Auto-Submit: Michael Knyszek -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Carlos Amedee ---- - src/crypto/x509/verify.go | 2 +- - src/crypto/x509/verify_test.go | 19 +++++++++++++++++++ - 2 files changed, 20 insertions(+), 1 deletion(-) - -diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go -index 345d434453c..56a1a1725cc 100644 ---- a/src/crypto/x509/verify.go -+++ b/src/crypto/x509/verify.go -@@ -899,7 +899,7 @@ func (c *Certificate) buildChains(currentChain []*Certificate, sigChecks *int, o - ) - - considerCandidate := func(certType int, candidate *Certificate) { -- if alreadyInChain(candidate, currentChain) { -+ if candidate.PublicKey == nil || alreadyInChain(candidate, currentChain) { - return - } - -diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go -index 3551b470ced..d8678d03f93 100644 ---- a/src/crypto/x509/verify_test.go -+++ b/src/crypto/x509/verify_test.go -@@ -2693,3 +2693,22 @@ func TestVerifyEKURootAsLeaf(t *testing.T) { - } - - } -+ -+func TestVerifyNilPubKey(t *testing.T) { -+ c := &Certificate{ -+ RawIssuer: []byte{1, 2, 3}, -+ AuthorityKeyId: []byte{1, 2, 3}, -+ } -+ opts := &VerifyOptions{} -+ opts.Roots = NewCertPool() -+ r := &Certificate{ -+ RawSubject: []byte{1, 2, 3}, -+ SubjectKeyId: []byte{1, 2, 3}, -+ } -+ opts.Roots.AddCert(r) -+ -+ _, err := c.buildChains([]*Certificate{r}, nil, opts) -+ if _, ok := err.(UnknownAuthorityError); !ok { -+ t.Fatalf("buildChains returned unexpected error, got: %v, want %v", err, UnknownAuthorityError{}) -+ } -+} --- -2.33.0 - diff --git a/backport-0002-release-branch.go1.21-html-template-escape-additiona.patch b/backport-0002-release-branch.go1.21-html-template-escape-additiona.patch deleted file mode 100644 index 403cf6be5088fd97556b3871884641a3afa75d72..0000000000000000000000000000000000000000 --- a/backport-0002-release-branch.go1.21-html-template-escape-additiona.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 0787ee55dd0d42dd8bef97d4e7ed7584f44c16e9 Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Wed, 14 Feb 2024 17:18:36 -0800 -Subject: [PATCH 2/4] [release-branch.go1.21] html/template: escape additional - tokens in MarshalJSON errors - -Escape " -Reviewed-by: Damien Neil -(cherry picked from commit ccbc725f2d678255df1bd326fa511a492aa3a0aa) -Reviewed-on: https://go-review.googlesource.com/c/go/+/567515 -Reviewed-by: Carlos Amedee ---- - src/html/template/js.go | 22 ++++++++- - src/html/template/js_test.go | 96 ++++++++++++++++++++---------------- - 2 files changed, 74 insertions(+), 44 deletions(-) - -diff --git a/src/html/template/js.go b/src/html/template/js.go -index 4e05c145572..f4d1303bebe 100644 ---- a/src/html/template/js.go -+++ b/src/html/template/js.go -@@ -171,13 +171,31 @@ func jsValEscaper(args ...any) string { - // cyclic data. This may be an unacceptable DoS risk. - b, err := json.Marshal(a) - if err != nil { -- // Put a space before comment so that if it is flush against -+ // While the standard JSON marshaller does not include user controlled -+ // information in the error message, if a type has a MarshalJSON method, -+ // the content of the error message is not guaranteed. Since we insert -+ // the error into the template, as part of a comment, we attempt to -+ // prevent the error from either terminating the comment, or the script -+ // block itself. -+ // -+ // In particular we: -+ // * replace "*/" comment end tokens with "* /", which does not -+ // terminate the comment -+ // * replace " 1 so this loses precision in JS - // but it is still a representable integer literal. -- {uint64(1)<<53 + 1, " 9007199254740993 "}, -- {float32(1.0), " 1 "}, -- {float32(-1.0), " -1 "}, -- {float32(0.5), " 0.5 "}, -- {float32(-0.5), " -0.5 "}, -- {float32(1.0) / float32(256), " 0.00390625 "}, -- {float32(0), " 0 "}, -- {math.Copysign(0, -1), " -0 "}, -- {float64(1.0), " 1 "}, -- {float64(-1.0), " -1 "}, -- {float64(0.5), " 0.5 "}, -- {float64(-0.5), " -0.5 "}, -- {float64(0), " 0 "}, -- {math.Copysign(0, -1), " -0 "}, -- {"", `""`}, -- {"foo", `"foo"`}, -+ {uint64(1)<<53 + 1, " 9007199254740993 ", false}, -+ {float32(1.0), " 1 ", false}, -+ {float32(-1.0), " -1 ", false}, -+ {float32(0.5), " 0.5 ", false}, -+ {float32(-0.5), " -0.5 ", false}, -+ {float32(1.0) / float32(256), " 0.00390625 ", false}, -+ {float32(0), " 0 ", false}, -+ {math.Copysign(0, -1), " -0 ", false}, -+ {float64(1.0), " 1 ", false}, -+ {float64(-1.0), " -1 ", false}, -+ {float64(0.5), " 0.5 ", false}, -+ {float64(-0.5), " -0.5 ", false}, -+ {float64(0), " 0 ", false}, -+ {math.Copysign(0, -1), " -0 ", false}, -+ {"", `""`, false}, -+ {"foo", `"foo"`, false}, - // Newlines. -- {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`}, -+ {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`, false}, - // "\v" == "v" on IE 6 so use "\u000b" instead. -- {"\t\x0b", `"\t\u000b"`}, -- {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`}, -- {[]any{}, "[]"}, -- {[]any{42, "foo", nil}, `[42,"foo",null]`}, -- {[]string{""}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`}, -- {"", `"--\u003e"`}, -- {"", `"]]\u003e"`}, -- {"", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`, false}, -+ {"", `"--\u003e"`, false}, -+ {"", `"]]\u003e"`, false}, -+ {" -Date: Tue, 16 Jan 2024 15:37:52 -0800 -Subject: [PATCH 3/4] [release-branch.go1.21] net/textproto, mime/multipart: - avoid unbounded read in MIME header - -mime/multipart.Reader.ReadForm allows specifying the maximum amount -of memory that will be consumed by the form. While this limit is -correctly applied to the parsed form data structure, it was not -being applied to individual header lines in a form. - -For example, when presented with a form containing a header line -that never ends, ReadForm will continue to read the line until it -runs out of memory. - -Limit the amount of data consumed when reading a header. - -Fixes CVE-2023-45290 -Fixes #65389 -For #65383 - -Change-Id: I7f9264d25752009e95f6b2c80e3d76aaf321d658 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2134435 -Reviewed-by: Roland Shoemaker -Reviewed-by: Tatiana Bradley -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173776 -Reviewed-by: Carlos Amedee -Reviewed-on: https://go-review.googlesource.com/c/go/+/569240 -Auto-Submit: Michael Knyszek -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Carlos Amedee ---- - src/mime/multipart/formdata_test.go | 42 +++++++++++++++++++++++++ - src/net/textproto/reader.go | 48 ++++++++++++++++++++--------- - src/net/textproto/reader_test.go | 12 ++++++++ - 3 files changed, 87 insertions(+), 15 deletions(-) - -diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go -index d422729c96a..bfa9f683825 100644 ---- a/src/mime/multipart/formdata_test.go -+++ b/src/mime/multipart/formdata_test.go -@@ -452,6 +452,48 @@ func TestReadFormLimits(t *testing.T) { - } - } - -+func TestReadFormEndlessHeaderLine(t *testing.T) { -+ for _, test := range []struct { -+ name string -+ prefix string -+ }{{ -+ name: "name", -+ prefix: "X-", -+ }, { -+ name: "value", -+ prefix: "X-Header: ", -+ }, { -+ name: "continuation", -+ prefix: "X-Header: foo\r\n ", -+ }} { -+ t.Run(test.name, func(t *testing.T) { -+ const eol = "\r\n" -+ s := `--boundary` + eol -+ s += `Content-Disposition: form-data; name="a"` + eol -+ s += `Content-Type: text/plain` + eol -+ s += test.prefix -+ fr := io.MultiReader( -+ strings.NewReader(s), -+ neverendingReader('X'), -+ ) -+ r := NewReader(fr, "boundary") -+ _, err := r.ReadForm(1 << 20) -+ if err != ErrMessageTooLarge { -+ t.Fatalf("ReadForm(1 << 20): %v, want ErrMessageTooLarge", err) -+ } -+ }) -+ } -+} -+ -+type neverendingReader byte -+ -+func (r neverendingReader) Read(p []byte) (n int, err error) { -+ for i := range p { -+ p[i] = byte(r) -+ } -+ return len(p), nil -+} -+ - func BenchmarkReadForm(b *testing.B) { - for _, test := range []struct { - name string -diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go -index fc2590b1cdc..fcd1a011ac7 100644 ---- a/src/net/textproto/reader.go -+++ b/src/net/textproto/reader.go -@@ -16,6 +16,10 @@ import ( - "sync" - ) - -+// TODO: This should be a distinguishable error (ErrMessageTooLarge) -+// to allow mime/multipart to detect it. -+var errMessageTooLarge = errors.New("message too large") -+ - // A Reader implements convenience methods for reading requests - // or responses from a text protocol network connection. - type Reader struct { -@@ -36,20 +40,23 @@ func NewReader(r *bufio.Reader) *Reader { - // ReadLine reads a single line from r, - // eliding the final \n or \r\n from the returned string. - func (r *Reader) ReadLine() (string, error) { -- line, err := r.readLineSlice() -+ line, err := r.readLineSlice(-1) - return string(line), err - } - - // ReadLineBytes is like ReadLine but returns a []byte instead of a string. - func (r *Reader) ReadLineBytes() ([]byte, error) { -- line, err := r.readLineSlice() -+ line, err := r.readLineSlice(-1) - if line != nil { - line = bytes.Clone(line) - } - return line, err - } - --func (r *Reader) readLineSlice() ([]byte, error) { -+// readLineSlice reads a single line from r, -+// up to lim bytes long (or unlimited if lim is less than 0), -+// eliding the final \r or \r\n from the returned string. -+func (r *Reader) readLineSlice(lim int64) ([]byte, error) { - r.closeDot() - var line []byte - for { -@@ -57,6 +64,9 @@ func (r *Reader) readLineSlice() ([]byte, error) { - if err != nil { - return nil, err - } -+ if lim >= 0 && int64(len(line))+int64(len(l)) > lim { -+ return nil, errMessageTooLarge -+ } - // Avoid the copy if the first call produced a full line. - if line == nil && !more { - return l, nil -@@ -88,7 +98,7 @@ func (r *Reader) readLineSlice() ([]byte, error) { - // - // Empty lines are never continued. - func (r *Reader) ReadContinuedLine() (string, error) { -- line, err := r.readContinuedLineSlice(noValidation) -+ line, err := r.readContinuedLineSlice(-1, noValidation) - return string(line), err - } - -@@ -109,7 +119,7 @@ func trim(s []byte) []byte { - // ReadContinuedLineBytes is like ReadContinuedLine but - // returns a []byte instead of a string. - func (r *Reader) ReadContinuedLineBytes() ([]byte, error) { -- line, err := r.readContinuedLineSlice(noValidation) -+ line, err := r.readContinuedLineSlice(-1, noValidation) - if line != nil { - line = bytes.Clone(line) - } -@@ -120,13 +130,14 @@ func (r *Reader) ReadContinuedLineBytes() ([]byte, error) { - // returning a byte slice with all lines. The validateFirstLine function - // is run on the first read line, and if it returns an error then this - // error is returned from readContinuedLineSlice. --func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([]byte, error) { -+// It reads up to lim bytes of data (or unlimited if lim is less than 0). -+func (r *Reader) readContinuedLineSlice(lim int64, validateFirstLine func([]byte) error) ([]byte, error) { - if validateFirstLine == nil { - return nil, fmt.Errorf("missing validateFirstLine func") - } - - // Read the first line. -- line, err := r.readLineSlice() -+ line, err := r.readLineSlice(lim) - if err != nil { - return nil, err - } -@@ -154,13 +165,21 @@ func (r *Reader) readContinuedLineSlice(validateFirstLine func([]byte) error) ([ - // copy the slice into buf. - r.buf = append(r.buf[:0], trim(line)...) - -+ if lim < 0 { -+ lim = math.MaxInt64 -+ } -+ lim -= int64(len(r.buf)) -+ - // Read continuation lines. - for r.skipSpace() > 0 { -- line, err := r.readLineSlice() -+ r.buf = append(r.buf, ' ') -+ if int64(len(r.buf)) >= lim { -+ return nil, errMessageTooLarge -+ } -+ line, err := r.readLineSlice(lim - int64(len(r.buf))) - if err != nil { - break - } -- r.buf = append(r.buf, ' ') - r.buf = append(r.buf, trim(line)...) - } - return r.buf, nil -@@ -507,7 +526,8 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) - - // The first line cannot start with a leading space. - if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') { -- line, err := r.readLineSlice() -+ const errorLimit = 80 // arbitrary limit on how much of the line we'll quote -+ line, err := r.readLineSlice(errorLimit) - if err != nil { - return m, err - } -@@ -515,7 +535,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) - } - - for { -- kv, err := r.readContinuedLineSlice(mustHaveFieldNameColon) -+ kv, err := r.readContinuedLineSlice(maxMemory, mustHaveFieldNameColon) - if len(kv) == 0 { - return m, err - } -@@ -544,7 +564,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) - - maxHeaders-- - if maxHeaders < 0 { -- return nil, errors.New("message too large") -+ return nil, errMessageTooLarge - } - - // Skip initial spaces in value. -@@ -557,9 +577,7 @@ func readMIMEHeader(r *Reader, maxMemory, maxHeaders int64) (MIMEHeader, error) - } - maxMemory -= int64(len(value)) - if maxMemory < 0 { -- // TODO: This should be a distinguishable error (ErrMessageTooLarge) -- // to allow mime/multipart to detect it. -- return m, errors.New("message too large") -+ return m, errMessageTooLarge - } - if vv == nil && len(strs) > 0 { - // More than likely this will be a single-element key. -diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go -index 696ae406f38..26ff617470b 100644 ---- a/src/net/textproto/reader_test.go -+++ b/src/net/textproto/reader_test.go -@@ -36,6 +36,18 @@ func TestReadLine(t *testing.T) { - } - } - -+func TestReadLineLongLine(t *testing.T) { -+ line := strings.Repeat("12345", 10000) -+ r := reader(line + "\r\n") -+ s, err := r.ReadLine() -+ if err != nil { -+ t.Fatalf("Line 1: %v", err) -+ } -+ if s != line { -+ t.Fatalf("%v-byte line does not match expected %v-byte line", len(s), len(line)) -+ } -+} -+ - func TestReadContinuedLine(t *testing.T) { - r := reader("line1\nline\n 2\nline3\n") - s, err := r.ReadContinuedLine() --- -2.33.0 - diff --git a/backport-0004-release-branch.go1.21-net-http-net-http-cookiejar-av.patch b/backport-0004-release-branch.go1.21-net-http-net-http-cookiejar-av.patch deleted file mode 100644 index db25f1e17f2c3a6a2eb7dd1ff3330add6693d8a7..0000000000000000000000000000000000000000 --- a/backport-0004-release-branch.go1.21-net-http-net-http-cookiejar-av.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 6021dca711926c32959c2dc4c2a68c9494e9a4fc Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Thu, 11 Jan 2024 11:31:57 -0800 -Subject: [PATCH 4/4] [release-branch.go1.21] net/http, net/http/cookiejar: - avoid subdomain matches on IPv6 zones - -When deciding whether to forward cookies or sensitive headers -across a redirect, do not attempt to interpret an IPv6 address -as a domain name. - -Avoids a case where a maliciously-crafted redirect to an -IPv6 address with a scoped addressing zone could be -misinterpreted as a within-domain redirect. For example, -we could interpret "::1%.www.example.com" as a subdomain -of "www.example.com". - -Thanks to Juho Nurminen of Mattermost for reporting this issue. - -Fixes CVE-2023-45289 -Fixes #65385 -For #65065 - -Change-Id: I8f463f59f0e700c8a18733d2b264a8bcb3a19599 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2131938 -Reviewed-by: Tatiana Bradley -Reviewed-by: Roland Shoemaker -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2173775 -Reviewed-by: Carlos Amedee -Reviewed-on: https://go-review.googlesource.com/c/go/+/569239 -Reviewed-by: Carlos Amedee -Auto-Submit: Michael Knyszek -TryBot-Bypass: Michael Knyszek ---- - src/net/http/client.go | 6 ++++++ - src/net/http/client_test.go | 1 + - src/net/http/cookiejar/jar.go | 7 +++++++ - src/net/http/cookiejar/jar_test.go | 10 ++++++++++ - 4 files changed, 24 insertions(+) - -diff --git a/src/net/http/client.go b/src/net/http/client.go -index 2cab53a585a..77a701b8061 100644 ---- a/src/net/http/client.go -+++ b/src/net/http/client.go -@@ -1014,6 +1014,12 @@ func isDomainOrSubdomain(sub, parent string) bool { - if sub == parent { - return true - } -+ // If sub contains a :, it's probably an IPv6 address (and is definitely not a hostname). -+ // Don't check the suffix in this case, to avoid matching the contents of a IPv6 zone. -+ // For example, "::1%.www.example.com" is not a subdomain of "www.example.com". -+ if strings.ContainsAny(sub, ":%") { -+ return false -+ } - // If sub is "foo.example.com" and parent is "example.com", - // that means sub must end in "."+parent. - // Do it without allocating. -diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go -index 0fe555af38f..fc1d7916124 100644 ---- a/src/net/http/client_test.go -+++ b/src/net/http/client_test.go -@@ -1725,6 +1725,7 @@ func TestShouldCopyHeaderOnRedirect(t *testing.T) { - {"authorization", "http://foo.com/", "https://foo.com/", true}, - {"authorization", "http://foo.com:1234/", "http://foo.com:4321/", true}, - {"www-authenticate", "http://foo.com/", "http://bar.com/", false}, -+ {"authorization", "http://foo.com/", "http://[::1%25.foo.com]/", false}, - - // But subdomains should work: - {"www-authenticate", "http://foo.com/", "http://foo.com/", true}, -diff --git a/src/net/http/cookiejar/jar.go b/src/net/http/cookiejar/jar.go -index 273b54c84c7..4b16266057b 100644 ---- a/src/net/http/cookiejar/jar.go -+++ b/src/net/http/cookiejar/jar.go -@@ -362,6 +362,13 @@ func jarKey(host string, psl PublicSuffixList) string { - - // isIP reports whether host is an IP address. - func isIP(host string) bool { -+ if strings.ContainsAny(host, ":%") { -+ // Probable IPv6 address. -+ // Hostnames can't contain : or %, so this is definitely not a valid host. -+ // Treating it as an IP is the more conservative option, and avoids the risk -+ // of interpeting ::1%.www.example.com as a subtomain of www.example.com. -+ return true -+ } - return net.ParseIP(host) != nil - } - -diff --git a/src/net/http/cookiejar/jar_test.go b/src/net/http/cookiejar/jar_test.go -index 56d0695a660..251f7c16171 100644 ---- a/src/net/http/cookiejar/jar_test.go -+++ b/src/net/http/cookiejar/jar_test.go -@@ -252,6 +252,7 @@ var isIPTests = map[string]bool{ - "127.0.0.1": true, - "1.2.3.4": true, - "2001:4860:0:2001::68": true, -+ "::1%zone": true, - "example.com": false, - "1.1.1.300": false, - "www.foo.bar.net": false, -@@ -629,6 +630,15 @@ var basicsTests = [...]jarTest{ - {"http://www.host.test:1234/", "a=1"}, - }, - }, -+ { -+ "IPv6 zone is not treated as a host.", -+ "https://example.com/", -+ []string{"a=1"}, -+ "a=1", -+ []query{ -+ {"https://[::1%25.example.com]:80/", ""}, -+ }, -+ }, - } - - func TestBasics(t *testing.T) { --- -2.33.0 - diff --git a/backport-0005-release-branch.go1.21-net-mail-properly-handle-speci.patch b/backport-0005-release-branch.go1.21-net-mail-properly-handle-speci.patch deleted file mode 100644 index fc7b26cbdba9a208f3b2b0e0ff1b998e2105de43..0000000000000000000000000000000000000000 --- a/backport-0005-release-branch.go1.21-net-mail-properly-handle-speci.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 11c0f19796e30484848a6c9c469364c0841c17ef Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Wed, 10 Jan 2024 11:02:14 -0800 -Subject: [PATCH] [release-branch.go1.21] net/mail: properly handle special - characters in phrase and obs-phrase - -Fixes a couple of misalignments with RFC 5322 which introduce -significant diffs between (mostly) conformant parsers. - -This change reverts the changes made in CL50911, which allowed certain -special RFC 5322 characters to appear unquoted in the "phrase" syntax. -It is unclear why this change was made in the first place, and created -a divergence from comformant parsers. In particular this resulted in -treating comments in display names incorrectly. - -Additionally properly handle trailing malformed comments in the group -syntax. - -For #65083 -Fixes #65848 - -Change-Id: I00dddc044c6ae3381154e43236632604c390f672 -Reviewed-on: https://go-review.googlesource.com/c/go/+/555596 -Reviewed-by: Damien Neil -LUCI-TryBot-Result: Go LUCI -Reviewed-on: https://go-review.googlesource.com/c/go/+/566195 -Reviewed-by: Carlos Amedee ---- - src/net/mail/message.go | 30 +++++++++++++++------------ - src/net/mail/message_test.go | 40 ++++++++++++++++++++++++++---------- - 2 files changed, 46 insertions(+), 24 deletions(-) - -diff --git a/src/net/mail/message.go b/src/net/mail/message.go -index af516fc30f..fc2a9e46f8 100644 ---- a/src/net/mail/message.go -+++ b/src/net/mail/message.go -@@ -280,7 +280,7 @@ func (a *Address) String() string { - // Add quotes if needed - quoteLocal := false - for i, r := range local { -- if isAtext(r, false, false) { -+ if isAtext(r, false) { - continue - } - if r == '.' { -@@ -444,7 +444,7 @@ func (p *addrParser) parseAddress(handleGroup bool) ([]*Address, error) { - if !p.consume('<') { - atext := true - for _, r := range displayName { -- if !isAtext(r, true, false) { -+ if !isAtext(r, true) { - atext = false - break - } -@@ -479,7 +479,9 @@ func (p *addrParser) consumeGroupList() ([]*Address, error) { - // handle empty group. - p.skipSpace() - if p.consume(';') { -- p.skipCFWS() -+ if !p.skipCFWS() { -+ return nil, errors.New("mail: misformatted parenthetical comment") -+ } - return group, nil - } - -@@ -496,7 +498,9 @@ func (p *addrParser) consumeGroupList() ([]*Address, error) { - return nil, errors.New("mail: misformatted parenthetical comment") - } - if p.consume(';') { -- p.skipCFWS() -+ if !p.skipCFWS() { -+ return nil, errors.New("mail: misformatted parenthetical comment") -+ } - break - } - if !p.consume(',') { -@@ -566,6 +570,12 @@ func (p *addrParser) consumePhrase() (phrase string, err error) { - var words []string - var isPrevEncoded bool - for { -+ // obs-phrase allows CFWS after one word -+ if len(words) > 0 { -+ if !p.skipCFWS() { -+ return "", errors.New("mail: misformatted parenthetical comment") -+ } -+ } - // word = atom / quoted-string - var word string - p.skipSpace() -@@ -661,7 +671,6 @@ Loop: - // If dot is true, consumeAtom parses an RFC 5322 dot-atom instead. - // If permissive is true, consumeAtom will not fail on: - // - leading/trailing/double dots in the atom (see golang.org/issue/4938) --// - special characters (RFC 5322 3.2.3) except '<', '>', ':' and '"' (see golang.org/issue/21018) - func (p *addrParser) consumeAtom(dot bool, permissive bool) (atom string, err error) { - i := 0 - -@@ -672,7 +681,7 @@ Loop: - case size == 1 && r == utf8.RuneError: - return "", fmt.Errorf("mail: invalid utf-8 in address: %q", p.s) - -- case size == 0 || !isAtext(r, dot, permissive): -+ case size == 0 || !isAtext(r, dot): - break Loop - - default: -@@ -850,18 +859,13 @@ func (e charsetError) Error() string { - - // isAtext reports whether r is an RFC 5322 atext character. - // If dot is true, period is included. --// If permissive is true, RFC 5322 3.2.3 specials is included, --// except '<', '>', ':' and '"'. --func isAtext(r rune, dot, permissive bool) bool { -+func isAtext(r rune, dot bool) bool { - switch r { - case '.': - return dot - - // RFC 5322 3.2.3. specials -- case '(', ')', '[', ']', ';', '@', '\\', ',': -- return permissive -- -- case '<', '>', '"', ':': -+ case '(', ')', '<', '>', '[', ']', ':', ';', '@', '\\', ',', '"': // RFC 5322 3.2.3. specials - return false - } - return isVchar(r) -diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go -index 1e1bb4092f..1f2f62afbf 100644 ---- a/src/net/mail/message_test.go -+++ b/src/net/mail/message_test.go -@@ -385,8 +385,11 @@ func TestAddressParsingError(t *testing.T) { - 13: {"group not closed: null@example.com", "expected comma"}, - 14: {"group: first@example.com, second@example.com;", "group with multiple addresses"}, - 15: {"john.doe", "missing '@' or angle-addr"}, -- 16: {"john.doe@", "no angle-addr"}, -+ 16: {"john.doe@", "missing '@' or angle-addr"}, - 17: {"John Doe@foo.bar", "no angle-addr"}, -+ 18: {" group: null@example.com; (asd", "misformatted parenthetical comment"}, -+ 19: {" group: ; (asd", "misformatted parenthetical comment"}, -+ 20: {`(John) Doe `, "missing word in phrase:"}, - } - - for i, tc := range mustErrTestCases { -@@ -436,24 +439,19 @@ func TestAddressParsing(t *testing.T) { - Address: "john.q.public@example.com", - }}, - }, -- { -- `"John (middle) Doe" `, -- []*Address{{ -- Name: "John (middle) Doe", -- Address: "jdoe@machine.example", -- }}, -- }, -+ // Comment in display name - { - `John (middle) Doe `, - []*Address{{ -- Name: "John (middle) Doe", -+ Name: "John Doe", - Address: "jdoe@machine.example", - }}, - }, -+ // Display name is quoted string, so comment is not a comment - { -- `John !@M@! Doe `, -+ `"John (middle) Doe" `, - []*Address{{ -- Name: "John !@M@! Doe", -+ Name: "John (middle) Doe", - Address: "jdoe@machine.example", - }}, - }, -@@ -788,6 +786,26 @@ func TestAddressParsing(t *testing.T) { - }, - }, - }, -+ // Comment in group display name -+ { -+ `group (comment:): a@example.com, b@example.com;`, -+ []*Address{ -+ { -+ Address: "a@example.com", -+ }, -+ { -+ Address: "b@example.com", -+ }, -+ }, -+ }, -+ { -+ `x(:"):"@a.example;("@b.example;`, -+ []*Address{ -+ { -+ Address: `@a.example;(@b.example`, -+ }, -+ }, -+ }, - } - for _, test := range tests { - if len(test.exp) == 1 { --- -2.33.0 - diff --git a/backport-0006-Backport-net-http-update-bundled-golang.org-x-net-ht.patch b/backport-0006-Backport-net-http-update-bundled-golang.org-x-net-ht.patch deleted file mode 100644 index ab4dfb26ee02452ab3fdfcf7861b42cc2f3818d9..0000000000000000000000000000000000000000 --- a/backport-0006-Backport-net-http-update-bundled-golang.org-x-net-ht.patch +++ /dev/null @@ -1,82 +0,0 @@ -From a65a2b54e18a7e269bff32526b4180ece22e9aa6 Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Thu, 28 Mar 2024 16:57:51 -0700 -Subject: [PATCH] [Backport] net/http: update bundled golang.org/x/net/http2 - -Offering: Cloud Core Network -CVE: CVE-2023-45288 -Reference: https://go-review.googlesource.com/c/go/+/576076 - -Disable cmd/internal/moddeps test, since this update includes PRIVATE -track fixes. - -Fixes CVE-2023-45288 -For #65051 -Fixes #66298 - -Change-Id: I5bbf774ebe7651e4bb7e55139d3794bd2b8e8fa8 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2197227 -Reviewed-by: Tatiana Bradley -Run-TryBot: Damien Neil -Reviewed-by: Dmitri Shuralyov -Reviewed-on: https://go-review.googlesource.com/c/go/+/576076 -Auto-Submit: Dmitri Shuralyov -TryBot-Bypass: Dmitri Shuralyov -Reviewed-by: Than McIntosh -Signed-off-by: Ma Chang Wang machangwang@huawei.com ---- - src/net/http/h2_bundle.go | 31 +++++++++++++++++++++++++++++++ - 1 file changed, 31 insertions(+) - -diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go -index dd59e1f4f2..cd95f84269 100644 ---- a/src/net/http/h2_bundle.go -+++ b/src/net/http/h2_bundle.go -@@ -2966,6 +2966,7 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - if size > remainSize { - hdec.SetEmitEnabled(false) - mh.Truncated = true -+ remainSize = 0 - return - } - remainSize -= size -@@ -2978,6 +2979,36 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - var hc http2headersOrContinuation = hf - for { - frag := hc.HeaderBlockFragment() -+ -+ // Avoid parsing large amounts of headers that we will then discard. -+ // If the sender exceeds the max header list size by too much, -+ // skip parsing the fragment and close the connection. -+ // -+ // "Too much" is either any CONTINUATION frame after we've already -+ // exceeded the max header list size (in which case remainSize is 0), -+ // or a frame whose encoded size is more than twice the remaining -+ // header list bytes we're willing to accept. -+ if int64(len(frag)) > int64(2*remainSize) { -+ if http2VerboseLogs { -+ log.Printf("http2: header list too large") -+ } -+ // It would be nice to send a RST_STREAM before sending the GOAWAY, -+ // but the struture of the server's frame writer makes this difficult. -+ return nil, http2ConnectionError(http2ErrCodeProtocol) -+ } -+ -+ // Also close the connection after any CONTINUATION frame following an -+ // invalid header, since we stop tracking the size of the headers after -+ // an invalid one. -+ if invalid != nil { -+ if http2VerboseLogs { -+ log.Printf("http2: invalid header: %v", invalid) -+ } -+ // It would be nice to send a RST_STREAM before sending the GOAWAY, -+ // but the struture of the server's frame writer makes this difficult. -+ return nil, http2ConnectionError(http2ErrCodeProtocol) -+ } -+ - if _, err := hdec.Write(frag); err != nil { - return nil, http2ConnectionError(http2ErrCodeCompression) - } --- -2.33.0 - diff --git a/backport-0007-Backport-cmd-go-disallow-lto_library-in-LDFLAGS.patch b/backport-0007-Backport-cmd-go-disallow-lto_library-in-LDFLAGS.patch deleted file mode 100644 index b1c16a57272a2bf324a3b7f41903651bea8b75bb..0000000000000000000000000000000000000000 --- a/backport-0007-Backport-cmd-go-disallow-lto_library-in-LDFLAGS.patch +++ /dev/null @@ -1,133 +0,0 @@ -From 7edadbad6c5ba7db3c4ab6925369096dedcf8e0b Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Thu, 25 Apr 2024 13:09:54 -0700 -Subject: [PATCH] [Backport] cmd/go: disallow -lto_library in LDFLAGS -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Offering: Cloud Core Network -CVE: CVE-2024-24787 -Reference: https://go-review.googlesource.com/c/go/+/583796 - -The darwin linker allows setting the LTO library with the -lto_library -flag. This wasn't caught by our "safe linker flags" check because it -was covered by the -lx flag used for linking libraries. This change -adds a specific check for excluded flags which otherwise satisfy our -existing checks. - -Loading a mallicious LTO library would allow an attacker to cause the -linker to execute abritrary code when "go build" was called. - -Thanks to Juho Forsén of Mattermost for reporting this issue. - -Fixes #67119 -Fixes #67122 -Fixes CVE-2024-24787 - -Change-Id: I77ac8585efbdbdfd5f39c39ed623b9408a0f9eaf -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1380 -Reviewed-by: Russ Cox -Reviewed-by: Damien Neil -(cherry picked from commit 9a79141fbbca1105e5c786f15e38741ca7843290) -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1420 -Reviewed-by: Tatiana Bradley -Reviewed-on: https://go-review.googlesource.com/c/go/+/583796 -Reviewed-by: David Chase -LUCI-TryBot-Result: Go LUCI -Signed-off-by: Ma Chang Wang machangwang@huawei.com ---- - src/cmd/go/internal/work/security.go | 19 +++++++++++++++---- - .../script/darwin_lto_library_ldflag.txt | 17 +++++++++++++++++ - 2 files changed, 32 insertions(+), 4 deletions(-) - create mode 100644 src/cmd/go/testdata/script/darwin_lto_library_ldflag.txt - -diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go -index 270a34e9c7..db49eb6488 100644 ---- a/src/cmd/go/internal/work/security.go -+++ b/src/cmd/go/internal/work/security.go -@@ -141,6 +141,12 @@ var validCompilerFlagsWithNextArg = []string{ - "-x", - } - -+var invalidLinkerFlags = []*lazyregexp.Regexp{ -+ // On macOS this means the linker loads and executes the next argument. -+ // Have to exclude separately because -lfoo is allowed in general. -+ re(`-lto_library`), -+} -+ - var validLinkerFlags = []*lazyregexp.Regexp{ - re(`-F([^@\-].*)`), - re(`-l([^@\-].*)`), -@@ -231,12 +237,12 @@ var validLinkerFlagsWithNextArg = []string{ - - func checkCompilerFlags(name, source string, list []string) error { - checkOverrides := true -- return checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides) -+ return checkFlags(name, source, list, nil, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides) - } - - func checkLinkerFlags(name, source string, list []string) error { - checkOverrides := true -- return checkFlags(name, source, list, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides) -+ return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides) - } - - // checkCompilerFlagsForInternalLink returns an error if 'list' -@@ -245,7 +251,7 @@ func checkLinkerFlags(name, source string, list []string) error { - // external linker). - func checkCompilerFlagsForInternalLink(name, source string, list []string) error { - checkOverrides := false -- if err := checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides); err != nil { -+ if err := checkFlags(name, source, list, nil, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides); err != nil { - return err - } - // Currently the only flag on the allow list that causes problems -@@ -258,7 +264,7 @@ func checkCompilerFlagsForInternalLink(name, source string, list []string) error - return nil - } - --func checkFlags(name, source string, list []string, valid []*lazyregexp.Regexp, validNext []string, checkOverrides bool) error { -+func checkFlags(name, source string, list []string, invalid, valid []*lazyregexp.Regexp, validNext []string, checkOverrides bool) error { - // Let users override rules with $CGO_CFLAGS_ALLOW, $CGO_CFLAGS_DISALLOW, etc. - var ( - allow *regexp.Regexp -@@ -290,6 +296,11 @@ Args: - if allow != nil && allow.FindString(arg) == arg { - continue Args - } -+ for _, re := range invalid { -+ if re.FindString(arg) == arg { // must be complete match -+ goto Bad -+ } -+ } - for _, re := range valid { - if re.FindString(arg) == arg { // must be complete match - continue Args -diff --git a/src/cmd/go/testdata/script/darwin_lto_library_ldflag.txt b/src/cmd/go/testdata/script/darwin_lto_library_ldflag.txt -new file mode 100644 -index 0000000000..d7acefdbad ---- /dev/null -+++ b/src/cmd/go/testdata/script/darwin_lto_library_ldflag.txt -@@ -0,0 +1,17 @@ -+[!GOOS:darwin] skip -+[!cgo] skip -+ -+! go build -+stderr 'invalid flag in #cgo LDFLAGS: -lto_library' -+ -+-- go.mod -- -+module ldflag -+ -+-- main.go -- -+package main -+ -+// #cgo CFLAGS: -flto -+// #cgo LDFLAGS: -lto_library bad.dylib -+import "C" -+ -+func main() {} -\ No newline at end of file --- -2.33.0 - diff --git a/backport-0008-release-branch.go1.21-net-netip-check-if-address-is-v6.patch b/backport-0008-release-branch.go1.21-net-netip-check-if-address-is-v6.patch deleted file mode 100644 index 261dbe02f2559fd4471dcbd66b6145aac482d504..0000000000000000000000000000000000000000 --- a/backport-0008-release-branch.go1.21-net-netip-check-if-address-is-v6.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 051bdf3fd12a40307606ff9381138039c5f452f0 Mon Sep 17 00:00:00 2001 -From: Roland Shoemaker -Date: Tue, 28 May 2024 13:26:31 -0700 -Subject: [PATCH] [release-branch.go1.21] net/netip: check if address is v6 - mapped in Is methods - -In all of the Is* methods, check if the address is a v6 mapped v4 -address, and unmap it if so. - -Thanks to Enze Wang of Alioth (@zer0yu) and Jianjun Chen of Zhongguancun -Lab (@chenjj) for reporting this issue. - -Fixes #67680 -Fixes #67681 -Fixes CVE-2024-24790 - -Change-Id: I6bd03ca1a5d93a0b59027d861c84060967b265b0 -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1460 -Reviewed-by: Russ Cox -Reviewed-by: Damien Neil -(cherry picked from commit f7f270c1621fdc7ee48e0487b2fac0356947d19b) -Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1500 -Reviewed-by: Tatiana Bradley -Reviewed-on: https://go-review.googlesource.com/c/go/+/590315 -Auto-Submit: Michael Knyszek -LUCI-TryBot-Result: Go LUCI -Reviewed-by: David Chase ---- - src/net/netip/inlining_test.go | 2 -- - src/net/netip/netip.go | 26 +++++++++++++++++- - src/net/netip/netip_test.go | 50 +++++++++++++++++++++++++++++++--- - 3 files changed, 71 insertions(+), 7 deletions(-) - -diff --git a/src/net/netip/inlining_test.go b/src/net/netip/inlining_test.go -index b521eeebfd8f3..98584b098df1b 100644 ---- a/src/net/netip/inlining_test.go -+++ b/src/net/netip/inlining_test.go -@@ -36,8 +36,6 @@ func TestInlining(t *testing.T) { - "Addr.Is4", - "Addr.Is4In6", - "Addr.Is6", -- "Addr.IsLoopback", -- "Addr.IsMulticast", - "Addr.IsInterfaceLocalMulticast", - "Addr.IsValid", - "Addr.IsUnspecified", -diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go -index a44b09495549d..9e4d41f8fb7b9 100644 ---- a/src/net/netip/netip.go -+++ b/src/net/netip/netip.go -@@ -507,6 +507,10 @@ func (ip Addr) hasZone() bool { - - // IsLinkLocalUnicast reports whether ip is a link-local unicast address. - func (ip Addr) IsLinkLocalUnicast() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Dynamic Configuration of IPv4 Link-Local Addresses - // https://datatracker.ietf.org/doc/html/rfc3927#section-2.1 - if ip.Is4() { -@@ -522,6 +526,10 @@ func (ip Addr) IsLinkLocalUnicast() bool { - - // IsLoopback reports whether ip is a loopback address. - func (ip Addr) IsLoopback() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Requirements for Internet Hosts -- Communication Layers (3.2.1.3 Addressing) - // https://datatracker.ietf.org/doc/html/rfc1122#section-3.2.1.3 - if ip.Is4() { -@@ -537,6 +545,10 @@ func (ip Addr) IsLoopback() bool { - - // IsMulticast reports whether ip is a multicast address. - func (ip Addr) IsMulticast() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Host Extensions for IP Multicasting (4. HOST GROUP ADDRESSES) - // https://datatracker.ietf.org/doc/html/rfc1112#section-4 - if ip.Is4() { -@@ -555,7 +567,7 @@ func (ip Addr) IsMulticast() bool { - func (ip Addr) IsInterfaceLocalMulticast() bool { - // IPv6 Addressing Architecture (2.7.1. Pre-Defined Multicast Addresses) - // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1 -- if ip.Is6() { -+ if ip.Is6() && !ip.Is4In6() { - return ip.v6u16(0)&0xff0f == 0xff01 - } - return false // zero value -@@ -563,6 +575,10 @@ func (ip Addr) IsInterfaceLocalMulticast() bool { - - // IsLinkLocalMulticast reports whether ip is a link-local multicast address. - func (ip Addr) IsLinkLocalMulticast() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // IPv4 Multicast Guidelines (4. Local Network Control Block (224.0.0/24)) - // https://datatracker.ietf.org/doc/html/rfc5771#section-4 - if ip.Is4() { -@@ -591,6 +607,10 @@ func (ip Addr) IsGlobalUnicast() bool { - return false - } - -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Match package net's IsGlobalUnicast logic. Notably private IPv4 addresses - // and ULA IPv6 addresses are still considered "global unicast". - if ip.Is4() && (ip == IPv4Unspecified() || ip == AddrFrom4([4]byte{255, 255, 255, 255})) { -@@ -608,6 +628,10 @@ func (ip Addr) IsGlobalUnicast() bool { - // ip is in 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or fc00::/7. This is the - // same as net.IP.IsPrivate. - func (ip Addr) IsPrivate() bool { -+ if ip.Is4In6() { -+ ip = ip.Unmap() -+ } -+ - // Match the stdlib's IsPrivate logic. - if ip.Is4() { - // RFC 1918 allocates 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16 as -diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go -index 0f80bb0ab0e56..5c7ad14c5c702 100644 ---- a/src/net/netip/netip_test.go -+++ b/src/net/netip/netip_test.go -@@ -589,10 +589,13 @@ func TestIPProperties(t *testing.T) { - ilm6 = mustIP("ff01::1") - ilmZone6 = mustIP("ff01::1%eth0") - -- private4a = mustIP("10.0.0.1") -- private4b = mustIP("172.16.0.1") -- private4c = mustIP("192.168.1.1") -- private6 = mustIP("fd00::1") -+ private4a = mustIP("10.0.0.1") -+ private4b = mustIP("172.16.0.1") -+ private4c = mustIP("192.168.1.1") -+ private6 = mustIP("fd00::1") -+ private6mapped4a = mustIP("::ffff:10.0.0.1") -+ private6mapped4b = mustIP("::ffff:172.16.0.1") -+ private6mapped4c = mustIP("::ffff:192.168.1.1") - ) - - tests := []struct { -@@ -616,6 +619,11 @@ func TestIPProperties(t *testing.T) { - ip: unicast4, - globalUnicast: true, - }, -+ { -+ name: "unicast v6 mapped v4Addr", -+ ip: AddrFrom16(unicast4.As16()), -+ globalUnicast: true, -+ }, - { - name: "unicast v6Addr", - ip: unicast6, -@@ -637,6 +645,12 @@ func TestIPProperties(t *testing.T) { - linkLocalMulticast: true, - multicast: true, - }, -+ { -+ name: "multicast v6 mapped v4Addr", -+ ip: AddrFrom16(multicast4.As16()), -+ linkLocalMulticast: true, -+ multicast: true, -+ }, - { - name: "multicast v6Addr", - ip: multicast6, -@@ -654,6 +668,11 @@ func TestIPProperties(t *testing.T) { - ip: llu4, - linkLocalUnicast: true, - }, -+ { -+ name: "link-local unicast v6 mapped v4Addr", -+ ip: AddrFrom16(llu4.As16()), -+ linkLocalUnicast: true, -+ }, - { - name: "link-local unicast v6Addr", - ip: llu6, -@@ -679,6 +698,11 @@ func TestIPProperties(t *testing.T) { - ip: IPv6Loopback(), - loopback: true, - }, -+ { -+ name: "loopback v6 mapped v4Addr", -+ ip: AddrFrom16(IPv6Loopback().As16()), -+ loopback: true, -+ }, - { - name: "interface-local multicast v6Addr", - ip: ilm6, -@@ -715,6 +739,24 @@ func TestIPProperties(t *testing.T) { - globalUnicast: true, - private: true, - }, -+ { -+ name: "private v6 mapped v4Addr 10/8", -+ ip: private6mapped4a, -+ globalUnicast: true, -+ private: true, -+ }, -+ { -+ name: "private v6 mapped v4Addr 172.16/12", -+ ip: private6mapped4b, -+ globalUnicast: true, -+ private: true, -+ }, -+ { -+ name: "private v6 mapped v4Addr 192.168/16", -+ ip: private6mapped4c, -+ globalUnicast: true, -+ private: true, -+ }, - { - name: "unspecified v4Addr", - ip: IPv4Unspecified(), diff --git a/backport-0009-Backport-cmd-go-internal-vcs-error-out-if-the-reques.patch b/backport-0009-Backport-cmd-go-internal-vcs-error-out-if-the-reques.patch deleted file mode 100644 index fb5d4bba65e97453590ced9ae1b4d0fa90afa1b1..0000000000000000000000000000000000000000 --- a/backport-0009-Backport-cmd-go-internal-vcs-error-out-if-the-reques.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 558cbc498c70278bea8297272f2d4fc50d67893b Mon Sep 17 00:00:00 2001 -From: "Bryan C. Mills" -Date: Thu, 2 Nov 2023 15:06:35 -0400 -Subject: [PATCH] [Backport] cmd/go/internal/vcs: error out if the requested - repo does not support a secure protocol - -CVE: CVE-2023-45285 -Reference: https://go-review.googlesource.com/c/go/+/540335 - -Updates #63845. -Fixes #63972. - -Change-Id: If86d6b13d3b55877b35c087112bd76388c9404b8 -Reviewed-on: https://go-review.googlesource.com/c/go/+/539321 -Reviewed-by: Michael Matloob -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Roland Shoemaker -Auto-Submit: Bryan Mills -(cherry picked from commit be26ae18caf7ddffca4073333f80d0d9e76483c3) -Reviewed-on: https://go-review.googlesource.com/c/go/+/540335 -Auto-Submit: Dmitri Shuralyov -Reviewed-by: Dmitri Shuralyov -Signed-off-by: wangbingyao 00557526 ---- - src/cmd/go/internal/vcs/vcs.go | 25 +++++++++++++---- - .../script/mod_insecure_issue63845.txt | 28 +++++++++++++++++++ - 2 files changed, 47 insertions(+), 6 deletions(-) - create mode 100644 src/cmd/go/testdata/script/mod_insecure_issue63845.txt - -diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go -index c65dd0f624..dbf16d1de7 100644 ---- a/src/cmd/go/internal/vcs/vcs.go -+++ b/src/cmd/go/internal/vcs/vcs.go -@@ -1204,18 +1204,31 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths - var ok bool - repoURL, ok = interceptVCSTest(repo, vcs, security) - if !ok { -- scheme := vcs.Scheme[0] // default to first scheme -- if vcs.PingCmd != "" { -- // If we know how to test schemes, scan to find one. -+ scheme, err := func() (string, error) { - for _, s := range vcs.Scheme { - if security == web.SecureOnly && !vcs.isSecureScheme(s) { - continue - } -- if vcs.Ping(s, repo) == nil { -- scheme = s -- break -+ -+ // If we know how to ping URL schemes for this VCS, -+ // check that this repo works. -+ // Otherwise, default to the first scheme -+ // that meets the requested security level. -+ if vcs.PingCmd == "" { -+ return s, nil -+ } -+ if err := vcs.Ping(s, repo); err == nil { -+ return s, nil - } - } -+ securityFrag := "" -+ if security == web.SecureOnly { -+ securityFrag = "secure " -+ } -+ return "", fmt.Errorf("no %sprotocol found for repository", securityFrag) -+ }() -+ if err != nil { -+ return nil, err - } - repoURL = scheme + "://" + repo - } -diff --git a/src/cmd/go/testdata/script/mod_insecure_issue63845.txt b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt -new file mode 100644 -index 0000000000..5fa6a4f12b ---- /dev/null -+++ b/src/cmd/go/testdata/script/mod_insecure_issue63845.txt -@@ -0,0 +1,28 @@ -+# Regression test for https://go.dev/issue/63845: -+# If 'git ls-remote' fails for all secure protocols, -+# we should fail instead of falling back to an arbitrary protocol. -+# -+# Note that this test does not use the local vcweb test server -+# (vcs-test.golang.org), because the hook for redirecting to that -+# server bypasses the "ping to determine protocol" logic -+# in cmd/go/internal/vcs. -+ -+[!net] skip -+[!git] skip -+[short] skip 'tries to access a nonexistent external Git repo' -+ -+env GOPRIVATE=golang.org -+env CURLOPT_TIMEOUT_MS=100 -+env GIT_SSH_COMMAND=false -+ -+! go get -x golang.org/nonexist.git@latest -+stderr '^git ls-remote https://golang.org/nonexist$' -+stderr '^git ls-remote git\+ssh://golang.org/nonexist' -+stderr '^git ls-remote ssh://golang.org/nonexist$' -+! stderr 'git://' -+stderr '^go: golang.org/nonexist.git@latest: no secure protocol found for repository$' -+ -+-- go.mod -- -+module example -+ -+go 1.19 --- -2.33.0 - diff --git a/backport-0010-release-branch.go1.21-net-http-limit-chunked-data-ov.patch b/backport-0010-release-branch.go1.21-net-http-limit-chunked-data-ov.patch deleted file mode 100644 index 67367a4942d08229540ec978cdc78945705ee85f..0000000000000000000000000000000000000000 --- a/backport-0010-release-branch.go1.21-net-http-limit-chunked-data-ov.patch +++ /dev/null @@ -1,175 +0,0 @@ -From 43c0e9116f26416de7454855852eba9083d94d03 Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Tue, 7 Nov 2023 10:47:56 -0800 -Subject: [PATCH 1/2] [release-branch.go1.21] net/http: limit chunked data - overhead - -The chunked transfer encoding adds some overhead to -the content transferred. When writing one byte per -chunk, for example, there are five bytes of overhead -per byte of data transferred: "1\r\nX\r\n" to send "X". - -Chunks may include "chunk extensions", -which we skip over and do not use. -For example: "1;chunk extension here\r\nX\r\n". - -A malicious sender can use chunk extensions to add -about 4k of overhead per byte of data. -(The maximum chunk header line size we will accept.) - -Track the amount of overhead read in chunked data, -and produce an error if it seems excessive. - -Updates #64433 -Fixes #64435 -Fixes CVE-2023-39326 - -Change-Id: I40f8d70eb6f9575fb43f506eb19132ccedafcf39 -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2076135 -Reviewed-by: Tatiana Bradley -Reviewed-by: Roland Shoemaker -(cherry picked from commit 3473ae72ee66c60744665a24b2fde143e8964d4f) -Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2095408 -Run-TryBot: Roland Shoemaker -Reviewed-by: Damien Neil -Reviewed-on: https://go-review.googlesource.com/c/go/+/547356 -Reviewed-by: Dmitri Shuralyov -LUCI-TryBot-Result: Go LUCI ---- - src/net/http/internal/chunked.go | 34 ++++++++++++--- - src/net/http/internal/chunked_test.go | 59 +++++++++++++++++++++++++++ - 2 files changed, 87 insertions(+), 6 deletions(-) - -diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go -index 5a174415dc4..aad8e5aa09e 100644 ---- a/src/net/http/internal/chunked.go -+++ b/src/net/http/internal/chunked.go -@@ -39,7 +39,8 @@ type chunkedReader struct { - n uint64 // unread bytes in chunk - err error - buf [2]byte -- checkEnd bool // whether need to check for \r\n chunk footer -+ checkEnd bool // whether need to check for \r\n chunk footer -+ excess int64 // "excessive" chunk overhead, for malicious sender detection - } - - func (cr *chunkedReader) beginChunk() { -@@ -49,10 +50,36 @@ func (cr *chunkedReader) beginChunk() { - if cr.err != nil { - return - } -+ cr.excess += int64(len(line)) + 2 // header, plus \r\n after the chunk data -+ line = trimTrailingWhitespace(line) -+ line, cr.err = removeChunkExtension(line) -+ if cr.err != nil { -+ return -+ } - cr.n, cr.err = parseHexUint(line) - if cr.err != nil { - return - } -+ // A sender who sends one byte per chunk will send 5 bytes of overhead -+ // for every byte of data. ("1\r\nX\r\n" to send "X".) -+ // We want to allow this, since streaming a byte at a time can be legitimate. -+ // -+ // A sender can use chunk extensions to add arbitrary amounts of additional -+ // data per byte read. ("1;very long extension\r\nX\r\n" to send "X".) -+ // We don't want to disallow extensions (although we discard them), -+ // but we also don't want to allow a sender to reduce the signal/noise ratio -+ // arbitrarily. -+ // -+ // We track the amount of excess overhead read, -+ // and produce an error if it grows too large. -+ // -+ // Currently, we say that we're willing to accept 16 bytes of overhead per chunk, -+ // plus twice the amount of real data in the chunk. -+ cr.excess -= 16 + (2 * int64(cr.n)) -+ cr.excess = max(cr.excess, 0) -+ if cr.excess > 16*1024 { -+ cr.err = errors.New("chunked encoding contains too much non-data") -+ } - if cr.n == 0 { - cr.err = io.EOF - } -@@ -140,11 +167,6 @@ func readChunkLine(b *bufio.Reader) ([]byte, error) { - if len(p) >= maxLineLength { - return nil, ErrLineTooLong - } -- p = trimTrailingWhitespace(p) -- p, err = removeChunkExtension(p) -- if err != nil { -- return nil, err -- } - return p, nil - } - -diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go -index 5e29a786dd6..b99090c1f8a 100644 ---- a/src/net/http/internal/chunked_test.go -+++ b/src/net/http/internal/chunked_test.go -@@ -239,3 +239,62 @@ func TestChunkEndReadError(t *testing.T) { - t.Errorf("expected %v, got %v", readErr, err) - } - } -+ -+func TestChunkReaderTooMuchOverhead(t *testing.T) { -+ // If the sender is sending 100x as many chunk header bytes as chunk data, -+ // we should reject the stream at some point. -+ chunk := []byte("1;") -+ for i := 0; i < 100; i++ { -+ chunk = append(chunk, 'a') // chunk extension -+ } -+ chunk = append(chunk, "\r\nX\r\n"...) -+ const bodylen = 1 << 20 -+ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) { -+ if i < bodylen { -+ return chunk, nil -+ } -+ return []byte("0\r\n"), nil -+ }}) -+ _, err := io.ReadAll(r) -+ if err == nil { -+ t.Fatalf("successfully read body with excessive overhead; want error") -+ } -+} -+ -+func TestChunkReaderByteAtATime(t *testing.T) { -+ // Sending one byte per chunk should not trip the excess-overhead detection. -+ const bodylen = 1 << 20 -+ r := NewChunkedReader(&funcReader{f: func(i int) ([]byte, error) { -+ if i < bodylen { -+ return []byte("1\r\nX\r\n"), nil -+ } -+ return []byte("0\r\n"), nil -+ }}) -+ got, err := io.ReadAll(r) -+ if err != nil { -+ t.Errorf("unexpected error: %v", err) -+ } -+ if len(got) != bodylen { -+ t.Errorf("read %v bytes, want %v", len(got), bodylen) -+ } -+} -+ -+type funcReader struct { -+ f func(iteration int) ([]byte, error) -+ i int -+ b []byte -+ err error -+} -+ -+func (r *funcReader) Read(p []byte) (n int, err error) { -+ if len(r.b) == 0 && r.err == nil { -+ r.b, r.err = r.f(r.i) -+ r.i++ -+ } -+ n = copy(p, r.b) -+ r.b = r.b[n:] -+ if len(r.b) > 0 { -+ return n, nil -+ } -+ return n, r.err -+} --- -2.33.0 - diff --git a/backport-0011-Backport-archive-zip-treat-truncated-EOCDR-comment-a.patch b/backport-0011-Backport-archive-zip-treat-truncated-EOCDR-comment-a.patch deleted file mode 100644 index 55beba5543b0f50020df5f9ac2e93e73f850b63b..0000000000000000000000000000000000000000 --- a/backport-0011-Backport-archive-zip-treat-truncated-EOCDR-comment-a.patch +++ /dev/null @@ -1,58 +0,0 @@ -From c69c5c62775d84aa56a43bedaa4fcacbb73d403d Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Tue, 14 May 2024 14:39:10 -0700 -Subject: [PATCH] [Backport] archive/zip: treat truncated EOCDR comment as an - error - -CVE: CVE-2024-24789 -Reference: https://go-review.googlesource.com/c/go/+/588796 - -When scanning for an end of central directory record, -treat an EOCDR signature with a record containing a truncated -comment as an error. Previously, we would skip over the invalid -record and look for another one. Other implementations do not -do this (they either consider this a hard error, or just ignore -the truncated comment). This parser misalignment allowed -presenting entirely different archive contents to Go programs -and other zip decoders. - -For #66869 -Fixes #67554 -Fixes CVE-2024-24789 - -Change-Id: I94e5cb028534bb5704588b8af27f1e22ea49c7c6 -Reviewed-on: https://go-review.googlesource.com/c/go/+/585397 -Reviewed-by: Joseph Tsai -Reviewed-by: Dmitri Shuralyov -LUCI-TryBot-Result: Go LUCI -(cherry picked from commit 33d725e5758bf1fea62e6c77fc70b57a828a49f5) -Reviewed-on: https://go-review.googlesource.com/c/go/+/588796 -Reviewed-by: Matthew Dempsky -Signed-off-by: Ma Chang Wang machangwang@huawei.com ---- - src/archive/zip/reader.go | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go -index 1fde1decc4..20356bde0e 100644 ---- a/src/archive/zip/reader.go -+++ b/src/archive/zip/reader.go -@@ -699,9 +699,13 @@ func findSignatureInBlock(b []byte) int { - if b[i] == 'P' && b[i+1] == 'K' && b[i+2] == 0x05 && b[i+3] == 0x06 { - // n is length of comment - n := int(b[i+directoryEndLen-2]) | int(b[i+directoryEndLen-1])<<8 -- if n+directoryEndLen+i <= len(b) { -- return i -+ if n+directoryEndLen+i > len(b) { -+ // Truncated comment. -+ // Some parsers (such as Info-ZIP) ignore the truncated comment -+ // rather than treating it as a hard error. -+ return -1 - } -+ return i - } - } - return -1 --- -2.33.0 - diff --git a/backport-0012-net-http-send-body-or-close-connection-on-expect-100.patch b/backport-0012-net-http-send-body-or-close-connection-on-expect-100.patch deleted file mode 100644 index 30501ff1b2c80b5dec252f3f0fd8d2347f1f2647..0000000000000000000000000000000000000000 --- a/backport-0012-net-http-send-body-or-close-connection-on-expect-100.patch +++ /dev/null @@ -1,353 +0,0 @@ -From c9be6ae748b7679b644a38182d456cb5a6ac06ee Mon Sep 17 00:00:00 2001 -From: Damien Neil -Date: Thu, 6 Jun 2024 12:50:46 -0700 -Subject: [PATCH] [release-branch.go1.21] net/http: send body or close - connection on expect-100-continue requests - -When sending a request with an "Expect: 100-continue" header, -we must send the request body before sending any further requests -on the connection. - -When receiving a non-1xx response to an "Expect: 100-continue" request, -send the request body if the connection isn't being closed after -processing the response. In other words, if either the request -or response contains a "Connection: close" header, then skip sending -the request body (because the connection will not be used for -further requests), but otherwise send it. - -Correct a comment on the server-side Expect: 100-continue handling -that implied sending the request body is optional. It isn't. - -For #67555 -Fixes #68199 - -Change-Id: Ia2f12091bee697771087f32ac347509ec5922d54 -Reviewed-on: https://go-review.googlesource.com/c/go/+/591255 -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Jonathan Amsterdam -(cherry picked from commit cf501e05e138e6911f759a5db786e90b295499b9) -Reviewed-on: https://go-review.googlesource.com/c/go/+/595096 -Reviewed-by: Joedian Reid -Reviewed-by: Dmitri Shuralyov ---- - src/net/http/server.go | 25 ++-- - src/net/http/transport.go | 34 ++++-- - src/net/http/transport_test.go | 202 ++++++++++++++++++++------------- - 3 files changed, 164 insertions(+), 97 deletions(-) - -diff --git a/src/net/http/server.go b/src/net/http/server.go -index 8f63a90299..111adb0ecd 100644 ---- a/src/net/http/server.go -+++ b/src/net/http/server.go -@@ -1352,16 +1352,21 @@ func (cw *chunkWriter) writeHeader(p []byte) { - - // If the client wanted a 100-continue but we never sent it to - // them (or, more strictly: we never finished reading their -- // request body), don't reuse this connection because it's now -- // in an unknown state: we might be sending this response at -- // the same time the client is now sending its request body -- // after a timeout. (Some HTTP clients send Expect: -- // 100-continue but knowing that some servers don't support -- // it, the clients set a timer and send the body later anyway) -- // If we haven't seen EOF, we can't skip over the unread body -- // because we don't know if the next bytes on the wire will be -- // the body-following-the-timer or the subsequent request. -- // See Issue 11549. -+ // request body), don't reuse this connection. -+ // -+ // This behavior was first added on the theory that we don't know -+ // if the next bytes on the wire are going to be the remainder of -+ // the request body or the subsequent request (see issue 11549), -+ // but that's not correct: If we keep using the connection, -+ // the client is required to send the request body whether we -+ // asked for it or not. -+ // -+ // We probably do want to skip reusing the connection in most cases, -+ // however. If the client is offering a large request body that we -+ // don't intend to use, then it's better to close the connection -+ // than to read the body. For now, assume that if we're sending -+ // headers, the handler is done reading the body and we should -+ // drop the connection if we haven't seen EOF. - if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF.Load() { - w.closeAfterReply = true - } -diff --git a/src/net/http/transport.go b/src/net/http/transport.go -index c07352b018..30bce98736 100644 ---- a/src/net/http/transport.go -+++ b/src/net/http/transport.go -@@ -2313,17 +2313,12 @@ func (pc *persistConn) readResponse(rc requestAndChan, trace *httptrace.ClientTr - return - } - resCode := resp.StatusCode -- if continueCh != nil { -- if resCode == 100 { -- if trace != nil && trace.Got100Continue != nil { -- trace.Got100Continue() -- } -- continueCh <- struct{}{} -- continueCh = nil -- } else if resCode >= 200 { -- close(continueCh) -- continueCh = nil -+ if continueCh != nil && resCode == StatusContinue { -+ if trace != nil && trace.Got100Continue != nil { -+ trace.Got100Continue() - } -+ continueCh <- struct{}{} -+ continueCh = nil - } - is1xx := 100 <= resCode && resCode <= 199 - // treat 101 as a terminal status, see issue 26161 -@@ -2346,6 +2341,25 @@ func (pc *persistConn) readResponse(rc requestAndChan, trace *httptrace.ClientTr - if resp.isProtocolSwitch() { - resp.Body = newReadWriteCloserBody(pc.br, pc.conn) - } -+ if continueCh != nil { -+ // We send an "Expect: 100-continue" header, but the server -+ // responded with a terminal status and no 100 Continue. -+ // -+ // If we're going to keep using the connection, we need to send the request body. -+ // Tell writeLoop to skip sending the body if we're going to close the connection, -+ // or to send it otherwise. -+ // -+ // The case where we receive a 101 Switching Protocols response is a bit -+ // ambiguous, since we don't know what protocol we're switching to. -+ // Conceivably, it's one that doesn't need us to send the body. -+ // Given that we'll send the body if ExpectContinueTimeout expires, -+ // be consistent and always send it if we aren't closing the connection. -+ if resp.Close || rc.req.Close { -+ close(continueCh) // don't send the body; the connection will close -+ } else { -+ continueCh <- struct{}{} // send the body -+ } -+ } - - resp.TLS = pc.tlsState - return -diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go -index 028fecc961..b8c930ab8f 100644 ---- a/src/net/http/transport_test.go -+++ b/src/net/http/transport_test.go -@@ -1135,94 +1135,142 @@ func testTransportGzip(t *testing.T, mode testMode) { - } - } - --// If a request has Expect:100-continue header, the request blocks sending body until the first response. --// Premature consumption of the request body should not be occurred. --func TestTransportExpect100Continue(t *testing.T) { -- run(t, testTransportExpect100Continue, []testMode{http1Mode}) -+// A transport100Continue test exercises Transport behaviors when sending a -+// request with an Expect: 100-continue header. -+type transport100ContinueTest struct { -+ t *testing.T -+ -+ reqdone chan struct{} -+ resp *Response -+ respErr error -+ -+ conn net.Conn -+ reader *bufio.Reader - } --func testTransportExpect100Continue(t *testing.T, mode testMode) { -- ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) { -- switch req.URL.Path { -- case "/100": -- // This endpoint implicitly responds 100 Continue and reads body. -- if _, err := io.Copy(io.Discard, req.Body); err != nil { -- t.Error("Failed to read Body", err) -- } -- rw.WriteHeader(StatusOK) -- case "/200": -- // Go 1.5 adds Connection: close header if the client expect -- // continue but not entire request body is consumed. -- rw.WriteHeader(StatusOK) -- case "/500": -- rw.WriteHeader(StatusInternalServerError) -- case "/keepalive": -- // This hijacked endpoint responds error without Connection:close. -- _, bufrw, err := rw.(Hijacker).Hijack() -- if err != nil { -- log.Fatal(err) -- } -- bufrw.WriteString("HTTP/1.1 500 Internal Server Error\r\n") -- bufrw.WriteString("Content-Length: 0\r\n\r\n") -- bufrw.Flush() -- case "/timeout": -- // This endpoint tries to read body without 100 (Continue) response. -- // After ExpectContinueTimeout, the reading will be started. -- conn, bufrw, err := rw.(Hijacker).Hijack() -- if err != nil { -- log.Fatal(err) -- } -- if _, err := io.CopyN(io.Discard, bufrw, req.ContentLength); err != nil { -- t.Error("Failed to read Body", err) -- } -- bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n") -- bufrw.Flush() -- conn.Close() -- } - -- })).ts -+const transport100ContinueTestBody = "request body" - -- tests := []struct { -- path string -- body []byte -- sent int -- status int -- }{ -- {path: "/100", body: []byte("hello"), sent: 5, status: 200}, // Got 100 followed by 200, entire body is sent. -- {path: "/200", body: []byte("hello"), sent: 0, status: 200}, // Got 200 without 100. body isn't sent. -- {path: "/500", body: []byte("hello"), sent: 0, status: 500}, // Got 500 without 100. body isn't sent. -- {path: "/keepalive", body: []byte("hello"), sent: 0, status: 500}, // Although without Connection:close, body isn't sent. -- {path: "/timeout", body: []byte("hello"), sent: 5, status: 200}, // Timeout exceeded and entire body is sent. -+// newTransport100ContinueTest creates a Transport and sends an Expect: 100-continue -+// request on it. -+func newTransport100ContinueTest(t *testing.T, timeout time.Duration) *transport100ContinueTest { -+ ln := newLocalListener(t) -+ defer ln.Close() -+ -+ test := &transport100ContinueTest{ -+ t: t, -+ reqdone: make(chan struct{}), - } - -- c := ts.Client() -- for i, v := range tests { -- tr := &Transport{ -- ExpectContinueTimeout: 2 * time.Second, -- } -- defer tr.CloseIdleConnections() -- c.Transport = tr -- body := bytes.NewReader(v.body) -- req, err := NewRequest("PUT", ts.URL+v.path, body) -- if err != nil { -- t.Fatal(err) -- } -+ tr := &Transport{ -+ ExpectContinueTimeout: timeout, -+ } -+ go func() { -+ defer close(test.reqdone) -+ body := strings.NewReader(transport100ContinueTestBody) -+ req, _ := NewRequest("PUT", "http://"+ln.Addr().String(), body) - req.Header.Set("Expect", "100-continue") -- req.ContentLength = int64(len(v.body)) -+ req.ContentLength = int64(len(transport100ContinueTestBody)) -+ test.resp, test.respErr = tr.RoundTrip(req) -+ test.resp.Body.Close() -+ }() - -- resp, err := c.Do(req) -- if err != nil { -- t.Fatal(err) -+ c, err := ln.Accept() -+ if err != nil { -+ t.Fatalf("Accept: %v", err) -+ } -+ t.Cleanup(func() { -+ c.Close() -+ }) -+ br := bufio.NewReader(c) -+ _, err = ReadRequest(br) -+ if err != nil { -+ t.Fatalf("ReadRequest: %v", err) -+ } -+ test.conn = c -+ test.reader = br -+ t.Cleanup(func() { -+ <-test.reqdone -+ tr.CloseIdleConnections() -+ got, _ := io.ReadAll(test.reader) -+ if len(got) > 0 { -+ t.Fatalf("Transport sent unexpected bytes: %q", got) - } -- resp.Body.Close() -+ }) - -- sent := len(v.body) - body.Len() -- if v.status != resp.StatusCode { -- t.Errorf("test %d: status code should be %d but got %d. (%s)", i, v.status, resp.StatusCode, v.path) -- } -- if v.sent != sent { -- t.Errorf("test %d: sent body should be %d but sent %d. (%s)", i, v.sent, sent, v.path) -+ return test -+} -+ -+// respond sends response lines from the server to the transport. -+func (test *transport100ContinueTest) respond(lines ...string) { -+ for _, line := range lines { -+ if _, err := test.conn.Write([]byte(line + "\r\n")); err != nil { -+ test.t.Fatalf("Write: %v", err) - } - } -+ if _, err := test.conn.Write([]byte("\r\n")); err != nil { -+ test.t.Fatalf("Write: %v", err) -+ } -+} -+ -+// wantBodySent ensures the transport has sent the request body to the server. -+func (test *transport100ContinueTest) wantBodySent() { -+ got, err := io.ReadAll(io.LimitReader(test.reader, int64(len(transport100ContinueTestBody)))) -+ if err != nil { -+ test.t.Fatalf("unexpected error reading body: %v", err) -+ } -+ if got, want := string(got), transport100ContinueTestBody; got != want { -+ test.t.Fatalf("unexpected body: got %q, want %q", got, want) -+ } -+} -+ -+// wantRequestDone ensures the Transport.RoundTrip has completed with the expected status. -+func (test *transport100ContinueTest) wantRequestDone(want int) { -+ <-test.reqdone -+ if test.respErr != nil { -+ test.t.Fatalf("unexpected RoundTrip error: %v", test.respErr) -+ } -+ if got := test.resp.StatusCode; got != want { -+ test.t.Fatalf("unexpected response code: got %v, want %v", got, want) -+ } -+} -+ -+func TestTransportExpect100ContinueSent(t *testing.T) { -+ test := newTransport100ContinueTest(t, 1*time.Hour) -+ // Server sends a 100 Continue response, and the client sends the request body. -+ test.respond("HTTP/1.1 100 Continue") -+ test.wantBodySent() -+ test.respond("HTTP/1.1 200", "Content-Length: 0") -+ test.wantRequestDone(200) -+} -+ -+func TestTransportExpect100Continue200ResponseNoConnClose(t *testing.T) { -+ test := newTransport100ContinueTest(t, 1*time.Hour) -+ // No 100 Continue response, no Connection: close header. -+ test.respond("HTTP/1.1 200", "Content-Length: 0") -+ test.wantBodySent() -+ test.wantRequestDone(200) -+} -+ -+func TestTransportExpect100Continue200ResponseWithConnClose(t *testing.T) { -+ test := newTransport100ContinueTest(t, 1*time.Hour) -+ // No 100 Continue response, Connection: close header set. -+ test.respond("HTTP/1.1 200", "Connection: close", "Content-Length: 0") -+ test.wantRequestDone(200) -+} -+ -+func TestTransportExpect100Continue500ResponseNoConnClose(t *testing.T) { -+ test := newTransport100ContinueTest(t, 1*time.Hour) -+ // No 100 Continue response, no Connection: close header. -+ test.respond("HTTP/1.1 500", "Content-Length: 0") -+ test.wantBodySent() -+ test.wantRequestDone(500) -+} -+ -+func TestTransportExpect100Continue500ResponseTimeout(t *testing.T) { -+ test := newTransport100ContinueTest(t, 5*time.Millisecond) // short timeout -+ test.wantBodySent() // after timeout -+ test.respond("HTTP/1.1 200", "Content-Length: 0") -+ test.wantRequestDone(200) - } - - func TestSOCKS5Proxy(t *testing.T) { --- -2.41.0 - diff --git a/backport-0013-release-branch.go1.21-net-http-update-bundled-golang.patch b/backport-0013-release-branch.go1.21-net-http-update-bundled-golang.patch deleted file mode 100644 index e6db2741763df402343c5a10914cc9ab186dfe83..0000000000000000000000000000000000000000 --- a/backport-0013-release-branch.go1.21-net-http-update-bundled-golang.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0574d64ad35b51eb770d6cb59b46c9b3d8540999 Mon Sep 17 00:00:00 2001 -From: Dmitri Shuralyov -Date: Fri, 12 Apr 2024 15:46:59 -0400 -Subject: [PATCH] [release-branch.go1.21] net/http: update bundled - golang.org/x/net/http2 - -Reference:https://go-review.googlesource.com/c/go/+/578357 -Conflict:NA -Pull in CL 578336: - - ef58d90f http2: send correct LastStreamID in stream-caused GOAWAY - -For #66668. -Fixes #66697. - -Change-Id: I91fc8a67f21fadcb1801ff29d5e2b0453db89617 -Reviewed-on: https://go-review.googlesource.com/c/go/+/578357 -Reviewed-by: Carlos Amedee -Reviewed-by: Dmitri Shuralyov -LUCI-TryBot-Result: Go LUCI ---- - src/net/http/h2_bundle.go | 22 +++++++++++++++------- - 1 file changed, 15 insertions(+), 7 deletions(-) - -diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go -index cd95f84269..5ad0c2819b 100644 ---- a/src/net/http/h2_bundle.go -+++ b/src/net/http/h2_bundle.go -@@ -1891,6 +1891,9 @@ func http2terminalReadFrameError(err error) bool { - // returned error is ErrFrameTooLarge. Other errors may be of type - // ConnectionError, StreamError, or anything else from the underlying - // reader. -+// -+// If ReadFrame returns an error and a non-nil Frame, the Frame's StreamID -+// indicates the stream responsible for the error. - func (fr *http2Framer) ReadFrame() (http2Frame, error) { - fr.errDetail = nil - if fr.lastFrame != nil { -@@ -2923,7 +2926,7 @@ func (fr *http2Framer) maxHeaderStringLen() int { - // readMetaFrame returns 0 or more CONTINUATION frames from fr and - // merge them into the provided hf and returns a MetaHeadersFrame - // with the decoded hpack values. --func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFrame, error) { -+func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (http2Frame, error) { - if fr.AllowIllegalReads { - return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders") - } -@@ -2993,8 +2996,8 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - log.Printf("http2: header list too large") - } - // It would be nice to send a RST_STREAM before sending the GOAWAY, -- // but the struture of the server's frame writer makes this difficult. -- return nil, http2ConnectionError(http2ErrCodeProtocol) -+ // but the structure of the server's frame writer makes this difficult. -+ return mh, http2ConnectionError(http2ErrCodeProtocol) - } - - // Also close the connection after any CONTINUATION frame following an -@@ -3005,12 +3008,12 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - log.Printf("http2: invalid header: %v", invalid) - } - // It would be nice to send a RST_STREAM before sending the GOAWAY, -- // but the struture of the server's frame writer makes this difficult. -- return nil, http2ConnectionError(http2ErrCodeProtocol) -+ // but the structure of the server's frame writer makes this difficult. -+ return mh, http2ConnectionError(http2ErrCodeProtocol) - } - - if _, err := hdec.Write(frag); err != nil { -- return nil, http2ConnectionError(http2ErrCodeCompression) -+ return mh, http2ConnectionError(http2ErrCodeCompression) - } - - if hc.HeadersEnded() { -@@ -3027,7 +3030,7 @@ func (fr *http2Framer) readMetaFrame(hf *http2HeadersFrame) (*http2MetaHeadersFr - mh.http2HeadersFrame.invalidate() - - if err := hdec.Close(); err != nil { -- return nil, http2ConnectionError(http2ErrCodeCompression) -+ return mh, http2ConnectionError(http2ErrCodeCompression) - } - if invalid != nil { - fr.errDetail = invalid -@@ -5337,6 +5340,11 @@ func (sc *http2serverConn) processFrameFromReader(res http2readFrameResult) bool - sc.goAway(http2ErrCodeFlowControl) - return true - case http2ConnectionError: -+ if res.f != nil { -+ if id := res.f.Header().StreamID; id > sc.maxClientStreamID { -+ sc.maxClientStreamID = id -+ } -+ } - sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev) - sc.goAway(http2ErrCode(ev)) - return true // goAway will handle shutdown --- -2.33.0 - diff --git a/backport-0014-cmd-compile-handle-constant-pointer-offsets-in-dead-.patch b/backport-0014-cmd-compile-handle-constant-pointer-offsets-in-dead-.patch deleted file mode 100644 index 80c9bbc435bc29922bb31de2ca8c5d820bafd1f4..0000000000000000000000000000000000000000 --- a/backport-0014-cmd-compile-handle-constant-pointer-offsets-in-dead-.patch +++ /dev/null @@ -1,143 +0,0 @@ -From 131f773664fa2d0dbc870e11c388a3131a3a2029 Mon Sep 17 00:00:00 2001 -From: Keith Randall -Date: Sun, 29 Oct 2023 21:00:29 -0700 -Subject: cmd/compile: handle constant pointer offsets in dead store elimination - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/538595 - -Update #63657 -Update #45573 - -Change-Id: I163c6038c13d974dc0ca9f02144472bc05331826 -Reviewed-on: https://go-review.googlesource.com/c/go/+/538595 -LUCI-TryBot-Result: Go LUCI -Reviewed-by: David Chase -Reviewed-by: Keith Randall ---- - src/cmd/compile/internal/ssa/deadstore.go | 64 ++++++++++++++++++++--- - src/cmd/compile/internal/ssa/rewrite.go | 6 +++ - 2 files changed, 62 insertions(+), 8 deletions(-) - -diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go -index 648b68af78b1..7656e45cb9d5 100644 ---- a/src/cmd/compile/internal/ssa/deadstore.go -+++ b/src/cmd/compile/internal/ssa/deadstore.go -@@ -73,9 +73,9 @@ func dse(f *Func) { - } - - // Walk backwards looking for dead stores. Keep track of shadowed addresses. -- // A "shadowed address" is a pointer and a size describing a memory region that -- // is known to be written. We keep track of shadowed addresses in the shadowed -- // map, mapping the ID of the address to the size of the shadowed region. -+ // A "shadowed address" is a pointer, offset, and size describing a memory region that -+ // is known to be written. We keep track of shadowed addresses in the shadowed map, -+ // mapping the ID of the address to a shadowRange where future writes will happen. - // Since we're walking backwards, writes to a shadowed region are useless, - // as they will be immediately overwritten. - shadowed.clear() -@@ -88,13 +88,20 @@ func dse(f *Func) { - shadowed.clear() - } - if v.Op == OpStore || v.Op == OpZero { -+ ptr := v.Args[0] -+ var off int64 -+ for ptr.Op == OpOffPtr { // Walk to base pointer -+ off += ptr.AuxInt -+ ptr = ptr.Args[0] -+ } - var sz int64 - if v.Op == OpStore { - sz = v.Aux.(*types.Type).Size() - } else { // OpZero - sz = v.AuxInt - } -- if shadowedSize := int64(shadowed.get(v.Args[0].ID)); shadowedSize != -1 && shadowedSize >= sz { -+ sr := shadowRange(shadowed.get(ptr.ID)) -+ if sr.contains(off, off+sz) { - // Modify the store/zero into a copy of the memory state, - // effectively eliding the store operation. - if v.Op == OpStore { -@@ -108,10 +115,8 @@ func dse(f *Func) { - v.AuxInt = 0 - v.Op = OpCopy - } else { -- if sz > 0x7fffffff { // work around sparseMap's int32 value type -- sz = 0x7fffffff -- } -- shadowed.set(v.Args[0].ID, int32(sz)) -+ // Extend shadowed region. -+ shadowed.set(ptr.ID, int32(sr.merge(off, off+sz))) - } - } - // walk to previous store -@@ -131,6 +136,49 @@ func dse(f *Func) { - } - } - -+// A shadowRange encodes a set of byte offsets [lo():hi()] from -+// a given pointer that will be written to later in the block. -+// A zero shadowRange encodes an empty shadowed range (and so -+// does a -1 shadowRange, which is what sparsemap.get returns -+// on a failed lookup). -+type shadowRange int32 -+ -+func (sr shadowRange) lo() int64 { -+ return int64(sr & 0xffff) -+} -+func (sr shadowRange) hi() int64 { -+ return int64((sr >> 16) & 0xffff) -+} -+ -+// contains reports whether [lo:hi] is completely within sr. -+func (sr shadowRange) contains(lo, hi int64) bool { -+ return lo >= sr.lo() && hi <= sr.hi() -+} -+ -+// merge returns the union of sr and [lo:hi]. -+// merge is allowed to return something smaller than the union. -+func (sr shadowRange) merge(lo, hi int64) shadowRange { -+ if lo < 0 || hi > 0xffff { -+ // Ignore offsets that are too large or small. -+ return sr -+ } -+ if sr.lo() == sr.hi() { -+ // Old range is empty - use new one. -+ return shadowRange(lo + hi<<16) -+ } -+ if hi < sr.lo() || lo > sr.hi() { -+ // The two regions don't overlap or abut, so we would -+ // have to keep track of multiple disjoint ranges. -+ // Because we can only keep one, keep the larger one. -+ if sr.hi()-sr.lo() >= hi-lo { -+ return sr -+ } -+ return shadowRange(lo + hi<<16) -+ } -+ // Regions overlap or abut - compute the union. -+ return shadowRange(min(lo, sr.lo()) + max(hi, sr.hi())<<16) -+} -+ - // elimDeadAutosGeneric deletes autos that are never accessed. To achieve this - // we track the operations that the address of each auto reaches and if it only - // reaches stores then we delete all the stores. The other operations will then -diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go -index 43843bda5536..5c7ed16f12be 100644 ---- a/src/cmd/compile/internal/ssa/rewrite.go -+++ b/src/cmd/compile/internal/ssa/rewrite.go -@@ -1183,6 +1183,12 @@ func min(x, y int64) int64 { - } - return y - } -+func max(x, y int64) int64 { -+ if x > y { -+ return x -+ } -+ return y -+} - - func isConstZero(v *Value) bool { - switch v.Op { --- -2.33.0 - diff --git a/backport-0015-release-branch.go1.21-cmd-compile-ensure-pointer-ari.patch b/backport-0015-release-branch.go1.21-cmd-compile-ensure-pointer-ari.patch deleted file mode 100644 index 19223d4f424cf18282f3b633985ebe11cf44284b..0000000000000000000000000000000000000000 --- a/backport-0015-release-branch.go1.21-cmd-compile-ensure-pointer-ari.patch +++ /dev/null @@ -1,650 +0,0 @@ -From 8aa0b89560d65438d18fb8ed5ea90d7db2e18fa0 Mon Sep 17 00:00:00 2001 -From: Keith Randall -Date: Wed, 25 Oct 2023 13:35:13 -0700 -Subject: [release-branch.go1.21] cmd/compile: ensure pointer arithmetic - happens after the nil check - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/537775 - -Have nil checks return a pointer that is known non-nil. Users of -that pointer can use the result, ensuring that they are ordered -after the nil check itself. - -The order dependence goes away after scheduling, when we've fixed -an order. At that point we move uses back to the original pointer -so it doesn't change regalloc any. - -This prevents pointer arithmetic on nil from being spilled to the -stack and then observed by a stack scan. - -Fixes #63743 - -Change-Id: I1a5fa4f2e6d9000d672792b4f90dfc1b7b67f6ea -Reviewed-on: https://go-review.googlesource.com/c/go/+/537775 -Reviewed-by: David Chase -LUCI-TryBot-Result: Go LUCI -Reviewed-by: Keith Randall -(cherry picked from commit 962ccbef91057f91518443b648e02fc3afe8c764) -Reviewed-on: https://go-review.googlesource.com/c/go/+/538717 -Auto-Submit: Heschi Kreinick -Reviewed-by: Heschi Kreinick ---- - .../compile/internal/ssa/_gen/generic.rules | 14 ++-- - .../compile/internal/ssa/_gen/genericOps.go | 2 +- - src/cmd/compile/internal/ssa/check.go | 23 ++++++- - src/cmd/compile/internal/ssa/deadcode.go | 7 +- - src/cmd/compile/internal/ssa/deadstore.go | 2 +- - src/cmd/compile/internal/ssa/fuse.go | 2 +- - src/cmd/compile/internal/ssa/fuse_test.go | 2 +- - src/cmd/compile/internal/ssa/nilcheck.go | 42 ++++++------ - src/cmd/compile/internal/ssa/opGen.go | 7 +- - src/cmd/compile/internal/ssa/rewrite.go | 3 + - .../compile/internal/ssa/rewritegeneric.go | 67 ++++++++++--------- - src/cmd/compile/internal/ssa/schedule.go | 18 ++++- - src/cmd/compile/internal/ssa/value.go | 6 +- - src/cmd/compile/internal/ssagen/ssa.go | 17 +++-- - test/fixedbugs/issue63657.go | 48 +++++++++++++ - 15 files changed, 179 insertions(+), 81 deletions(-) - create mode 100644 test/fixedbugs/issue63657.go - -diff --git a/src/cmd/compile/internal/ssa/_gen/generic.rules b/src/cmd/compile/internal/ssa/_gen/generic.rules -index cdb346321e56..d3af465d0e0d 100644 ---- a/src/cmd/compile/internal/ssa/_gen/generic.rules -+++ b/src/cmd/compile/internal/ssa/_gen/generic.rules -@@ -981,7 +981,7 @@ - (ConstNil ) - (ConstNil )) - --(NilCheck (GetG mem) mem) => mem -+(NilCheck ptr:(GetG mem) mem) => ptr - - (If (Not cond) yes no) => (If cond no yes) - (If (ConstBool [c]) yes no) && c => (First yes no) -@@ -2055,19 +2055,19 @@ - && isSameCall(call.Aux, "runtime.newobject") - => mem - --(NilCheck (SelectN [0] call:(StaticLECall _ _)) _) -+(NilCheck ptr:(SelectN [0] call:(StaticLECall _ _)) _) - && isSameCall(call.Aux, "runtime.newobject") - && warnRule(fe.Debug_checknil(), v, "removed nil check") -- => (Invalid) -+ => ptr - --(NilCheck (OffPtr (SelectN [0] call:(StaticLECall _ _))) _) -+(NilCheck ptr:(OffPtr (SelectN [0] call:(StaticLECall _ _))) _) - && isSameCall(call.Aux, "runtime.newobject") - && warnRule(fe.Debug_checknil(), v, "removed nil check") -- => (Invalid) -+ => ptr - - // Addresses of globals are always non-nil. --(NilCheck (Addr {_} (SB)) _) => (Invalid) --(NilCheck (Convert (Addr {_} (SB)) _) _) => (Invalid) -+(NilCheck ptr:(Addr {_} (SB)) _) => ptr -+(NilCheck ptr:(Convert (Addr {_} (SB)) _) _) => ptr - - // for late-expanded calls, recognize memequal applied to a single constant byte - // Support is limited by 1, 2, 4, 8 byte sizes -diff --git a/src/cmd/compile/internal/ssa/_gen/genericOps.go b/src/cmd/compile/internal/ssa/_gen/genericOps.go -index 53ff57f6b12e..aa5fb0e03e66 100644 ---- a/src/cmd/compile/internal/ssa/_gen/genericOps.go -+++ b/src/cmd/compile/internal/ssa/_gen/genericOps.go -@@ -471,7 +471,7 @@ var genericOps = []opData{ - {name: "IsNonNil", argLength: 1, typ: "Bool"}, // arg0 != nil - {name: "IsInBounds", argLength: 2, typ: "Bool"}, // 0 <= arg0 < arg1. arg1 is guaranteed >= 0. - {name: "IsSliceInBounds", argLength: 2, typ: "Bool"}, // 0 <= arg0 <= arg1. arg1 is guaranteed >= 0. -- {name: "NilCheck", argLength: 2, typ: "Void"}, // arg0=ptr, arg1=mem. Panics if arg0 is nil. Returns void. -+ {name: "NilCheck", argLength: 2, nilCheck: true}, // arg0=ptr, arg1=mem. Panics if arg0 is nil. Returns the ptr unmodified. - - // Pseudo-ops - {name: "GetG", argLength: 1, zeroWidth: true}, // runtime.getg() (read g pointer). arg0=mem -diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go -index f34b9074197b..bbfdaceaad90 100644 ---- a/src/cmd/compile/internal/ssa/check.go -+++ b/src/cmd/compile/internal/ssa/check.go -@@ -317,7 +317,28 @@ func checkFunc(f *Func) { - if !v.Aux.(*ir.Name).Type().HasPointers() { - f.Fatalf("vardef must have pointer type %s", v.Aux.(*ir.Name).Type().String()) - } -- -+ case OpNilCheck: -+ // nil checks have pointer type before scheduling, and -+ // void type after scheduling. -+ if f.scheduled { -+ if v.Uses != 0 { -+ f.Fatalf("nilcheck must have 0 uses %s", v.Uses) -+ } -+ if !v.Type.IsVoid() { -+ f.Fatalf("nilcheck must have void type %s", v.Type.String()) -+ } -+ } else { -+ if !v.Type.IsPtrShaped() && !v.Type.IsUintptr() { -+ f.Fatalf("nilcheck must have pointer type %s", v.Type.String()) -+ } -+ } -+ if !v.Args[0].Type.IsPtrShaped() && !v.Args[0].Type.IsUintptr() { -+ f.Fatalf("nilcheck must have argument of pointer type %s", v.Args[0].Type.String()) -+ } -+ if !v.Args[1].Type.IsMemory() { -+ f.Fatalf("bad arg 1 type to %s: want mem, have %s", -+ v.Op, v.Args[1].Type.String()) -+ } - } - - // TODO: check for cycles in values -diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go -index 52cc7f2ca74d..ae9fd2ef2426 100644 ---- a/src/cmd/compile/internal/ssa/deadcode.go -+++ b/src/cmd/compile/internal/ssa/deadcode.go -@@ -110,16 +110,15 @@ func liveValues(f *Func, reachable []bool) (live []bool, liveOrderStmts []*Value - } - } - for _, v := range b.Values { -- if (opcodeTable[v.Op].call || opcodeTable[v.Op].hasSideEffects) && !live[v.ID] { -+ if (opcodeTable[v.Op].call || opcodeTable[v.Op].hasSideEffects || opcodeTable[v.Op].nilCheck) && !live[v.ID] { - live[v.ID] = true - q = append(q, v) - if v.Pos.IsStmt() != src.PosNotStmt { - liveOrderStmts = append(liveOrderStmts, v) - } - } -- if v.Type.IsVoid() && !live[v.ID] { -- // The only Void ops are nil checks and inline marks. We must keep these. -- if v.Op == OpInlMark && !liveInlIdx[int(v.AuxInt)] { -+ if v.Op == OpInlMark { -+ if !liveInlIdx[int(v.AuxInt)] { - // We don't need marks for bodies that - // have been completely optimized away. - // TODO: save marks only for bodies which -diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go -index 7656e45cb9d5..cb3427103c50 100644 ---- a/src/cmd/compile/internal/ssa/deadstore.go -+++ b/src/cmd/compile/internal/ssa/deadstore.go -@@ -249,7 +249,7 @@ func elimDeadAutosGeneric(f *Func) { - } - - if v.Uses == 0 && v.Op != OpNilCheck && !v.Op.IsCall() && !v.Op.HasSideEffects() || len(args) == 0 { -- // Nil check has no use, but we need to keep it. -+ // We need to keep nil checks even if they have no use. - // Also keep calls and values that have side effects. - return - } -diff --git a/src/cmd/compile/internal/ssa/fuse.go b/src/cmd/compile/internal/ssa/fuse.go -index 6d3fb7078059..68defde7b4b9 100644 ---- a/src/cmd/compile/internal/ssa/fuse.go -+++ b/src/cmd/compile/internal/ssa/fuse.go -@@ -169,7 +169,7 @@ func fuseBlockIf(b *Block) bool { - // There may be false positives. - func isEmpty(b *Block) bool { - for _, v := range b.Values { -- if v.Uses > 0 || v.Op.IsCall() || v.Op.HasSideEffects() || v.Type.IsVoid() { -+ if v.Uses > 0 || v.Op.IsCall() || v.Op.HasSideEffects() || v.Type.IsVoid() || opcodeTable[v.Op].nilCheck { - return false - } - } -diff --git a/src/cmd/compile/internal/ssa/fuse_test.go b/src/cmd/compile/internal/ssa/fuse_test.go -index fa7921a18f6f..2f89938d1d92 100644 ---- a/src/cmd/compile/internal/ssa/fuse_test.go -+++ b/src/cmd/compile/internal/ssa/fuse_test.go -@@ -254,7 +254,7 @@ func TestFuseSideEffects(t *testing.T) { - Valu("p", OpArg, c.config.Types.IntPtr, 0, nil), - If("c1", "z0", "exit")), - Bloc("z0", -- Valu("nilcheck", OpNilCheck, types.TypeVoid, 0, nil, "p", "mem"), -+ Valu("nilcheck", OpNilCheck, c.config.Types.IntPtr, 0, nil, "p", "mem"), - Goto("exit")), - Bloc("exit", - Exit("mem"), -diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go -index 4f797a473f71..c69cd8c32ed3 100644 ---- a/src/cmd/compile/internal/ssa/nilcheck.go -+++ b/src/cmd/compile/internal/ssa/nilcheck.go -@@ -38,11 +38,14 @@ func nilcheckelim(f *Func) { - work := make([]bp, 0, 256) - work = append(work, bp{block: f.Entry}) - -- // map from value ID to bool indicating if value is known to be non-nil -- // in the current dominator path being walked. This slice is updated by -+ // map from value ID to known non-nil version of that value ID -+ // (in the current dominator path being walked). This slice is updated by - // walkStates to maintain the known non-nil values. -- nonNilValues := f.Cache.allocBoolSlice(f.NumValues()) -- defer f.Cache.freeBoolSlice(nonNilValues) -+ // If there is extrinsic information about non-nil-ness, this map -+ // points a value to itself. If a value is known non-nil because we -+ // already did a nil check on it, it points to the nil check operation. -+ nonNilValues := f.Cache.allocValueSlice(f.NumValues()) -+ defer f.Cache.freeValueSlice(nonNilValues) - - // make an initial pass identifying any non-nil values - for _, b := range f.Blocks { -@@ -54,7 +57,7 @@ func nilcheckelim(f *Func) { - // We assume that SlicePtr is non-nil because we do a bounds check - // before the slice access (and all cap>0 slices have a non-nil ptr). See #30366. - if v.Op == OpAddr || v.Op == OpLocalAddr || v.Op == OpAddPtr || v.Op == OpOffPtr || v.Op == OpAdd32 || v.Op == OpAdd64 || v.Op == OpSub32 || v.Op == OpSub64 || v.Op == OpSlicePtr { -- nonNilValues[v.ID] = true -+ nonNilValues[v.ID] = v - } - } - } -@@ -68,16 +71,16 @@ func nilcheckelim(f *Func) { - if v.Op == OpPhi { - argsNonNil := true - for _, a := range v.Args { -- if !nonNilValues[a.ID] { -+ if nonNilValues[a.ID] == nil { - argsNonNil = false - break - } - } - if argsNonNil { -- if !nonNilValues[v.ID] { -+ if nonNilValues[v.ID] == nil { - changed = true - } -- nonNilValues[v.ID] = true -+ nonNilValues[v.ID] = v - } - } - } -@@ -103,8 +106,8 @@ func nilcheckelim(f *Func) { - if len(b.Preds) == 1 { - p := b.Preds[0].b - if p.Kind == BlockIf && p.Controls[0].Op == OpIsNonNil && p.Succs[0].b == b { -- if ptr := p.Controls[0].Args[0]; !nonNilValues[ptr.ID] { -- nonNilValues[ptr.ID] = true -+ if ptr := p.Controls[0].Args[0]; nonNilValues[ptr.ID] == nil { -+ nonNilValues[ptr.ID] = ptr - work = append(work, bp{op: ClearPtr, ptr: ptr}) - } - } -@@ -117,14 +120,11 @@ func nilcheckelim(f *Func) { - pendingLines.clear() - - // Next, process values in the block. -- i := 0 - for _, v := range b.Values { -- b.Values[i] = v -- i++ - switch v.Op { - case OpIsNonNil: - ptr := v.Args[0] -- if nonNilValues[ptr.ID] { -+ if nonNilValues[ptr.ID] != nil { - if v.Pos.IsStmt() == src.PosIsStmt { // Boolean true is a terrible statement boundary. - pendingLines.add(v.Pos) - v.Pos = v.Pos.WithNotStmt() -@@ -135,7 +135,7 @@ func nilcheckelim(f *Func) { - } - case OpNilCheck: - ptr := v.Args[0] -- if nonNilValues[ptr.ID] { -+ if nilCheck := nonNilValues[ptr.ID]; nilCheck != nil { - // This is a redundant implicit nil check. - // Logging in the style of the former compiler -- and omit line 1, - // which is usually in generated code. -@@ -145,14 +145,13 @@ func nilcheckelim(f *Func) { - if v.Pos.IsStmt() == src.PosIsStmt { // About to lose a statement boundary - pendingLines.add(v.Pos) - } -- v.reset(OpUnknown) -- f.freeValue(v) -- i-- -+ v.Op = OpCopy -+ v.SetArgs1(nilCheck) - continue - } - // Record the fact that we know ptr is non nil, and remember to - // undo that information when this dominator subtree is done. -- nonNilValues[ptr.ID] = true -+ nonNilValues[ptr.ID] = v - work = append(work, bp{op: ClearPtr, ptr: ptr}) - fallthrough // a non-eliminated nil check might be a good place for a statement boundary. - default: -@@ -163,7 +162,7 @@ func nilcheckelim(f *Func) { - } - } - // This reduces the lost statement count in "go" by 5 (out of 500 total). -- for j := 0; j < i; j++ { // is this an ordering problem? -+ for j := range b.Values { // is this an ordering problem? - v := b.Values[j] - if v.Pos.IsStmt() != src.PosNotStmt && !isPoorStatementOp(v.Op) && pendingLines.contains(v.Pos) { - v.Pos = v.Pos.WithIsStmt() -@@ -174,7 +173,6 @@ func nilcheckelim(f *Func) { - b.Pos = b.Pos.WithIsStmt() - pendingLines.remove(b.Pos) - } -- b.truncateValues(i) - - // Add all dominated blocks to the work list. - for w := sdom[node.block.ID].child; w != nil; w = sdom[w.ID].sibling { -@@ -182,7 +180,7 @@ func nilcheckelim(f *Func) { - } - - case ClearPtr: -- nonNilValues[node.ptr.ID] = false -+ nonNilValues[node.ptr.ID] = nil - continue - } - } -diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go -index 1480fcf45bfd..e7caf9050c15 100644 ---- a/src/cmd/compile/internal/ssa/opGen.go -+++ b/src/cmd/compile/internal/ssa/opGen.go -@@ -39373,9 +39373,10 @@ var opcodeTable = [...]opInfo{ - generic: true, - }, - { -- name: "NilCheck", -- argLen: 2, -- generic: true, -+ name: "NilCheck", -+ argLen: 2, -+ nilCheck: true, -+ generic: true, - }, - { - name: "GetG", -diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go -index 5c7ed16f12be..1cfdc3e10d10 100644 ---- a/src/cmd/compile/internal/ssa/rewrite.go -+++ b/src/cmd/compile/internal/ssa/rewrite.go -@@ -859,6 +859,9 @@ func disjoint(p1 *Value, n1 int64, p2 *Value, n2 int64) bool { - offset += base.AuxInt - base = base.Args[0] - } -+ if opcodeTable[base.Op].nilCheck { -+ base = base.Args[0] -+ } - return base, offset - } - p1, off1 := baseAndOffset(p1) -diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go -index e5bd8bc36f7d..574ac7a1a3ab 100644 ---- a/src/cmd/compile/internal/ssa/rewritegeneric.go -+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go -@@ -18967,79 +18967,84 @@ func rewriteValuegeneric_OpNilCheck(v *Value) bool { - v_0 := v.Args[0] - b := v.Block - fe := b.Func.fe -- // match: (NilCheck (GetG mem) mem) -- // result: mem -+ // match: (NilCheck ptr:(GetG mem) mem) -+ // result: ptr - for { -- if v_0.Op != OpGetG { -+ ptr := v_0 -+ if ptr.Op != OpGetG { - break - } -- mem := v_0.Args[0] -+ mem := ptr.Args[0] - if mem != v_1 { - break - } -- v.copyOf(mem) -+ v.copyOf(ptr) - return true - } -- // match: (NilCheck (SelectN [0] call:(StaticLECall _ _)) _) -+ // match: (NilCheck ptr:(SelectN [0] call:(StaticLECall _ _)) _) - // cond: isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check") -- // result: (Invalid) -+ // result: ptr - for { -- if v_0.Op != OpSelectN || auxIntToInt64(v_0.AuxInt) != 0 { -+ ptr := v_0 -+ if ptr.Op != OpSelectN || auxIntToInt64(ptr.AuxInt) != 0 { - break - } -- call := v_0.Args[0] -+ call := ptr.Args[0] - if call.Op != OpStaticLECall || len(call.Args) != 2 || !(isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")) { - break - } -- v.reset(OpInvalid) -+ v.copyOf(ptr) - return true - } -- // match: (NilCheck (OffPtr (SelectN [0] call:(StaticLECall _ _))) _) -+ // match: (NilCheck ptr:(OffPtr (SelectN [0] call:(StaticLECall _ _))) _) - // cond: isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check") -- // result: (Invalid) -+ // result: ptr - for { -- if v_0.Op != OpOffPtr { -+ ptr := v_0 -+ if ptr.Op != OpOffPtr { - break - } -- v_0_0 := v_0.Args[0] -- if v_0_0.Op != OpSelectN || auxIntToInt64(v_0_0.AuxInt) != 0 { -+ ptr_0 := ptr.Args[0] -+ if ptr_0.Op != OpSelectN || auxIntToInt64(ptr_0.AuxInt) != 0 { - break - } -- call := v_0_0.Args[0] -+ call := ptr_0.Args[0] - if call.Op != OpStaticLECall || len(call.Args) != 2 || !(isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")) { - break - } -- v.reset(OpInvalid) -+ v.copyOf(ptr) - return true - } -- // match: (NilCheck (Addr {_} (SB)) _) -- // result: (Invalid) -+ // match: (NilCheck ptr:(Addr {_} (SB)) _) -+ // result: ptr - for { -- if v_0.Op != OpAddr { -+ ptr := v_0 -+ if ptr.Op != OpAddr { - break - } -- v_0_0 := v_0.Args[0] -- if v_0_0.Op != OpSB { -+ ptr_0 := ptr.Args[0] -+ if ptr_0.Op != OpSB { - break - } -- v.reset(OpInvalid) -+ v.copyOf(ptr) - return true - } -- // match: (NilCheck (Convert (Addr {_} (SB)) _) _) -- // result: (Invalid) -+ // match: (NilCheck ptr:(Convert (Addr {_} (SB)) _) _) -+ // result: ptr - for { -- if v_0.Op != OpConvert { -+ ptr := v_0 -+ if ptr.Op != OpConvert { - break - } -- v_0_0 := v_0.Args[0] -- if v_0_0.Op != OpAddr { -+ ptr_0 := ptr.Args[0] -+ if ptr_0.Op != OpAddr { - break - } -- v_0_0_0 := v_0_0.Args[0] -- if v_0_0_0.Op != OpSB { -+ ptr_0_0 := ptr_0.Args[0] -+ if ptr_0_0.Op != OpSB { - break - } -- v.reset(OpInvalid) -+ v.copyOf(ptr) - return true - } - return false -diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go -index 19b98cc4b83b..0a7425c01729 100644 ---- a/src/cmd/compile/internal/ssa/schedule.go -+++ b/src/cmd/compile/internal/ssa/schedule.go -@@ -312,14 +312,21 @@ func schedule(f *Func) { - } - - // Remove SPanchored now that we've scheduled. -+ // Also unlink nil checks now that ordering is assured -+ // between the nil check and the uses of the nil-checked pointer. - for _, b := range f.Blocks { - for _, v := range b.Values { - for i, a := range v.Args { -- if a.Op == OpSPanchored { -+ if a.Op == OpSPanchored || opcodeTable[a.Op].nilCheck { - v.SetArg(i, a.Args[0]) - } - } - } -+ for i, c := range b.ControlValues() { -+ if c.Op == OpSPanchored || opcodeTable[c.Op].nilCheck { -+ b.ReplaceControl(i, c.Args[0]) -+ } -+ } - } - for _, b := range f.Blocks { - i := 0 -@@ -332,6 +339,15 @@ func schedule(f *Func) { - v.resetArgs() - f.freeValue(v) - } else { -+ if opcodeTable[v.Op].nilCheck { -+ if v.Uses != 0 { -+ base.Fatalf("nilcheck still has %d uses", v.Uses) -+ } -+ // We can't delete the nil check, but we mark -+ // it as having void type so regalloc won't -+ // try to allocate a register for it. -+ v.Type = types.TypeVoid -+ } - b.Values[i] = v - i++ - } -diff --git a/src/cmd/compile/internal/ssa/value.go b/src/cmd/compile/internal/ssa/value.go -index e89024b3c665..9b52da1c58a9 100644 ---- a/src/cmd/compile/internal/ssa/value.go -+++ b/src/cmd/compile/internal/ssa/value.go -@@ -552,7 +552,11 @@ func (v *Value) LackingPos() bool { - // if its use count drops to 0. - func (v *Value) removeable() bool { - if v.Type.IsVoid() { -- // Void ops, like nil pointer checks, must stay. -+ // Void ops (inline marks), must stay. -+ return false -+ } -+ if opcodeTable[v.Op].nilCheck { -+ // Nil pointer checks must stay. - return false - } - if v.Type.IsMemory() { -diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go -index 597a196ba8c4..e994577c641d 100644 ---- a/src/cmd/compile/internal/ssagen/ssa.go -+++ b/src/cmd/compile/internal/ssagen/ssa.go -@@ -1991,7 +1991,8 @@ func (s *state) stmt(n ir.Node) { - case ir.OCHECKNIL: - n := n.(*ir.UnaryExpr) - p := s.expr(n.X) -- s.nilCheck(p) -+ _ = s.nilCheck(p) -+ // TODO: check that throwing away the nilcheck result is ok. - - case ir.OINLMARK: - n := n.(*ir.InlineMarkStmt) -@@ -5621,18 +5622,20 @@ func (s *state) exprPtr(n ir.Node, bounded bool, lineno src.XPos) *ssa.Value { - } - return p - } -- s.nilCheck(p) -+ p = s.nilCheck(p) - return p - } - - // nilCheck generates nil pointer checking code. - // Used only for automatically inserted nil checks, - // not for user code like 'x != nil'. --func (s *state) nilCheck(ptr *ssa.Value) { -+// Returns a "definitely not nil" copy of x to ensure proper ordering -+// of the uses of the post-nilcheck pointer. -+func (s *state) nilCheck(ptr *ssa.Value) *ssa.Value { - if base.Debug.DisableNil != 0 || s.curfn.NilCheckDisabled() { -- return -+ return ptr - } -- s.newValue2(ssa.OpNilCheck, types.TypeVoid, ptr, s.mem()) -+ return s.newValue2(ssa.OpNilCheck, ptr.Type, ptr, s.mem()) - } - - // boundsCheck generates bounds checking code. Checks if 0 <= idx <[=] len, branches to exit if not. -@@ -5984,8 +5987,8 @@ func (s *state) slice(v, i, j, k *ssa.Value, bounded bool) (p, l, c *ssa.Value) - if !t.Elem().IsArray() { - s.Fatalf("bad ptr to array in slice %v\n", t) - } -- s.nilCheck(v) -- ptr = s.newValue1(ssa.OpCopy, types.NewPtr(t.Elem().Elem()), v) -+ nv := s.nilCheck(v) -+ ptr = s.newValue1(ssa.OpCopy, types.NewPtr(t.Elem().Elem()), nv) - len = s.constInt(types.Types[types.TINT], t.Elem().NumElem()) - cap = len - default: -diff --git a/test/fixedbugs/issue63657.go b/test/fixedbugs/issue63657.go -new file mode 100644 -index 000000000000..e32a4a34fbb6 ---- /dev/null -+++ b/test/fixedbugs/issue63657.go -@@ -0,0 +1,48 @@ -+// run -+ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+// Make sure address calculations don't float up before -+// the corresponding nil check. -+ -+package main -+ -+type T struct { -+ a, b int -+} -+ -+//go:noinline -+func f(x *T, p *bool, n int) { -+ *p = n != 0 -+ useStack(1000) -+ g(&x.b) -+} -+ -+//go:noinline -+func g(p *int) { -+} -+ -+func useStack(n int) { -+ if n == 0 { -+ return -+ } -+ useStack(n - 1) -+} -+ -+func main() { -+ mustPanic(func() { -+ var b bool -+ f(nil, &b, 3) -+ }) -+} -+ -+func mustPanic(f func()) { -+ defer func() { -+ if recover() == nil { -+ panic("expected panic, got nil") -+ } -+ }() -+ f() -+} --- -2.33.0 - diff --git a/backport-0016-release-branch.go1.21-internal-poll-add-SPLICE_F_NON.patch b/backport-0016-release-branch.go1.21-internal-poll-add-SPLICE_F_NON.patch deleted file mode 100644 index 134d88f55bbf2f5a1f485d2ce03bdaa272aaae56..0000000000000000000000000000000000000000 --- a/backport-0016-release-branch.go1.21-internal-poll-add-SPLICE_F_NON.patch +++ /dev/null @@ -1,79 +0,0 @@ -From fef8644451930464ffd9f13c82bcd451f58fa575 Mon Sep 17 00:00:00 2001 -From: Andy Pan -Date: Tue, 17 Oct 2023 22:38:17 +0800 -Subject: [PATCH 03/20] [release-branch.go1.21] internal/poll: add - SPLICE_F_NONBLOCK flag for splice to avoid inconsistency with O_NONBLOCK - -Fixes #63801 -Updates #59041 -Updates #63795 - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/536015 - -Details: https://github.com/golang/go/issues/59041#issuecomment-1766610087 - -Change-Id: Id3fc1df6d86b7c4cc383d09f9465fa8f4cc2a559 -Reviewed-on: https://go-review.googlesource.com/c/go/+/536015 -Reviewed-by: Bryan Mills -Reviewed-by: Ian Lance Taylor -LUCI-TryBot-Result: Go LUCI -Auto-Submit: Ian Lance Taylor -(cherry picked from commit 40cdf69fc9279ab28f84a6e0f965de8382c578fe) -Reviewed-on: https://go-review.googlesource.com/c/go/+/538117 -Auto-Submit: Heschi Kreinick -Reviewed-by: Mauri de Souza Meneguzzo -Reviewed-by: Heschi Kreinick ---- - src/internal/poll/splice_linux.go | 21 +++++++++++++++++++-- - 1 file changed, 19 insertions(+), 2 deletions(-) - -diff --git a/src/internal/poll/splice_linux.go b/src/internal/poll/splice_linux.go -index 9505c5dcfc1e..72cca34fe4ae 100644 ---- a/src/internal/poll/splice_linux.go -+++ b/src/internal/poll/splice_linux.go -@@ -13,6 +13,12 @@ import ( - ) - - const ( -+ // spliceNonblock doesn't make the splice itself necessarily nonblocking -+ // (because the actual file descriptors that are spliced from/to may block -+ // unless they have the O_NONBLOCK flag set), but it makes the splice pipe -+ // operations nonblocking. -+ spliceNonblock = 0x2 -+ - // maxSpliceSize is the maximum amount of data Splice asks - // the kernel to move in a single call to splice(2). - // We use 1MB as Splice writes data through a pipe, and 1MB is the default maximum pipe buffer size, -@@ -89,7 +95,11 @@ func spliceDrain(pipefd int, sock *FD, max int) (int, error) { - return 0, err - } - for { -- n, err := splice(pipefd, sock.Sysfd, max, 0) -+ // In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here, -+ // because it could return EAGAIN ceaselessly when the write end of the pipe is full, -+ // but this shouldn't be a concern here, since the pipe buffer must be sufficient for -+ // this data transmission on the basis of the workflow in Splice. -+ n, err := splice(pipefd, sock.Sysfd, max, spliceNonblock) - if err == syscall.EINTR { - continue - } -@@ -127,7 +137,14 @@ func splicePump(sock *FD, pipefd int, inPipe int) (int, error) { - } - written := 0 - for inPipe > 0 { -- n, err := splice(sock.Sysfd, pipefd, inPipe, 0) -+ // In theory calling splice(2) with SPLICE_F_NONBLOCK could end up an infinite loop here, -+ // because it could return EAGAIN ceaselessly when the read end of the pipe is empty, -+ // but this shouldn't be a concern here, since the pipe buffer must contain inPipe size of -+ // data on the basis of the workflow in Splice. -+ n, err := splice(sock.Sysfd, pipefd, inPipe, spliceNonblock) -+ if err == syscall.EINTR { -+ continue -+ } - // Here, the condition n == 0 && err == nil should never be - // observed, since Splice controls the write side of the pipe. - if n > 0 { --- -2.33.0 - diff --git a/backport-0017-release-branch.go1.21-runtime-call-enableMetadataHug.patch b/backport-0017-release-branch.go1.21-runtime-call-enableMetadataHug.patch deleted file mode 100644 index dec6f61483b459de5946ef69b7ca9f4580255393..0000000000000000000000000000000000000000 --- a/backport-0017-release-branch.go1.21-runtime-call-enableMetadataHug.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 05bf700ebeec865b73500bd6a2ae93ddbd051692 Mon Sep 17 00:00:00 2001 -From: Michael Anthony Knyszek -Date: Fri, 10 Nov 2023 21:23:38 +0000 -Subject: [PATCH 04/20] [release-branch.go1.21] runtime: call - enableMetadataHugePages and its callees on the systemstack - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/541635 - -These functions acquire the heap lock. If they're not called on the -systemstack, a stack growth could cause a self-deadlock since stack -growth may allocate memory from the page heap. - -This has been a problem for a while. If this is what's plaguing the -ppc64 port right now, it's very surprising (and probably just -coincidental) that it's showing up now. - -For #64050. -For #64062. -For #64067. -Fixes #64073. - -Change-Id: I2b95dc134d17be63b9fe8f7a3370fe5b5438682f -Reviewed-on: https://go-review.googlesource.com/c/go/+/541635 -LUCI-TryBot-Result: Go LUCI -Run-TryBot: Michael Knyszek -Auto-Submit: Michael Knyszek -TryBot-Result: Gopher Robot -Reviewed-by: Michael Pratt -Reviewed-by: Paul Murphy -(cherry picked from commit 5f08b4479930af266d4a84c1533b320ed75edba7) -Reviewed-on: https://go-review.googlesource.com/c/go/+/541955 -Reviewed-by: Dmitri Shuralyov -Reviewed-by: Dmitri Shuralyov -Auto-Submit: Dmitri Shuralyov ---- - src/runtime/malloc.go | 4 ++++ - src/runtime/mgc.go | 4 +++- - src/runtime/mpagealloc.go | 4 ++++ - 3 files changed, 11 insertions(+), 1 deletion(-) - -diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go -index 44479cc2be26..b2026ad0dc72 100644 ---- a/src/runtime/malloc.go -+++ b/src/runtime/malloc.go -@@ -853,6 +853,10 @@ retry: - // - // The heap lock must not be held over this operation, since it will briefly acquire - // the heap lock. -+// -+// Must be called on the system stack because it acquires the heap lock. -+// -+//go:systemstack - func (h *mheap) enableMetadataHugePages() { - // Enable huge pages for page structure. - h.pages.enableChunkHugePages() -diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go -index de5ae0ae00c4..a12dbfe9df29 100644 ---- a/src/runtime/mgc.go -+++ b/src/runtime/mgc.go -@@ -1186,7 +1186,9 @@ func gcMarkTermination() { - - // Enable huge pages on some metadata if we cross a heap threshold. - if gcController.heapGoal() > minHeapForMetadataHugePages { -- mheap_.enableMetadataHugePages() -+ systemstack(func() { -+ mheap_.enableMetadataHugePages() -+ }) - } - - semrelease(&worldsema) -diff --git a/src/runtime/mpagealloc.go b/src/runtime/mpagealloc.go -index 3e789ab85cc0..2861fa93ebf0 100644 ---- a/src/runtime/mpagealloc.go -+++ b/src/runtime/mpagealloc.go -@@ -437,6 +437,10 @@ func (p *pageAlloc) grow(base, size uintptr) { - // - // The heap lock must not be held over this operation, since it will briefly acquire - // the heap lock. -+// -+// Must be called on the system stack because it acquires the heap lock. -+// -+//go:systemstack - func (p *pageAlloc) enableChunkHugePages() { - // Grab the heap lock to turn on huge pages for new chunks and clone the current - // heap address space ranges. --- -2.33.0 - diff --git a/backport-0018-release-branch.go1.21-cmd-compile-fix-findIndVar-so-.patch b/backport-0018-release-branch.go1.21-cmd-compile-fix-findIndVar-so-.patch deleted file mode 100644 index fbd8b6a600b340a0173205e7cec69ac8c5e1da15..0000000000000000000000000000000000000000 --- a/backport-0018-release-branch.go1.21-cmd-compile-fix-findIndVar-so-.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 4ef68a16e21a2e63f2f6bdc498fe34c9ca994011 Mon Sep 17 00:00:00 2001 -From: Jorropo -Date: Sun, 5 Nov 2023 22:40:01 +0100 -Subject: [PATCH 05/20] [release-branch.go1.21] cmd/compile: fix findIndVar so - it does not match disjointed loop headers - -Fix #63984 - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/539977 - -parseIndVar, prove and maybe more are on the assumption that the loop header -is a single block. This can be wrong, ensure we don't match theses cases we -don't know how to handle. - -In the future we could update them so that they know how to handle such cases -but theses cases seems rare so I don't think the value would be really high. -We could also run a loop canonicalization pass first which could handle this. - -The repro case looks weird because I massaged it so it would crash with the -previous compiler. - -Change-Id: I4aa8afae9e90a17fa1085832250fc1139c97faa6 -Reviewed-on: https://go-review.googlesource.com/c/go/+/539977 -Reviewed-by: Heschi Kreinick -Reviewed-by: Keith Randall -Reviewed-by: Keith Randall -LUCI-TryBot-Result: Go LUCI -(cherry picked from commit 8b4e1259d0e82c8fe38a1456f997a4e9d63573a2) -Reviewed-on: https://go-review.googlesource.com/c/go/+/540535 -Reviewed-by: Jorropo -Reviewed-by: Mauri de Souza Meneguzzo -Reviewed-by: Dmitri Shuralyov -Reviewed-by: Dmitri Shuralyov -Auto-Submit: Dmitri Shuralyov -Reviewed-by: Michael Knyszek ---- - src/cmd/compile/internal/ssa/loopbce.go | 7 +++++++ - test/fixedbugs/issue63955.go | 22 ++++++++++++++++++++++ - 2 files changed, 29 insertions(+) - create mode 100644 test/fixedbugs/issue63955.go - -diff --git a/src/cmd/compile/internal/ssa/loopbce.go b/src/cmd/compile/internal/ssa/loopbce.go -index b7dfaa33e3bf..7f432e61ba50 100644 ---- a/src/cmd/compile/internal/ssa/loopbce.go -+++ b/src/cmd/compile/internal/ssa/loopbce.go -@@ -127,6 +127,13 @@ func findIndVar(f *Func) []indVar { - less = false - } - -+ if ind.Block != b { -+ // TODO: Could be extended to include disjointed loop headers. -+ // I don't think this is causing missed optimizations in real world code often. -+ // See https://go.dev/issue/63955 -+ continue -+ } -+ - // Expect the increment to be a nonzero constant. - if !inc.isGenericIntConst() { - continue -diff --git a/test/fixedbugs/issue63955.go b/test/fixedbugs/issue63955.go -new file mode 100644 -index 000000000000..258e874220f0 ---- /dev/null -+++ b/test/fixedbugs/issue63955.go -@@ -0,0 +1,22 @@ -+// compile -+ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package j -+ -+func f(try func() int, shouldInc func() bool, N func(int) int) { -+ var n int -+loop: // we want to have 3 preds here, the function entry and both gotos -+ if v := try(); v == 42 || v == 1337 { // the two || are to trick findIndVar -+ if n < 30 { // this aims to be the matched block -+ if shouldInc() { -+ n++ -+ goto loop -+ } -+ n = N(n) // try to prevent some block joining -+ goto loop -+ } -+ } -+} --- -2.33.0 - diff --git a/backport-0019-release-branch.go1.21-cmd-compile-fix-escape-analysi.patch b/backport-0019-release-branch.go1.21-cmd-compile-fix-escape-analysi.patch deleted file mode 100644 index 8aa6e2e6589c8a1a2243dd94781268b2b2a65a0d..0000000000000000000000000000000000000000 --- a/backport-0019-release-branch.go1.21-cmd-compile-fix-escape-analysi.patch +++ /dev/null @@ -1,112 +0,0 @@ -From ce09caaeea688251e21a1749ccb89d9160fe2fb2 Mon Sep 17 00:00:00 2001 -From: Matthew Dempsky -Date: Tue, 5 Dec 2023 12:56:04 -0800 -Subject: [PATCH 06/20] [release-branch.go1.21] cmd/compile: fix escape - analysis of string min/max - -Conflict:NA -Reference:https://go-review.googlesource.com/c/go/+/547715 - -When I was plumbing min/max support through the compiler, I was -thinking mostly about numeric argument types. As a result, I forgot -that escape analysis would need to be aware that min/max can operate -on string values, which contain pointers. - -Updates #64565. -Fixes #64567. - -Change-Id: I36127ce5a2da942401910fa0f9de922726c9f94d -Reviewed-on: https://go-review.googlesource.com/c/go/+/547715 -Reviewed-by: Keith Randall -Reviewed-by: Mauri de Souza Meneguzzo -Auto-Submit: Matthew Dempsky -LUCI-TryBot-Result: Go LUCI -(cherry picked from commit 34416d7f6f93cd6562636e311c362ebe421f1a4c) -Reviewed-on: https://go-review.googlesource.com/c/go/+/547757 -Reviewed-by: Cuong Manh Le -Reviewed-by: Keith Randall ---- - src/cmd/compile/internal/escape/call.go | 10 +++++++++- - test/escape_calls.go | 7 +++++++ - test/fixedbugs/issue64565.go | 15 +++++++++++++++ - test/fixedbugs/issue64565.out | 3 +++ - 4 files changed, 34 insertions(+), 1 deletion(-) - create mode 100644 test/fixedbugs/issue64565.go - create mode 100644 test/fixedbugs/issue64565.out - -diff --git a/src/cmd/compile/internal/escape/call.go b/src/cmd/compile/internal/escape/call.go -index c69eca199877..36e606bf2090 100644 ---- a/src/cmd/compile/internal/escape/call.go -+++ b/src/cmd/compile/internal/escape/call.go -@@ -186,7 +186,7 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir - argument(e.discardHole(), &call.X) - argument(e.discardHole(), &call.Y) - -- case ir.ODELETE, ir.OMAX, ir.OMIN, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: -+ case ir.ODELETE, ir.OPRINT, ir.OPRINTN, ir.ORECOVER: - call := call.(*ir.CallExpr) - fixRecoverCall(call) - for i := range call.Args { -@@ -194,6 +194,14 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir - } - argumentRType(&call.RType) - -+ case ir.OMIN, ir.OMAX: -+ call := call.(*ir.CallExpr) -+ fixRecoverCall(call) -+ for i := range call.Args { -+ argument(ks[0], &call.Args[i]) -+ } -+ argumentRType(&call.RType) -+ - case ir.OLEN, ir.OCAP, ir.OREAL, ir.OIMAG, ir.OCLOSE, ir.OCLEAR: - call := call.(*ir.UnaryExpr) - argument(e.discardHole(), &call.X) -diff --git a/test/escape_calls.go b/test/escape_calls.go -index aa7c7f516cf9..5424c006ee4d 100644 ---- a/test/escape_calls.go -+++ b/test/escape_calls.go -@@ -52,3 +52,10 @@ func bar() { - s := "string" - f([]string{s}) // ERROR "\[\]string{...} escapes to heap" - } -+ -+func strmin(a, b, c string) string { // ERROR "leaking param: a to result ~r0 level=0" "leaking param: b to result ~r0 level=0" "leaking param: c to result ~r0 level=0" -+ return min(a, b, c) -+} -+func strmax(a, b, c string) string { // ERROR "leaking param: a to result ~r0 level=0" "leaking param: b to result ~r0 level=0" "leaking param: c to result ~r0 level=0" -+ return max(a, b, c) -+} -diff --git a/test/fixedbugs/issue64565.go b/test/fixedbugs/issue64565.go -new file mode 100644 -index 000000000000..634025ce3ece ---- /dev/null -+++ b/test/fixedbugs/issue64565.go -@@ -0,0 +1,15 @@ -+// run -+ -+// Copyright 2023 The Go Authors. All rights reserved. -+// Use of this source code is governed by a BSD-style -+// license that can be found in the LICENSE file. -+ -+package main -+ -+func main() { -+ m := "0" -+ for _, c := range "321" { -+ m = max(string(c), m) -+ println(m) -+ } -+} -diff --git a/test/fixedbugs/issue64565.out b/test/fixedbugs/issue64565.out -new file mode 100644 -index 000000000000..1f242fa6f000 ---- /dev/null -+++ b/test/fixedbugs/issue64565.out -@@ -0,0 +1,3 @@ -+3 -+3 -+3 --- -2.33.0 - diff --git a/go1.21.4.src.tar.gz b/go1.22.0.src.tar.gz similarity index 71% rename from go1.21.4.src.tar.gz rename to go1.22.0.src.tar.gz index 9b9ceeb53d04f98af4fa203b68ea2ebdb035cdc2..3878ecd8293db8a294a8ab157790d64e5aede062 100644 Binary files a/go1.21.4.src.tar.gz and b/go1.22.0.src.tar.gz differ diff --git a/golang.spec b/golang.spec index da4b9b0637fd03ee4e584dd5fcbc4b29f061596e..b6a23457839ec6c09bf06a5144957e34f9b2f8ee 100644 --- a/golang.spec +++ b/golang.spec @@ -65,8 +65,8 @@ %endif Name: golang -Version: 1.21.4 -Release: 21 +Version: 1.22.0 +Release: 1 Summary: The Go Programming Language License: BSD and Public Domain URL: https://golang.org/ @@ -120,26 +120,6 @@ Obsoletes: %{name}-vim < 1.4 Obsoletes: emacs-%{name} < 1.4 Requires: %{vendor}-rpm-config -Patch6001: backport-0001-release-branch.go1.21-crypto-x509-make-sure-pub-key-.patch -Patch6002: backport-0002-release-branch.go1.21-html-template-escape-additiona.patch -Patch6003: backport-0003-release-branch.go1.21-net-textproto-mime-multipart-a.patch -Patch6004: backport-0004-release-branch.go1.21-net-http-net-http-cookiejar-av.patch -Patch6005: backport-0005-release-branch.go1.21-net-mail-properly-handle-speci.patch -Patch6006: backport-0006-Backport-net-http-update-bundled-golang.org-x-net-ht.patch -Patch6007: backport-0007-Backport-cmd-go-disallow-lto_library-in-LDFLAGS.patch -Patch6008: backport-0008-release-branch.go1.21-net-netip-check-if-address-is-v6.patch -Patch6009: backport-0009-Backport-cmd-go-internal-vcs-error-out-if-the-reques.patch -Patch6010: backport-0010-release-branch.go1.21-net-http-limit-chunked-data-ov.patch -Patch6011: backport-0011-Backport-archive-zip-treat-truncated-EOCDR-comment-a.patch -Patch6012: backport-0012-net-http-send-body-or-close-connection-on-expect-100.patch -Patch6013: backport-0013-release-branch.go1.21-net-http-update-bundled-golang.patch -Patch6014: backport-0014-cmd-compile-handle-constant-pointer-offsets-in-dead-.patch -Patch6015: backport-0015-release-branch.go1.21-cmd-compile-ensure-pointer-ari.patch -Patch6016: backport-0016-release-branch.go1.21-internal-poll-add-SPLICE_F_NON.patch -Patch6017: backport-0017-release-branch.go1.21-runtime-call-enableMetadataHug.patch -Patch6018: backport-0018-release-branch.go1.21-cmd-compile-fix-findIndVar-so-.patch -Patch6019: backport-0019-release-branch.go1.21-cmd-compile-fix-escape-analysi.patch - ExclusiveArch: %{golang_arches} %description @@ -377,6 +357,9 @@ fi %files devel -f go-tests.list -f go-misc.list -f go-src.list %changelog +* Tue Sep 24 2024 shafeipaozi - 1.22.0-1 +- upgrade to 1.22.0 + * Thu Sep 19 2024 Vanient - 1.21.4-21 - cmd/compile: fix escape analysis of string min/max