Merge branch 'el6' into epel7
This commit is contained in:
commit
ebf90baf57
|
@ -1,3 +1,4 @@
|
|||
*.rpm
|
||||
/go1.1.1.src.tar.gz
|
||||
/go1.1.2.src.tar.gz
|
||||
/go1.2.1.src.tar.gz
|
||||
|
@ -6,8 +7,49 @@
|
|||
/go1.3.1.src.tar.gz
|
||||
/go1.3.2.src.tar.gz
|
||||
/go1.3.3.src.tar.gz
|
||||
/go1.3.src.tar.gz
|
||||
/go1.3beta2.src.tar.gz
|
||||
/go1.3rc1.src.tar.gz
|
||||
/go1.3rc2.src.tar.gz
|
||||
/go1.3.src.tar.gz
|
||||
/go1.4.1.src.tar.gz
|
||||
/go1.4.2.src.tar.gz
|
||||
/go1.4.src.tar.gz
|
||||
/go1.4beta1.src.tar.gz
|
||||
/go1.4rc1.src.tar.gz
|
||||
/go1.4rc2.src.tar.gz
|
||||
/go1.5beta1.src.tar.gz
|
||||
/golang-19087:a15f344a9efa-xattrs.tar
|
||||
/go1.5beta2.src.tar.gz
|
||||
/go1.5beta3.src.tar.gz
|
||||
/go1.5rc1.src.tar.gz
|
||||
/go1.5.src.tar.gz
|
||||
/go1.5.1.src.tar.gz
|
||||
/go1.5.2.src.tar.gz
|
||||
/Mark.Twain-Tom.Sawyer.txt.bz2
|
||||
/go1.5.3.src.tar.gz
|
||||
/go1.6rc1.src.tar.gz
|
||||
/go1.6.src.tar.gz
|
||||
/go1.6.1.src.tar.gz
|
||||
/go1.6.2.src.tar.gz
|
||||
/go1.7rc2.src.tar.gz
|
||||
/go1.7rc5.src.tar.gz
|
||||
/go1.7.src.tar.gz
|
||||
/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
|
||||
/go1.8.3.src.tar.gz
|
||||
/go1.9beta2.src.tar.gz
|
||||
/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.11.1.src.tar.gz
|
||||
/go1.11.2.src.tar.gz
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
From edce31a2904846ae74e3c011f2cf5fddc963459e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jakub=20=C4=8Cajka?= <jcajka@redhat.com>
|
||||
Date: Thu, 22 Mar 2018 12:07:32 +0100
|
||||
Subject: [PATCH 1/3] Don't use the bundled tzdata at runtime, except for the
|
||||
internal test suite
|
||||
|
||||
---
|
||||
src/time/internal_test.go | 7 +++++--
|
||||
src/time/zoneinfo_test.go | 3 ++-
|
||||
src/time/zoneinfo_unix.go | 2 --
|
||||
3 files changed, 7 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/time/internal_test.go b/src/time/internal_test.go
|
||||
index 76d5524124..e81ace5f64 100644
|
||||
--- a/src/time/internal_test.go
|
||||
+++ b/src/time/internal_test.go
|
||||
@@ -4,13 +4,15 @@
|
||||
|
||||
package time
|
||||
|
||||
+import "runtime"
|
||||
+
|
||||
func init() {
|
||||
// force US/Pacific for time zone tests
|
||||
ForceUSPacificForTesting()
|
||||
}
|
||||
|
||||
func initTestingZone() {
|
||||
- z, err := loadLocation("America/Los_Angeles", zoneSources[len(zoneSources)-1:])
|
||||
+ z, err := loadLocation("America/Los_Angeles", zoneSources)
|
||||
if err != nil {
|
||||
panic("cannot load America/Los_Angeles for testing: " + err.Error())
|
||||
}
|
||||
@@ -21,8 +23,9 @@ func initTestingZone() {
|
||||
var OrigZoneSources = zoneSources
|
||||
|
||||
func forceZipFileForTesting(zipOnly bool) {
|
||||
- zoneSources = make([]string, len(OrigZoneSources))
|
||||
+ zoneSources = make([]string, len(OrigZoneSources)+1)
|
||||
copy(zoneSources, OrigZoneSources)
|
||||
+ zoneSources = append(zoneSources, runtime.GOROOT()+"/lib/time/zoneinfo.zip")
|
||||
if zipOnly {
|
||||
zoneSources = zoneSources[len(zoneSources)-1:]
|
||||
}
|
||||
diff --git a/src/time/zoneinfo_test.go b/src/time/zoneinfo_test.go
|
||||
index 7a55d4f618..6063ca1195 100644
|
||||
--- a/src/time/zoneinfo_test.go
|
||||
+++ b/src/time/zoneinfo_test.go
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
+ "runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -128,7 +129,7 @@ func TestLoadLocationFromTZData(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
- tzinfo, err := time.LoadTzinfo(locationName, time.OrigZoneSources[len(time.OrigZoneSources)-1])
|
||||
+ tzinfo, err := time.LoadTzinfo(locationName, runtime.GOROOT()+"/lib/time/zoneinfo.zip")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
diff --git a/src/time/zoneinfo_unix.go b/src/time/zoneinfo_unix.go
|
||||
index 88313aa0ed..d9596115ef 100644
|
||||
--- a/src/time/zoneinfo_unix.go
|
||||
+++ b/src/time/zoneinfo_unix.go
|
||||
@@ -12,7 +12,6 @@
|
||||
package time
|
||||
|
||||
import (
|
||||
- "runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
@@ -22,7 +21,6 @@ var zoneSources = []string{
|
||||
"/usr/share/zoneinfo/",
|
||||
"/usr/share/lib/zoneinfo/",
|
||||
"/usr/lib/locale/TZ/",
|
||||
- runtime.GOROOT() + "/lib/time/zoneinfo.zip",
|
||||
}
|
||||
|
||||
func initLocal() {
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
From 817407fc2d6a861e65086388766f58082d38bc0b Mon Sep 17 00:00:00 2001
|
||||
From: Michael Munday <munday@ca.ibm.com>
|
||||
Date: Tue, 17 Jan 2017 11:33:38 -0500
|
||||
Subject: [PATCH 2/3] syscall: expose IfInfomsg.X__ifi_pad on s390x
|
||||
|
||||
Exposing this field on s390x improves compatibility with the other
|
||||
linux architectures, all of which already expose it.
|
||||
|
||||
Fixes #18628 and updates #18632.
|
||||
|
||||
Change-Id: I08e8e1eb705f898cd8822f8bee0d61ce11d514b5
|
||||
---
|
||||
src/syscall/ztypes_linux_s390x.go | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/syscall/ztypes_linux_s390x.go b/src/syscall/ztypes_linux_s390x.go
|
||||
index 63c4a83b19..b5894255df 100644
|
||||
--- a/src/syscall/ztypes_linux_s390x.go
|
||||
+++ b/src/syscall/ztypes_linux_s390x.go
|
||||
@@ -449,12 +449,12 @@ type RtAttr struct {
|
||||
}
|
||||
|
||||
type IfInfomsg struct {
|
||||
- Family uint8
|
||||
- _ uint8
|
||||
- Type uint16
|
||||
- Index int32
|
||||
- Flags uint32
|
||||
- Change uint32
|
||||
+ Family uint8
|
||||
+ X__ifi_pad uint8
|
||||
+ Type uint16
|
||||
+ Index int32
|
||||
+ Flags uint32
|
||||
+ Change uint32
|
||||
}
|
||||
|
||||
type IfAddrmsg struct {
|
||||
--
|
||||
2.14.3
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
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 {
|
|
@ -0,0 +1,112 @@
|
|||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,225 @@
|
|||
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
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
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 {
|
|
@ -0,0 +1,144 @@
|
|||
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 {
|
|
@ -0,0 +1,7 @@
|
|||
// +build rpm_crashtraceback
|
||||
|
||||
package runtime
|
||||
|
||||
func init() {
|
||||
setTraceback("crash")
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Cristian Staretu <unclejacksons@gmail.com>
|
||||
# Date 1405555229 -36000
|
||||
# Thu Jul 17 10:00:29 2014 +1000
|
||||
# Node ID 1b17b3426e3c281a973d2d7bbf235b936d6a0942
|
||||
# Parent 278365dff593f027db6c6b2c0a89262490d6b676
|
||||
archive/tar: fix writing of pax headers
|
||||
|
||||
"archive/tar: reuse temporary buffer in writeHeader" introduced a
|
||||
change which was supposed to help lower the number of allocations from
|
||||
512 bytes for every call to writeHeader. This change broke the writing
|
||||
of PAX headers.
|
||||
|
||||
writeHeader calls writePAXHeader and writePAXHeader calls writeHeader
|
||||
again. writeHeader will end up writing the PAX header twice.
|
||||
|
||||
example broken header:
|
||||
PaxHeaders.4007/NetLock_Arany_=Class_Gold=_Ftanstvny.crt0000000000000000000000000000007112301216634021512 xustar0000000000000000
|
||||
PaxHeaders.4007/NetLock_Arany_=Class_Gold=_Ftanstvny.crt0000000000000000000000000000007112301216634021512 xustar0000000000000000
|
||||
|
||||
example correct header:
|
||||
PaxHeaders.4290/NetLock_Arany_=Class_Gold=_Ftanstvny.crt0000000000000000000000000000007112301216634021516 xustar0000000000000000
|
||||
0100644000000000000000000000270412301216634007250 0ustar0000000000000000
|
||||
|
||||
This commit adds a dedicated buffer for pax headers to the Writer
|
||||
struct. This change increases the size of the struct by 512 bytes, but
|
||||
allows tar/writer to avoid allocating 512 bytes for all written
|
||||
headers and it avoids allocating 512 more bytes for pax headers.
|
||||
|
||||
LGTM=dsymonds
|
||||
R=dsymonds, dave, iant
|
||||
CC=golang-codereviews
|
||||
https://codereview.appspot.com/110480043
|
||||
|
||||
Committer: David Symonds <dsymonds@golang.org>
|
||||
|
||||
diff -r 278365dff593 -r 1b17b3426e3c src/pkg/archive/tar/writer.go
|
||||
--- a/src/pkg/archive/tar/writer.go Wed Jul 16 16:29:51 2014 -0700
|
||||
+++ b/src/pkg/archive/tar/writer.go Thu Jul 17 10:00:29 2014 +1000
|
||||
@@ -39,7 +39,8 @@
|
||||
closed bool
|
||||
usedBinary bool // whether the binary numeric field extension was used
|
||||
preferPax bool // use pax header instead of binary numeric header
|
||||
- hdrBuff [blockSize]byte // buffer to use in writeHeader
|
||||
+ hdrBuff [blockSize]byte // buffer to use in writeHeader when writing a regular header
|
||||
+ paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header
|
||||
}
|
||||
|
||||
// NewWriter creates a new Writer writing to w.
|
||||
@@ -161,7 +162,17 @@
|
||||
// subsecond time resolution, but for now let's just capture
|
||||
// too long fields or non ascii characters
|
||||
|
||||
- header := tw.hdrBuff[:]
|
||||
+ var header []byte
|
||||
+
|
||||
+ // We need to select which scratch buffer to use carefully,
|
||||
+ // since this method is called recursively to write PAX headers.
|
||||
+ // If allowPax is true, this is the non-recursive call, and we will use hdrBuff.
|
||||
+ // If allowPax is false, we are being called by writePAXHeader, and hdrBuff is
|
||||
+ // already being used by the non-recursive call, so we must use paxHdrBuff.
|
||||
+ header = tw.hdrBuff[:]
|
||||
+ if !allowPax {
|
||||
+ header = tw.paxHdrBuff[:]
|
||||
+ }
|
||||
copy(header, zeroBlock)
|
||||
s := slicer(header)
|
||||
|
||||
diff -r 278365dff593 -r 1b17b3426e3c src/pkg/archive/tar/writer_test.go
|
||||
--- a/src/pkg/archive/tar/writer_test.go Wed Jul 16 16:29:51 2014 -0700
|
||||
+++ b/src/pkg/archive/tar/writer_test.go Thu Jul 17 10:00:29 2014 +1000
|
||||
@@ -454,3 +454,38 @@
|
||||
t.Fatal("Couldn't recover long name")
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestValidTypeflagWithPAXHeader(t *testing.T) {
|
||||
+ var buffer bytes.Buffer
|
||||
+ tw := NewWriter(&buffer)
|
||||
+
|
||||
+ fileName := strings.Repeat("ab", 100)
|
||||
+
|
||||
+ hdr := &Header{
|
||||
+ Name: fileName,
|
||||
+ Size: 4,
|
||||
+ Typeflag: 0,
|
||||
+ }
|
||||
+ if err := tw.WriteHeader(hdr); err != nil {
|
||||
+ t.Fatalf("Failed to write header: %s", err)
|
||||
+ }
|
||||
+ if _, err := tw.Write([]byte("fooo")); err != nil {
|
||||
+ t.Fatalf("Failed to write the file's data: %s", err)
|
||||
+ }
|
||||
+ tw.Close()
|
||||
+
|
||||
+ tr := NewReader(&buffer)
|
||||
+
|
||||
+ for {
|
||||
+ header, err := tr.Next()
|
||||
+ if err == io.EOF {
|
||||
+ break
|
||||
+ }
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("Failed to read header: %s", err)
|
||||
+ }
|
||||
+ if header.Typeflag != 0 {
|
||||
+ t.Fatalf("Typeflag should've been 0, found %d", header.Typeflag)
|
||||
+ }
|
||||
+ }
|
||||
+}
|
|
@ -1,64 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Cristian Staretu <unclejacksons@gmail.com>
|
||||
# Date 1404344479 -36000
|
||||
# Thu Jul 03 09:41:19 2014 +1000
|
||||
# Node ID 17404efd6b02d4b3acd17070e3f89de97a145877
|
||||
# Parent 837348e418f33fc7a242f56dbe2feff829532526
|
||||
archive/tar: reuse temporary buffer in readHeader
|
||||
|
||||
A temporary 512 bytes buffer is allocated for every call to
|
||||
readHeader. This buffer isn't returned to the caller and it could
|
||||
be reused to lower the number of memory allocations.
|
||||
|
||||
This CL improves it by using a pool and zeroing out the buffer before
|
||||
putting it back into the pool.
|
||||
|
||||
benchmark old ns/op new ns/op delta
|
||||
BenchmarkListFiles100k 545249903 538832687 -1.18%
|
||||
|
||||
benchmark old allocs new allocs delta
|
||||
BenchmarkListFiles100k 2105167 2005692 -4.73%
|
||||
|
||||
benchmark old bytes new bytes delta
|
||||
BenchmarkListFiles100k 105903472 54831527 -48.22%
|
||||
|
||||
This improvement is very important if your code has to deal with a lot
|
||||
of tarballs which contain a lot of files.
|
||||
|
||||
LGTM=dsymonds
|
||||
R=golang-codereviews, dave, dsymonds, bradfitz
|
||||
CC=golang-codereviews
|
||||
https://codereview.appspot.com/108240044
|
||||
|
||||
Committer: David Symonds <dsymonds@golang.org>
|
||||
|
||||
diff -r 837348e418f3 -r 17404efd6b02 src/pkg/archive/tar/reader.go
|
||||
--- a/src/pkg/archive/tar/reader.go Thu Jul 03 09:40:53 2014 +1000
|
||||
+++ b/src/pkg/archive/tar/reader.go Thu Jul 03 09:41:19 2014 +1000
|
||||
@@ -29,10 +29,11 @@
|
||||
// The Next method advances to the next file in the archive (including the first),
|
||||
// and then it can be treated as an io.Reader to access the file's data.
|
||||
type Reader struct {
|
||||
- r io.Reader
|
||||
- err error
|
||||
- pad int64 // amount of padding (ignored) after current file entry
|
||||
- curr numBytesReader // reader for current file entry
|
||||
+ r io.Reader
|
||||
+ err error
|
||||
+ pad int64 // amount of padding (ignored) after current file entry
|
||||
+ curr numBytesReader // reader for current file entry
|
||||
+ hdrBuff [blockSize]byte // buffer to use in readHeader
|
||||
}
|
||||
|
||||
// A numBytesReader is an io.Reader with a numBytes method, returning the number
|
||||
@@ -426,7 +427,9 @@
|
||||
}
|
||||
|
||||
func (tr *Reader) readHeader() *Header {
|
||||
- header := make([]byte, blockSize)
|
||||
+ header := tr.hdrBuff[:]
|
||||
+ copy(header, zeroBlock)
|
||||
+
|
||||
if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
|
||||
return nil
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Cristian Staretu <unclejacksons@gmail.com>
|
||||
# Date 1404344453 -36000
|
||||
# Thu Jul 03 09:40:53 2014 +1000
|
||||
# Node ID 837348e418f33fc7a242f56dbe2feff829532526
|
||||
# Parent c5f72a685e256457a0872f6587e2bb9500eac7c4
|
||||
archive/tar: reuse temporary buffer in writeHeader
|
||||
|
||||
A temporary 512 bytes buffer is allocated for every call to
|
||||
writeHeader. This buffer could be reused the lower the number
|
||||
of memory allocations.
|
||||
|
||||
benchmark old ns/op new ns/op delta
|
||||
BenchmarkWriteFiles100k 634622051 583810847 -8.01%
|
||||
|
||||
benchmark old allocs new allocs delta
|
||||
BenchmarkWriteFiles100k 2701920 2602621 -3.68%
|
||||
|
||||
benchmark old bytes new bytes delta
|
||||
BenchmarkWriteFiles100k 115383884 64349922 -44.23%
|
||||
|
||||
This change is very important if your code has to write a lot of
|
||||
tarballs with a lot of files.
|
||||
|
||||
LGTM=dsymonds
|
||||
R=golang-codereviews, dave, dsymonds
|
||||
CC=golang-codereviews
|
||||
https://codereview.appspot.com/107440043
|
||||
|
||||
Committer: David Symonds <dsymonds@golang.org>
|
||||
|
||||
diff -r c5f72a685e25 -r 837348e418f3 src/pkg/archive/tar/writer.go
|
||||
--- a/src/pkg/archive/tar/writer.go Wed Jul 02 15:28:57 2014 -0700
|
||||
+++ b/src/pkg/archive/tar/writer.go Thu Jul 03 09:40:53 2014 +1000
|
||||
@@ -37,8 +37,9 @@
|
||||
nb int64 // number of unwritten bytes for current file entry
|
||||
pad int64 // amount of padding to write after current file entry
|
||||
closed bool
|
||||
- usedBinary bool // whether the binary numeric field extension was used
|
||||
- preferPax bool // use pax header instead of binary numeric header
|
||||
+ usedBinary bool // whether the binary numeric field extension was used
|
||||
+ preferPax bool // use pax header instead of binary numeric header
|
||||
+ hdrBuff [blockSize]byte // buffer to use in writeHeader
|
||||
}
|
||||
|
||||
// NewWriter creates a new Writer writing to w.
|
||||
@@ -160,7 +161,8 @@
|
||||
// subsecond time resolution, but for now let's just capture
|
||||
// too long fields or non ascii characters
|
||||
|
||||
- header := make([]byte, blockSize)
|
||||
+ header := tw.hdrBuff[:]
|
||||
+ copy(header, zeroBlock)
|
||||
s := slicer(header)
|
||||
|
||||
// keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
|
|
@ -0,0 +1,12 @@
|
|||
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)
|
|
@ -1,19 +0,0 @@
|
|||
Index: go/include/u.h
|
||||
===================================================================
|
||||
--- go.orig/include/u.h
|
||||
+++ go/include/u.h
|
||||
@@ -38,10 +38,13 @@ extern "C" {
|
||||
# define __MAKECONTEXT_V2_SOURCE 1
|
||||
# endif
|
||||
#endif
|
||||
+#if defined __linux__ || defined __GNU__ || defined __GLIBC__
|
||||
+#define _DEFAULT_SOURCE 1
|
||||
+#else
|
||||
#define _BSD_SOURCE 1
|
||||
#define _NETBSD_SOURCE 1 /* NetBSD */
|
||||
-#define _DEFAULT_SOURCE 1 /* glibc > 2.19 */
|
||||
#define _SVID_SOURCE 1
|
||||
+#endif
|
||||
#if !defined(__APPLE__) && !defined(__OpenBSD__)
|
||||
# define _XOPEN_SOURCE 1000
|
||||
# define _XOPEN_SOURCE_EXTENDED 1
|
|
@ -1,197 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Alexander Larsson <alexander.larsson@gmail.com>
|
||||
# Date 1392282510 -39600
|
||||
# Node ID a15f344a9efa35ef168c8feaa92a15a1cdc93db5
|
||||
# Parent 1a32fe60e0798d82bbff6c945001c7f0ba8de5ea
|
||||
archive/tar: support extended attributes
|
||||
|
||||
This adds support for archives with the SCHILY.xattr field in the
|
||||
pax header. This is what gnu tar and star generate.
|
||||
Fixes issue 7154.
|
||||
|
||||
LGTM=dsymonds
|
||||
R=golang-codereviews, gobot, dsymonds
|
||||
CC=golang-codereviews
|
||||
https://codereview.appspot.com/54570043
|
||||
|
||||
Committer: David Symonds <dsymonds@golang.org>
|
||||
|
||||
diff -r 1a32fe60e079 -r a15f344a9efa src/pkg/archive/tar/common.go
|
||||
--- a/src/pkg/archive/tar/common.go Thu Feb 13 03:09:03 2014 -0500
|
||||
+++ b/src/pkg/archive/tar/common.go Thu Feb 13 20:08:30 2014 +1100
|
||||
@@ -57,6 +57,7 @@
|
||||
Devminor int64 // minor number of character or block device
|
||||
AccessTime time.Time // access time
|
||||
ChangeTime time.Time // status change time
|
||||
+ Xattrs map[string]string
|
||||
}
|
||||
|
||||
// File name constants from the tar spec.
|
||||
@@ -189,6 +190,7 @@
|
||||
paxSize = "size"
|
||||
paxUid = "uid"
|
||||
paxUname = "uname"
|
||||
+ paxXattr = "SCHILY.xattr."
|
||||
paxNone = ""
|
||||
)
|
||||
|
||||
diff -r 1a32fe60e079 -r a15f344a9efa src/pkg/archive/tar/reader.go
|
||||
--- a/src/pkg/archive/tar/reader.go Thu Feb 13 03:09:03 2014 -0500
|
||||
+++ b/src/pkg/archive/tar/reader.go Thu Feb 13 20:08:30 2014 +1100
|
||||
@@ -139,8 +139,14 @@
|
||||
return err
|
||||
}
|
||||
hdr.Size = int64(size)
|
||||
+ default:
|
||||
+ if strings.HasPrefix(k, paxXattr) {
|
||||
+ if hdr.Xattrs == nil {
|
||||
+ hdr.Xattrs = make(map[string]string)
|
||||
+ }
|
||||
+ hdr.Xattrs[k[len(paxXattr):]] = v
|
||||
+ }
|
||||
}
|
||||
-
|
||||
}
|
||||
return nil
|
||||
}
|
||||
diff -r 1a32fe60e079 -r a15f344a9efa src/pkg/archive/tar/reader_test.go
|
||||
--- a/src/pkg/archive/tar/reader_test.go Thu Feb 13 03:09:03 2014 -0500
|
||||
+++ b/src/pkg/archive/tar/reader_test.go Thu Feb 13 20:08:30 2014 +1100
|
||||
@@ -161,6 +161,46 @@
|
||||
},
|
||||
},
|
||||
},
|
||||
+ {
|
||||
+ file: "testdata/xattrs.tar",
|
||||
+ headers: []*Header{
|
||||
+ {
|
||||
+ Name: "small.txt",
|
||||
+ Mode: 0644,
|
||||
+ Uid: 1000,
|
||||
+ Gid: 10,
|
||||
+ Size: 5,
|
||||
+ ModTime: time.Unix(1386065770, 448252320),
|
||||
+ Typeflag: '0',
|
||||
+ Uname: "alex",
|
||||
+ Gname: "wheel",
|
||||
+ AccessTime: time.Unix(1389782991, 419875220),
|
||||
+ ChangeTime: time.Unix(1389782956, 794414986),
|
||||
+ Xattrs: map[string]string{
|
||||
+ "user.key": "value",
|
||||
+ "user.key2": "value2",
|
||||
+ // Interestingly, selinux encodes the terminating null inside the xattr
|
||||
+ "security.selinux": "unconfined_u:object_r:default_t:s0\x00",
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ Name: "small2.txt",
|
||||
+ Mode: 0644,
|
||||
+ Uid: 1000,
|
||||
+ Gid: 10,
|
||||
+ Size: 11,
|
||||
+ ModTime: time.Unix(1386065770, 449252304),
|
||||
+ Typeflag: '0',
|
||||
+ Uname: "alex",
|
||||
+ Gname: "wheel",
|
||||
+ AccessTime: time.Unix(1389782991, 419875220),
|
||||
+ ChangeTime: time.Unix(1386065770, 449252304),
|
||||
+ Xattrs: map[string]string{
|
||||
+ "security.selinux": "unconfined_u:object_r:default_t:s0\x00",
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
+ },
|
||||
}
|
||||
|
||||
func TestReader(t *testing.T) {
|
||||
@@ -180,7 +220,7 @@
|
||||
f.Close()
|
||||
continue testLoop
|
||||
}
|
||||
- if *hdr != *header {
|
||||
+ if !reflect.DeepEqual(*hdr, *header) {
|
||||
t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v",
|
||||
i, j, *hdr, *header)
|
||||
}
|
||||
@@ -253,7 +293,7 @@
|
||||
}
|
||||
|
||||
// check the header
|
||||
- if *hdr != *headers[nread] {
|
||||
+ if !reflect.DeepEqual(*hdr, *headers[nread]) {
|
||||
t.Errorf("Incorrect header:\nhave %+v\nwant %+v",
|
||||
*hdr, headers[nread])
|
||||
}
|
||||
diff -r 1a32fe60e079 -r a15f344a9efa src/pkg/archive/tar/writer.go
|
||||
--- a/src/pkg/archive/tar/writer.go Thu Feb 13 03:09:03 2014 -0500
|
||||
+++ b/src/pkg/archive/tar/writer.go Thu Feb 13 20:08:30 2014 +1100
|
||||
@@ -236,6 +236,12 @@
|
||||
return tw.err
|
||||
}
|
||||
|
||||
+ if allowPax {
|
||||
+ for k, v := range hdr.Xattrs {
|
||||
+ paxHeaders[paxXattr+k] = v
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if len(paxHeaders) > 0 {
|
||||
if !allowPax {
|
||||
return errInvalidHeader
|
||||
diff -r 1a32fe60e079 -r a15f344a9efa src/pkg/archive/tar/writer_test.go
|
||||
--- a/src/pkg/archive/tar/writer_test.go Thu Feb 13 03:09:03 2014 -0500
|
||||
+++ b/src/pkg/archive/tar/writer_test.go Thu Feb 13 20:08:30 2014 +1100
|
||||
@@ -10,6 +10,7 @@
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
+ "reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/iotest"
|
||||
@@ -338,6 +339,45 @@
|
||||
}
|
||||
}
|
||||
|
||||
+func TestPaxXattrs(t *testing.T) {
|
||||
+ xattrs := map[string]string{
|
||||
+ "user.key": "value",
|
||||
+ }
|
||||
+
|
||||
+ // Create an archive with an xattr
|
||||
+ fileinfo, err := os.Stat("testdata/small.txt")
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ hdr, err := FileInfoHeader(fileinfo, "")
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("os.Stat: %v", err)
|
||||
+ }
|
||||
+ contents := "Kilts"
|
||||
+ hdr.Xattrs = xattrs
|
||||
+ var buf bytes.Buffer
|
||||
+ writer := NewWriter(&buf)
|
||||
+ if err := writer.WriteHeader(hdr); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ if _, err = writer.Write([]byte(contents)); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ if err := writer.Close(); err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ // Test that we can get the xattrs back out of the archive.
|
||||
+ reader := NewReader(&buf)
|
||||
+ hdr, err = reader.Next()
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ if !reflect.DeepEqual(hdr.Xattrs, xattrs) {
|
||||
+ t.Fatalf("xattrs did not survive round trip: got %+v, want %+v",
|
||||
+ hdr.Xattrs, xattrs)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func TestPAXHeader(t *testing.T) {
|
||||
medName := strings.Repeat("CD", 50)
|
||||
longName := strings.Repeat("AB", 100)
|
|
@ -1,172 +0,0 @@
|
|||
Index: go/api/go1.txt
|
||||
===================================================================
|
||||
--- go.orig/api/go1.txt
|
||||
+++ go/api/go1.txt
|
||||
@@ -412,7 +412,6 @@ pkg crypto/ecdsa, type PublicKey struct,
|
||||
pkg crypto/ecdsa, type PublicKey struct, embedded elliptic.Curve
|
||||
pkg crypto/elliptic, func GenerateKey(Curve, io.Reader) ([]uint8, *big.Int, *big.Int, error)
|
||||
pkg crypto/elliptic, func Marshal(Curve, *big.Int, *big.Int) []uint8
|
||||
-pkg crypto/elliptic, func P224() Curve
|
||||
pkg crypto/elliptic, func P256() Curve
|
||||
pkg crypto/elliptic, func P384() Curve
|
||||
pkg crypto/elliptic, func P521() Curve
|
||||
Index: go/src/pkg/crypto/ecdsa/ecdsa_test.go
|
||||
===================================================================
|
||||
--- go.orig/src/pkg/crypto/ecdsa/ecdsa_test.go
|
||||
+++ go/src/pkg/crypto/ecdsa/ecdsa_test.go
|
||||
@@ -33,7 +33,6 @@ func testKeyGeneration(t *testing.T, c e
|
||||
}
|
||||
|
||||
func TestKeyGeneration(t *testing.T) {
|
||||
- testKeyGeneration(t, elliptic.P224(), "p224")
|
||||
if testing.Short() {
|
||||
return
|
||||
}
|
||||
@@ -63,7 +62,6 @@ func testSignAndVerify(t *testing.T, c e
|
||||
}
|
||||
|
||||
func TestSignAndVerify(t *testing.T) {
|
||||
- testSignAndVerify(t, elliptic.P224(), "p224")
|
||||
if testing.Short() {
|
||||
return
|
||||
}
|
||||
@@ -129,8 +127,6 @@ func TestVectors(t *testing.T) {
|
||||
parts := strings.SplitN(line, ",", 2)
|
||||
|
||||
switch parts[0] {
|
||||
- case "P-224":
|
||||
- pub.Curve = elliptic.P224()
|
||||
case "P-256":
|
||||
pub.Curve = elliptic.P256()
|
||||
case "P-384":
|
||||
Index: go/src/pkg/crypto/elliptic/bottombits.go
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ go/src/pkg/crypto/elliptic/bottombits.go
|
||||
@@ -0,0 +1,14 @@
|
||||
+
|
||||
+// Copyright 2012 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 elliptic
|
||||
+
|
||||
+const bottom12Bits = 0xfff
|
||||
+const bottom28Bits = 0xfffffff
|
||||
+
|
||||
+const two31p3 = 1<<31 + 1<<3
|
||||
+const two31m3 = 1<<31 - 1<<3
|
||||
+const two31m15m3 = 1<<31 - 1<<15 - 1<<3
|
||||
+
|
||||
Index: go/src/pkg/crypto/elliptic/elliptic.go
|
||||
===================================================================
|
||||
--- go.orig/src/pkg/crypto/elliptic/elliptic.go
|
||||
+++ go/src/pkg/crypto/elliptic/elliptic.go
|
||||
@@ -326,7 +326,6 @@ var p384 *CurveParams
|
||||
var p521 *CurveParams
|
||||
|
||||
func initAll() {
|
||||
- initP224()
|
||||
initP256()
|
||||
initP384()
|
||||
initP521()
|
||||
Index: go/src/pkg/crypto/elliptic/elliptic_test.go
|
||||
===================================================================
|
||||
--- go.orig/src/pkg/crypto/elliptic/elliptic_test.go
|
||||
+++ go/src/pkg/crypto/elliptic/elliptic_test.go
|
||||
@@ -1,3 +1,5 @@
|
||||
+// +build ignore
|
||||
+
|
||||
// Copyright 2010 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.
|
||||
Index: go/src/pkg/crypto/elliptic/p224.go
|
||||
===================================================================
|
||||
--- go.orig/src/pkg/crypto/elliptic/p224.go
|
||||
+++ go/src/pkg/crypto/elliptic/p224.go
|
||||
@@ -1,3 +1,5 @@
|
||||
+// +build ignore
|
||||
+
|
||||
// Copyright 2012 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.
|
||||
@@ -183,10 +185,6 @@ func p224Add(out, a, b *p224FieldElement
|
||||
}
|
||||
}
|
||||
|
||||
-const two31p3 = 1<<31 + 1<<3
|
||||
-const two31m3 = 1<<31 - 1<<3
|
||||
-const two31m15m3 = 1<<31 - 1<<15 - 1<<3
|
||||
-
|
||||
// p224ZeroModP31 is 0 mod p where bit 31 is set in all limbs so that we can
|
||||
// subtract smaller amounts without underflow. See the section "Subtraction" in
|
||||
// [1] for reasoning.
|
||||
@@ -215,9 +213,6 @@ const two63m35m19 = 1<<63 - 1<<35 - 1<<1
|
||||
// "Subtraction" in [1] for why.
|
||||
var p224ZeroModP63 = [8]uint64{two63p35, two63m35, two63m35, two63m35, two63m35m19, two63m35, two63m35, two63m35}
|
||||
|
||||
-const bottom12Bits = 0xfff
|
||||
-const bottom28Bits = 0xfffffff
|
||||
-
|
||||
// p224Mul computes *out = a*b
|
||||
//
|
||||
// a[i] < 2**29, b[i] < 2**30 (or vice versa)
|
||||
Index: go/src/pkg/crypto/elliptic/p224_test.go
|
||||
===================================================================
|
||||
--- go.orig/src/pkg/crypto/elliptic/p224_test.go
|
||||
+++ go/src/pkg/crypto/elliptic/p224_test.go
|
||||
@@ -1,3 +1,5 @@
|
||||
+// +build ignore
|
||||
+
|
||||
// Copyright 2012 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.
|
||||
Index: go/src/pkg/crypto/x509/x509.go
|
||||
===================================================================
|
||||
--- go.orig/src/pkg/crypto/x509/x509.go
|
||||
+++ go/src/pkg/crypto/x509/x509.go
|
||||
@@ -306,9 +306,6 @@ func getPublicKeyAlgorithmFromOID(oid as
|
||||
|
||||
// RFC 5480, 2.1.1.1. Named Curve
|
||||
//
|
||||
-// secp224r1 OBJECT IDENTIFIER ::= {
|
||||
-// iso(1) identified-organization(3) certicom(132) curve(0) 33 }
|
||||
-//
|
||||
// secp256r1 OBJECT IDENTIFIER ::= {
|
||||
// iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
|
||||
// prime(1) 7 }
|
||||
@@ -321,7 +318,6 @@ func getPublicKeyAlgorithmFromOID(oid as
|
||||
//
|
||||
// NB: secp256r1 is equivalent to prime256v1
|
||||
var (
|
||||
- oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
|
||||
oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
|
||||
oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
|
||||
oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
|
||||
@@ -329,8 +325,6 @@ var (
|
||||
|
||||
func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
|
||||
switch {
|
||||
- case oid.Equal(oidNamedCurveP224):
|
||||
- return elliptic.P224()
|
||||
case oid.Equal(oidNamedCurveP256):
|
||||
return elliptic.P256()
|
||||
case oid.Equal(oidNamedCurveP384):
|
||||
@@ -343,8 +337,6 @@ func namedCurveFromOID(oid asn1.ObjectId
|
||||
|
||||
func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
|
||||
switch curve {
|
||||
- case elliptic.P224():
|
||||
- return oidNamedCurveP224, true
|
||||
case elliptic.P256():
|
||||
return oidNamedCurveP256, true
|
||||
case elliptic.P384():
|
||||
@@ -1371,7 +1363,7 @@ func signingParamsForPrivateKey(priv int
|
||||
pubType = ECDSA
|
||||
|
||||
switch priv.Curve {
|
||||
- case elliptic.P224(), elliptic.P256():
|
||||
+ case elliptic.P256():
|
||||
hashFunc = crypto.SHA256
|
||||
sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
|
||||
case elliptic.P384():
|
|
@ -1,12 +0,0 @@
|
|||
diff -r 87dea3f5ebe7 src/pkg/runtime/pprof/pprof_test.go
|
||||
--- a/src/pkg/runtime/pprof/pprof_test.go Fri Nov 29 08:32:31 2013 +1100
|
||||
+++ b/src/pkg/runtime/pprof/pprof_test.go Fri Jan 24 13:47:42 2014 -0500
|
||||
@@ -32,7 +32,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
-func TestCPUProfileMultithreaded(t *testing.T) {
|
||||
+func testCPUProfileMultithreaded(t *testing.T) {
|
||||
buf := make([]byte, 100000)
|
||||
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
|
||||
testCPUProfile(t, []string{"crc32.ChecksumIEEE", "crc32.Update"}, func() {
|
|
@ -1,19 +0,0 @@
|
|||
Index: go/src/make.bash
|
||||
===================================================================
|
||||
--- go.orig/src/make.bash
|
||||
+++ go/src/make.bash
|
||||
@@ -161,12 +161,12 @@ if [ "$GOHOSTARCH" != "$GOARCH" -o "$GOH
|
||||
# CC_FOR_TARGET is recorded as the default compiler for the go tool. When building for the host, however,
|
||||
# use the host compiler, CC, from `cmd/dist/dist env` instead.
|
||||
CC=$CC GOOS=$GOHOSTOS GOARCH=$GOHOSTARCH \
|
||||
- "$GOTOOLDIR"/go_bootstrap install -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
|
||||
+ "$GOTOOLDIR"/go_bootstrap install -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v -x std
|
||||
echo
|
||||
fi
|
||||
|
||||
echo "# Building packages and commands for $GOOS/$GOARCH."
|
||||
-CC=$CC_FOR_TARGET "$GOTOOLDIR"/go_bootstrap install $GO_FLAGS -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v std
|
||||
+CC=$CC_FOR_TARGET "$GOTOOLDIR"/go_bootstrap install $GO_FLAGS -ccflags "$GO_CCFLAGS" -gcflags "$GO_GCFLAGS" -ldflags "$GO_LDFLAGS" -v -x std
|
||||
echo
|
||||
|
||||
rm -f "$GOTOOLDIR"/go_bootstrap
|
|
@ -0,0 +1,309 @@
|
|||
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)
|
||||
+ }
|
||||
+}
|
|
@ -1,11 +0,0 @@
|
|||
--- src/pkg/os/os_test.go.orig 2014-02-20 13:14:45.543644182 -0600
|
||||
+++ src/pkg/os/os_test.go 2014-02-20 13:14:55.934813622 -0600
|
||||
@@ -854,7 +854,7 @@
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer r.Close()
|
||||
- p, err := StartProcess("/bin/hostname", []string{"hostname"}, &ProcAttr{Files: []*File{nil, w, Stderr}})
|
||||
+ p, err := StartProcess("/usr/bin/hostname", []string{"hostname"}, &ProcAttr{Files: []*File{nil, w, Stderr}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
|
@ -1 +1 @@
|
|||
add-auto-load-safe-path /usr/lib/golang/src/pkg/runtime/runtime-gdb.py
|
||||
add-auto-load-safe-path /usr/lib/golang/src/runtime/runtime-gdb.py
|
||||
|
|
1300
golang.spec
1300
golang.spec
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,457 @@
|
|||
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")
|
|
@ -0,0 +1,150 @@
|
|||
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 {
|
3
sources
3
sources
|
@ -1,2 +1 @@
|
|||
d76dc07e475b2905b5fec1cf319b6356 golang-19087:a15f344a9efa-xattrs.tar
|
||||
2cdbad6baefcf1007f3cf54a5bc878b7 go1.3.3.src.tar.gz
|
||||
SHA512 (go1.11.2.src.tar.gz) = 3d9b182718c7615975a4b47cecb9ff2a8ce62156461e4112452c14617ea226121e7ab736a469050f14c89861cc4934ddd2df295b80fffff0a2dd6c155eaf0aee
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
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)
|
Loading…
Reference in New Issue