Compare commits

..

23 Commits

Author SHA1 Message Date
Jakub Čajka 27a8ad3859
Rebase to go1.15.5
Security fix for CVE-2020-28362, CVE-2020-28367 and CVE-2020-28366
Resolves: BZ#1897342, BZ#1897636, BZ#1897644, BZ#1897647
2020-11-14 08:55:50 +01:00
Jakub Čajka c88a8dfff5
Rebase to go1.15.4
Resolves BZ#1895189
2020-11-06 16:34:38 +01:00
Jakub Čajka 61730a32f4
Rebase to go1.15.3
Resolves: BZ#1888443
2020-10-15 13:41:00 +02:00
Jakub Čajka d7ab797463
Rebase to go1.15.2
Resolves: BZ#1877565
2020-09-10 12:57:26 +02:00
Jakub Čajka fb39d90765
Rebase to go1.15.1
Security fix for CVE-2020-24553
Resolves: BZ#1874858, BZ#1866892
2020-09-04 15:43:41 +02:00
Jakub Čajka d3aa981e83
Rebase to go1.15 proper
Resolves: BZ#1859241, BZ#1866892
2020-08-12 10:33:11 +02:00
Jakub Čajka dac586c9c7
Rebase to go1.15rc1
Security fix for CVE-2020-16845
Resolves: BZ#1867101
Related: BZ#1859241
2020-08-10 12:04:23 +02:00
Fedora Release Engineering e8c1f5c4a2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>
2020-07-27 20:57:54 +00:00
Jakub Čajka 132cf34fe6
Rebase to go1.15rc1
Related: BZ#1859241
2020-07-27 10:26:48 +02:00
Jakub Čajka a3e201c572
Rebase to go1.15beta1 2020-07-20 18:36:44 +02:00
Jakub Čajka 6db1c7a908
Rebase to go1.14.6
Security fix for CVE-2020-14040 and CVE-2020-15586
Resolves: BZ#1842708, BZ#1856957, BZ#1853653
2020-07-20 10:27:10 +02:00
Alejandro Sáez 0cb15e561e Add patch that fixes issue in ppc64le
Fix: https://golang.org/issue/39991
Add sources
2020-07-14 14:48:03 +02:00
Jakub Čajka 91d21a3bde
It is FALGS 2020-07-03 08:31:27 +02:00
Jakub Čajka ea99ebaff6
Workaround tests failures on aarch64 2020-07-02 21:35:44 +02:00
Alejandro Sáez ecf8f72447 Rebase to go1.14.4
Related: BZ#1842708
2020-07-02 18:30:16 +00:00
Jakub Čajka fde02715d5
Add new sources and BZ 2020-05-21 08:37:26 +02:00
Álex Sáez 8716ef4de3 Rebase to go1.14.3 2020-05-18 19:59:24 +02:00
Jakub Čajka aa89c2b0f2
Rebase to go1.14.2
Resolves: BZ#1815282
2020-04-20 13:34:36 +02:00
Neal Gompa 1f08860197 Fix building on older than EL8
Signed-off-by: Neal Gompa <ngompa13@gmail.com>
2020-04-18 13:26:06 -04:00
Jakub Čajka 4487a1b142
Rebase to go1.14 proper
Resolves: BZ#1792475
2020-02-26 15:26:46 +01:00
Jakub Čajka 9f5b8dce35
Rebase to go1.14rc1 2020-02-06 13:40:49 +01:00
Fedora Release Engineering 4751ecad2f - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
Signed-off-by: Fedora Release Engineering <releng@fedoraproject.org>
2020-01-28 23:13:43 +00:00
Jakub Čajka fd2a3fb06e
Rebase to go1.14beta1
Resolves: BZ#1792475
2020-01-21 10:24:40 +01:00
16 changed files with 306 additions and 1877 deletions

28
.gitignore vendored
View File

@ -37,7 +37,6 @@
/go1.7.1.src.tar.gz
/go1.7.3.src.tar.gz
/go1.7.4.src.tar.gz
/go1.7.6.src.tar.gz
/go1.8rc3.src.tar.gz
/go1.8.src.tar.gz
/go1.8.1.src.tar.gz
@ -46,11 +45,6 @@
/go1.9.src.tar.gz
/go1.9.1.src.tar.gz
/go1.9.2.src.tar.gz
/go1.9.3.src.tar.gz
/go1.9.4.src.tar.gz
/go1.9.5.src.tar.gz
/go1.9.6.src.tar.gz
/go1.9.7.src.tar.gz
/go1.10beta1.src.tar.gz
/go1.10beta2.src.tar.gz
/go1.10rc1.src.tar.gz
@ -68,12 +62,6 @@
/go1.11.1.src.tar.gz
/go1.11.2.src.tar.gz
/go1.11.4.src.tar.gz
/go1.11.5.src.tar.gz
/go1.11.6.src.tar.gz
/go1.11.7.src.tar.gz
/go1.11.10.src.tar.gz
/go1.11.11.src.tar.gz
/go1.11.12.src.tar.gz
/go1.12beta2.src.tar.gz
/go1.12rc1.src.tar.gz
/go1.12.src.tar.gz
@ -91,3 +79,19 @@
/go1.13.4.src.tar.gz
/go1.13.5.src.tar.gz
/go1.13.6.src.tar.gz
/go1.14beta1.src.tar.gz
/go1.14rc1.src.tar.gz
/go1.14.src.tar.gz
/go1.14.2.src.tar.gz
/go1.14.3.src.tar.gz
/go1.14.4.src.tar.gz
/go1.14.6.src.tar.gz
/go1.15beta1.src.tar.gz
/go1.15rc1.src.tar.gz
/go1.15rc2.src.tar.gz
/go1.15.src.tar.gz
/go1.15.1.src.tar.gz
/go1.15.2.src.tar.gz
/go1.15.3.src.tar.gz
/go1.15.4.src.tar.gz
/go1.15.5.src.tar.gz

View File

@ -1,28 +1,34 @@
From 014cbe9e8cdc1a5f78f3e792309133eaaabdfc8f Mon Sep 17 00:00:00 2001
From b38cd2374c2395f5a77802ef8ea3d7ac5b8a86ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jakub=20=C4=8Cajka?= <jcajka@redhat.com>
Date: Mon, 27 May 2019 15:12:53 +0200
Subject: [PATCH 3/3] cmd/go: disable Google's proxy and sumdb
---
src/cmd/go/internal/cfg/cfg.go | 4 ++--
src/cmd/go/testdata/script/mod_sumdb_golang.txt | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
src/cmd/go/internal/cfg/cfg.go | 10 +++++-----
src/cmd/go/testdata/script/mod_sumdb_golang.txt | 6 +++---
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go
index a0b51a72c3..b972a81df2 100644
index 61dc6bdda6..e8658dc56c 100644
--- a/src/cmd/go/internal/cfg/cfg.go
+++ b/src/cmd/go/internal/cfg/cfg.go
@@ -292,8 +292,8 @@ var (
@@ -245,11 +245,11 @@ var (
GOPPC64 = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", objabi.GOPPC64))
GOWASM = envOr("GOWASM", fmt.Sprint(objabi.GOWASM))
- GOPROXY = envOr("GOPROXY", "https://proxy.golang.org,direct")
- GOSUMDB = envOr("GOSUMDB", "sum.golang.org")
- GOPROXY = envOr("GOPROXY", "https://proxy.golang.org,direct")
- GOSUMDB = envOr("GOSUMDB", "sum.golang.org")
- GOPRIVATE = Getenv("GOPRIVATE")
- GONOPROXY = envOr("GONOPROXY", GOPRIVATE)
- GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE)
+ GOPROXY = envOr("GOPROXY", "direct")
+ GOSUMDB = envOr("GOSUMDB", "off")
GOPRIVATE = Getenv("GOPRIVATE")
GONOPROXY = envOr("GONOPROXY", GOPRIVATE)
GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE)
+ GOPRIVATE = Getenv("GOPRIVATE")
+ GONOPROXY = envOr("GONOPROXY", GOPRIVATE)
+ GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE)
GOINSECURE = Getenv("GOINSECURE")
)
diff --git a/src/cmd/go/testdata/script/mod_sumdb_golang.txt b/src/cmd/go/testdata/script/mod_sumdb_golang.txt
index 40a07fc7e9..50436e32d7 100644
--- a/src/cmd/go/testdata/script/mod_sumdb_golang.txt

View File

@ -1,135 +0,0 @@
commit 117ddcb83d7f42d6aa72241240af99ded81118e9
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Jun 30 09:22:41 2015 -0700
net/textproto: don't treat spaces as hyphens in header keys
This was originally done in https://codereview.appspot.com/5690059
(Feb 2012) to deal with bad response headers coming back from webcams,
but it presents a potential security problem with HTTP request
smuggling for request headers containing "Content Length" instead of
"Content-Length".
Part of overall HTTP hardening for request smuggling. See RFC 7230.
Thanks to Régis Leroy for the report.
Change-Id: I92b17fb637c9171c5774ea1437979ae2c17ca88a
Reviewed-on: https://go-review.googlesource.com/11772
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/net/http/header.go b/src/net/http/header.go
index 153b943..d847b13 100644
--- a/src/net/http/header.go
+++ b/src/net/http/header.go
@@ -168,6 +168,8 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) error {
// letter and any letter following a hyphen to upper case;
// the rest are converted to lowercase. For example, the
// canonical key for "accept-encoding" is "Accept-Encoding".
+// If s contains a space or invalid header field bytes, it is
+// returned without modifications.
func CanonicalHeaderKey(s string) string { return textproto.CanonicalMIMEHeaderKey(s) }
// hasToken reports whether token appears with v, ASCII
diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
index e4b8f6b..91303fe 100644
--- a/src/net/textproto/reader.go
+++ b/src/net/textproto/reader.go
@@ -547,11 +547,16 @@ func (r *Reader) upcomingHeaderNewlines() (n int) {
// the rest are converted to lowercase. For example, the
// canonical key for "accept-encoding" is "Accept-Encoding".
// MIME header keys are assumed to be ASCII only.
+// If s contains a space or invalid header field bytes, it is
+// returned without modifications.
func CanonicalMIMEHeaderKey(s string) string {
// Quick check for canonical encoding.
upper := true
for i := 0; i < len(s); i++ {
c := s[i]
+ if !validHeaderFieldByte(c) {
+ return s
+ }
if upper && 'a' <= c && c <= 'z' {
return canonicalMIMEHeaderKey([]byte(s))
}
@@ -565,19 +570,44 @@ func CanonicalMIMEHeaderKey(s string) string {
const toLower = 'a' - 'A'
+// validHeaderFieldByte reports whether b is a valid byte in a header
+// field key. This is actually stricter than RFC 7230, which says:
+// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
+// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
+// token = 1*tchar
+// TODO: revisit in Go 1.6+ and possibly expand this. But note that many
+// servers have historically dropped '_' to prevent ambiguities when mapping
+// to CGI environment variables.
+func validHeaderFieldByte(b byte) bool {
+ return ('A' <= b && b <= 'Z') ||
+ ('a' <= b && b <= 'z') ||
+ ('0' <= b && b <= '9') ||
+ b == '-'
+}
+
// canonicalMIMEHeaderKey is like CanonicalMIMEHeaderKey but is
// allowed to mutate the provided byte slice before returning the
// string.
+//
+// For invalid inputs (if a contains spaces or non-token bytes), a
+// is unchanged and a string copy is returned.
func canonicalMIMEHeaderKey(a []byte) string {
+ // See if a looks like a header key. If not, return it unchanged.
+ for _, c := range a {
+ if validHeaderFieldByte(c) {
+ continue
+ }
+ // Don't canonicalize.
+ return string(a)
+ }
+
upper := true
for i, c := range a {
// Canonicalize: first letter upper case
// and upper case after each dash.
// (Host, User-Agent, If-Modified-Since).
// MIME headers are ASCII only, so no Unicode issues.
- if c == ' ' {
- c = '-'
- } else if upper && 'a' <= c && c <= 'z' {
+ if upper && 'a' <= c && c <= 'z' {
c -= toLower
} else if !upper && 'A' <= c && c <= 'Z' {
c += toLower
diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
index 6bbd993..8fce7dd 100644
--- a/src/net/textproto/reader_test.go
+++ b/src/net/textproto/reader_test.go
@@ -24,11 +24,14 @@ var canonicalHeaderKeyTests = []canonicalHeaderKeyTest{
{"uSER-aGENT", "User-Agent"},
{"user-agent", "User-Agent"},
{"USER-AGENT", "User-Agent"},
- {"üser-agenT", "üser-Agent"}, // non-ASCII unchanged
+
+ // Non-ASCII or anything with spaces or non-token chars is unchanged:
+ {"üser-agenT", "üser-agenT"},
+ {"a B", "a B"},
// This caused a panic due to mishandling of a space:
- {"C Ontent-Transfer-Encoding", "C-Ontent-Transfer-Encoding"},
- {"foo bar", "Foo-Bar"},
+ {"C Ontent-Transfer-Encoding", "C Ontent-Transfer-Encoding"},
+ {"foo bar", "foo bar"},
}
func TestCanonicalMIMEHeaderKey(t *testing.T) {
@@ -194,7 +197,7 @@ func TestReadMIMEHeaderNonCompliant(t *testing.T) {
"Foo": {"bar"},
"Content-Language": {"en"},
"Sid": {"0"},
- "Audio-Mode": {"None"},
+ "Audio Mode": {"None"},
"Privilege": {"127"},
}
if !reflect.DeepEqual(m, want) || err != nil {

View File

@ -1,112 +0,0 @@
commit 143822585e32449860e624cace9d2e521deee62e
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Jul 7 13:19:44 2015 -0600
net/http: revert overly-strict part of earlier smuggling defense
The recent https://golang.org/cl/11810 is reportedly a bit too
aggressive.
Apparently some HTTP requests in the wild do contain both a
Transfer-Encoding along with a bogus Content-Length. Instead of
returning a 400 Bad Request error, we should just ignore the
Content-Length like we did before.
Change-Id: I0001be90d09f8293a34f04691f608342875ff5c4
Reviewed-on: https://go-review.googlesource.com/11962
Reviewed-by: Andrew Gerrand <adg@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/net/http/readrequest_test.go b/src/net/http/readrequest_test.go
index 1a3cf91..60e2be4 100644
--- a/src/net/http/readrequest_test.go
+++ b/src/net/http/readrequest_test.go
@@ -178,6 +178,36 @@ var reqTests = []reqTest{
noError,
},
+ // Tests chunked body and a bogus Content-Length which should be deleted.
+ {
+ "POST / HTTP/1.1\r\n" +
+ "Host: foo.com\r\n" +
+ "Transfer-Encoding: chunked\r\n" +
+ "Content-Length: 9999\r\n\r\n" + // to be removed.
+ "3\r\nfoo\r\n" +
+ "3\r\nbar\r\n" +
+ "0\r\n" +
+ "\r\n",
+ &Request{
+ Method: "POST",
+ URL: &url.URL{
+ Path: "/",
+ },
+ TransferEncoding: []string{"chunked"},
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Header: Header{},
+ ContentLength: -1,
+ Host: "foo.com",
+ RequestURI: "/",
+ },
+
+ "foobar",
+ noTrailer,
+ noError,
+ },
+
// CONNECT request with domain name:
{
"CONNECT www.google.com:443 HTTP/1.1\r\n\r\n",
@@ -400,11 +430,6 @@ Content-Length: 3
Content-Length: 4
abc`)},
- {"smuggle_chunked_and_len", reqBytes(`POST / HTTP/1.1
-Transfer-Encoding: chunked
-Content-Length: 3
-
-abc`)},
{"smuggle_content_len_head", reqBytes(`HEAD / HTTP/1.1
Host: foo
Content-Length: 5`)},
diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go
index 3c868bd..fbbbf24 100644
--- a/src/net/http/transfer.go
+++ b/src/net/http/transfer.go
@@ -430,7 +430,6 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) (
if !present {
return nil, nil
}
- isRequest := !isResponse
delete(header, "Transfer-Encoding")
encodings := strings.Split(raw[0], ",")
@@ -458,12 +457,20 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) (
// RFC 7230 3.3.2 says "A sender MUST NOT send a
// Content-Length header field in any message that
// contains a Transfer-Encoding header field."
- if len(header["Content-Length"]) > 0 {
- if isRequest {
- return nil, errors.New("http: invalid Content-Length with Transfer-Encoding")
- }
- delete(header, "Content-Length")
- }
+ //
+ // but also:
+ // "If a message is received with both a
+ // Transfer-Encoding and a Content-Length header
+ // field, the Transfer-Encoding overrides the
+ // Content-Length. Such a message might indicate an
+ // attempt to perform request smuggling (Section 9.5)
+ // or response splitting (Section 9.4) and ought to be
+ // handled as an error. A sender MUST remove the
+ // received Content-Length field prior to forwarding
+ // such a message downstream."
+ //
+ // Reportedly, these appear in the wild.
+ delete(header, "Content-Length")
return te, nil
}

View File

@ -1,225 +0,0 @@
commit 300d9a21583e7cf0149a778a0611e76ff7c6680f
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Jun 30 14:21:15 2015 -0700
net/http: harden Server against request smuggling
See RFC 7230.
Thanks to Régis Leroy for the report.
Change-Id: Ic1779bc2180900430d4d7a4938cac04ed73c304c
Reviewed-on: https://go-review.googlesource.com/11810
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/src/net/http/readrequest_test.go b/src/net/http/readrequest_test.go
index e930d99..1a3cf91 100644
--- a/src/net/http/readrequest_test.go
+++ b/src/net/http/readrequest_test.go
@@ -9,6 +9,7 @@ import (
"bytes"
"fmt"
"io"
+ "io/ioutil"
"net/url"
"reflect"
"strings"
@@ -323,6 +324,32 @@ var reqTests = []reqTest{
noTrailer,
noError,
},
+
+ // HEAD with Content-Length 0. Make sure this is permitted,
+ // since I think we used to send it.
+ {
+ "HEAD / HTTP/1.1\r\nHost: issue8261.com\r\nConnection: close\r\nContent-Length: 0\r\n\r\n",
+ &Request{
+ Method: "HEAD",
+ URL: &url.URL{
+ Path: "/",
+ },
+ Header: Header{
+ "Connection": []string{"close"},
+ "Content-Length": []string{"0"},
+ },
+ Host: "issue8261.com",
+ Proto: "HTTP/1.1",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ Close: true,
+ RequestURI: "/",
+ },
+
+ noBody,
+ noTrailer,
+ noError,
+ },
}
func TestReadRequest(t *testing.T) {
@@ -356,3 +383,39 @@ func TestReadRequest(t *testing.T) {
}
}
}
+
+// reqBytes treats req as a request (with \n delimiters) and returns it with \r\n delimiters,
+// ending in \r\n\r\n
+func reqBytes(req string) []byte {
+ return []byte(strings.Replace(strings.TrimSpace(req), "\n", "\r\n", -1) + "\r\n\r\n")
+}
+
+var badRequestTests = []struct {
+ name string
+ req []byte
+}{
+ {"bad_connect_host", reqBytes("CONNECT []%20%48%54%54%50%2f%31%2e%31%0a%4d%79%48%65%61%64%65%72%3a%20%31%32%33%0a%0a HTTP/1.0")},
+ {"smuggle_two_contentlen", reqBytes(`POST / HTTP/1.1
+Content-Length: 3
+Content-Length: 4
+
+abc`)},
+ {"smuggle_chunked_and_len", reqBytes(`POST / HTTP/1.1
+Transfer-Encoding: chunked
+Content-Length: 3
+
+abc`)},
+ {"smuggle_content_len_head", reqBytes(`HEAD / HTTP/1.1
+Host: foo
+Content-Length: 5`)},
+}
+
+func TestReadRequest_Bad(t *testing.T) {
+ for _, tt := range badRequestTests {
+ got, err := ReadRequest(bufio.NewReader(bytes.NewReader(tt.req)))
+ if err == nil {
+ all, err := ioutil.ReadAll(got.Body)
+ t.Errorf("%s: got unexpected request = %#v\n Body = %q, %v", tt.name, got, all, err)
+ }
+ }
+}
diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go
index 5205003..3887604 100644
--- a/src/net/http/transfer.go
+++ b/src/net/http/transfer.go
@@ -143,6 +143,9 @@ func (t *transferWriter) shouldSendContentLength() bool {
return true
}
if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
+ if t.Method == "GET" || t.Method == "HEAD" {
+ return false
+ }
return true
}
@@ -310,6 +313,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
}
case *Request:
t.Header = rr.Header
+ t.RequestMethod = rr.Method
t.ProtoMajor = rr.ProtoMajor
t.ProtoMinor = rr.ProtoMinor
// Transfer semantics for Requests are exactly like those for
@@ -325,7 +329,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
}
// Transfer encoding, content length
- t.TransferEncoding, err = fixTransferEncoding(t.RequestMethod, t.Header)
+ t.TransferEncoding, err = fixTransferEncoding(isResponse, t.RequestMethod, t.Header)
if err != nil {
return err
}
@@ -413,12 +417,12 @@ func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
// Sanitize transfer encoding
-func fixTransferEncoding(requestMethod string, header Header) ([]string, error) {
+func fixTransferEncoding(isResponse bool, requestMethod string, header Header) ([]string, error) {
raw, present := header["Transfer-Encoding"]
if !present {
return nil, nil
}
-
+ isRequest := !isResponse
delete(header, "Transfer-Encoding")
encodings := strings.Split(raw[0], ",")
@@ -443,10 +447,15 @@ func fixTransferEncoding(requestMethod string, header Header) ([]string, error)
return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")}
}
if len(te) > 0 {
- // Chunked encoding trumps Content-Length. See RFC 2616
- // Section 4.4. Currently len(te) > 0 implies chunked
- // encoding.
- delete(header, "Content-Length")
+ // RFC 7230 3.3.2 says "A sender MUST NOT send a
+ // Content-Length header field in any message that
+ // contains a Transfer-Encoding header field."
+ if len(header["Content-Length"]) > 0 {
+ if isRequest {
+ return nil, errors.New("http: invalid Content-Length with Transfer-Encoding")
+ }
+ delete(header, "Content-Length")
+ }
return te, nil
}
@@ -457,9 +466,17 @@ func fixTransferEncoding(requestMethod string, header Header) ([]string, error)
// function is not a method, because ultimately it should be shared by
// ReadResponse and ReadRequest.
func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) {
-
+ contentLens := header["Content-Length"]
+ isRequest := !isResponse
// Logic based on response type or status
if noBodyExpected(requestMethod) {
+ // For HTTP requests, as part of hardening against request
+ // smuggling (RFC 7230), don't allow a Content-Length header for
+ // methods which don't permit bodies. As an exception, allow
+ // exactly one Content-Length header if its value is "0".
+ if isRequest && len(contentLens) > 0 && !(len(contentLens) == 1 && contentLens[0] == "0") {
+ return 0, fmt.Errorf("http: method cannot contain a Content-Length; got %q", contentLens)
+ }
return 0, nil
}
if status/100 == 1 {
@@ -470,13 +487,21 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
return 0, nil
}
+ if len(contentLens) > 1 {
+ // harden against HTTP request smuggling. See RFC 7230.
+ return 0, errors.New("http: message cannot contain multiple Content-Length headers")
+ }
+
// Logic based on Transfer-Encoding
if chunked(te) {
return -1, nil
}
// Logic based on Content-Length
- cl := strings.TrimSpace(header.get("Content-Length"))
+ var cl string
+ if len(contentLens) == 1 {
+ cl = strings.TrimSpace(contentLens[0])
+ }
if cl != "" {
n, err := parseContentLength(cl)
if err != nil {
@@ -487,11 +512,14 @@ func fixLength(isResponse bool, status int, requestMethod string, header Header,
header.Del("Content-Length")
}
- if !isResponse && requestMethod == "GET" {
- // RFC 2616 doesn't explicitly permit nor forbid an
+ if !isResponse {
+ // RFC 2616 neither explicitly permits nor forbids an
// entity-body on a GET request so we permit one if
// declared, but we default to 0 here (not -1 below)
// if there's no mention of a body.
+ // Likewise, all other request methods are assumed to have
+ // no body if neither Transfer-Encoding chunked nor a
+ // Content-Length are set.
return 0, nil
}

View File

@ -1,127 +0,0 @@
diff -up go/src/cmd/go/get.go.cve go/src/cmd/go/get.go
--- go/src/cmd/go/get.go.cve 2017-05-23 20:35:22.000000000 +0200
+++ go/src/cmd/go/get.go 2017-10-10 10:25:24.485047705 +0200
@@ -401,6 +401,11 @@ func downloadPackage(p *Package) error {
p.build.PkgRoot = filepath.Join(list[0], "pkg")
}
root := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
+
+ if err := checkNestedVCS(vcs, root, p.build.SrcRoot); err != nil {
+ return err
+ }
+
// If we've considered this repository already, don't do it again.
if downloadRootCache[root] {
return nil
diff -up go/src/cmd/go/go_test.go.cve go/src/cmd/go/go_test.go
--- go/src/cmd/go/go_test.go.cve 2017-05-23 20:35:22.000000000 +0200
+++ go/src/cmd/go/go_test.go 2017-10-10 10:25:24.485047705 +0200
@@ -1235,6 +1235,25 @@ func TestGetGitDefaultBranch(t *testing.
tg.grepStdout(`\* another-branch`, "not on correct default branch")
}
+func TestAccidentalGitCheckout(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+ if _, err := exec.LookPath("git"); err != nil {
+ t.Skip("skipping because git binary not found")
+ }
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.parallel()
+ tg.tempDir("src")
+ tg.setenv("GOPATH", tg.path("."))
+
+ tg.runFail("get", "-u", "vcs-test.golang.org/go/test1-svn-git")
+ tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
+
+ tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main")
+ tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
+}
+
func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
diff -up go/src/cmd/go/vcs.go.cve go/src/cmd/go/vcs.go
--- go/src/cmd/go/vcs.go.cve 2017-05-23 20:35:22.000000000 +0200
+++ go/src/cmd/go/vcs.go 2017-10-10 10:30:52.151621206 +0200
@@ -479,11 +479,29 @@ func vcsFromDir(dir, srcRoot string) (vc
return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
}
+ var vcsRet *vcsCmd
+ var rootRet string
+
origDir := dir
for len(dir) > len(srcRoot) {
for _, vcs := range vcsList {
if fi, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil && fi.IsDir() {
- return vcs, filepath.ToSlash(dir[len(srcRoot)+1:]), nil
+ root := filepath.ToSlash(dir[len(srcRoot)+1:])
+ // Record first VCS we find, but keep looking,
+ // to detect mistakes like one kind of VCS inside another.
+ if vcsRet == nil {
+ vcsRet = vcs
+ rootRet = root
+ continue
+ }
+ // Allow .git inside .git, which can arise due to submodules.
+ if vcsRet == vcs && vcs.cmd == "git" {
+ continue
+ }
+ // Otherwise, we have one VCS inside a different VCS.
+ return nil, "", fmt.Errorf("directory %q uses %s, but parent %q uses %s",
+ filepath.Join(srcRoot, rootRet), vcsRet.cmd, filepath.Join(srcRoot, root), vcs.cmd)
+
}
}
@@ -496,9 +514,48 @@ func vcsFromDir(dir, srcRoot string) (vc
dir = ndir
}
+ if vcsRet != nil {
+ return vcsRet, rootRet, nil
+ }
+
return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir)
}
+// checkNestedVCS checks for an incorrectly-nested VCS-inside-VCS
+// situation for dir, checking parents up until srcRoot.
+func checkNestedVCS(vcs *vcsCmd, dir, srcRoot string) error {
+ if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
+ return fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
+ }
+
+ otherDir := dir
+ for len(otherDir) > len(srcRoot) {
+ for _, otherVCS := range vcsList {
+ if _, err := os.Stat(filepath.Join(dir, "."+otherVCS.cmd)); err == nil {
+ // Allow expected vcs in original dir.
+ if otherDir == dir && otherVCS == vcs {
+ continue
+ }
+ // Allow .git inside .git, which can arise due to submodules.
+ if otherVCS == vcs && vcs.cmd == "git" {
+ continue
+ }
+ // Otherwise, we have one VCS inside a different VCS.
+ return fmt.Errorf("directory %q uses %s, but parent %q uses %s", dir, vcs.cmd, otherDir, otherVCS.cmd)
+ }
+ }
+ // Move to parent.
+ newDir := filepath.Dir(otherDir)
+ if len(newDir) >= len(otherDir) {
+ // Shouldn't happen, but just in case, stop.
+ break
+ }
+ otherDir = newDir
+ }
+
+ return nil
+}
+
// repoRoot represents a version control system, a repo, and a root of
// where to put it on disk.
type repoRoot struct {

View File

@ -1,144 +0,0 @@
From 4be3fc33ef512532b916aa14258087e89eb47347 Mon Sep 17 00:00:00 2001
From: Russ Cox <rsc@golang.org>
Date: Wed, 4 Oct 2017 13:24:49 -0400
Subject: [PATCH] [release-branch.go1.8] net/smtp: fix PlainAuth to refuse to
send passwords to non-TLS servers
PlainAuth originally refused to send passwords to non-TLS servers
and was documented as such.
In 2013, issue #5184 was filed objecting to the TLS requirement,
despite the fact that it is spelled out clearly in RFC 4954.
The only possibly legitimate use case raised was using PLAIN auth
for connections to localhost, and the suggested fix was to let the
server decide: if it advertises that PLAIN auth is OK, believe it.
That approach was adopted in CL 8279043 and released in Go 1.1.
Unfortunately, this is exactly wrong. The whole point of the TLS
requirement is to make sure not to send the password to the wrong
server or to a man-in-the-middle. Instead of implementing this rule,
CL 8279043 blindly trusts the server, so that if a man-in-the-middle
says "it's OK, you can send me your password," PlainAuth does.
And the documentation was not updated to reflect any of this.
This CL restores the original TLS check, as required by RFC 4954
and as promised in the documentation for PlainAuth.
It then carves out a documented exception for connections made
to localhost (defined as "localhost", "127.0.0.1", or "::1").
Cherry-pick of CL 68170.
Change-Id: I1d3729bbd33aa2f11a03f4c000e6bb473164957b
Reviewed-on: https://go-review.googlesource.com/68023
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Chris Broadfoot <cbro@golang.org>
---
src/net/smtp/auth.go | 33 ++++++++++++++++++---------------
src/net/smtp/smtp_test.go | 32 ++++++++++++++++++++++----------
2 files changed, 40 insertions(+), 25 deletions(-)
diff --git a/src/net/smtp/auth.go b/src/net/smtp/auth.go
index 3f1339ebc56..fd1a472f930 100644
--- a/src/net/smtp/auth.go
+++ b/src/net/smtp/auth.go
@@ -44,26 +44,29 @@ type plainAuth struct {
}
// PlainAuth returns an Auth that implements the PLAIN authentication
-// mechanism as defined in RFC 4616.
-// The returned Auth uses the given username and password to authenticate
-// on TLS connections to host and act as identity. Usually identity will be
-// left blank to act as username.
+// mechanism as defined in RFC 4616. The returned Auth uses the given
+// username and password to authenticate to host and act as identity.
+// Usually identity should be the empty string, to act as username.
+//
+// PlainAuth will only send the credentials if the connection is using TLS
+// or is connected to localhost. Otherwise authentication will fail with an
+// error, without sending the credentials.
func PlainAuth(identity, username, password, host string) Auth {
return &plainAuth{identity, username, password, host}
}
+func isLocalhost(name string) bool {
+ return name == "localhost" || name == "127.0.0.1" || name == "::1"
+}
+
func (a *plainAuth) Start(server *ServerInfo) (string, []byte, error) {
- if !server.TLS {
- advertised := false
- for _, mechanism := range server.Auth {
- if mechanism == "PLAIN" {
- advertised = true
- break
- }
- }
- if !advertised {
- return "", nil, errors.New("unencrypted connection")
- }
+ // Must have TLS, or else localhost server.
+ // Note: If TLS is not true, then we can't trust ANYTHING in ServerInfo.
+ // In particular, it doesn't matter if the server advertises PLAIN auth.
+ // That might just be the attacker saying
+ // "it's ok, you can trust me with your password."
+ if !server.TLS && !isLocalhost(server.Name) {
+ return "", nil, errors.New("unencrypted connection")
}
if server.Name != a.host {
return "", nil, errors.New("wrong host name")
diff --git a/src/net/smtp/smtp_test.go b/src/net/smtp/smtp_test.go
index c48fae6d5ac..15eaca524be 100644
--- a/src/net/smtp/smtp_test.go
+++ b/src/net/smtp/smtp_test.go
@@ -60,29 +60,41 @@ testLoop:
}
func TestAuthPlain(t *testing.T) {
- auth := PlainAuth("foo", "bar", "baz", "servername")
tests := []struct {
- server *ServerInfo
- err string
+ authName string
+ server *ServerInfo
+ err string
}{
{
- server: &ServerInfo{Name: "servername", TLS: true},
+ authName: "servername",
+ server: &ServerInfo{Name: "servername", TLS: true},
},
{
- // Okay; explicitly advertised by server.
- server: &ServerInfo{Name: "servername", Auth: []string{"PLAIN"}},
+ // OK to use PlainAuth on localhost without TLS
+ authName: "localhost",
+ server: &ServerInfo{Name: "localhost", TLS: false},
},
{
- server: &ServerInfo{Name: "servername", Auth: []string{"CRAM-MD5"}},
- err: "unencrypted connection",
+ // NOT OK on non-localhost, even if server says PLAIN is OK.
+ // (We don't know that the server is the real server.)
+ authName: "servername",
+ server: &ServerInfo{Name: "servername", Auth: []string{"PLAIN"}},
+ err: "unencrypted connection",
},
{
- server: &ServerInfo{Name: "attacker", TLS: true},
- err: "wrong host name",
+ authName: "servername",
+ server: &ServerInfo{Name: "servername", Auth: []string{"CRAM-MD5"}},
+ err: "unencrypted connection",
+ },
+ {
+ authName: "servername",
+ server: &ServerInfo{Name: "attacker", TLS: true},
+ err: "wrong host name",
},
}
for i, tt := range tests {
+ auth := PlainAuth("foo", "bar", "baz", tt.authName)
_, _, err := auth.Start(tt.server)
got := ""
if err != nil {

View File

@ -1,12 +0,0 @@
diff -up go/src/runtime/runtime-gdb_test.go.gdb go/src/runtime/runtime-gdb_test.go
--- go/src/runtime/runtime-gdb_test.go.gdb 2016-04-28 10:31:13.005689813 +0200
+++ go/src/runtime/runtime-gdb_test.go 2016-04-28 10:32:12.202935125 +0200
@@ -72,7 +72,7 @@ func main() {
}
`
-func TestGdbPython(t *testing.T) {
+func testGdbPython(t *testing.T) {
checkGdbEnvironment(t)
checkGdbVersion(t)
checkGdbPython(t)

View File

@ -1,309 +0,0 @@
commit a3156aaa121446c4136927f8c2139fefe05ba82c
Author: Brad Fitzpatrick <bradfitz@golang.org>
Date: Tue Sep 29 14:26:48 2015 -0700
net/http/httptest: change Server to use http.Server.ConnState for accounting
With this CL, httptest.Server now uses connection-level accounting of
outstanding requests instead of ServeHTTP-level accounting. This is
more robust and results in a non-racy shutdown.
This is much easier now that net/http.Server has the ConnState hook.
Fixes #12789
Fixes #12781
Change-Id: I098cf334a6494316acb66cd07df90766df41764b
Reviewed-on: https://go-review.googlesource.com/15151
Reviewed-by: Andrew Gerrand <adg@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/net/http/httptest/server.go b/src/net/http/httptest/server.go
index 96eb0ef..e4f680f 100644
--- a/src/net/http/httptest/server.go
+++ b/src/net/http/httptest/server.go
@@ -7,13 +7,17 @@
package httptest
import (
+ "bytes"
"crypto/tls"
"flag"
"fmt"
+ "log"
"net"
"net/http"
"os"
+ "runtime"
"sync"
+ "time"
)
// A Server is an HTTP server listening on a system-chosen port on the
@@ -34,24 +38,10 @@ type Server struct {
// wg counts the number of outstanding HTTP requests on this server.
// Close blocks until all requests are finished.
wg sync.WaitGroup
-}
-
-// historyListener keeps track of all connections that it's ever
-// accepted.
-type historyListener struct {
- net.Listener
- sync.Mutex // protects history
- history []net.Conn
-}
-func (hs *historyListener) Accept() (c net.Conn, err error) {
- c, err = hs.Listener.Accept()
- if err == nil {
- hs.Lock()
- hs.history = append(hs.history, c)
- hs.Unlock()
- }
- return
+ mu sync.Mutex // guards closed and conns
+ closed bool
+ conns map[net.Conn]http.ConnState // except terminal states
}
func newLocalListener() net.Listener {
@@ -103,10 +93,9 @@ func (s *Server) Start() {
if s.URL != "" {
panic("Server already started")
}
- s.Listener = &historyListener{Listener: s.Listener}
s.URL = "http://" + s.Listener.Addr().String()
- s.wrapHandler()
- go s.Config.Serve(s.Listener)
+ s.wrap()
+ s.goServe()
if *serve != "" {
fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL)
select {}
@@ -134,23 +123,10 @@ func (s *Server) StartTLS() {
if len(s.TLS.Certificates) == 0 {
s.TLS.Certificates = []tls.Certificate{cert}
}
- tlsListener := tls.NewListener(s.Listener, s.TLS)
-
- s.Listener = &historyListener{Listener: tlsListener}
+ s.Listener = tls.NewListener(s.Listener, s.TLS)
s.URL = "https://" + s.Listener.Addr().String()
- s.wrapHandler()
- go s.Config.Serve(s.Listener)
-}
-
-func (s *Server) wrapHandler() {
- h := s.Config.Handler
- if h == nil {
- h = http.DefaultServeMux
- }
- s.Config.Handler = &waitGroupHandler{
- s: s,
- h: h,
- }
+ s.wrap()
+ s.goServe()
}
// NewTLSServer starts and returns a new Server using TLS.
@@ -161,43 +137,139 @@ func NewTLSServer(handler http.Handler) *Server {
return ts
}
+type closeIdleTransport interface {
+ CloseIdleConnections()
+}
+
// Close shuts down the server and blocks until all outstanding
// requests on this server have completed.
func (s *Server) Close() {
- s.Listener.Close()
- s.wg.Wait()
- s.CloseClientConnections()
- if t, ok := http.DefaultTransport.(*http.Transport); ok {
+ s.mu.Lock()
+ if !s.closed {
+ s.closed = true
+ s.Listener.Close()
+ s.Config.SetKeepAlivesEnabled(false)
+ for c, st := range s.conns {
+ if st == http.StateIdle {
+ s.closeConn(c)
+ }
+ }
+ // If this server doesn't shut down in 5 seconds, tell the user why.
+ t := time.AfterFunc(5*time.Second, s.logCloseHangDebugInfo)
+ defer t.Stop()
+ }
+ s.mu.Unlock()
+
+ // Not part of httptest.Server's correctness, but assume most
+ // users of httptest.Server will be using the standard
+ // transport, so help them out and close any idle connections for them.
+ if t, ok := http.DefaultTransport.(closeIdleTransport); ok {
t.CloseIdleConnections()
}
+
+ s.wg.Wait()
}
-// CloseClientConnections closes any currently open HTTP connections
-// to the test Server.
+func (s *Server) logCloseHangDebugInfo() {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ var buf bytes.Buffer
+ buf.WriteString("httptest.Server blocked in Close after 5 seconds, waiting for connections:\n")
+ for c, st := range s.conns {
+ fmt.Fprintf(&buf, " %T %p %v in state %v\n", c, c, c.RemoteAddr(), st)
+ }
+ log.Print(buf.String())
+}
+
+// CloseClientConnections closes any open HTTP connections to the test Server.
func (s *Server) CloseClientConnections() {
- hl, ok := s.Listener.(*historyListener)
- if !ok {
- return
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ for c := range s.conns {
+ s.closeConn(c)
}
- hl.Lock()
- for _, conn := range hl.history {
- conn.Close()
+}
+
+func (s *Server) goServe() {
+ s.wg.Add(1)
+ go func() {
+ defer s.wg.Done()
+ s.Config.Serve(s.Listener)
+ }()
+}
+
+// wrap installs the connection state-tracking hook to know which
+// connections are idle.
+func (s *Server) wrap() {
+ oldHook := s.Config.ConnState
+ s.Config.ConnState = func(c net.Conn, cs http.ConnState) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ switch cs {
+ case http.StateNew:
+ s.wg.Add(1)
+ if _, exists := s.conns[c]; exists {
+ panic("invalid state transition")
+ }
+ if s.conns == nil {
+ s.conns = make(map[net.Conn]http.ConnState)
+ }
+ s.conns[c] = cs
+ if s.closed {
+ // Probably just a socket-late-binding dial from
+ // the default transport that lost the race (and
+ // thus this connection is now idle and will
+ // never be used).
+ s.closeConn(c)
+ }
+ case http.StateActive:
+ if oldState, ok := s.conns[c]; ok {
+ if oldState != http.StateNew && oldState != http.StateIdle {
+ panic("invalid state transition")
+ }
+ s.conns[c] = cs
+ }
+ case http.StateIdle:
+ if oldState, ok := s.conns[c]; ok {
+ if oldState != http.StateActive {
+ panic("invalid state transition")
+ }
+ s.conns[c] = cs
+ }
+ if s.closed {
+ s.closeConn(c)
+ }
+ case http.StateHijacked, http.StateClosed:
+ s.forgetConn(c)
+ }
+ if oldHook != nil {
+ oldHook(c, cs)
+ }
}
- hl.Unlock()
}
-// waitGroupHandler wraps a handler, incrementing and decrementing a
-// sync.WaitGroup on each request, to enable Server.Close to block
-// until outstanding requests are finished.
-type waitGroupHandler struct {
- s *Server
- h http.Handler // non-nil
+// closeConn closes c. Except on plan9, which is special. See comment below.
+// s.mu must be held.
+func (s *Server) closeConn(c net.Conn) {
+ if runtime.GOOS == "plan9" {
+ // Go's Plan 9 net package isn't great at unblocking reads when
+ // their underlying TCP connections are closed. Don't trust
+ // that that the ConnState state machine will get to
+ // StateClosed. Instead, just go there directly. Plan 9 may leak
+ // resources if the syscall doesn't end up returning. Oh well.
+ s.forgetConn(c)
+ }
+ go c.Close()
}
-func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- h.s.wg.Add(1)
- defer h.s.wg.Done() // a defer, in case ServeHTTP below panics
- h.h.ServeHTTP(w, r)
+// forgetConn removes c from the set of tracked conns and decrements it from the
+// waitgroup, unless it was previously removed.
+// s.mu must be held.
+func (s *Server) forgetConn(c net.Conn) {
+ if _, ok := s.conns[c]; ok {
+ delete(s.conns, c)
+ s.wg.Done()
+ }
}
// localhostCert is a PEM-encoded TLS cert with SAN IPs
diff --git a/src/net/http/httptest/server_test.go b/src/net/http/httptest/server_test.go
index 500a9f0..90901ce 100644
--- a/src/net/http/httptest/server_test.go
+++ b/src/net/http/httptest/server_test.go
@@ -27,3 +27,30 @@ func TestServer(t *testing.T) {
t.Errorf("got %q, want hello", string(got))
}
}
+
+// Issue 12781
+func TestGetAfterClose(t *testing.T) {
+ ts := NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Write([]byte("hello"))
+ }))
+
+ res, err := http.Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ got, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(got) != "hello" {
+ t.Fatalf("got %q, want hello", string(got))
+ }
+
+ ts.Close()
+
+ res, err = http.Get(ts.URL)
+ if err == nil {
+ body, _ := ioutil.ReadAll(res.Body)
+ t.Fatalf("Unexected response after close: %v, %v, %s", res.Status, res.Header, body)
+ }
+}

View File

@ -1,3 +0,0 @@
# there are ELF files in src which are testdata and shouldn't be modified
-b /usr/lib/golang/src
-b /usr/lib64/golang/src

View File

@ -1,5 +1,12 @@
%bcond_with bootstrap
# temporalily ignore test failures
# due to https://github.com/golang/go/issues/39466
%ifarch aarch64
%bcond_without ignore_tests
%else
%bcond_with ignore_tests
%endif
# build ids are not currently generated:
# https://code.google.com/p/go/issues/detail?id=5238
#
@ -26,6 +33,9 @@
%global golibdir %{_libdir}/golang
# This macro may not always be defined, ensure it is
%{!?gopath: %global gopath %{_datadir}/gocode}
# Golang build options.
# Build golang using external/internal(close to cgo disabled) linking.
@ -50,7 +60,7 @@
%endif
# Controls what ever we fail on failed tests
%ifarch x86_64
%if %{with ignore_tests}
%global fail_on_tests 0
%else
%global fail_on_tests 1
@ -72,9 +82,6 @@
# Fedora GOROOT
%global goroot /usr/lib/%{name}
%global gopath %{_datadir}/gocode
%global go_arches %{ix86} x86_64 %{arm} aarch64 ppc64le
%global golibdir %{_libdir}/golang
%ifarch x86_64
%global gohostarch amd64
@ -98,11 +105,11 @@
%global gohostarch s390x
%endif
%global go_api 1.13
%global go_version 1.13.6
%global go_api 1.15
%global go_version 1.15.5
Name: golang
Version: 1.13.6
Version: 1.15.5
Release: 1%{?dist}
Summary: The Go Programming Language
# source tree includes several copies of Mark.Twain-Tom.Sawyer.txt under Public Domain
@ -124,19 +131,18 @@ BuildRequires: hostname
BuildRequires: net-tools
%endif
# for tests
BuildRequires: pcre-devel, glibc-static, perl
BuildRequires: pcre-devel, glibc-static, perl-interpreter, procps-ng
Provides: go = %{version}-%{release}
Provides: go-srpm-macros
# Bundled/Vendored provides generated by
# go list -f {{.ImportPath}} ./src/vendor/... | sed "s:_$PWD/src/vendor/::g;s:_:.:;s:.*:Provides\: bundled(golang(&)):" && go list -f {{.ImportPath}} ./src/cmd/vendor/... | sed "s:_$PWD/src/cmd/vendor/::g;s:_:.:;s:.*:Provides\: bundled(golang(&)):"
Provides: bundled(golang(golang.org/x/crypto/chacha20))
Provides: bundled(golang(golang.org/x/crypto/chacha20poly1305))
Provides: bundled(golang(golang.org/x/crypto/cryptobyte))
Provides: bundled(golang(golang.org/x/crypto/cryptobyte/asn1))
Provides: bundled(golang(golang.org/x/crypto/curve25519))
Provides: bundled(golang(golang.org/x/crypto/hkdf))
Provides: bundled(golang(golang.org/x/crypto/internal/chacha20))
Provides: bundled(golang(golang.org/x/crypto/internal/subtle))
Provides: bundled(golang(golang.org/x/crypto/poly1305))
Provides: bundled(golang(golang.org/x/net/dns/dnsmessage))
@ -170,9 +176,20 @@ Provides: bundled(golang(golang.org/x/arch/arm/armasm))
Provides: bundled(golang(golang.org/x/arch/arm64/arm64asm))
Provides: bundled(golang(golang.org/x/arch/ppc64/ppc64asm))
Provides: bundled(golang(golang.org/x/arch/x86/x86asm))
Provides: bundled(golang(golang.org/x/crypto/ed25519))
Provides: bundled(golang(golang.org/x/crypto/ed25519/internal/edwards25519))
Provides: bundled(golang(golang.org/x/crypto/ssh/terminal))
Provides: bundled(golang(golang.org/x/mod/internal/lazyregexp))
Provides: bundled(golang(golang.org/x/mod/modfile))
Provides: bundled(golang(golang.org/x/mod/module))
Provides: bundled(golang(golang.org/x/mod/semver))
Provides: bundled(golang(golang.org/x/mod/sumdb))
Provides: bundled(golang(golang.org/x/mod/sumdb/dirhash))
Provides: bundled(golang(golang.org/x/mod/sumdb/note))
Provides: bundled(golang(golang.org/x/mod/sumdb/tlog))
Provides: bundled(golang(golang.org/x/mod/zip))
Provides: bundled(golang(golang.org/x/sys/internal/unsafeheader))
Provides: bundled(golang(golang.org/x/sys/unix))
Provides: bundled(golang(golang.org/x/sys/windows))
Provides: bundled(golang(golang.org/x/tools/go/analysis))
Provides: bundled(golang(golang.org/x/tools/go/analysis/internal/analysisflags))
Provides: bundled(golang(golang.org/x/tools/go/analysis/internal/facts))
@ -187,6 +204,7 @@ Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/copylock))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/ctrlflow))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/errorsas))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/httpresponse))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/ifaceassert))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/inspect))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/internal/analysisutil))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/loopclosure))
@ -195,6 +213,7 @@ Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/nilfunc))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/printf))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/shift))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/stdmethods))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/stringintconv))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/structtag))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/tests))
Provides: bundled(golang(golang.org/x/tools/go/analysis/passes/unmarshal))
@ -207,6 +226,9 @@ Provides: bundled(golang(golang.org/x/tools/go/ast/inspector))
Provides: bundled(golang(golang.org/x/tools/go/cfg))
Provides: bundled(golang(golang.org/x/tools/go/types/objectpath))
Provides: bundled(golang(golang.org/x/tools/go/types/typeutil))
Provides: bundled(golang(golang.org/x/tools/internal/analysisinternal))
Provides: bundled(golang(golang.org/x/xerrors))
Provides: bundled(golang(golang.org/x/xerrors/internal))
Requires: %{name}-bin = %{version}-%{release}
Requires: %{name}-src = %{version}-%{release}
@ -227,11 +249,9 @@ Obsoletes: %{name}-vim < 1.4
Obsoletes: emacs-%{name} < 1.4
# These are the only RHEL/Fedora architectures that we compile this package for
ExclusiveArch: %{go_arches}
ExclusiveArch: %{golang_arches}
Source100: golang-gdbinit
Source101: golang-prelink.conf
Source102: macros.golang
%description
%{summary}.
@ -307,7 +327,11 @@ Requires(preun): %{_sbindir}/update-alternatives
# This is an odd issue, still looking for a better fix.
Requires: glibc
Requires: gcc
Requires: git, subversion, mercurial
%if 0%{?rhel} && 0%{?rhel} < 8
Requires: git, subversion, mercurial
%else
Recommends: git, subversion, mercurial
%endif
%description bin
%{summary}
@ -490,21 +514,6 @@ ln -sf /etc/alternatives/gofmt $RPM_BUILD_ROOT%{_bindir}/gofmt
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/gdbinit.d
cp -av %{SOURCE100} $RPM_BUILD_ROOT%{_sysconfdir}/gdbinit.d/golang.gdb
# prelink blacklist
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/prelink.conf.d
cp -av %{SOURCE101} $RPM_BUILD_ROOT%{_sysconfdir}/prelink.conf.d/golang.conf
# rpm macros
mkdir -p %{buildroot}
%if 0%{?rhel} > 6 || 0%{?fedora} > 0
mkdir -p $RPM_BUILD_ROOT%{_rpmconfigdir}/macros.d
cp -av %{SOURCE102} $RPM_BUILD_ROOT%{_rpmconfigdir}/macros.d/macros.golang
%else
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/rpm
cp -av %{SOURCE102} $RPM_BUILD_ROOT%{_sysconfdir}/rpm/macros.golang
%endif
%check
export GOROOT=$(pwd -P)
export PATH="$GOROOT"/bin:"$PATH"
@ -519,6 +528,12 @@ export GO_LDFLAGS="-linkmode internal"
%if !%{cgo_enabled} || !%{external_linker}
export CGO_ENABLED=0
%endif
# workaround for https://github.com/golang/go/issues/39466 until it gests fixed
# Commented until the patch is ready, this work around suggested in the link avobe
# doesn't work properly
#ifarch aarch64
#export CGO_CFLAGS="-mno-outline-atomics"
#endif
# make sure to not timeout
export GO_TEST_TIMEOUT_SCALE=2
@ -548,7 +563,6 @@ fi
# VERSION has to be present in the GOROOT, for `go install std` to work
%doc %{goroot}/VERSION
%dir %{goroot}/doc
%doc %{goroot}/doc/*
# go files
%dir %{goroot}
@ -571,17 +585,7 @@ fi
# gdbinit (for gdb debugging)
%{_sysconfdir}/gdbinit.d
# prelink blacklist
%{_sysconfdir}/prelink.conf.d
%if 0%{?rhel} > 6 || 0%{?fedora} > 0
%{_rpmconfigdir}/macros.d/macros.golang
%else
%{_sysconfdir}/rpm/macros.golang
%endif
%files -f go-src.list src
%files src -f go-src.list
%files docs -f go-docs.list
@ -604,62 +608,256 @@ fi
%endif
%changelog
* Mon Feb 03 2020 Jakub Čajka <jcajka@redhat.com> - 1.13.6-1
* Fri Nov 13 2020 Jakub Čajka <jcajka@redhat.com> - 1.15.5-1
- Rebase to go1.15.5
- Security fix for CVE-2020-28362, CVE-2020-28367 and CVE-2020-28366
- Resolves: BZ#1897342, BZ#1897636, BZ#1897644, BZ#1897647
* Fri Nov 06 2020 Jakub Čajka <jcajka@redhat.com> - 1.15.4-1
- Rebase to go1.15.4
- Resolves: BZ#1895189
* Thu Oct 15 2020 Jakub Čajka <jcajka@redhat.com> - 1.15.3-1
- Rebase to go1.15.3
- Resolves: BZ#1888443
* Thu Sep 10 2020 Jakub Čajka <jcajka@redhat.com> - 1.15.2-1
- Rebase to go1.15.2
- Resolves: BZ#1877565
* Thu Sep 03 2020 Jakub Čajka <jcajka@redhat.com> - 1.15.1-1
- Rebase to go1.15.1
- Security fix for CVE-2020-24553
- Resolves: BZ#1874858, BZ#1866892
* Wed Aug 12 2020 Jakub Čajka <jcajka@redhat.com> - 1.15-1
- Rebase to go1.15 proper
- Resolves: BZ#1859241, BZ#1866892
* Mon Aug 10 2020 Jakub Čajka <jcajka@redhat.com> - 1.15-0.rc2.0
- Rebase to go1.15rc1
- Security fix for CVE-2020-16845
- Resolves: BZ#1867101
- Related: BZ#1859241
* Mon Jul 27 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.15-0.rc1.0.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Mon Jul 27 2020 Jakub Čajka <jcajka@redhat.com> - 1.15-0.rc1.0
- Rebase to go1.15rc1
- Related: BZ#1859241
* Mon Jul 20 2020 Jakub Čajka <jcajka@redhat.com> - 1.15-0.beta1.0
- Rebase to go1.15beta1
* Mon Jul 20 2020 Jakub Čajka <jcajka@redhat.com> - 1.14.6-1
- Rebase to go1.14.6
- Security fix for CVE-2020-14040 and CVE-2020-15586
- Resolves: BZ#1842708, BZ#1856957, BZ#1853653
* Tue Jun 30 2020 Alejandro Sáez <asm@redhat.com> - 1.14.4-1
- Rebase to go1.14.4
- Add patch that fixes: https://golang.org/issue/39991
- Related: BZ#1842708
* Mon May 18 2020 Álex Sáez <asm@redhat.com> - 1.14.3-1
- Rebase to go1.14.3
- Resolves: BZ#1836015
* Mon Apr 20 2020 Jakub Čajka <jcajka@redhat.com> - 1.14.2-1
- Rebase to go1.14.2
- Resolves: BZ#1815282
* Wed Feb 26 2020 Jakub Čajka <jcajka@redhat.com> - 1.14-1
- Rebase to go1.14 proper
- Resolves: BZ#1792475
* Thu Feb 06 2020 Jakub Čajka <jcajka@redhat.com> - 1.14-0.rc1.0
- Rebase to go1.14.rc1
- Related: BZ#1792475
* Tue Jan 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 1.14-0.beta1.0.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Mon Jan 20 2020 Jakub Čajka <jcajka@redhat.com> - 1.14-0.beta1.0
- Rebase to go1.14beta1
- Resolves: BZ#1792475
* Mon Jan 13 2020 Jakub Čajka <jcajka@redhat.com> - 1.13.6-1
- Rebase to go1.13.6
* Wed Nov 13 2019 Jakub Čajka <jcajka@redhat.com> - 1.13.4-1
- Rebase to go1.13.4
* Thu Dec 05 2019 Jakub Čajka <jcajka@redhat.com> - 1.13.5-1
- Rebase to go1.13.5
* Wed Oct 30 2019 Jakub Čajka <jcajka@redhat.com> - 1.13.3-1
* Tue Nov 26 2019 Neal Gompa <ngompa@datto.com> - 1.13.4-2
- Small fixes to the spec and tighten up the file list
* Fri Nov 01 2019 Jakub Čajka <jcajka@redhat.com> - 1.13.4-1
- Rebase to go1.13.4
- Resolves BZ#1767673
* Sat Oct 19 2019 Jakub Čajka <jcajka@redhat.com> - 1.13.3-1
- Rebase to go1.13.3
- Fix for CVE-2019-17596
- Resolves: BZ#1763311
- Resolves: BZ#1755639, BZ#1763312
* Sat Oct 5 2019 Jakub Čajka <jcajka@redhat.com> - 1.13.1-1
* Fri Sep 27 2019 Jakub Čajka <jcajka@redhat.com> - 1.13.1-1
- Rebase to go1.13.1
- Fix for CVE-2019-16276
- Resolves: BZ#1755971
- Resolves: BZ#1755970
* Tue Sep 10 2019 Jakub Čajka <jcajka@redhat.com> - 1.13-1
* Thu Sep 05 2019 Jakub Čajka <jcajka@redhat.com> - 1.13-2
- Back to go1.13 tls1.3 behavior
* Wed Sep 04 2019 Jakub Čajka <jcajka@redhat.com> - 1.13-1
- Rebase to go1.13
- Fix for CVE-2019-9512, CVE-2019-9514, CVE-2019-14809
- Resolves: BZ#1741815, BZ#1741826, BZ#1743130
* Thu Aug 08 2019 Jakub Čajka <jcajka@redhat.com> - 1.11.12-1
- Rebase to 1.11.12
* Fri Aug 30 2019 Jakub Čajka <jcajka@redhat.com> - 1.13-0.rc2.1
- Rebase to go1.13rc2
- Do not enable tls1.3 by default
- Related: BZ#1737471
* Mon Feb 04 2019 Jakub Čajka <jcajka@redhat.com> - 1.11.5-1
- Rebase to go1.11.5
* Wed Aug 28 2019 Jakub Čajka <jcajka@redhat.com> - 1.13-0.rc1.2
- Actually fix CVE-2019-9514 and CVE-2019-9512
- Related: BZ#1741816, BZ#1741827
* Mon Aug 26 2019 Jakub Čajka <jcajka@redhat.com> - 1.13-0.rc1.1
- Rebase to 1.13rc1
- Fix for CVE-2019-14809, CVE-2019-9514 and CVE-2019-9512
- Resolves: BZ#1741816, BZ#1741827 and BZ#1743131
* Thu Aug 01 2019 Jakub Čajka <jcajka@redhat.com> - 1.13-0.beta1.2.2
- Fix ICE affecting aarch64
- Resolves: BZ#1735290
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.13-0.beta1.2.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Wed Jul 24 2019 Jakub Čajka <jcajka@redhat.com> - 1.13-0.beta1.2
- De-configure sumdb and go proxy
* Wed Jul 24 2019 Jakub Čajka <jcajka@redhat.com> - 1.13-0.beta1.1
- Rebase to 1.13beta1
- Related: BZ#1732118
* Tue Jul 09 2019 Jakub Čajka <jcajka@redhat.com> - 1.12.7-1
- Rebase to 1.12.7
- Resolves: BZ#1728056
* Wed Jun 12 2019 Jakub Čajka <jcajka@redhat.com> - 1.12.6-1
- Rebase to 1.12.6
- Resolves: BZ#1719483
* Tue May 07 2019 Jakub Čajka <jcajka@redhat.com> - 1.12.5-1
- Rebase to 1.12.5
- Resolves: BZ#1707187
* Mon Apr 08 2019 Jakub Čajka <jcajka@redhat.com> - 1.12.2-1
- Rebase to 1.12.2
- Resolves: BZ#1688996
* Mon Apr 01 2019 Jakub Čajka <jcajka@redhat.com> - 1.12.1-2
- Fix up change log, respective CVE has been fixed in go1.12rc1
* Fri Mar 15 2019 Jakub Čajka <jcajka@redhat.com> - 1.12.1-1
- Rebase to 1.12.1
- Fix requirement for %%preun (instead of %%postun) scriptlet thanks to Tim Landscheidt
- Use weak deps for SCM deps
* Wed Feb 27 2019 Jakub Čajka <jcajka@redhat.com> - 1.12-1
- Rebase to go1.12 proper
- Resolves: BZ#1680040
* Mon Feb 18 2019 Jakub Čajka <jcajka@redhat.com> - 1.12-0.rc1.1
- Rebase to go1.12rc1
* Thu Jan 31 2019 Fedora Release Engineering <releng@fedoraproject.org> - 1.12-0.beta2.2.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Sun Jan 27 2019 Jakub Čajka <jcajka@redhat.com> - 1.12-0.beta2.2
- Fix for CVE-2019-6486
- Resolves: BZ#1668975
- Resolves: BZ#1668973
* Fri Jan 11 2019 Jakub Čajka <jcajka@redhat.com> - 1.12-0.beta2.1
- Rebase to go1.12beta2
* Wed Jan 02 2019 Jakub Čajka <jcajka@redhat.com> - 1.11.4-1
- Rebase to go1.11.4
- Fix for CVE-2018-16875, CVE-2018-16874 and CVE-2018-16873
- Resolves: BZ#1664332
- Resolves: BZ#1659290, BZ#1659289, BZ#1659288
* Fri Nov 30 2018 Jakub Čajka <jcajka@redhat.com> - 1.11.2-3
- add ppc64le proper
* Mon Nov 26 2018 Jakub Čajka <jcajka@redhat.com> - 1.11.2-2
- fix up macros file for aarch64
* Fri Nov 23 2018 Jakub Čajka <jcajka@redhat.com> - 1.11.2-1
* Mon Nov 05 2018 Jakub Čajka <jcajka@redhat.com> - 1.11.2-1
- Rebase to go1.11.2
* Sun Oct 07 2018 Jakub Čajka <jcajka@redhat.com> - 1.11.1-1
* Thu Oct 04 2018 Jakub Čajka <jcajka@redhat.com> - 1.11.1-1
- Rebase to go1.11.1
* Mon Jun 11 2018 Jakub Čajka <jcajka@redhat.com> - 1.9.7-1
- Rebase to 1.9.7
* Mon Aug 27 2018 Jakub Čajka <jcajka@redhat.com> - 1.11-1
- Rebase to go1.11 release
* Thu May 10 2018 Jakub Čajka <jcajka@redhat.com> - 1.9.6-1
- Rebase to 1.9.6
* Thu Aug 23 2018 Jakub Čajka <jcajka@redhat.com> - 1.11-0.rc2.1
- Rebase to go1.11rc2
- Reduce size of bin package
* Tue Mar 20 2018 Jakub Čajka <jcajka@redhat.com> - 1.9.4-1
- Rebase to 1.9.4
- Fix CVE-2018-6574 and CVE-2018-7187
- Resolves: BZ#1543561, BZ#1543563, BZ#1546386, BZ#1546387
* Tue Aug 14 2018 Jakub Čajka <jcajka@redhat.com> - 1.11-0.rc1.1
- Rebase to go1.11rc1
* Mon Aug 06 2018 Jakub Čajka <jcajka@redhat.com> - 1.11-0.beta3.1
- Rebase to go1.11beta3
* Fri Jul 27 2018 Jakub Čajka <jcajka@redhat.com> - 1.11-0.beta2.2
- Turn on back DWARF compression by default
- Use less memory on 32bit targets during build
- Resolves: BZ#1607270
- Related: BZ#1602096
* Fri Jul 20 2018 Jakub Čajka <jcajka@redhat.com> - 1.11-0.beta2.1
- Rebase to 1.11beta2
* Wed Jul 18 2018 Jakub Čajka <jcajka@redhat.com> - 1.11-0.beta1.2
- Turn off DWARF compression by default as it is not supported by rpm/debuginfo
- Related: BZ#1602096
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.11-0.beta1.1.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Wed Jul 04 2018 Jakub Čajka <jcajka@redhat.com> - 1.11-0.beta1.1
* Rebase to 1.11beta1
* Fri Jun 08 2018 Jakub Čajka <jcajka@redhat.com> - 1.10.3-1
- Rebase to 1.10.3
* Wed May 02 2018 Jakub Čajka <jcajka@redhat.com> - 1.10.2-1
- Rebase to 1.10.2
* Wed Apr 04 2018 Jakub Čajka <jcajka@redhat.com> - 1.10.1-1
- Rebase to 1.10.1
- Resolves: BZ#1562270
* Sat Mar 03 2018 Jakub Čajka <jcajka@redhat.com> - 1.10-2
- Fix CVE-2018-7187
- Resolves: BZ#1546386, BZ#1546388
* Wed Feb 21 2018 Jakub Čajka <jcajka@redhat.com> - 1.10-1
- Rebase to 1.10
* Thu Feb 08 2018 Jakub Čajka <jcajka@redhat.com> - 1.10-0.rc2.1
- Rebase to 1.10rc2
- Fix CVE-2018-6574
- Resolves: BZ#1543561, BZ#1543562
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 1.10-0.rc1.1.1
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Fri Jan 26 2018 Jakub Čajka <jcajka@redhat.com> - 1.10-0.rc1.1
- Rebase to 1.10rc1
* Fri Jan 12 2018 Jakub Čajka <jcajka@redhat.com> - 1.10-0.beta2.1
- Rebase to 1.10beta2
* Mon Jan 08 2018 Jakub Čajka <jcajka@redhat.com> - 1.10-0.beta1.1
- Rebase to 1.10beta1
- Drop verbose patch as most of it is now implemented by bootstrap tool and is easily toggled by passing -v flag to make.bash
* Thu Oct 26 2017 Jakub Čajka <jcajka@redhat.com> - 1.9.2-1
- Rebase to 1.9.2

View File

@ -1,8 +0,0 @@
# Where to set GOPATH for builds. Like:
# export GOPATH=$(pwd)/_build:%{gopath}
%gopath %{_datadir}/gocode
# for use like:
# ExclusiveArch: %{go_arches}
%go_arches %{ix86} x86_64 %{arm} aarch64 ppc64le

View File

@ -1,457 +0,0 @@
From d6beea7f9ea1aa2ae5abca7fccb252767820aa13 Mon Sep 17 00:00:00 2001
From: Lynn Boger <laboger@linux.vnet.ibm.com>
Date: Tue, 26 Jul 2016 08:51:10 -0500
Subject: [PATCH] cmd/link: split large elf text sections for ppc64x
Some applications built with Go on ppc64x with
external linking can fail to link with relocation
truncation errors, due to the way that the golang
compiler generates a single go.o file containing
a single large text section to send to the GNU
linker. If the size of the single text section is
greater than 2^26, this can lead to link errors
due to 24 bit offset field in the bl (call)
instruction.
This fix solves the problem by splitting into
multiple text sections when this limit is reached.
When this is done then the GNU linker can fix the
long calls and insert jump tables where needed.
---
src/cmd/link/internal/ld/data.go | 52 +++++++++++++++++++++++++++++--
src/cmd/link/internal/ld/elf.go | 60 ++++++++++++++++++++++++++++++++---
src/cmd/link/internal/ld/lib.go | 20 ++++++++++++
src/cmd/link/internal/ld/symtab.go | 64 ++++++++++++++++++++++++++++++++++++++
src/cmd/link/internal/ppc64/asm.go | 12 ++++---
src/runtime/symtab.go | 34 +++++++++++++++-----
src/runtime/type.go | 16 +++++++++-
7 files changed, 237 insertions(+), 21 deletions(-)
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index 57a0dad..58ce18c 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -527,7 +527,15 @@ func relocsym(s *LSym) {
o = Symaddr(r.Sym) + r.Add - int64(r.Sym.Sect.Vaddr)
case obj.R_ADDROFF:
- o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add
+
+ // The method offset tables using this relocation expect the offset to be relative
+ // to the start of the first text section, even if there are multiple.
+
+ if Linkmode == LinkExternal && r.Sym.Sect.Name == ".text" && r.Sym.Sect.Vaddr != Segtext.Vaddr {
+ o = Symaddr(r.Sym) - int64(Segtext.Vaddr) + r.Add
+ } else {
+ o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add
+ }
// r->sym can be null when CALL $(constant) is transformed from absolute PC to relative PC call.
case obj.R_CALL, obj.R_GOTPCREL, obj.R_PCREL:
@@ -1926,6 +1934,7 @@ func textaddress() {
}
va := uint64(INITTEXT)
sect.Vaddr = va
+ n := 1
for _, sym := range Ctxt.Textp {
sym.Sect = sect
if sym.Type&obj.SSUB != 0 {
@@ -1948,9 +1957,30 @@ func textaddress() {
} else {
va += uint64(sym.Size)
}
+ // On ppc64x a text section should not be larger than 2^26 bytes due to the size of
+ // call target offset field in the bl instruction. Splitting into text
+ // sections smaller than this limit allows the GNU linker to modify the long calls
+ // appropriately. The limit allows for the space for linker tables.
+
+ // Only break at outermost syms.
+
+ if sym.Outer == nil && Iself && Linkmode == LinkExternal && SysArch.InFamily(sys.PPC64) && va-sect.Vaddr > uint64(0x1c00000) {
+
+ // Set the length for the previous text section
+ sect.Length = va - sect.Vaddr
+
+ // Create new section, set the starting Vaddr
+ sect = addsection(&Segtext, ".text", 05)
+ sect.Vaddr = va
+
+ // Create a symbol for the start and end of the secondary text section
+ Linklookup(Ctxt, fmt.Sprintf("runtime.text.%d", n), 0).Sect = sect
+ n++
+ }
}
sect.Length = va - sect.Vaddr
+ Linklookup(Ctxt, "runtime.etext", 0).Sect = sect
}
// assign addresses
@@ -2057,11 +2087,27 @@ func address() {
Segdwarf.Filelen = va - Segdwarf.Vaddr
text := Segtext.Sect
+ lasttext := text
var rodata *Section
if Segrodata.Sect != nil {
rodata = Segrodata.Sect
} else {
- rodata = text.Next
+ // Could be multiple .text sections
+ n := 1
+ for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
+ if sect.Name != ".text" {
+ break
+ }
+ lasttext = sect
+ symname := fmt.Sprintf("runtime.text.%d", n)
+ xdefine(symname, obj.STEXT, int64(sect.Vaddr))
+ n++
+ }
+
+ rodata = lasttext.Next
+ if rodata != nil && rodata.Name != ".rodata" {
+ Diag("Unexpected section order in text segment")
+ }
}
var relrodata *Section
typelink := rodata.Next
@@ -2108,7 +2154,7 @@ func address() {
}
xdefine("runtime.text", obj.STEXT, int64(text.Vaddr))
- xdefine("runtime.etext", obj.STEXT, int64(text.Vaddr+text.Length))
+ xdefine("runtime.etext", obj.STEXT, int64(lasttext.Vaddr+lasttext.Length))
if HEADTYPE == obj.Hwindows {
xdefine(".text", obj.STEXT, int64(text.Vaddr))
}
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index 39d3609..ecb00c2 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -1623,6 +1623,25 @@ func elfshname(name string) *ElfShdr {
return nil
}
+// Create an ElfShdr for the section with name.
+// A new one is created even if one already exists with
+// the same name.
+func elfshnamedup(name string) *ElfShdr {
+ var off int
+ var sh *ElfShdr
+
+ for i := 0; i < nelfstr; i++ {
+ if name == elfstr[i].s {
+ off = elfstr[i].off
+ sh = newElfShdr(int64(off))
+ return sh
+ }
+ }
+ Diag("cannot find elf name %s", name)
+ errorexit()
+ return nil
+}
+
func elfshalloc(sect *Section) *ElfShdr {
sh := elfshname(sect.Name)
sect.Elfsect = sh
@@ -1630,7 +1649,17 @@ func elfshalloc(sect *Section) *ElfShdr {
}
func elfshbits(sect *Section) *ElfShdr {
- sh := elfshalloc(sect)
+ var sh *ElfShdr
+
+ if sect.Name == ".text" {
+ if sect.Elfsect == nil {
+ sect.Elfsect = elfshnamedup(sect.Name)
+ }
+ sh = sect.Elfsect
+ } else {
+ sh = elfshalloc(sect)
+ }
+
// If this section has already been set up as a note, we assume type_ and
// flags are already correct, but the other fields still need filling in.
if sh.type_ == SHT_NOTE {
@@ -1706,6 +1735,15 @@ func elfshreloc(sect *Section) *ElfShdr {
}
sh := elfshname(elfRelType + sect.Name)
+
+ // There could be multiple text sections but each needs
+ // its own .rela.text.
+ if sect.Name == ".text" {
+ if sh.info != 0 && sh.info != uint32(sect.Elfsect.shnum) {
+ sh = elfshnamedup(elfRelType + sect.Name)
+ }
+ }
+
sh.type_ = uint32(typ)
sh.entsize = uint64(SysArch.RegSize) * 2
if typ == SHT_RELA {
@@ -1776,9 +1814,12 @@ func Elfemitreloc() {
Cput(0)
}
- elfrelocsect(Segtext.Sect, Ctxt.Textp)
- for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
- elfrelocsect(sect, datap)
+ for sect := Segtext.Sect; sect != nil; sect = sect.Next {
+ if sect.Name == ".text" {
+ elfrelocsect(sect, Ctxt.Textp)
+ } else {
+ elfrelocsect(sect, datap)
+ }
}
for sect := Segrodata.Sect; sect != nil; sect = sect.Next {
elfrelocsect(sect, datap)
@@ -2109,7 +2150,16 @@ func Asmbelfsetup() {
elfshname("")
for sect := Segtext.Sect; sect != nil; sect = sect.Next {
- elfshalloc(sect)
+
+ // There could be multiple .text sections. Instead check the Elfsect
+ // field to determine if already has an ElfShdr and if not, create one.
+ if sect.Name == ".text" {
+ if sect.Elfsect == nil {
+ sect.Elfsect = elfshnamedup(sect.Name)
+ }
+ } else {
+ elfshalloc(sect)
+ }
}
for sect := Segrodata.Sect; sect != nil; sect = sect.Next {
elfshalloc(sect)
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 14f4fa9..709e7ca 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1956,6 +1956,26 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
if s.Type == obj.STEXT {
put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), nil)
}
+ n := 0
+
+ // Generate base addresses for all text sections if there are multiple
+ for sect := Segtext.Sect; sect != nil; sect = sect.Next {
+ if n == 0 {
+ n++
+ continue
+ }
+ if sect.Name != ".text" {
+ break
+ }
+ s = Linkrlookup(Ctxt, fmt.Sprintf("runtime.text.%d", n), 0)
+ if s == nil {
+ break
+ }
+ if s.Type == obj.STEXT {
+ put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), nil)
+ }
+ n++
+ }
s = Linklookup(Ctxt, "runtime.etext", 0)
if s.Type == obj.STEXT {
put(s, s.Name, 'T', s.Value, s.Size, int(s.Version), nil)
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 06d7792..80eb33d 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -315,6 +315,62 @@ func (libs byPkg) Swap(a, b int) {
libs[a], libs[b] = libs[b], libs[a]
}
+// Create a table with information on the text sections.
+
+func textsectionmap() uint32 {
+
+ t := Linklookup(Ctxt, "runtime.textsectionmap", 0)
+ t.Type = obj.SRODATA
+ t.Attr |= AttrReachable
+ nsections := int64(0)
+
+ for sect := Segtext.Sect; sect != nil; sect = sect.Next {
+ if sect.Name == ".text" {
+ nsections++
+ } else {
+ break
+ }
+ }
+ Symgrow(Ctxt, t, nsections*3*8)
+
+ off := int64(0)
+ n := 0
+
+ // The vaddr for each text section is the difference between the section's
+ // Vaddr and the Vaddr for the first text section as determined at compile
+ // time.
+
+ // The symbol name for the start address of the first text section is
+ // runtime.text. Additional text sections are named runtime.text.n where n is the
+ // order of creation starting with 1. These symbols provide the section's
+ // start address after relocation by the linker.
+
+ textbase := Segtext.Sect.Vaddr
+ for sect := Segtext.Sect; sect != nil; sect = sect.Next {
+ if sect.Name != ".text" {
+ break
+ }
+ off = setuintxx(Ctxt, t, off, sect.Vaddr-textbase, int64(SysArch.IntSize))
+ off = setuintxx(Ctxt, t, off, sect.Length, int64(SysArch.IntSize))
+ if n == 0 {
+ s := Linkrlookup(Ctxt, "runtime.text", 0)
+ if s == nil {
+ Diag("Unable to find symbol runtime.text\n")
+ }
+ off = setaddr(Ctxt, t, off, s)
+
+ } else {
+ s := Linklookup(Ctxt, fmt.Sprintf("runtime.text.%d", n), 0)
+ if s == nil {
+ Diag("Unable to find symbol runtime.text.%d\n", n)
+ }
+ off = setaddr(Ctxt, t, off, s)
+ }
+ n++
+ }
+ return uint32(n)
+}
+
func symtab() {
dosymtype()
@@ -489,6 +545,8 @@ func symtab() {
adduint(Ctxt, abihashgostr, uint64(hashsym.Size))
}
+ nsections := textsectionmap()
+
// Information about the layout of the executable image for the
// runtime to use. Any changes here must be matched by changes to
// the definition of moduledata in runtime/symtab.go.
@@ -527,6 +585,12 @@ func symtab() {
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0))
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.types", 0))
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etypes", 0))
+
+ // text section information
+ Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.textsectionmap", 0))
+ adduint(Ctxt, moduledata, uint64(nsections))
+ adduint(Ctxt, moduledata, uint64(nsections))
+
// The typelinks slice
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0))
adduint(Ctxt, moduledata, uint64(ntypelinks))
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index bd2e23f..ab59fa8 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -813,12 +813,14 @@ func asmb() {
ld.Asmbelfsetup()
}
- sect := ld.Segtext.Sect
- ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
- ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
- for sect = sect.Next; sect != nil; sect = sect.Next {
+ for sect := ld.Segtext.Sect; sect != nil; sect = sect.Next {
ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
- ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
+ // Might have multiple text sections
+ if sect.Name == ".text" {
+ ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
+ } else {
+ ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
+ }
}
if ld.Segrodata.Filelen > 0 {
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
index 4f6fae2..23e80ce 100644
--- a/src/runtime/symtab.go
+++ b/src/runtime/symtab.go
@@ -195,8 +195,9 @@ type moduledata struct {
end, gcdata, gcbss uintptr
types, etypes uintptr
- typelinks []int32 // offsets from types
- itablinks []*itab
+ textsectmap []textsect
+ typelinks []int32 // offsets from types
+ itablinks []*itab
modulename string
modulehashes []modulehash
@@ -226,6 +227,14 @@ type functab struct {
funcoff uintptr
}
+// Mapping information for secondary text sections
+
+type textsect struct {
+ vaddr uint64 // prelinked section vaddr
+ length uint64 // section length
+ baseaddr uintptr // relocated section address
+}
+
const minfunc = 16 // minimum function size
const pcbucketsize = 256 * minfunc // size of bucket in the pc->func lookup table
@@ -368,12 +377,23 @@ func findfunc(pc uintptr) *_func {
ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
idx := ffb.idx + uint32(ffb.subbuckets[i])
if pc < datap.ftab[idx].entry {
- throw("findfunc: bad findfunctab entry")
- }
- // linear search to find func with pc >= entry.
- for datap.ftab[idx+1].entry <= pc {
- idx++
+ // If there are multiple text sections then the buckets for the secondary
+ // text sections will be off because the addresses in those text sections
+ // were relocated to higher addresses. Search back to find it.
+
+ for datap.ftab[idx].entry > pc && idx > 0 {
+ idx--
+ }
+ if idx == 0 {
+ throw("findfunc: bad findfunctab entry idx")
+ }
+ } else {
+
+ // linear search to find func with pc >= entry.
+ for datap.ftab[idx+1].entry <= pc {
+ idx++
+ }
}
return (*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[idx].funcoff]))
}
diff --git a/src/runtime/type.go b/src/runtime/type.go
index 5ef11a4..f641adc 100644
--- a/src/runtime/type.go
+++ b/src/runtime/type.go
@@ -257,7 +257,21 @@ func (t *_type) textOff(off textOff) unsafe.Pointer {
}
return res
}
- res := md.text + uintptr(off)
+ res := uintptr(0)
+
+ // Find the text section range that contains the offset to determine the section's base
+ // address. In cases where there are multiple text sections, the base address might be
+ // relocated by the linker.
+
+ for i := 0; i < len(md.textsectmap); i++ {
+ sectaddr := md.textsectmap[i].vaddr
+ sectlen := md.textsectmap[i].length
+ if uint64(off) >= sectaddr && uint64(off) <= sectaddr+sectlen {
+ res = md.textsectmap[i].baseaddr + uintptr(off) - uintptr(md.textsectmap[i].vaddr)
+ break
+ }
+ }
+
if res > md.etext {
println("runtime: textOff", hex(off), "out of range", hex(md.text), "-", hex(md.etext))
throw("runtime: text offset out of range")

View File

@ -1,150 +0,0 @@
From a5b97a846d70cd8db7f33c24f2b9159f935ce318 Mon Sep 17 00:00:00 2001
From: Lynn Boger <laboger@linux.vnet.ibm.com>
Date: Tue, 13 Sep 2016 15:13:08 -0500
Subject: [PATCH] cmd/compile: large text sections on ppc64le
Additional fixes as submitted upstream.
---
src/cmd/link/internal/ld/data.go | 24 ++++++++++++------------
src/cmd/link/internal/ld/lib.go | 2 +-
src/cmd/link/internal/ld/symtab.go | 2 +-
src/runtime/type.go | 28 ++++++++++++++++++----------
4 files changed, 32 insertions(+), 24 deletions(-)
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index 58ce18c..d8e43ff 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -531,7 +531,7 @@ func relocsym(s *LSym) {
// The method offset tables using this relocation expect the offset to be relative
// to the start of the first text section, even if there are multiple.
- if Linkmode == LinkExternal && r.Sym.Sect.Name == ".text" && r.Sym.Sect.Vaddr != Segtext.Vaddr {
+ if r.Sym.Sect.Name == ".text" {
o = Symaddr(r.Sym) - int64(Segtext.Vaddr) + r.Add
} else {
o = Symaddr(r.Sym) - int64(r.Sym.Sect.Vaddr) + r.Add
@@ -1928,7 +1928,6 @@ func textaddress() {
sect.Align = int32(Funcalign)
Linklookup(Ctxt, "runtime.text", 0).Sect = sect
- Linklookup(Ctxt, "runtime.etext", 0).Sect = sect
if HEADTYPE == obj.Hwindows {
Linklookup(Ctxt, ".text", 0).Sect = sect
}
@@ -1964,7 +1963,7 @@ func textaddress() {
// Only break at outermost syms.
- if sym.Outer == nil && Iself && Linkmode == LinkExternal && SysArch.InFamily(sys.PPC64) && va-sect.Vaddr > uint64(0x1c00000) {
+ if sym.Outer == nil && Iself && Linkmode == LinkExternal && SysArch.InFamily(sys.PPC64) && va-sect.Vaddr > 0x1c00000 {
// Set the length for the previous text section
sect.Length = va - sect.Vaddr
@@ -1973,7 +1972,7 @@ func textaddress() {
sect = addsection(&Segtext, ".text", 05)
sect.Vaddr = va
- // Create a symbol for the start and end of the secondary text section
+ // Create a symbol for the start of the secondary text section
Linklookup(Ctxt, fmt.Sprintf("runtime.text.%d", n), 0).Sect = sect
n++
}
@@ -2093,15 +2092,8 @@ func address() {
rodata = Segrodata.Sect
} else {
// Could be multiple .text sections
- n := 1
- for sect := Segtext.Sect.Next; sect != nil; sect = sect.Next {
- if sect.Name != ".text" {
- break
- }
+ for sect := Segtext.Sect.Next; sect != nil && sect.Name == ".text"; sect = sect.Next {
lasttext = sect
- symname := fmt.Sprintf("runtime.text.%d", n)
- xdefine(symname, obj.STEXT, int64(sect.Vaddr))
- n++
}
rodata = lasttext.Next
@@ -2155,6 +2147,14 @@ func address() {
xdefine("runtime.text", obj.STEXT, int64(text.Vaddr))
xdefine("runtime.etext", obj.STEXT, int64(lasttext.Vaddr+lasttext.Length))
+
+ n := 1
+ for sect := Segtext.Sect.Next; sect != nil && sect.Name == ".text"; sect = sect.Next {
+ symname := fmt.Sprintf("runtime.text.%d", n)
+ xdefine(symname, obj.STEXT, int64(sect.Vaddr))
+ n++
+ }
+
if HEADTYPE == obj.Hwindows {
xdefine(".text", obj.STEXT, int64(text.Vaddr))
}
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 709e7ca..c37ef92 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1958,7 +1958,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
}
n := 0
- // Generate base addresses for all text sections if there are multiple
+ // Generate base addresses for all text sections if there are multiple.
for sect := Segtext.Sect; sect != nil; sect = sect.Next {
if n == 0 {
n++
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 80eb33d..ec26f88 100644
--- a/src/cmd/link/internal/ld/symtab.go
+++ b/src/cmd/link/internal/ld/symtab.go
@@ -331,7 +331,7 @@ func textsectionmap() uint32 {
break
}
}
- Symgrow(Ctxt, t, nsections*3*8)
+ Symgrow(Ctxt, t, nsections*(2*int64(SysArch.IntSize)+int64(SysArch.PtrSize)))
off := int64(0)
n := 0
diff --git a/src/runtime/type.go b/src/runtime/type.go
index f641adc..d4df5a9 100644
--- a/src/runtime/type.go
+++ b/src/runtime/type.go
@@ -259,17 +259,25 @@ func (t *_type) textOff(off textOff) unsafe.Pointer {
}
res := uintptr(0)
- // Find the text section range that contains the offset to determine the section's base
- // address. In cases where there are multiple text sections, the base address might be
- // relocated by the linker.
-
- for i := 0; i < len(md.textsectmap); i++ {
- sectaddr := md.textsectmap[i].vaddr
- sectlen := md.textsectmap[i].length
- if uint64(off) >= sectaddr && uint64(off) <= sectaddr+sectlen {
- res = md.textsectmap[i].baseaddr + uintptr(off) - uintptr(md.textsectmap[i].vaddr)
- break
+ // The text, or instruction stream is generated as one large buffer. The off (offset) for a method is
+ // its offset within this buffer. If the total text size gets too large, there can be issues on platforms like ppc64 if
+ // the target of calls are too far for the call instruction. To resolve the large text issue, the text is split
+ // into multiple text sections to allow the linker to generate long calls when necessary. When this happens, the vaddr
+ // for each text section is set to its offset within the text. Each method's offset is compared against the section
+ // vaddrs and sizes to determine the containing section. Then the section relative offset is added to the section's
+ // relocated baseaddr to compute the method addess.
+
+ if len(md.textsectmap) > 1 {
+ for i := 0; i < len(md.textsectmap); i++ {
+ sectaddr := md.textsectmap[i].vaddr
+ sectlen := md.textsectmap[i].length
+ if uint64(off) >= sectaddr && uint64(off) <= sectaddr+sectlen {
+ res = md.textsectmap[i].baseaddr + uintptr(off) - uintptr(md.textsectmap[i].vaddr)
+ break
+ }
}
+ } else {
+ res = md.text + uintptr(off)
}
if res > md.etext {

View File

@ -1 +1 @@
SHA512 (go1.13.6.src.tar.gz) = dffb6e06eea0b1541901dfbed8d28e8cc1eac3184dc40a19ed3637737df796a67a2e7170b228e1003d36b14e6f0f13bb8be9d2a702834a9c06228d1821659528
SHA512 (go1.15.5.src.tar.gz) = 8e1d71f628d364b949b1e124af8950a563bbe9d9ae73b94c66af6ce029f67c26e2654556c0c118d0bc8566af52a7e9ed736b4667bbef7ccdab2bd338c43e6eb4

View File

@ -1,97 +0,0 @@
From 8890527476e25747f063377d637b106db0008329 Mon Sep 17 00:00:00 2001
From: Alberto Donizetti <alb.donizetti@gmail.com>
Date: Thu, 9 Mar 2017 13:20:54 +0100
Subject: [PATCH] [release-branch.go1.8] time: make the ParseInLocation test
more robust
The tzdata 2017a update (2017-02-28) changed the abbreviation of the
Asia/Baghdad time zone (used in TestParseInLocation) from 'AST' to the
numeric '+03'.
Update the test so that it skips the checks if we're using a recent
tzdata release.
Fixes #19457
Change-Id: I45d705a5520743a611bdd194dc8f8d618679980c
Reviewed-on: https://go-review.googlesource.com/37964
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
(cherry picked from commit 91563ced5897faf729a34be7081568efcfedda31)
Reviewed-on: https://go-review.googlesource.com/37991
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
---
src/time/format_test.go | 41 +++++++++++++++++++++++++++++++----------
1 file changed, 31 insertions(+), 10 deletions(-)
diff --git a/src/time/format_test.go b/src/time/format_test.go
index 219c2ca..d0013bc 100644
--- a/src/time/format_test.go
+++ b/src/time/format_test.go
@@ -245,27 +245,45 @@ func TestParseDayOutOfRange(t *testing.T) {
}
}
+// TestParseInLocation checks that the Parse and ParseInLocation
+// functions do not get confused by the fact that AST (Arabia Standard
+// Time) and AST (Atlantic Standard Time) are different time zones,
+// even though they have the same abbreviation.
+//
+// ICANN has been slowly phasing out invented abbreviation in favor of
+// numeric time zones (for example, the Asia/Baghdad time zone
+// abbreviation got changed from AST to +03 in the 2017a tzdata
+// release); but we still want to make sure that the time package does
+// not get confused on systems with slightly older tzdata packages.
func TestParseInLocation(t *testing.T) {
- // Check that Parse (and ParseInLocation) understand that
- // Feb 01 AST (Arabia Standard Time) and Feb 01 AST (Atlantic Standard Time)
- // are in different time zones even though both are called AST
baghdad, err := LoadLocation("Asia/Baghdad")
if err != nil {
t.Fatal(err)
}
- t1, err := ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", baghdad)
+ var t1, t2 Time
+
+ t1, err = ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", baghdad)
if err != nil {
t.Fatal(err)
}
- t2 := Date(2013, February, 1, 00, 00, 00, 0, baghdad)
- if t1 != t2 {
- t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad) = %v, want %v", t1, t2)
- }
+
_, offset := t1.Zone()
- if offset != 3*60*60 {
- t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad).Zone = _, %d, want _, %d", offset, 3*60*60)
+
+ // A zero offset means that ParseInLocation did not recognize the
+ // 'AST' abbreviation as matching the current location (Baghdad,
+ // where we'd expect a +03 hrs offset); likely because we're using
+ // a recent tzdata release (2017a or newer).
+ // If it happens, skip the Baghdad test.
+ if offset != 0 {
+ t2 = Date(2013, February, 1, 00, 00, 00, 0, baghdad)
+ if t1 != t2 {
+ t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad) = %v, want %v", t1, t2)
+ }
+ if offset != 3*60*60 {
+ t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad).Zone = _, %d, want _, %d", offset, 3*60*60)
+ }
}
blancSablon, err := LoadLocation("America/Blanc-Sablon")
@@ -273,6 +291,9 @@ func TestParseInLocation(t *testing.T) {
t.Fatal(err)
}
+ // In this case 'AST' means 'Atlantic Standard Time', and we
+ // expect the abbreviation to correctly match the american
+ // location.
t1, err = ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", blancSablon)
if err != nil {
t.Fatal(err)