libgo: update to Go 1.11.1 release
authorIan Lance Taylor <ian@gcc.gnu.org>
Mon, 8 Oct 2018 14:21:30 +0000 (14:21 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 8 Oct 2018 14:21:30 +0000 (14:21 +0000)
    Reviewed-on: https://go-review.googlesource.com/c/140277

From-SVN: r264932

28 files changed:
gcc/go/gofrontend/MERGE
libgo/MERGE
libgo/VERSION
libgo/go/cmd/go/alldocs.go
libgo/go/cmd/go/internal/help/helpdoc.go
libgo/go/cmd/go/internal/work/exec.go
libgo/go/cmd/go/internal/work/security.go
libgo/go/cmd/go/script_test.go
libgo/go/crypto/x509/verify.go
libgo/go/crypto/x509/verify_test.go
libgo/go/encoding/json/decode.go
libgo/go/encoding/json/decode_test.go
libgo/go/go/types/api_test.go
libgo/go/go/types/builtins.go
libgo/go/net/dnsclient_unix.go
libgo/go/net/dnsclient_unix_test.go
libgo/go/net/http/roundtrip_js.go
libgo/go/net/lookup_unix.go
libgo/go/net/splice_test.go
libgo/go/reflect/all_test.go
libgo/go/reflect/makefunc_ffi.go
libgo/go/reflect/value.go
libgo/go/runtime/chan.go
libgo/go/runtime/mbarrier.go
libgo/go/runtime/os_darwin.go
libgo/go/runtime/os_netbsd.go
libgo/go/runtime/select.go
libgo/go/runtime/trace/annotation.go

index 2c7a860c8a8ffa7991bfef87a39e646455f1cb82..6e783c96d6d4021199699ac4b18bec4485858ec8 100644 (file)
@@ -1,4 +1,4 @@
-d0739c13ca3686df1f8d0fae7c6c5caaed058503
+a9da4d34a2f878a5058f7e7d2beef52aa62471a1
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 9b907987defff5b23c1d8f9665014a62cd7147a0..b2803e871c5f759fe08d8d8991b7ccd18d31df48 100644 (file)
@@ -1,4 +1,4 @@
-41e62b8c49d21659b48a95216e3062032285250f
+26957168c4c0cdcc7ca4f0b19d0eb19474d224ac
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
index f3220fb759237999ad9cac471b6564311ae68a79..0ff4ff61d198186b956c60c8596a89213baf6621 100644 (file)
@@ -1 +1 @@
-go1.11
+go1.11.1
index ebbd154f3e6ffd647a2013f7c9c4912527e10d5c..1060e779c1b6e7d6978c37b1cfc74e836511de9d 100644 (file)
 //             The directory where the go command will write
 //             temporary source files, packages, and binaries.
 //
+// Each entry in the GOFLAGS list must be a standalone flag.
+// Because the entries are space-separated, flag values must
+// not contain spaces. In some cases, you can provide multiple flag
+// values instead: for example, to set '-ldflags=-s -w'
+// you can use 'GOFLAGS=-ldflags=-s -ldflags=-w'.
+//
 // Environment variables for use with cgo:
 //
 //     CC
index aff4ce12f6c9ae05db4ff1ef24b0c267761a853e..e2c4e61615bcc7c63539101ba68ec2d2ee44df52 100644 (file)
@@ -507,6 +507,12 @@ General-purpose environment variables:
                The directory where the go command will write
                temporary source files, packages, and binaries.
 
+Each entry in the GOFLAGS list must be a standalone flag.
+Because the entries are space-separated, flag values must
+not contain spaces. In some cases, you can provide multiple flag
+values instead: for example, to set '-ldflags=-s -w'
+you can use 'GOFLAGS=-ldflags=-s -ldflags=-w'.
+
 Environment variables for use with cgo:
 
        CC
index 84870e52ccc05663e1df124b7eb61d4adccd370d..8aba293dd345ea574f422c5520d6f94cded2f409 100644 (file)
@@ -224,7 +224,9 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
                if len(p.SFiles) > 0 {
                        fmt.Fprintf(h, "asm %q %q %q\n", b.toolID("asm"), forcedAsmflags, p.Internal.Asmflags)
                }
-               fmt.Fprintf(h, "GO$GOARCH=%s\n", os.Getenv("GO"+strings.ToUpper(cfg.BuildContext.GOARCH))) // GO386, GOARM, etc
+               // GO386, GOARM, GOMIPS, etc.
+               baseArch := strings.TrimSuffix(cfg.BuildContext.GOARCH, "le")
+               fmt.Fprintf(h, "GO$GOARCH=%s\n", os.Getenv("GO"+strings.ToUpper(baseArch)))
 
                // TODO(rsc): Convince compiler team not to add more magic environment variables,
                // or perhaps restrict the environment variables passed to subprocesses.
index d5d126123a4b0b6839503dadf31e5bf54ff9b281..2132c5f3e15f41597a8a1f9656c9ef54e343aa7c 100644 (file)
@@ -170,6 +170,7 @@ var validLinkerFlags = []*regexp.Regexp{
        re(`-Wl,-e[=,][a-zA-Z0-9]*`),
        re(`-Wl,--enable-new-dtags`),
        re(`-Wl,--end-group`),
+       re(`-Wl,--(no-)?export-dynamic`),
        re(`-Wl,-framework,[^,@\-][^,]+`),
        re(`-Wl,-headerpad_max_install_names`),
        re(`-Wl,--no-undefined`),
index 9e958e0c6358ae934ff6067493d3879276a75aa0..6399faac0f456f93a813fbd4a47fb49d4a27d240 100644 (file)
@@ -635,6 +635,9 @@ func scriptMatch(ts *testScript, neg bool, args []string, text, name string) {
                text = string(data)
        }
 
+       // Matching against workdir would be misleading.
+       text = strings.Replace(text, ts.workdir, "$WORK", -1)
+
        if neg {
                if re.MatchString(text) {
                        if isGrep {
index 210db4c1d0eb301b36c0f14cb3be4b9a03aa6cee..0b75778a03840da7e75c57c94da8546372d1a605 100644 (file)
@@ -894,8 +894,8 @@ func validHostname(host string) bool {
                        if c == '-' && j != 0 {
                                continue
                        }
-                       if c == '_' {
-                               // _ is not a valid character in hostnames, but it's commonly
+                       if c == '_' || c == ':' {
+                               // Not valid characters in hostnames, but commonly
                                // found in deployments outside the WebPKI.
                                continue
                        }
index 768414583962f88ddf53fe64c4d7ea8836ff7469..0e24d3b5da3af3218f8d63992811ef674eba1ba8 100644 (file)
@@ -1881,6 +1881,7 @@ func TestValidHostname(t *testing.T) {
                {"foo.*.example.com", false},
                {"exa_mple.com", true},
                {"foo,bar", false},
+               {"project-dev:us-central1:main", true},
        }
        for _, tt := range tests {
                if got := validHostname(tt.host); got != tt.want {
index 0b29249218a32b037ff9f26fd617d118142d3e1d..7d235087e60f4bb998e4c5e862f27990f1b59034 100644 (file)
@@ -672,6 +672,7 @@ func (d *decodeState) object(v reflect.Value) error {
        }
 
        var mapElem reflect.Value
+       originalErrorContext := d.errorContext
 
        for {
                // Read opening " of string key or closing }.
@@ -832,8 +833,7 @@ func (d *decodeState) object(v reflect.Value) error {
                        return errPhase
                }
 
-               d.errorContext.Struct = ""
-               d.errorContext.Field = ""
+               d.errorContext = originalErrorContext
        }
        return nil
 }
@@ -991,7 +991,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
                        if fromQuoted {
                                return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
                        }
-                       return &UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}
+                       d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
                case reflect.Interface:
                        n, err := d.convertNumber(s)
                        if err != nil {
index ab83b81bb39584411ce0b5e260f04d1b8e77f26a..5746ddf9861e7e1f672ad92a5b6479331b868aa9 100644 (file)
@@ -371,6 +371,10 @@ func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error {
        return (*intWithMarshalText)(b).UnmarshalText(data)
 }
 
+type mapStringToStringData struct {
+       Data map[string]string `json:"data"`
+}
+
 type unmarshalTest struct {
        in                    string
        ptr                   interface{}
@@ -401,6 +405,7 @@ var unmarshalTests = []unmarshalTest{
        {in: `"invalid: \uD834x\uDD1E"`, ptr: new(string), out: "invalid: \uFFFDx\uFFFD"},
        {in: "null", ptr: new(interface{}), out: nil},
        {in: `{"X": [1,2,3], "Y": 4}`, ptr: new(T), out: T{Y: 4}, err: &UnmarshalTypeError{"array", reflect.TypeOf(""), 7, "T", "X"}},
+       {in: `{"X": 23}`, ptr: new(T), out: T{}, err: &UnmarshalTypeError{"number", reflect.TypeOf(""), 8, "T", "X"}}, {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
        {in: `{"x": 1}`, ptr: new(tx), out: tx{}},
        {in: `{"x": 1}`, ptr: new(tx), err: fmt.Errorf("json: unknown field \"x\""), disallowUnknownFields: true},
        {in: `{"F1":1,"F2":2,"F3":3}`, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: Number("3")}},
@@ -866,6 +871,18 @@ var unmarshalTests = []unmarshalTest{
                err:                   fmt.Errorf("json: unknown field \"extra\""),
                disallowUnknownFields: true,
        },
+       // issue 26444
+       // UnmarshalTypeError without field & struct values
+       {
+               in:  `{"data":{"test1": "bob", "test2": 123}}`,
+               ptr: new(mapStringToStringData),
+               err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 37, Struct: "mapStringToStringData", Field: "data"},
+       },
+       {
+               in:  `{"data":{"test1": 123, "test2": "bob"}}`,
+               ptr: new(mapStringToStringData),
+               err: &UnmarshalTypeError{Value: "number", Type: reflect.TypeOf(""), Offset: 21, Struct: "mapStringToStringData", Field: "data"},
+       },
 }
 
 func TestMarshal(t *testing.T) {
index d4ed400ea6816bcd9e4908001de41023da68ec9b..35050e1b9eb588991af2310fad323272b9b77e39 100644 (file)
@@ -262,6 +262,8 @@ func TestTypesInfo(t *testing.T) {
                {`package x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
                {`package x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
                {`package x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a; f: b;}}`, `b`, `string`},
+               {`package x3; var x = panic("");`, `panic`, `func(interface{})`},
+               {`package x4; func _() { panic("") }`, `panic`, `func(interface{})`},
        }
 
        for _, test := range tests {
index 05e032423ca2c84cb84c67ca5da1b81454c87c59..d3f0c4d40dfb1dead02852227521e0ca54e3ccd8 100644 (file)
@@ -476,7 +476,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // panic(x)
                // record panic call if inside a function with result parameters
                // (for use in Checker.isTerminating)
-               if check.sig.results.Len() > 0 {
+               if check.sig != nil && check.sig.results.Len() > 0 {
                        // function has result parameters
                        p := check.isPanic
                        if p == nil {
index 6ec2f44b7cb1dc19c2a2bb5851964d94af12a52a..3b0293025d9fdee2256bf8fad169f6487252fa68 100644 (file)
@@ -27,6 +27,20 @@ import (
        "golang_org/x/net/dns/dnsmessage"
 )
 
+var (
+       errLameReferral              = errors.New("lame referral")
+       errCannotUnmarshalDNSMessage = errors.New("cannot unmarshal DNS message")
+       errCannotMarshalDNSMessage   = errors.New("cannot marshal DNS message")
+       errServerMisbehaving         = errors.New("server misbehaving")
+       errInvalidDNSResponse        = errors.New("invalid DNS response")
+       errNoAnswerFromDNSServer     = errors.New("no answer from DNS server")
+
+       // errServerTemporarlyMisbehaving is like errServerMisbehaving, except
+       // that when it gets translated to a DNSError, the IsTemporary field
+       // gets set to true.
+       errServerTemporarlyMisbehaving = errors.New("server misbehaving")
+)
+
 func newRequest(q dnsmessage.Question) (id uint16, udpReq, tcpReq []byte, err error) {
        id = uint16(rand.Int()) ^ uint16(time.Now().UnixNano())
        b := dnsmessage.NewBuilder(make([]byte, 2, 514), dnsmessage.Header{ID: id, RecursionDesired: true})
@@ -105,14 +119,14 @@ func dnsStreamRoundTrip(c Conn, id uint16, query dnsmessage.Question, b []byte)
        var p dnsmessage.Parser
        h, err := p.Start(b[:n])
        if err != nil {
-               return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot unmarshal DNS message")
+               return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
        }
        q, err := p.Question()
        if err != nil {
-               return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot unmarshal DNS message")
+               return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotUnmarshalDNSMessage
        }
        if !checkResponse(id, query, h, q) {
-               return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("invalid DNS response")
+               return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
        }
        return p, h, nil
 }
@@ -122,7 +136,7 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
        q.Class = dnsmessage.ClassINET
        id, udpReq, tcpReq, err := newRequest(q)
        if err != nil {
-               return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("cannot marshal DNS message")
+               return dnsmessage.Parser{}, dnsmessage.Header{}, errCannotMarshalDNSMessage
        }
        for _, network := range []string{"udp", "tcp"} {
                ctx, cancel := context.WithDeadline(ctx, time.Now().Add(timeout))
@@ -147,31 +161,31 @@ func (r *Resolver) exchange(ctx context.Context, server string, q dnsmessage.Que
                        return dnsmessage.Parser{}, dnsmessage.Header{}, mapErr(err)
                }
                if err := p.SkipQuestion(); err != dnsmessage.ErrSectionDone {
-                       return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("invalid DNS response")
+                       return dnsmessage.Parser{}, dnsmessage.Header{}, errInvalidDNSResponse
                }
                if h.Truncated { // see RFC 5966
                        continue
                }
                return p, h, nil
        }
-       return dnsmessage.Parser{}, dnsmessage.Header{}, errors.New("no answer from DNS server")
+       return dnsmessage.Parser{}, dnsmessage.Header{}, errNoAnswerFromDNSServer
 }
 
 // checkHeader performs basic sanity checks on the header.
 func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string) error {
+       if h.RCode == dnsmessage.RCodeNameError {
+               return errNoSuchHost
+       }
+
        _, err := p.AnswerHeader()
        if err != nil && err != dnsmessage.ErrSectionDone {
-               return &DNSError{
-                       Err:    "cannot unmarshal DNS message",
-                       Name:   name,
-                       Server: server,
-               }
+               return errCannotUnmarshalDNSMessage
        }
 
        // libresolv continues to the next server when it receives
        // an invalid referral response. See golang.org/issue/15434.
        if h.RCode == dnsmessage.RCodeSuccess && !h.Authoritative && !h.RecursionAvailable && err == dnsmessage.ErrSectionDone {
-               return &DNSError{Err: "lame referral", Name: name, Server: server}
+               return errLameReferral
        }
 
        if h.RCode != dnsmessage.RCodeSuccess && h.RCode != dnsmessage.RCodeNameError {
@@ -180,11 +194,10 @@ func checkHeader(p *dnsmessage.Parser, h dnsmessage.Header, name, server string)
                // a name error and we didn't get success,
                // the server is behaving incorrectly or
                // having temporary trouble.
-               err := &DNSError{Err: "server misbehaving", Name: name, Server: server}
                if h.RCode == dnsmessage.RCodeServerFailure {
-                       err.IsTemporary = true
+                       return errServerTemporarlyMisbehaving
                }
-               return err
+               return errServerMisbehaving
        }
 
        return nil
@@ -194,28 +207,16 @@ func skipToAnswer(p *dnsmessage.Parser, qtype dnsmessage.Type, name, server stri
        for {
                h, err := p.AnswerHeader()
                if err == dnsmessage.ErrSectionDone {
-                       return &DNSError{
-                               Err:    errNoSuchHost.Error(),
-                               Name:   name,
-                               Server: server,
-                       }
+                       return errNoSuchHost
                }
                if err != nil {
-                       return &DNSError{
-                               Err:    "cannot unmarshal DNS message",
-                               Name:   name,
-                               Server: server,
-                       }
+                       return errCannotUnmarshalDNSMessage
                }
                if h.Type == qtype {
                        return nil
                }
                if err := p.SkipAnswer(); err != nil {
-                       return &DNSError{
-                               Err:    "cannot unmarshal DNS message",
-                               Name:   name,
-                               Server: server,
-                       }
+                       return errCannotUnmarshalDNSMessage
                }
        }
 }
@@ -229,7 +230,7 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
 
        n, err := dnsmessage.NewName(name)
        if err != nil {
-               return dnsmessage.Parser{}, "", errors.New("cannot marshal DNS message")
+               return dnsmessage.Parser{}, "", errCannotMarshalDNSMessage
        }
        q := dnsmessage.Question{
                Name:  n,
@@ -243,38 +244,62 @@ func (r *Resolver) tryOneName(ctx context.Context, cfg *dnsConfig, name string,
 
                        p, h, err := r.exchange(ctx, server, q, cfg.timeout)
                        if err != nil {
-                               lastErr = &DNSError{
+                               dnsErr := &DNSError{
                                        Err:    err.Error(),
                                        Name:   name,
                                        Server: server,
                                }
                                if nerr, ok := err.(Error); ok && nerr.Timeout() {
-                                       lastErr.(*DNSError).IsTimeout = true
+                                       dnsErr.IsTimeout = true
                                }
                                // Set IsTemporary for socket-level errors. Note that this flag
                                // may also be used to indicate a SERVFAIL response.
                                if _, ok := err.(*OpError); ok {
-                                       lastErr.(*DNSError).IsTemporary = true
+                                       dnsErr.IsTemporary = true
                                }
+                               lastErr = dnsErr
                                continue
                        }
 
-                       // The name does not exist, so trying another server won't help.
-                       //
-                       // TODO: indicate this in a more obvious way, such as a field on DNSError?
-                       if h.RCode == dnsmessage.RCodeNameError {
-                               return dnsmessage.Parser{}, "", &DNSError{Err: errNoSuchHost.Error(), Name: name, Server: server}
-                       }
-
-                       lastErr = checkHeader(&p, h, name, server)
-                       if lastErr != nil {
+                       if err := checkHeader(&p, h, name, server); err != nil {
+                               dnsErr := &DNSError{
+                                       Err:    err.Error(),
+                                       Name:   name,
+                                       Server: server,
+                               }
+                               if err == errServerTemporarlyMisbehaving {
+                                       dnsErr.IsTemporary = true
+                               }
+                               if err == errNoSuchHost {
+                                       // The name does not exist, so trying
+                                       // another server won't help.
+                                       //
+                                       // TODO: indicate this in a more
+                                       // obvious way, such as a field on
+                                       // DNSError?
+                                       return p, server, dnsErr
+                               }
+                               lastErr = dnsErr
                                continue
                        }
 
-                       lastErr = skipToAnswer(&p, qtype, name, server)
-                       if lastErr == nil {
+                       err = skipToAnswer(&p, qtype, name, server)
+                       if err == nil {
                                return p, server, nil
                        }
+                       lastErr = &DNSError{
+                               Err:    err.Error(),
+                               Name:   name,
+                               Server: server,
+                       }
+                       if err == errNoSuchHost {
+                               // The name does not exist, so trying another
+                               // server won't help.
+                               //
+                               // TODO: indicate this in a more obvious way,
+                               // such as a field on DNSError?
+                               return p, server, lastErr
+                       }
                }
        }
        return dnsmessage.Parser{}, "", lastErr
index f1bb09d161e4b16a601e47e95c2c3a2000e9f99c..8992480b6ac71ed6cbf40f2efd52cd3ba71953a0 100644 (file)
@@ -1427,28 +1427,35 @@ func TestDNSGoroutineRace(t *testing.T) {
        }
 }
 
+func lookupWithFake(fake fakeDNSServer, name string, typ dnsmessage.Type) error {
+       r := Resolver{PreferGo: true, Dial: fake.DialContext}
+
+       resolvConf.mu.RLock()
+       conf := resolvConf.dnsConfig
+       resolvConf.mu.RUnlock()
+
+       ctx, cancel := context.WithCancel(context.Background())
+       defer cancel()
+
+       _, _, err := r.tryOneName(ctx, conf, name, typ)
+       return err
+}
+
 // Issue 8434: verify that Temporary returns true on an error when rcode
 // is SERVFAIL
 func TestIssue8434(t *testing.T) {
-       msg := dnsmessage.Message{
-               Header: dnsmessage.Header{
-                       RCode: dnsmessage.RCodeServerFailure,
+       err := lookupWithFake(fakeDNSServer{
+               rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+                       return dnsmessage.Message{
+                               Header: dnsmessage.Header{
+                                       ID:       q.ID,
+                                       Response: true,
+                                       RCode:    dnsmessage.RCodeServerFailure,
+                               },
+                               Questions: q.Questions,
+                       }, nil
                },
-       }
-       b, err := msg.Pack()
-       if err != nil {
-               t.Fatal("Pack failed:", err)
-       }
-       var p dnsmessage.Parser
-       h, err := p.Start(b)
-       if err != nil {
-               t.Fatal("Start failed:", err)
-       }
-       if err := p.SkipAllQuestions(); err != nil {
-               t.Fatal("SkipAllQuestions failed:", err)
-       }
-
-       err = checkHeader(&p, h, "golang.org", "foo:53")
+       }, "golang.org.", dnsmessage.TypeALL)
        if err == nil {
                t.Fatal("expected an error")
        }
@@ -1464,50 +1471,76 @@ func TestIssue8434(t *testing.T) {
        }
 }
 
-// Issue 12778: verify that NXDOMAIN without RA bit errors as
-// "no such host" and not "server misbehaving"
+// TestNoSuchHost verifies that tryOneName works correctly when the domain does
+// not exist.
+//
+// Issue 12778: verify that NXDOMAIN without RA bit errors as "no such host"
+// and not "server misbehaving"
 //
 // Issue 25336: verify that NXDOMAIN errors fail fast.
-func TestIssue12778(t *testing.T) {
-       lookups := 0
-       fake := fakeDNSServer{
-               rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
-                       lookups++
-                       return dnsmessage.Message{
-                               Header: dnsmessage.Header{
-                                       ID:                 q.ID,
-                                       Response:           true,
-                                       RCode:              dnsmessage.RCodeNameError,
-                                       RecursionAvailable: false,
-                               },
-                               Questions: q.Questions,
-                       }, nil
+//
+// Issue 27525: verify that empty answers fail fast.
+func TestNoSuchHost(t *testing.T) {
+       tests := []struct {
+               name string
+               f    func(string, string, dnsmessage.Message, time.Time) (dnsmessage.Message, error)
+       }{
+               {
+                       "NXDOMAIN",
+                       func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+                               return dnsmessage.Message{
+                                       Header: dnsmessage.Header{
+                                               ID:                 q.ID,
+                                               Response:           true,
+                                               RCode:              dnsmessage.RCodeNameError,
+                                               RecursionAvailable: false,
+                                       },
+                                       Questions: q.Questions,
+                               }, nil
+                       },
+               },
+               {
+                       "no answers",
+                       func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+                               return dnsmessage.Message{
+                                       Header: dnsmessage.Header{
+                                               ID:                 q.ID,
+                                               Response:           true,
+                                               RCode:              dnsmessage.RCodeSuccess,
+                                               RecursionAvailable: false,
+                                               Authoritative:      true,
+                                       },
+                                       Questions: q.Questions,
+                               }, nil
+                       },
                },
        }
-       r := Resolver{PreferGo: true, Dial: fake.DialContext}
-
-       resolvConf.mu.RLock()
-       conf := resolvConf.dnsConfig
-       resolvConf.mu.RUnlock()
-
-       ctx, cancel := context.WithCancel(context.Background())
-       defer cancel()
 
-       _, _, err := r.tryOneName(ctx, conf, ".", dnsmessage.TypeALL)
+       for _, test := range tests {
+               t.Run(test.name, func(t *testing.T) {
+                       lookups := 0
+                       err := lookupWithFake(fakeDNSServer{
+                               rh: func(n, s string, q dnsmessage.Message, d time.Time) (dnsmessage.Message, error) {
+                                       lookups++
+                                       return test.f(n, s, q, d)
+                               },
+                       }, ".", dnsmessage.TypeALL)
 
-       if lookups != 1 {
-               t.Errorf("got %d lookups, wanted 1", lookups)
-       }
+                       if lookups != 1 {
+                               t.Errorf("got %d lookups, wanted 1", lookups)
+                       }
 
-       if err == nil {
-               t.Fatal("expected an error")
-       }
-       de, ok := err.(*DNSError)
-       if !ok {
-               t.Fatalf("err = %#v; wanted a *net.DNSError", err)
-       }
-       if de.Err != errNoSuchHost.Error() {
-               t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error())
+                       if err == nil {
+                               t.Fatal("expected an error")
+                       }
+                       de, ok := err.(*DNSError)
+                       if !ok {
+                               t.Fatalf("err = %#v; wanted a *net.DNSError", err)
+                       }
+                       if de.Err != errNoSuchHost.Error() {
+                               t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error())
+                       }
+               })
        }
 }
 
@@ -1535,3 +1568,56 @@ func TestDNSDialTCP(t *testing.T) {
                t.Fatal("exhange failed:", err)
        }
 }
+
+// Issue 27763: verify that two strings in one TXT record are concatenated.
+func TestTXTRecordTwoStrings(t *testing.T) {
+       fake := fakeDNSServer{
+               rh: func(n, _ string, q dnsmessage.Message, _ time.Time) (dnsmessage.Message, error) {
+                       r := dnsmessage.Message{
+                               Header: dnsmessage.Header{
+                                       ID:       q.Header.ID,
+                                       Response: true,
+                                       RCode:    dnsmessage.RCodeSuccess,
+                               },
+                               Questions: q.Questions,
+                               Answers: []dnsmessage.Resource{
+                                       {
+                                               Header: dnsmessage.ResourceHeader{
+                                                       Name:  q.Questions[0].Name,
+                                                       Type:  dnsmessage.TypeA,
+                                                       Class: dnsmessage.ClassINET,
+                                               },
+                                               Body: &dnsmessage.TXTResource{
+                                                       TXT: []string{"string1 ", "string2"},
+                                               },
+                                       },
+                                       {
+                                               Header: dnsmessage.ResourceHeader{
+                                                       Name:  q.Questions[0].Name,
+                                                       Type:  dnsmessage.TypeA,
+                                                       Class: dnsmessage.ClassINET,
+                                               },
+                                               Body: &dnsmessage.TXTResource{
+                                                       TXT: []string{"onestring"},
+                                               },
+                                       },
+                               },
+                       }
+                       return r, nil
+               },
+       }
+       r := Resolver{PreferGo: true, Dial: fake.DialContext}
+       txt, err := r.lookupTXT(context.Background(), "golang.org")
+       if err != nil {
+               t.Fatal("LookupTXT failed:", err)
+       }
+       if want := 2; len(txt) != want {
+               t.Fatalf("len(txt), got %d, want %d", len(txt), want)
+       }
+       if want := "string1 string2"; txt[0] != want {
+               t.Errorf("txt[0], got %q, want %q", txt[0], want)
+       }
+       if want := "onestring"; txt[1] != want {
+               t.Errorf("txt[1], got %q, want %q", txt[1], want)
+       }
+}
index 16b7b891c86b1562763640ea97f078ee33a25fd8..38e4f5573e60edcb7afcd9c9ae480e4c0395191a 100644 (file)
@@ -116,7 +116,9 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
 
                b := result.Get("body")
                var body io.ReadCloser
-               if b != js.Undefined() {
+               // The body is undefined when the browser does not support streaming response bodies (Firefox),
+               // and null in certain error cases, i.e. when the request is blocked because of CORS settings.
+               if b != js.Undefined() && b != js.Null() {
                        body = &streamReader{stream: b.Call("getReader")}
                } else {
                        // Fall back to using ArrayBuffer
index 76d6ae30f78b33af7440c45ab6dbe35829fd4624..39e8b720076b962c01906d9fc5a205b30c8f1f8d 100644 (file)
@@ -299,11 +299,21 @@ func (r *Resolver) lookupTXT(ctx context.Context, name string) ([]string, error)
                                Server: server,
                        }
                }
+               // Multiple strings in one TXT record need to be
+               // concatenated without separator to be consistent
+               // with previous Go resolver.
+               n := 0
+               for _, s := range txt.TXT {
+                       n += len(s)
+               }
+               txtJoin := make([]byte, 0, n)
+               for _, s := range txt.TXT {
+                       txtJoin = append(txtJoin, s...)
+               }
                if len(txts) == 0 {
-                       txts = txt.TXT
-               } else {
-                       txts = append(txts, txt.TXT...)
+                       txts = make([]string, 0, 1)
                }
+               txts = append(txts, string(txtJoin))
        }
        return txts, nil
 }
index 40ed19b8fa8f41b293dbd130b50a4d4387de8e70..3be1c7e5de11405df8e8342d30d48f09b620a17e 100644 (file)
@@ -124,6 +124,7 @@ func testSpliceBig(t *testing.T) {
 func testSpliceHonorsLimitedReader(t *testing.T) {
        t.Run("stopsAfterN", testSpliceStopsAfterN)
        t.Run("updatesN", testSpliceUpdatesN)
+       t.Run("readerAtLimit", testSpliceReaderAtLimit)
 }
 
 func testSpliceStopsAfterN(t *testing.T) {
@@ -210,7 +211,7 @@ func testSpliceUpdatesN(t *testing.T) {
        }
 }
 
-func testSpliceReaderAtEOF(t *testing.T) {
+func testSpliceReaderAtLimit(t *testing.T) {
        clientUp, serverUp, err := spliceTestSocketPair("tcp")
        if err != nil {
                t.Fatal(err)
@@ -224,22 +225,64 @@ func testSpliceReaderAtEOF(t *testing.T) {
        defer clientDown.Close()
        defer serverDown.Close()
 
-       serverUp.Close()
-       _, err, handled := splice(serverDown.(*TCPConn).fd, serverUp)
+       lr := &io.LimitedReader{
+               N: 0,
+               R: serverUp,
+       }
+       _, err, handled := splice(serverDown.(*TCPConn).fd, lr)
        if !handled {
                if serr, ok := err.(*os.SyscallError); ok && serr.Syscall == "pipe2" && serr.Err == syscall.ENOSYS {
                        t.Skip("pipe2 not supported")
                }
 
-               t.Errorf("closed connection: got err = %v, handled = %t, want handled = true", err, handled)
+               t.Errorf("exhausted LimitedReader: got err = %v, handled = %t, want handled = true", err, handled)
        }
-       lr := &io.LimitedReader{
-               N: 0,
-               R: serverUp,
+}
+
+func testSpliceReaderAtEOF(t *testing.T) {
+       clientUp, serverUp, err := spliceTestSocketPair("tcp")
+       if err != nil {
+               t.Fatal(err)
        }
-       _, err, handled = splice(serverDown.(*TCPConn).fd, lr)
-       if !handled {
-               t.Errorf("exhausted LimitedReader: got err = %v, handled = %t, want handled = true", err, handled)
+       defer clientUp.Close()
+       clientDown, serverDown, err := spliceTestSocketPair("tcp")
+       if err != nil {
+               t.Fatal(err)
+       }
+       defer clientDown.Close()
+
+       serverUp.Close()
+
+       // We'd like to call net.splice here and check the handled return
+       // value, but we disable splice on old Linux kernels.
+       //
+       // In that case, poll.Splice and net.splice return a non-nil error
+       // and handled == false. We'd ideally like to see handled == true
+       // because the source reader is at EOF, but if we're running on an old
+       // kernel, and splice is disabled, we won't see EOF from net.splice,
+       // because we won't touch the reader at all.
+       //
+       // Trying to untangle the errors from net.splice and match them
+       // against the errors created by the poll package would be brittle,
+       // so this is a higher level test.
+       //
+       // The following ReadFrom should return immediately, regardless of
+       // whether splice is disabled or not. The other side should then
+       // get a goodbye signal. Test for the goodbye signal.
+       msg := "bye"
+       go func() {
+               serverDown.(*TCPConn).ReadFrom(serverUp)
+               io.WriteString(serverDown, msg)
+               serverDown.Close()
+       }()
+
+       buf := make([]byte, 3)
+       _, err = io.ReadFull(clientDown, buf)
+       if err != nil {
+               t.Errorf("clientDown: %v", err)
+       }
+       if string(buf) != msg {
+               t.Errorf("clientDown got %q, want %q", buf, msg)
        }
 }
 
index eb893e965d1145aa4dff3c0e38d16747a18931ee..472988fe85622e9175e2a0535928881b24fbcc10 100644 (file)
@@ -5864,7 +5864,7 @@ func clobber() {
 type funcLayoutTest struct {
        rcvr, t                  Type
        size, argsize, retOffset uintptr
-       stack                    []byte // pointer bitmap: 1 is pointer, 0 is scalar (or uninitialized)
+       stack                    []byte // pointer bitmap: 1 is pointer, 0 is scalar
        gc                       []byte
 }
 
@@ -5886,7 +5886,7 @@ func init() {
                        6 * PtrSize,
                        4 * PtrSize,
                        4 * PtrSize,
-                       []byte{1, 0, 1},
+                       []byte{1, 0, 1, 0, 1},
                        []byte{1, 0, 1, 0, 1},
                })
 
index 2acf7bb887a2ba6fbd15c9ed8084cd690ecd211e..9d9cbdec25ddf210d0eefb5d84df7fecfcb28d23 100644 (file)
@@ -33,7 +33,7 @@ func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFunc
        ap := params
        for _, rt := range ftyp.in {
                p := unsafe_New(rt)
-               memmove(p, *(*unsafe.Pointer)(ap), rt.size)
+               typedmemmove(rt, p, *(*unsafe.Pointer)(ap))
                v := Value{rt, p, flag(rt.Kind()) | flagIndir}
                in = append(in, v)
                ap = (unsafe.Pointer)(uintptr(ap) + ptrSize)
@@ -59,7 +59,7 @@ func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFunc
                if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) {
                        *(*unsafe.Pointer)(addr) = v.ptr
                } else {
-                       memmove(addr, v.ptr, typ.size)
+                       typedmemmove(typ, addr, v.ptr)
                }
                off += typ.size
        }
index 5ddd30d4d279881ad703f701ad158feebcb03923..9f05744f8d13625c9cd817aea948be928c52dad7 100644 (file)
@@ -323,7 +323,7 @@ var callGC bool // for testing; see TestCallMethodJump
 
 func (v Value) call(op string, in []Value) []Value {
        // Get function pointer, type.
-       t := v.typ
+       t := (*funcType)(unsafe.Pointer(v.typ))
        var (
                fn   unsafe.Pointer
                rcvr Value
@@ -472,7 +472,7 @@ func (v Value) call(op string, in []Value) []Value {
 // The return value rcvrtype gives the method's actual receiver type.
 // The return value t gives the method type signature (without the receiver).
 // The return value fn is a pointer to the method code.
-func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn unsafe.Pointer) {
+func methodReceiver(op string, v Value, methodIndex int) (rcvrtype *rtype, t *funcType, fn unsafe.Pointer) {
        i := methodIndex
        if v.typ.Kind() == Interface {
                tt := (*interfaceType)(unsafe.Pointer(v.typ))
@@ -489,7 +489,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
                }
                rcvrtype = iface.itab.typ
                fn = unsafe.Pointer(&iface.itab.fun[i])
-               t = m.typ
+               t = (*funcType)(unsafe.Pointer(m.typ))
        } else {
                rcvrtype = v.typ
                ms := v.typ.exportedMethods()
@@ -501,7 +501,7 @@ func methodReceiver(op string, v Value, methodIndex int) (rcvrtype, t *rtype, fn
                        panic("reflect: " + op + " of unexported method")
                }
                fn = unsafe.Pointer(&m.tfn)
-               t = m.mtyp
+               t = (*funcType)(unsafe.Pointer(m.mtyp))
        }
        return
 }
@@ -2399,10 +2399,14 @@ func mapiternext(it unsafe.Pointer)
 
 //go:noescape
 func maplen(m unsafe.Pointer) int
-func call(typ *rtype, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
+func call(typ *funcType, fnaddr unsafe.Pointer, isInterface bool, isMethod bool, params *unsafe.Pointer, results *unsafe.Pointer)
 
 func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
 
+// memmove copies size bytes to dst from src. No write barriers are used.
+//go:noescape
+func memmove(dst, src unsafe.Pointer, size uintptr)
+
 // typedmemmove copies a value of type t to dst from src.
 //go:noescape
 func typedmemmove(t *rtype, dst, src unsafe.Pointer)
@@ -2412,10 +2416,6 @@ func typedmemmove(t *rtype, dst, src unsafe.Pointer)
 //go:noescape
 func typedslicecopy(elemType *rtype, dst, src sliceHeader) int
 
-//go:noescape
-//extern memmove
-func memmove(adst, asrc unsafe.Pointer, n uintptr)
-
 // Dummy annotation marking that the value x escapes,
 // for use in cases where the reflect code is so clever that
 // the compiler cannot follow.
index 88a8944112b42a1ec2afa2a5196fe9bf70f5e271..cb369effb8cd9f9452b192a61e571e8b21062ac9 100644 (file)
@@ -102,7 +102,7 @@ func makechan(t *chantype, size int) *hchan {
                // Queue or element size is zero.
                c = (*hchan)(mallocgc(hchanSize, nil, true))
                // Race detector uses this location for synchronization.
-               c.buf = unsafe.Pointer(c)
+               c.buf = c.raceaddr()
        case elem.kind&kindNoPointers != 0:
                // Elements do not contain pointers.
                // Allocate hchan and buf in one call.
@@ -166,7 +166,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
        }
 
        if raceenabled {
-               racereadpc(unsafe.Pointer(c), callerpc, funcPC(chansend))
+               racereadpc(c.raceaddr(), callerpc, funcPC(chansend))
        }
 
        // Fast path: check for failed non-blocking operation without acquiring the lock.
@@ -352,8 +352,8 @@ func closechan(c *hchan) {
 
        if raceenabled {
                callerpc := getcallerpc()
-               racewritepc(unsafe.Pointer(c), callerpc, funcPC(closechan))
-               racerelease(unsafe.Pointer(c))
+               racewritepc(c.raceaddr(), callerpc, funcPC(closechan))
+               racerelease(c.raceaddr())
        }
 
        c.closed = 1
@@ -376,7 +376,7 @@ func closechan(c *hchan) {
                gp := sg.g
                gp.param = nil
                if raceenabled {
-                       raceacquireg(gp, unsafe.Pointer(c))
+                       raceacquireg(gp, c.raceaddr())
                }
                gp.schedlink.set(glist)
                glist = gp
@@ -395,7 +395,7 @@ func closechan(c *hchan) {
                gp := sg.g
                gp.param = nil
                if raceenabled {
-                       raceacquireg(gp, unsafe.Pointer(c))
+                       raceacquireg(gp, c.raceaddr())
                }
                gp.schedlink.set(glist)
                glist = gp
@@ -477,7 +477,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
 
        if c.closed != 0 && c.qcount == 0 {
                if raceenabled {
-                       raceacquire(unsafe.Pointer(c))
+                       raceacquire(c.raceaddr())
                }
                unlock(&c.lock)
                if ep != nil {
@@ -755,6 +755,15 @@ func (q *waitq) dequeue() *sudog {
        }
 }
 
+func (c *hchan) raceaddr() unsafe.Pointer {
+       // Treat read-like and write-like operations on the channel to
+       // happen at this address. Avoid using the address of qcount
+       // or dataqsiz, because the len() and cap() builtins read
+       // those addresses, and we don't want them racing with
+       // operations like close().
+       return unsafe.Pointer(&c.buf)
+}
+
 func racesync(c *hchan, sg *sudog) {
        racerelease(chanbuf(c, 0))
        raceacquireg(sg.g, chanbuf(c, 0))
index 24e586551d8e0132f7776de716a8c4459787676d..487131576011fbaa76e572dc47f395133c1d9b99 100644 (file)
@@ -309,6 +309,19 @@ func typedmemclr(typ *_type, ptr unsafe.Pointer) {
        memclrNoHeapPointers(ptr, typ.size)
 }
 
+//go:linkname reflect_typedmemclr reflect.typedmemclr
+func reflect_typedmemclr(typ *_type, ptr unsafe.Pointer) {
+       typedmemclr(typ, ptr)
+}
+
+//go:linkname reflect_typedmemclrpartial reflect.typedmemclrpartial
+func reflect_typedmemclrpartial(typ *_type, ptr unsafe.Pointer, off, size uintptr) {
+       if typ.kind&kindNoPointers == 0 {
+               bulkBarrierPreWrite(uintptr(ptr), 0, size)
+       }
+       memclrNoHeapPointers(ptr, size)
+}
+
 // memclrHasPointers clears n bytes of typed memory starting at ptr.
 // The caller must ensure that the type of the object at ptr has
 // pointers, usually by checking typ.kind&kindNoPointers. However, ptr
index 95976331017574b5c45db9ba4fcef8e46a928785..235f7943f8d397512a640143b806e8b0e4afb555 100644 (file)
@@ -34,6 +34,10 @@ func semacreate(mp *m) {
 
 //go:nosplit
 func semasleep(ns int64) int32 {
+       var start int64
+       if ns >= 0 {
+               start = nanotime()
+       }
        mp := getg().m
        pthread_mutex_lock(&mp.mutex)
        for {
@@ -43,8 +47,13 @@ func semasleep(ns int64) int32 {
                        return 0
                }
                if ns >= 0 {
+                       spent := nanotime() - start
+                       if spent >= ns {
+                               pthread_mutex_unlock(&mp.mutex)
+                               return -1
+                       }
                        var t timespec
-                       t.set_nsec(ns)
+                       t.set_nsec(ns - spent)
                        err := pthread_cond_timedwait_relative_np(&mp.cond, &mp.mutex, &t)
                        if err == _ETIMEDOUT {
                                pthread_mutex_unlock(&mp.mutex)
index ea47e5cdc82dec2ff7cc4ebdf5856e1f7abcfdd3..16a11926dda4f44f568c9e58ec798131e29c4adc 100644 (file)
@@ -29,15 +29,9 @@ func semacreate(mp *m) {
 //go:nosplit
 func semasleep(ns int64) int32 {
        _g_ := getg()
-
-       // Compute sleep deadline.
-       var tsp *timespec
-       var ts timespec
+       var deadline int64
        if ns >= 0 {
-               var nsec int32
-               ts.set_sec(int64(timediv(ns, 1000000000, &nsec)))
-               ts.set_nsec(nsec)
-               tsp = &ts
+               deadline = nanotime() + ns
        }
 
        for {
@@ -50,18 +44,21 @@ func semasleep(ns int64) int32 {
                }
 
                // Sleep until unparked by semawakeup or timeout.
+               var tsp *timespec
+               var ts timespec
+               if ns >= 0 {
+                       wait := deadline - nanotime()
+                       if wait <= 0 {
+                               return -1
+                       }
+                       var nsec int32
+                       ts.set_sec(timediv(wait, 1000000000, &nsec))
+                       ts.set_nsec(nsec)
+                       tsp = &ts
+               }
                ret := lwp_park(_CLOCK_MONOTONIC, _TIMER_RELTIME, tsp, 0, unsafe.Pointer(&_g_.m.waitsemacount), nil)
                if ret == _ETIMEDOUT {
                        return -1
-               } else if ret == _EINTR && ns >= 0 {
-                       // Avoid sleeping forever if we keep getting
-                       // interrupted (for example by the profiling
-                       // timer). It would be if tsp upon return had the
-                       // remaining time to sleep, but this is good enough.
-                       var nsec int32
-                       ns /= 2
-                       ts.set_sec(timediv(ns, 1000000000, &nsec))
-                       ts.set_nsec(nsec)
                }
        }
 }
index 39c12dae6277d64961311b1ee3c792c5607871bd..fb8373f53b5801e0ca88d7a806a0599cd6117e1c 100644 (file)
@@ -426,7 +426,7 @@ rclose:
                typedmemclr(c.elemtype, cas.elem)
        }
        if raceenabled {
-               raceacquire(unsafe.Pointer(c))
+               raceacquire(c.raceaddr())
        }
        goto retc
 
index 3545ef3bba5719bb6a24bb03f19cbe67047341b4..d5a7d003fe2fc58a26dff8a653c195134c231a8f 100644 (file)
@@ -24,13 +24,13 @@ type traceContextKey struct{}
 // If the end function is called multiple times, only the first
 // call is used in the latency measurement.
 //
-//   ctx, task := trace.NewTask(ctx, "awesome task")
-//   trace.WithRegion(ctx, prepWork)
+//   ctx, task := trace.NewTask(ctx, "awesomeTask")
+//   trace.WithRegion(ctx, "preparation", prepWork)
 //   // preparation of the task
 //   go func() {  // continue processing the task in a separate goroutine.
 //       defer task.End()
-//       trace.WithRegion(ctx, remainingWork)
-//   }
+//       trace.WithRegion(ctx, "remainingWork", remainingWork)
+//   }()
 func NewTask(pctx context.Context, taskType string) (ctx context.Context, task *Task) {
        pid := fromContext(pctx).id
        id := newID()