mirror of
https://github.com/golang/go.git
synced 2025-05-17 13:24:38 +00:00
[dev.link] all: merge branch 'master' into dev.link
Clean merge. Change-Id: I2ae0e4cc67e24216c85619717657dce36e887a54
This commit is contained in:
commit
92051a989b
@ -466,7 +466,15 @@ Do not send CLs removing the interior tags from such phrases.
|
||||
certificate, and letting the package automatically select the best one.
|
||||
Note that the performance of this selection is going to be poor unless the
|
||||
<a href="/pkg/crypto/tls/#Certificate.Leaf"><code>Certificate.Leaf</code></a>
|
||||
field is set.
|
||||
field is set. The
|
||||
<a href="/pkg/crypto/tls/#Config.NameToCertificate"><code>Config.NameToCertificate</code></a>
|
||||
field, which only supports associating a single certificate with
|
||||
a give name, is now deprecated and should be left as <code>nil</code>.
|
||||
Similarly the
|
||||
<a href="/pkg/crypto/tls/#Config.BuildNameToCertificate"><code>Config.BuildNameToCertificate</code></a>
|
||||
method, which builds the <code>NameToCertificate</code> field
|
||||
from the leaf certificates, is now deprecated and should not be
|
||||
called.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 175517 -->
|
||||
|
@ -440,7 +440,7 @@ Do not send CLs removing the interior tags from such phrases.
|
||||
</dd>
|
||||
</dl><!-- crypto/rsa -->
|
||||
|
||||
<dl id="crypto/tls"><dt><a href="/crypto/tls/">crypto/tls</a></dt>
|
||||
<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 214977 -->
|
||||
The new
|
||||
@ -782,6 +782,20 @@ Do not send CLs removing the interior tags from such phrases.
|
||||
1.14 with the addition of asynchronous preemption. Now this is
|
||||
handled transparently.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 229101 -->
|
||||
The <a href="/pkg/os/#File"><code>os.File</code></a> type now
|
||||
supports a <a href="/pkg/os/#File.ReadFrom"><code>ReadFrom</code></a>
|
||||
method. This permits the use of the <code>copy_file_range</code>
|
||||
system call on some systems when using
|
||||
<a href="/pkg/io/#Copy"><code>io.Copy</code></a> to copy data
|
||||
from one <code>os.File</code> to another. A consequence is that
|
||||
<a href="/pkg/io/#CopyBuffer"><code>io.CopyBuffer</code></a>
|
||||
will not always use the provided buffer when copying to a
|
||||
<code>os.File</code>. If a program wants to force the use of
|
||||
the provided buffer, it can be done by writing
|
||||
<code>io.CopyBuffer(struct{ io.Writer }{dst}, src, buf)</code>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
@ -515,7 +515,7 @@ when used well, can result in clean error-handling code.
|
||||
See the <a href="/doc/articles/defer_panic_recover.html">Defer, Panic, and Recover</a> article for details.
|
||||
Also, the <a href="https://blog.golang.org/errors-are-values">Errors are values</a> blog post
|
||||
describes one approach to handling errors cleanly in Go by demonstrating that,
|
||||
since errors are just values, the full power of Go can deployed in error handling.
|
||||
since errors are just values, the full power of Go can be deployed in error handling.
|
||||
</p>
|
||||
|
||||
<h3 id="assertions">
|
||||
|
@ -1028,3 +1028,9 @@ func TestGeneratedHash(t *testing.T) {
|
||||
goCmd(nil, "install", "-buildmode=shared", "-linkshared", "./issue30768/issue30768lib")
|
||||
goCmd(nil, "test", "-linkshared", "./issue30768")
|
||||
}
|
||||
|
||||
// Test that packages can be added not in dependency order (here a depends on b, and a adds
|
||||
// before b). This could happen with e.g. go build -buildmode=shared std. See issue 39777.
|
||||
func TestPackageOrder(t *testing.T) {
|
||||
goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue39777/a", "./issue39777/b")
|
||||
}
|
||||
|
9
misc/cgo/testshared/testdata/issue39777/a/a.go
vendored
Normal file
9
misc/cgo/testshared/testdata/issue39777/a/a.go
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright 2020 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 a
|
||||
|
||||
import "testshared/issue39777/b"
|
||||
|
||||
func F() { b.F() }
|
7
misc/cgo/testshared/testdata/issue39777/b/b.go
vendored
Normal file
7
misc/cgo/testshared/testdata/issue39777/b/b.go
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// Copyright 2020 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 b
|
||||
|
||||
func F() {}
|
@ -73,9 +73,11 @@ func dse(f *Func) {
|
||||
}
|
||||
|
||||
// Walk backwards looking for dead stores. Keep track of shadowed addresses.
|
||||
// An "address" is an SSA Value which encodes both the address and size of
|
||||
// the write. This code will not remove dead stores to the same address
|
||||
// of different types.
|
||||
// A "shadowed address" is a pointer and a size describing a memory region that
|
||||
// is known to be written. We keep track of shadowed addresses in the shadowed
|
||||
// map, mapping the ID of the address to the size of the shadowed region.
|
||||
// Since we're walking backwards, writes to a shadowed region are useless,
|
||||
// as they will be immediately overwritten.
|
||||
shadowed.clear()
|
||||
v := last
|
||||
|
||||
@ -93,17 +95,13 @@ func dse(f *Func) {
|
||||
sz = v.AuxInt
|
||||
}
|
||||
if shadowedSize := int64(shadowed.get(v.Args[0].ID)); shadowedSize != -1 && shadowedSize >= sz {
|
||||
// Modify store into a copy
|
||||
// Modify the store/zero into a copy of the memory state,
|
||||
// effectively eliding the store operation.
|
||||
if v.Op == OpStore {
|
||||
// store addr value mem
|
||||
v.SetArgs1(v.Args[2])
|
||||
} else {
|
||||
// zero addr mem
|
||||
typesz := v.Args[0].Type.Elem().Size()
|
||||
if sz != typesz {
|
||||
f.Fatalf("mismatched zero/store sizes: %d and %d [%s]",
|
||||
sz, typesz, v.LongString())
|
||||
}
|
||||
v.SetArgs1(v.Args[1])
|
||||
}
|
||||
v.Aux = nil
|
||||
|
12
src/cmd/dist/test.go
vendored
12
src/cmd/dist/test.go
vendored
@ -461,6 +461,18 @@ func (t *tester) registerTests() {
|
||||
})
|
||||
}
|
||||
|
||||
// Test the ios build tag on darwin/amd64 for the iOS simulator.
|
||||
if goos == "darwin" && !t.iOS() {
|
||||
t.tests = append(t.tests, distTest{
|
||||
name: "amd64ios",
|
||||
heading: "ios tag on darwin/amd64",
|
||||
fn: func(dt *distTest) error {
|
||||
t.addCmd(dt, "src", t.goTest(), t.timeout(300), "-tags=ios", "-run=SystemRoots", "crypto/x509")
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if t.race {
|
||||
return
|
||||
}
|
||||
|
@ -160,7 +160,12 @@ func addlib(ctxt *Link, src, obj, lib string, fingerprint goobj2.FingerprintType
|
||||
pkg := pkgname(ctxt, lib)
|
||||
|
||||
// already loaded?
|
||||
if l := ctxt.LibraryByPkg[pkg]; l != nil {
|
||||
if l := ctxt.LibraryByPkg[pkg]; l != nil && !l.Fingerprint.IsZero() {
|
||||
// Normally, packages are loaded in dependency order, and if l != nil
|
||||
// l is already loaded with the actual fingerprint. In shared build mode,
|
||||
// however, packages may be added not in dependency order, and it is
|
||||
// possible that l's fingerprint is not yet loaded -- exclude it in
|
||||
// checking.
|
||||
checkFingerprint(l, l.Fingerprint, src, fingerprint)
|
||||
return l
|
||||
}
|
||||
|
@ -20,7 +20,10 @@ import (
|
||||
)
|
||||
|
||||
// A Curve represents a short-form Weierstrass curve with a=-3.
|
||||
// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
|
||||
//
|
||||
// Note that the point at infinity (0, 0) is not considered on the curve, and
|
||||
// although it can be returned by Add, Double, ScalarMult, or ScalarBaseMult, it
|
||||
// can't be marshaled or unmarshaled, and IsOnCurve will return false for it.
|
||||
type Curve interface {
|
||||
// Params returns the parameters for the curve.
|
||||
Params() *CurveParams
|
||||
@ -307,7 +310,8 @@ func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err e
|
||||
return
|
||||
}
|
||||
|
||||
// Marshal converts a point into the uncompressed form specified in section 4.3.6 of ANSI X9.62.
|
||||
// Marshal converts a point on the curve into the uncompressed form specified in
|
||||
// section 4.3.6 of ANSI X9.62.
|
||||
func Marshal(curve Curve, x, y *big.Int) []byte {
|
||||
byteLen := (curve.Params().BitSize + 7) / 8
|
||||
|
||||
@ -320,7 +324,8 @@ func Marshal(curve Curve, x, y *big.Int) []byte {
|
||||
return ret
|
||||
}
|
||||
|
||||
// MarshalCompressed converts a point into the compressed form specified in section 4.3.6 of ANSI X9.62.
|
||||
// MarshalCompressed converts a point on the curve into the compressed form
|
||||
// specified in section 4.3.6 of ANSI X9.62.
|
||||
func MarshalCompressed(curve Curve, x, y *big.Int) []byte {
|
||||
byteLen := (curve.Params().BitSize + 7) / 8
|
||||
compressed := make([]byte, 1+byteLen)
|
||||
|
@ -418,41 +418,62 @@ func TestP256Mult(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testInfinity(t *testing.T, curve Curve) {
|
||||
_, x, y, _ := GenerateKey(curve, rand.Reader)
|
||||
x, y = curve.ScalarMult(x, y, curve.Params().N.Bytes())
|
||||
if x.Sign() != 0 || y.Sign() != 0 {
|
||||
t.Errorf("x^q != ∞")
|
||||
}
|
||||
|
||||
x, y = curve.ScalarBaseMult([]byte{0})
|
||||
if x.Sign() != 0 || y.Sign() != 0 {
|
||||
t.Errorf("b^0 != ∞")
|
||||
x.SetInt64(0)
|
||||
y.SetInt64(0)
|
||||
}
|
||||
|
||||
x2, y2 := curve.Double(x, y)
|
||||
if x2.Sign() != 0 || y2.Sign() != 0 {
|
||||
t.Errorf("2∞ != ∞")
|
||||
}
|
||||
|
||||
baseX := curve.Params().Gx
|
||||
baseY := curve.Params().Gy
|
||||
|
||||
x3, y3 := curve.Add(baseX, baseY, x, y)
|
||||
if x3.Cmp(baseX) != 0 || y3.Cmp(baseY) != 0 {
|
||||
t.Errorf("x+∞ != x")
|
||||
}
|
||||
|
||||
x4, y4 := curve.Add(x, y, baseX, baseY)
|
||||
if x4.Cmp(baseX) != 0 || y4.Cmp(baseY) != 0 {
|
||||
t.Errorf("∞+x != x")
|
||||
}
|
||||
|
||||
if curve.IsOnCurve(x, y) {
|
||||
t.Errorf("IsOnCurve(∞) == true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInfinity(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
curve Curve
|
||||
}{
|
||||
{"p224", P224()},
|
||||
{"p256", P256()},
|
||||
{"P-224", P224()},
|
||||
{"P-256", P256()},
|
||||
{"P-256/Generic", P256().Params()},
|
||||
{"P-384", P384()},
|
||||
{"P-521", P521()},
|
||||
}
|
||||
if testing.Short() {
|
||||
tests = tests[:1]
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
curve := test.curve
|
||||
x, y := curve.ScalarBaseMult(nil)
|
||||
if x.Sign() != 0 || y.Sign() != 0 {
|
||||
t.Errorf("%s: x^0 != ∞", test.name)
|
||||
}
|
||||
x.SetInt64(0)
|
||||
y.SetInt64(0)
|
||||
|
||||
x2, y2 := curve.Double(x, y)
|
||||
if x2.Sign() != 0 || y2.Sign() != 0 {
|
||||
t.Errorf("%s: 2∞ != ∞", test.name)
|
||||
}
|
||||
|
||||
baseX := curve.Params().Gx
|
||||
baseY := curve.Params().Gy
|
||||
|
||||
x3, y3 := curve.Add(baseX, baseY, x, y)
|
||||
if x3.Cmp(baseX) != 0 || y3.Cmp(baseY) != 0 {
|
||||
t.Errorf("%s: x+∞ != x", test.name)
|
||||
}
|
||||
|
||||
x4, y4 := curve.Add(x, y, baseX, baseY)
|
||||
if x4.Cmp(baseX) != 0 || y4.Cmp(baseY) != 0 {
|
||||
t.Errorf("%s: ∞+x != x", test.name)
|
||||
}
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
testInfinity(t, curve)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,28 +213,72 @@ var testingOnlyForceDowngradeCanary bool
|
||||
|
||||
// ConnectionState records basic TLS details about the connection.
|
||||
type ConnectionState struct {
|
||||
Version uint16 // TLS version used by the connection (e.g. VersionTLS12)
|
||||
HandshakeComplete bool // TLS handshake is complete
|
||||
DidResume bool // connection resumes a previous TLS connection
|
||||
CipherSuite uint16 // cipher suite in use (TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, ...)
|
||||
NegotiatedProtocol string // negotiated next protocol (not guaranteed to be from Config.NextProtos)
|
||||
NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server (client side only)
|
||||
ServerName string // server name requested by client, if any
|
||||
PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
|
||||
VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
|
||||
SignedCertificateTimestamps [][]byte // SCTs from the peer, if any
|
||||
OCSPResponse []byte // stapled OCSP response from peer, if any
|
||||
// Version is the TLS version used by the connection (e.g. VersionTLS12).
|
||||
Version uint16
|
||||
|
||||
// HandshakeComplete is true if the handshake has concluded.
|
||||
HandshakeComplete bool
|
||||
|
||||
// DidResume is true if this connection was successfully resumed from a
|
||||
// previous session with a session ticket or similar mechanism.
|
||||
DidResume bool
|
||||
|
||||
// CipherSuite is the cipher suite negotiated for the connection (e.g.
|
||||
// TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_AES_128_GCM_SHA256).
|
||||
CipherSuite uint16
|
||||
|
||||
// NegotiatedProtocol is the application protocol negotiated with ALPN.
|
||||
//
|
||||
// Note that on the client side, this is currently not guaranteed to be from
|
||||
// Config.NextProtos.
|
||||
NegotiatedProtocol string
|
||||
|
||||
// NegotiatedProtocolIsMutual used to indicate a mutual NPN negotiation.
|
||||
//
|
||||
// Deprecated: this value is always true.
|
||||
NegotiatedProtocolIsMutual bool
|
||||
|
||||
// ServerName is the value of the Server Name Indication extension sent by
|
||||
// the client. It's available both on the server and on the client side.
|
||||
ServerName string
|
||||
|
||||
// PeerCertificates are the parsed certificates sent by the peer, in the
|
||||
// order in which they were sent. The first element is the leaf certificate
|
||||
// that the connection is verified against.
|
||||
//
|
||||
// On the client side, it can't be empty. On the server side, it can be
|
||||
// empty if Config.ClientAuth is not RequireAnyClientCert or
|
||||
// RequireAndVerifyClientCert.
|
||||
PeerCertificates []*x509.Certificate
|
||||
|
||||
// VerifiedChains is a list of one or more chains where the first element is
|
||||
// PeerCertificates[0] and the last element is from Config.RootCAs (on the
|
||||
// client side) or Config.ClientCAs (on the server side).
|
||||
//
|
||||
// On the client side, it's set if Config.InsecureSkipVerify is false. On
|
||||
// the server side, it's set if Config.ClientAuth is VerifyClientCertIfGiven
|
||||
// (and the peer provided a certificate) or RequireAndVerifyClientCert.
|
||||
VerifiedChains [][]*x509.Certificate
|
||||
|
||||
// SignedCertificateTimestamps is a list of SCTs provided by the peer
|
||||
// through the TLS handshake for the leaf certificate, if any.
|
||||
SignedCertificateTimestamps [][]byte
|
||||
|
||||
// OCSPResponse is a stapled Online Certificate Status Protocol (OCSP)
|
||||
// response provided by the peer for the leaf certificate, if any.
|
||||
OCSPResponse []byte
|
||||
|
||||
// TLSUnique contains the "tls-unique" channel binding value (see RFC 5929,
|
||||
// Section 3). This value will be nil for TLS 1.3 connections and for all
|
||||
// resumed connections.
|
||||
//
|
||||
// Deprecated: there are conditions in which this value might not be unique
|
||||
// to a connection. See the Security Considerations sections of RFC 5705 and
|
||||
// RFC 7627, and https://mitls.org/pages/attacks/3SHAKE#channelbindings.
|
||||
TLSUnique []byte
|
||||
|
||||
// ekm is a closure exposed via ExportKeyingMaterial.
|
||||
ekm func(label string, context []byte, length int) ([]byte, error)
|
||||
|
||||
// TLSUnique contains the "tls-unique" channel binding value (see RFC
|
||||
// 5929, section 3). For resumed sessions this value will be nil
|
||||
// because resumption does not include enough context (see
|
||||
// https://mitls.org/pages/attacks/3SHAKE#channelbindings). This will
|
||||
// change in future versions of Go once the TLS master-secret fix has
|
||||
// been standardized and implemented. It is not defined in TLS 1.3.
|
||||
TLSUnique []byte
|
||||
}
|
||||
|
||||
// ExportKeyingMaterial returns length bytes of exported key material in a new
|
||||
|
@ -7,7 +7,6 @@ package tls_test
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@ -184,54 +183,50 @@ EKTcWGekdmdDPsHloRNtsiCa697B2O9IFA==
|
||||
log.Fatal(srv.ListenAndServeTLS("", ""))
|
||||
}
|
||||
|
||||
func ExampleConfig_verifyPeerCertificate() {
|
||||
// VerifyPeerCertificate can be used to replace and customize certificate
|
||||
// verification. This example shows a VerifyPeerCertificate implementation
|
||||
// that will be approximately equivalent to what crypto/tls does normally.
|
||||
func ExampleConfig_verifyConnection() {
|
||||
// VerifyConnection can be used to replace and customize connection
|
||||
// verification. This example shows a VerifyConnection implementation that
|
||||
// will be approximately equivalent to what crypto/tls does normally to
|
||||
// verify the peer's certificate.
|
||||
|
||||
config := &tls.Config{
|
||||
// Client side configuration.
|
||||
_ = &tls.Config{
|
||||
// Set InsecureSkipVerify to skip the default validation we are
|
||||
// replacing. This will not disable VerifyPeerCertificate.
|
||||
// replacing. This will not disable VerifyConnection.
|
||||
InsecureSkipVerify: true,
|
||||
|
||||
// While packages like net/http will implicitly set ServerName, the
|
||||
// VerifyPeerCertificate callback can't access that value, so it has to be set
|
||||
// explicitly here or in VerifyPeerCertificate on the client side. If in
|
||||
// an http.Transport DialTLS callback, this can be obtained by passing
|
||||
// the addr argument to net.SplitHostPort.
|
||||
ServerName: "example.com",
|
||||
|
||||
// On the server side, set ClientAuth to require client certificates (or
|
||||
// VerifyPeerCertificate will run anyway and panic accessing certs[0])
|
||||
// but not verify them with the default verifier.
|
||||
// ClientAuth: tls.RequireAnyClientCert,
|
||||
}
|
||||
|
||||
config.VerifyPeerCertificate = func(certificates [][]byte, _ [][]*x509.Certificate) error {
|
||||
certs := make([]*x509.Certificate, len(certificates))
|
||||
for i, asn1Data := range certificates {
|
||||
cert, err := x509.ParseCertificate(asn1Data)
|
||||
if err != nil {
|
||||
return errors.New("tls: failed to parse certificate from server: " + err.Error())
|
||||
VerifyConnection: func(cs tls.ConnectionState) error {
|
||||
opts := x509.VerifyOptions{
|
||||
DNSName: cs.ServerName,
|
||||
Intermediates: x509.NewCertPool(),
|
||||
}
|
||||
certs[i] = cert
|
||||
}
|
||||
|
||||
opts := x509.VerifyOptions{
|
||||
Roots: config.RootCAs, // On the server side, use config.ClientCAs.
|
||||
DNSName: config.ServerName,
|
||||
Intermediates: x509.NewCertPool(),
|
||||
// On the server side, set KeyUsages to ExtKeyUsageClientAuth. The
|
||||
// default value is appropriate for clients side verification.
|
||||
// KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
for _, cert := range certs[1:] {
|
||||
opts.Intermediates.AddCert(cert)
|
||||
}
|
||||
_, err := certs[0].Verify(opts)
|
||||
return err
|
||||
for _, cert := range cs.PeerCertificates[1:] {
|
||||
opts.Intermediates.AddCert(cert)
|
||||
}
|
||||
_, err := cs.PeerCertificates[0].Verify(opts)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
// Note that when InsecureSkipVerify and VerifyPeerCertificate are in use,
|
||||
// Server side configuration.
|
||||
_ = &tls.Config{
|
||||
// Require client certificates (or VerifyConnection will run anyway and
|
||||
// panic accessing cs.PeerCertificates[0]) but don't verify them with the
|
||||
// default verifier. This will not disable VerifyConnection.
|
||||
ClientAuth: tls.RequireAnyClientCert,
|
||||
VerifyConnection: func(cs tls.ConnectionState) error {
|
||||
opts := x509.VerifyOptions{
|
||||
DNSName: cs.ServerName,
|
||||
Intermediates: x509.NewCertPool(),
|
||||
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
}
|
||||
for _, cert := range cs.PeerCertificates[1:] {
|
||||
opts.Intermediates.AddCert(cert)
|
||||
}
|
||||
_, err := cs.PeerCertificates[0].Verify(opts)
|
||||
return err
|
||||
},
|
||||
}
|
||||
|
||||
// Note that when certificates are not handled by the default verifier
|
||||
// ConnectionState.VerifiedChains will be nil.
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ func (d *Dialer) netDialer() *net.Dialer {
|
||||
return new(net.Dialer)
|
||||
}
|
||||
|
||||
// Dial connects to the given network address and initiates a TLS
|
||||
// DialContext connects to the given network address and initiates a TLS
|
||||
// handshake, returning the resulting TLS connection.
|
||||
//
|
||||
// The provided Context must be non-nil. If the context expires before
|
||||
|
@ -47,11 +47,15 @@ func (s *CertPool) copy() *CertPool {
|
||||
|
||||
// SystemCertPool returns a copy of the system cert pool.
|
||||
//
|
||||
// Any mutations to the returned pool are not written to disk and do
|
||||
// not affect any other pool returned by SystemCertPool.
|
||||
// On Unix systems other than macOS the environment variables SSL_CERT_FILE and
|
||||
// SSL_CERT_DIR can be used to override the system default locations for the SSL
|
||||
// certificate file and SSL certificate files directory, respectively. The
|
||||
// latter can be a colon-separated list.
|
||||
//
|
||||
// New changes in the system cert pool might not be reflected
|
||||
// in subsequent calls.
|
||||
// Any mutations to the returned pool are not written to disk and do not affect
|
||||
// any other pool returned by SystemCertPool.
|
||||
//
|
||||
// New changes in the system cert pool might not be reflected in subsequent calls.
|
||||
func SystemCertPool() (*CertPool, error) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// Issue 16736, 18609:
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package x509
|
||||
|
||||
//go:generate go run root_darwin_ios_gen.go -version 55161.80.1
|
||||
|
||||
import "sync"
|
||||
|
||||
var (
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !ios
|
||||
|
||||
package x509
|
||||
|
||||
// This cgo implementation exists only to support side-by-side testing by
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !ios
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
|
@ -1,188 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generates root_darwin_arm64.go.
|
||||
//
|
||||
// As of iOS 8, there is no API for querying the system trusted X.509 root
|
||||
// certificates. We could use SecTrustEvaluate to verify that a trust chain
|
||||
// exists for a certificate, but the x509 API requires returning the entire
|
||||
// chain.
|
||||
//
|
||||
// Apple publishes the list of trusted root certificates for iOS on
|
||||
// support.apple.com. So we parse the list and extract the certificates from
|
||||
// an OS X machine and embed them into the x509 package.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var output = flag.String("output", "root_darwin_arm64.go", "file name to write")
|
||||
|
||||
func main() {
|
||||
certs, err := selectCerts()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
fmt.Fprintf(buf, "%s", header)
|
||||
|
||||
fmt.Fprintf(buf, "const systemRootsPEM = `\n")
|
||||
for _, cert := range certs {
|
||||
b := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
if err := pem.Encode(buf, b); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(buf, "`")
|
||||
|
||||
source, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Fatal("source format error:", err)
|
||||
}
|
||||
if err := ioutil.WriteFile(*output, source, 0644); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func selectCerts() ([]*x509.Certificate, error) {
|
||||
ids, err := fetchCertIDs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scerts, err := sysCerts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var certs []*x509.Certificate
|
||||
for _, id := range ids {
|
||||
if c, ok := scerts[id.fingerprint]; ok {
|
||||
certs = append(certs, c)
|
||||
} else {
|
||||
fmt.Printf("WARNING: cannot find certificate: %s (fingerprint: %s)\n", id.name, id.fingerprint)
|
||||
}
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
func sysCerts() (certs map[string]*x509.Certificate, err error) {
|
||||
cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain")
|
||||
data, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certs = make(map[string]*x509.Certificate)
|
||||
for len(data) > 0 {
|
||||
var block *pem.Block
|
||||
block, data = pem.Decode(data)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
fingerprint := sha256.Sum256(cert.Raw)
|
||||
certs[hex.EncodeToString(fingerprint[:])] = cert
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
type certID struct {
|
||||
name string
|
||||
fingerprint string
|
||||
}
|
||||
|
||||
// fetchCertIDs fetches IDs of iOS X509 certificates from apple.com.
|
||||
func fetchCertIDs() ([]certID, error) {
|
||||
// Download the iOS 11 support page. The index for all iOS versions is here:
|
||||
// https://support.apple.com/en-us/HT204132
|
||||
resp, err := http.Get("https://support.apple.com/en-us/HT208125")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
text := string(body)
|
||||
text = text[strings.Index(text, "<div id=trusted"):]
|
||||
text = text[:strings.Index(text, "</div>")]
|
||||
|
||||
var ids []certID
|
||||
cols := make(map[string]int)
|
||||
for i, rowmatch := range regexp.MustCompile("(?s)<tr>(.*?)</tr>").FindAllStringSubmatch(text, -1) {
|
||||
row := rowmatch[1]
|
||||
if i == 0 {
|
||||
// Parse table header row to extract column names
|
||||
for i, match := range regexp.MustCompile("(?s)<th>(.*?)</th>").FindAllStringSubmatch(row, -1) {
|
||||
cols[match[1]] = i
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
values := regexp.MustCompile("(?s)<td>(.*?)</td>").FindAllStringSubmatch(row, -1)
|
||||
name := values[cols["Certificate name"]][1]
|
||||
fingerprint := values[cols["Fingerprint (SHA-256)"]][1]
|
||||
fingerprint = strings.ReplaceAll(fingerprint, "<br>", "")
|
||||
fingerprint = strings.ReplaceAll(fingerprint, "\n", "")
|
||||
fingerprint = strings.ReplaceAll(fingerprint, " ", "")
|
||||
fingerprint = strings.ToLower(fingerprint)
|
||||
|
||||
ids = append(ids, certID{
|
||||
name: name,
|
||||
fingerprint: fingerprint,
|
||||
})
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
const header = `// Code generated by root_darwin_arm64_gen.go; DO NOT EDIT.
|
||||
|
||||
//go:generate go run root_darwin_arm64_gen.go -output root_darwin_arm64.go
|
||||
|
||||
// +build !x509omitbundledroots
|
||||
|
||||
package x509
|
||||
|
||||
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// loadSystemRootsWithCgo is not available on iOS.
|
||||
var loadSystemRootsWithCgo func() (*CertPool, error)
|
||||
|
||||
func loadSystemRoots() (*CertPool, error) {
|
||||
p := NewCertPool()
|
||||
p.AppendCertsFromPEM([]byte(systemRootsPEM))
|
||||
return p, nil
|
||||
}
|
||||
`
|
File diff suppressed because it is too large
Load Diff
179
src/crypto/x509/root_darwin_ios_gen.go
Normal file
179
src/crypto/x509/root_darwin_ios_gen.go
Normal file
@ -0,0 +1,179 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generates root_darwin_ios.go.
|
||||
//
|
||||
// As of iOS 13, there is no API for querying the system trusted X.509 root
|
||||
// certificates.
|
||||
//
|
||||
// Apple publishes the trusted root certificates for iOS and macOS on
|
||||
// opensource.apple.com so we embed them into the x509 package.
|
||||
//
|
||||
// Note that this ignores distrusted and revoked certificates.
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var output = flag.String("output", "root_darwin_ios.go", "file name to write")
|
||||
var version = flag.String("version", "", "security_certificates version")
|
||||
flag.Parse()
|
||||
if *version == "" {
|
||||
log.Fatal("Select the latest security_certificates version from " +
|
||||
"https://opensource.apple.com/source/security_certificates/")
|
||||
}
|
||||
|
||||
url := "https://opensource.apple.com/tarballs/security_certificates/security_certificates-%s.tar.gz"
|
||||
hc := &http.Client{Timeout: 1 * time.Minute}
|
||||
resp, err := hc.Get(fmt.Sprintf(url, *version))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Fatalf("HTTP status not OK: %s", resp.Status)
|
||||
}
|
||||
|
||||
zr, err := gzip.NewReader(resp.Body)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer zr.Close()
|
||||
|
||||
var certs []*x509.Certificate
|
||||
pool := x509.NewCertPool()
|
||||
|
||||
tr := tar.NewReader(zr)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
rootsDirectory := fmt.Sprintf("security_certificates-%s/certificates/roots/", *version)
|
||||
if dir, file := path.Split(hdr.Name); hdr.Typeflag != tar.TypeReg ||
|
||||
dir != rootsDirectory || strings.HasPrefix(file, ".") {
|
||||
continue
|
||||
}
|
||||
|
||||
der, err := ioutil.ReadAll(tr)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
c, err := x509.ParseCertificate(der)
|
||||
if err != nil {
|
||||
log.Printf("Failed to parse certificate %q: %v", hdr.Name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
certs = append(certs, c)
|
||||
pool.AddCert(c)
|
||||
}
|
||||
|
||||
// Quick smoke test to check the pool is well formed, and that we didn't end
|
||||
// up trusting roots in the removed folder.
|
||||
for _, c := range certs {
|
||||
if c.Subject.CommonName == "Symantec Class 2 Public Primary Certification Authority - G4" {
|
||||
log.Fatal("The pool includes a removed root!")
|
||||
}
|
||||
}
|
||||
conn, err := tls.Dial("tcp", "mail.google.com:443", &tls.Config{
|
||||
RootCAs: pool,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
conn.Close()
|
||||
|
||||
certName := func(c *x509.Certificate) string {
|
||||
if c.Subject.CommonName != "" {
|
||||
return c.Subject.CommonName
|
||||
}
|
||||
if len(c.Subject.OrganizationalUnit) > 0 {
|
||||
return c.Subject.OrganizationalUnit[0]
|
||||
}
|
||||
return c.Subject.Organization[0]
|
||||
}
|
||||
sort.Slice(certs, func(i, j int) bool {
|
||||
if strings.ToLower(certName(certs[i])) != strings.ToLower(certName(certs[j])) {
|
||||
return strings.ToLower(certName(certs[i])) < strings.ToLower(certName(certs[j]))
|
||||
}
|
||||
return certs[i].NotBefore.Before(certs[j].NotBefore)
|
||||
})
|
||||
|
||||
out := new(bytes.Buffer)
|
||||
fmt.Fprintf(out, header, *version)
|
||||
fmt.Fprintf(out, "const systemRootsPEM = `\n")
|
||||
|
||||
for _, c := range certs {
|
||||
fmt.Fprintf(out, "# %q\n", certName(c))
|
||||
h := sha256.Sum256(c.Raw)
|
||||
fmt.Fprintf(out, "# % X\n", h[:len(h)/2])
|
||||
fmt.Fprintf(out, "# % X\n", h[len(h)/2:])
|
||||
b := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: c.Raw,
|
||||
}
|
||||
if err := pem.Encode(out, b); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(out, "`")
|
||||
|
||||
source, err := format.Source(out.Bytes())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := ioutil.WriteFile(*output, source, 0644); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
const header = `// Code generated by root_darwin_ios_gen.go -version %s; DO NOT EDIT.
|
||||
// Update the version in root.go and regenerate with "go generate".
|
||||
|
||||
// +build darwin,arm64 darwin,amd64,ios
|
||||
// +build !x509omitbundledroots
|
||||
|
||||
package x509
|
||||
|
||||
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// loadSystemRootsWithCgo is not available on iOS.
|
||||
var loadSystemRootsWithCgo func() (*CertPool, error)
|
||||
|
||||
func loadSystemRoots() (*CertPool, error) {
|
||||
p := NewCertPool()
|
||||
p.AppendCertsFromPEM([]byte(systemRootsPEM))
|
||||
return p, nil
|
||||
}
|
||||
`
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin,arm64,x509omitbundledroots
|
||||
// +build darwin,arm64 darwin,amd64,ios
|
||||
// +build x509omitbundledroots
|
||||
|
||||
// This file provides the loadSystemRoots func when the
|
||||
// "x509omitbundledroots" build tag has disabled bundling a copy,
|
||||
|
@ -2,7 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin,arm64,x509omitbundledroots
|
||||
// +build darwin,arm64 darwin,amd64,ios
|
||||
// +build x509omitbundledroots
|
||||
|
||||
package x509
|
||||
|
||||
|
@ -3,10 +3,6 @@
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package x509 parses X.509-encoded keys and certificates.
|
||||
//
|
||||
// On UNIX systems the environment variables SSL_CERT_FILE and SSL_CERT_DIR
|
||||
// can be used to override the system default locations for the SSL certificate
|
||||
// file and SSL certificate files directory, respectively.
|
||||
package x509
|
||||
|
||||
import (
|
||||
|
@ -30,11 +30,13 @@ import (
|
||||
// value is a filename on the native file system, not a URL, so it is separated
|
||||
// by filepath.Separator, which isn't necessarily '/'.
|
||||
//
|
||||
// Note that Dir will allow access to files and directories starting with a
|
||||
// period, which could expose sensitive directories like a .git directory or
|
||||
// sensitive files like .htpasswd. To exclude files with a leading period,
|
||||
// remove the files/directories from the server or create a custom FileSystem
|
||||
// implementation.
|
||||
// Note that Dir could expose sensitive files and directories. Dir will follow
|
||||
// symlinks pointing out of the directory tree, which can be especially dangerous
|
||||
// if serving from a directory in which users are able to create arbitrary symlinks.
|
||||
// Dir will also allow access to files and directories starting with a period,
|
||||
// which could expose sensitive directories like .git or sensitive files like
|
||||
// .htpasswd. To exclude files with a leading period, remove the files/directories
|
||||
// from the server or create a custom FileSystem implementation.
|
||||
//
|
||||
// An empty Dir is treated as ".".
|
||||
type Dir string
|
||||
|
@ -111,13 +111,13 @@ type Addr interface {
|
||||
// Multiple goroutines may invoke methods on a Conn simultaneously.
|
||||
type Conn interface {
|
||||
// Read reads data from the connection.
|
||||
// Read can be made to time out and return an Error with Timeout() == true
|
||||
// after a fixed time limit; see SetDeadline and SetReadDeadline.
|
||||
// Read can be made to time out and return an error after a fixed
|
||||
// time limit; see SetDeadline and SetReadDeadline.
|
||||
Read(b []byte) (n int, err error)
|
||||
|
||||
// Write writes data to the connection.
|
||||
// Write can be made to time out and return an Error with Timeout() == true
|
||||
// after a fixed time limit; see SetDeadline and SetWriteDeadline.
|
||||
// Write can be made to time out and return an error after a fixed
|
||||
// time limit; see SetDeadline and SetWriteDeadline.
|
||||
Write(b []byte) (n int, err error)
|
||||
|
||||
// Close closes the connection.
|
||||
@ -313,15 +313,13 @@ type PacketConn interface {
|
||||
// It returns the number of bytes read (0 <= n <= len(p))
|
||||
// and any error encountered. Callers should always process
|
||||
// the n > 0 bytes returned before considering the error err.
|
||||
// ReadFrom can be made to time out and return
|
||||
// an Error with Timeout() == true after a fixed time limit;
|
||||
// see SetDeadline and SetReadDeadline.
|
||||
// ReadFrom can be made to time out and return an error after a
|
||||
// fixed time limit; see SetDeadline and SetReadDeadline.
|
||||
ReadFrom(p []byte) (n int, addr Addr, err error)
|
||||
|
||||
// WriteTo writes a packet with payload p to addr.
|
||||
// WriteTo can be made to time out and return
|
||||
// an Error with Timeout() == true after a fixed time limit;
|
||||
// see SetDeadline and SetWriteDeadline.
|
||||
// WriteTo can be made to time out and return an Error after a
|
||||
// fixed time limit; see SetDeadline and SetWriteDeadline.
|
||||
// On packet-oriented connections, write timeouts are rare.
|
||||
WriteTo(p []byte, addr Addr) (n int, err error)
|
||||
|
||||
@ -337,11 +335,17 @@ type PacketConn interface {
|
||||
// SetReadDeadline and SetWriteDeadline.
|
||||
//
|
||||
// A deadline is an absolute time after which I/O operations
|
||||
// fail with a timeout (see type Error) instead of
|
||||
// blocking. The deadline applies to all future and pending
|
||||
// I/O, not just the immediately following call to ReadFrom or
|
||||
// WriteTo. After a deadline has been exceeded, the connection
|
||||
// can be refreshed by setting a deadline in the future.
|
||||
// fail instead of blocking. The deadline applies to all future
|
||||
// and pending I/O, not just the immediately following call to
|
||||
// Read or Write. After a deadline has been exceeded, the
|
||||
// connection can be refreshed by setting a deadline in the future.
|
||||
//
|
||||
// If the deadline is exceeded a call to Read or Write or to other
|
||||
// I/O methods will return an error that wraps os.ErrDeadlineExceeded.
|
||||
// This can be tested using errors.Is(err, os.ErrDeadlineExceeded).
|
||||
// The error's Timeout method will return true, but note that there
|
||||
// are other possible errors for which the Timeout method will
|
||||
// return true even if the deadline has not been exceeded.
|
||||
//
|
||||
// An idle timeout can be implemented by repeatedly extending
|
||||
// the deadline after successful ReadFrom or WriteTo calls.
|
||||
|
@ -233,10 +233,10 @@ func (f *File) Sync() error {
|
||||
var buf [syscall.STATFIXLEN]byte
|
||||
n, err := d.Marshal(buf[:])
|
||||
if err != nil {
|
||||
return NewSyscallError("fsync", err)
|
||||
return &PathError{"sync", f.name, err}
|
||||
}
|
||||
if err = syscall.Fwstat(f.fd, buf[:n]); err != nil {
|
||||
return NewSyscallError("fsync", err)
|
||||
return &PathError{"sync", f.name, err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -536,7 +536,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
|
||||
return
|
||||
}
|
||||
|
||||
if sig == sigPreempt {
|
||||
if sig == sigPreempt && debug.asyncpreemptoff == 0 {
|
||||
// Might be a preemption signal.
|
||||
doSigPreempt(gp, c)
|
||||
// Even if this was definitely a preemption signal, it
|
||||
|
@ -130,7 +130,7 @@ func fastrandn(n uint32) uint32 {
|
||||
//go:linkname sync_fastrand sync.fastrand
|
||||
func sync_fastrand() uint32 { return fastrand() }
|
||||
|
||||
// in asm_*.s
|
||||
// in internal/bytealg/equal_*.s
|
||||
//go:noescape
|
||||
func memequal(a, b unsafe.Pointer, size uintptr) bool
|
||||
|
||||
|
@ -35,6 +35,20 @@ func Creat(path string, mode uint32) (fd int, err error) {
|
||||
return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
|
||||
}
|
||||
|
||||
func isGroupMember(gid int) bool {
|
||||
groups, err := Getgroups()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, g := range groups {
|
||||
if g == gid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//sys faccessat(dirfd int, path string, mode uint32) (err error)
|
||||
|
||||
func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||
@ -92,7 +106,7 @@ func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||
gid = Getgid()
|
||||
}
|
||||
|
||||
if uint32(gid) == st.Gid {
|
||||
if uint32(gid) == st.Gid || isGroupMember(gid) {
|
||||
fmode = (st.Mode >> 3) & 7
|
||||
} else {
|
||||
fmode = st.Mode & 7
|
||||
|
@ -349,7 +349,7 @@ func (i *IdentifierNode) Copy() Node {
|
||||
return NewIdentifier(i.Ident).SetTree(i.tr).SetPos(i.Pos)
|
||||
}
|
||||
|
||||
// AssignNode holds a list of variable names, possibly with chained field
|
||||
// VariableNode holds a list of variable names, possibly with chained field
|
||||
// accesses. The dollar sign is part of the (first) name.
|
||||
type VariableNode struct {
|
||||
NodeType
|
||||
|
22
test/fixedbugs/issue39459.go
Normal file
22
test/fixedbugs/issue39459.go
Normal file
@ -0,0 +1,22 @@
|
||||
// compile
|
||||
|
||||
// Copyright 2020 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 p
|
||||
|
||||
type T struct { // big enough to be an unSSAable type
|
||||
a, b, c, d, e, f int
|
||||
}
|
||||
|
||||
func f(x interface{}, p *int) {
|
||||
_ = *p // trigger nil check here, removing it from below
|
||||
switch x := x.(type) {
|
||||
case *T:
|
||||
// Zero twice, so one of them will be removed by the deadstore pass
|
||||
*x = T{}
|
||||
*p = 0 // store op to prevent Zero ops from being optimized by the earlier opt pass rewrite rules
|
||||
*x = T{}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user