diff options
-rw-r--r-- | src/cmd/compile/internal/ssa/expand_calls.go | 2 | ||||
-rw-r--r-- | src/cmd/go/script_test.go | 1 | ||||
-rw-r--r-- | src/cmd/go/testdata/script/mod_get_direct.txt | 2 | ||||
-rw-r--r-- | src/go.mod | 2 | ||||
-rw-r--r-- | src/go.sum | 4 | ||||
-rw-r--r-- | src/net/http/client.go | 1 | ||||
-rw-r--r-- | src/net/http/client_test.go | 27 | ||||
-rw-r--r-- | src/net/http/clientserver_test.go | 34 | ||||
-rw-r--r-- | src/net/http/h2_bundle.go | 81 | ||||
-rw-r--r-- | src/net/http/httptest/server.go | 7 | ||||
-rw-r--r-- | src/net/http/server.go | 7 | ||||
-rw-r--r-- | src/runtime/sys_darwin.go | 94 | ||||
-rw-r--r-- | src/runtime/sys_darwin_arm64.go | 4 | ||||
-rw-r--r-- | src/runtime/sys_openbsd.go | 22 | ||||
-rw-r--r-- | src/runtime/sys_openbsd1.go | 5 | ||||
-rw-r--r-- | src/runtime/sys_openbsd2.go | 36 | ||||
-rw-r--r-- | src/runtime/syscall_solaris.go | 2 | ||||
-rw-r--r-- | src/runtime/syscall_windows.go | 4 | ||||
-rw-r--r-- | src/time/time.go | 14 | ||||
-rw-r--r-- | src/time/time_test.go | 42 | ||||
-rw-r--r-- | src/vendor/modules.txt | 2 | ||||
-rw-r--r-- | test/fixedbugs/issue49249.go | 55 | ||||
-rw-r--r-- | test/fixedbugs/issue49378.go | 25 |
23 files changed, 396 insertions, 77 deletions
diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index 679ee8ad16..e06ed882f0 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -527,6 +527,7 @@ func expandCalls(f *Func) { // it could be a leaf type, but the "leaf" could be complex64 (for example) return storeArgOrLoad(pos, b, base, source, mem, t, offset) } + source.Type = t for i := int64(0); i < t.NumElem(); i++ { sel := source.Block.NewValue1I(pos, OpArraySelect, elt, i, source) mem = storeArgOrLoad(pos, b, base, sel, mem, elt, offset+i*elt.Width) @@ -559,6 +560,7 @@ func expandCalls(f *Func) { return storeArgOrLoad(pos, b, base, source, mem, t, offset) } + source.Type = t for i := 0; i < t.NumFields(); i++ { fld := t.Field(i) sel := source.Block.NewValue1I(pos, OpStructSelect, fld.Type, int64(i), source) diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index dfaa40548e..2ae30e146e 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -105,6 +105,7 @@ var extraEnvKeys = []string{ "GO_TESTING_GOTOOLS", // for gccgo testing "GCCGO", // for gccgo testing "GCCGOTOOLDIR", // for gccgo testing + "MallocNanoZone", // Needed to work around an apparent kernel bug in macOS 12; see https://golang.org/issue/49138. } // setup sets up the test execution temporary directory and environment. diff --git a/src/cmd/go/testdata/script/mod_get_direct.txt b/src/cmd/go/testdata/script/mod_get_direct.txt index 42ccbcd38a..856e05bc32 100644 --- a/src/cmd/go/testdata/script/mod_get_direct.txt +++ b/src/cmd/go/testdata/script/mod_get_direct.txt @@ -10,7 +10,7 @@ env GO111MODULE=on env GOPROXY=direct env GOSUMDB=off -go list -m cloud.google.com/go@master +go list -m cloud.google.com/go@main ! stdout 'v0.0.0-' -- go.mod -- diff --git a/src/go.mod b/src/go.mod index 25e7992a87..1040d0506f 100644 --- a/src/go.mod +++ b/src/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/net v0.0.0-20211101194150-d8c3cde3c676 + golang.org/x/net v0.0.0-20211201233224-64539c132272 golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect golang.org/x/text v0.3.4 // indirect ) diff --git a/src/go.sum b/src/go.sum index e5467ea1ca..6e22abb20a 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,8 +2,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20211101194150-d8c3cde3c676 h1:HdGRNh1uWfD+9WfeSGYgD64N7Nmu3oMnSkdZAONtoU8= -golang.org/x/net v0.0.0-20211101194150-d8c3cde3c676/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211201233224-64539c132272 h1:yz7zX5EMX9IFSUDQtHpohPOP+fh7w1Me4FH/El1jctU= +golang.org/x/net v0.0.0-20211201233224-64539c132272/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/src/net/http/client.go b/src/net/http/client.go index 88e2028bc3..5cb39f1c9a 100644 --- a/src/net/http/client.go +++ b/src/net/http/client.go @@ -940,7 +940,6 @@ func (b *cancelTimerBody) Read(p []byte) (n int, err error) { if err == nil { return n, nil } - b.stop() if err == io.EOF { return n, err } diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go index d90b4841c6..a182743d52 100644 --- a/src/net/http/client_test.go +++ b/src/net/http/client_test.go @@ -1353,6 +1353,33 @@ func TestClientTimeoutCancel(t *testing.T) { } } +func TestClientTimeoutDoesNotExpire_h1(t *testing.T) { testClientTimeoutDoesNotExpire(t, h1Mode) } +func TestClientTimeoutDoesNotExpire_h2(t *testing.T) { testClientTimeoutDoesNotExpire(t, h2Mode) } + +// Issue 49366: if Client.Timeout is set but not hit, no error should be returned. +func testClientTimeoutDoesNotExpire(t *testing.T, h2 bool) { + setParallel(t) + defer afterTest(t) + + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { + w.Write([]byte("body")) + })) + defer cst.close() + + cst.c.Timeout = 1 * time.Hour + req, _ := NewRequest("GET", cst.ts.URL, nil) + res, err := cst.c.Do(req) + if err != nil { + t.Fatal(err) + } + if _, err = io.Copy(io.Discard, res.Body); err != nil { + t.Fatalf("io.Copy(io.Discard, res.Body) = %v, want nil", err) + } + if err = res.Body.Close(); err != nil { + t.Fatalf("res.Body.Close() = %v, want nil", err) + } +} + func TestClientRedirectEatsBody_h1(t *testing.T) { testClientRedirectEatsBody(t, h1Mode) } func TestClientRedirectEatsBody_h2(t *testing.T) { testClientRedirectEatsBody(t, h2Mode) } func testClientRedirectEatsBody(t *testing.T, h2 bool) { diff --git a/src/net/http/clientserver_test.go b/src/net/http/clientserver_test.go index 5e227181ac..125d63566b 100644 --- a/src/net/http/clientserver_test.go +++ b/src/net/http/clientserver_test.go @@ -1582,3 +1582,37 @@ func TestH12_WebSocketUpgrade(t *testing.T) { }, }.run(t) } + +func TestIdentityTransferEncoding_h1(t *testing.T) { testIdentityTransferEncoding(t, h1Mode) } +func TestIdentityTransferEncoding_h2(t *testing.T) { testIdentityTransferEncoding(t, h2Mode) } + +func testIdentityTransferEncoding(t *testing.T, h2 bool) { + setParallel(t) + defer afterTest(t) + + const body = "body" + cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { + gotBody, _ := io.ReadAll(r.Body) + if got, want := string(gotBody), body; got != want { + t.Errorf("got request body = %q; want %q", got, want) + } + w.Header().Set("Transfer-Encoding", "identity") + w.WriteHeader(StatusOK) + w.(Flusher).Flush() + io.WriteString(w, body) + })) + defer cst.close() + req, _ := NewRequest("GET", cst.ts.URL, strings.NewReader(body)) + res, err := cst.c.Do(req) + if err != nil { + t.Fatal(err) + } + defer res.Body.Close() + gotBody, err := io.ReadAll(res.Body) + if err != nil { + t.Fatal(err) + } + if got, want := string(gotBody), body; got != want { + t.Errorf("got response body = %q; want %q", got, want) + } +} diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 0fd8da1d15..735f1b5eac 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -7653,36 +7653,49 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { } } + handleResponseHeaders := func() (*Response, error) { + res := cs.res + if res.StatusCode > 299 { + // On error or status code 3xx, 4xx, 5xx, etc abort any + // ongoing write, assuming that the server doesn't care + // about our request body. If the server replied with 1xx or + // 2xx, however, then assume the server DOES potentially + // want our body (e.g. full-duplex streaming: + // golang.org/issue/13444). If it turns out the server + // doesn't, they'll RST_STREAM us soon enough. This is a + // heuristic to avoid adding knobs to Transport. Hopefully + // we can keep it. + cs.abortRequestBodyWrite() + } + res.Request = req + res.TLS = cc.tlsState + if res.Body == http2noBody && http2actualContentLength(req) == 0 { + // If there isn't a request or response body still being + // written, then wait for the stream to be closed before + // RoundTrip returns. + if err := waitDone(); err != nil { + return nil, err + } + } + return res, nil + } + for { select { case <-cs.respHeaderRecv: - res := cs.res - if res.StatusCode > 299 { - // On error or status code 3xx, 4xx, 5xx, etc abort any - // ongoing write, assuming that the server doesn't care - // about our request body. If the server replied with 1xx or - // 2xx, however, then assume the server DOES potentially - // want our body (e.g. full-duplex streaming: - // golang.org/issue/13444). If it turns out the server - // doesn't, they'll RST_STREAM us soon enough. This is a - // heuristic to avoid adding knobs to Transport. Hopefully - // we can keep it. - cs.abortRequestBodyWrite() - } - res.Request = req - res.TLS = cc.tlsState - if res.Body == http2noBody && http2actualContentLength(req) == 0 { - // If there isn't a request or response body still being - // written, then wait for the stream to be closed before - // RoundTrip returns. - if err := waitDone(); err != nil { - return nil, err - } - } - return res, nil + return handleResponseHeaders() case <-cs.abort: - waitDone() - return nil, cs.abortErr + select { + case <-cs.respHeaderRecv: + // If both cs.respHeaderRecv and cs.abort are signaling, + // pick respHeaderRecv. The server probably wrote the + // response and immediately reset the stream. + // golang.org/issue/49645 + return handleResponseHeaders() + default: + waitDone() + return nil, cs.abortErr + } case <-ctx.Done(): err := ctx.Err() cs.abortStream(err) @@ -7742,6 +7755,9 @@ func (cs *http2clientStream) writeRequest(req *Request) (err error) { return err } cc.addStreamLocked(cs) // assigns stream ID + if http2isConnectionCloseRequest(req) { + cc.doNotReuse = true + } cc.mu.Unlock() // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere? @@ -7765,12 +7781,12 @@ func (cs *http2clientStream) writeRequest(req *Request) (err error) { } continueTimeout := cc.t.expectContinueTimeout() - if continueTimeout != 0 && - !httpguts.HeaderValuesContainsToken( - req.Header["Expect"], - "100-continue") { - continueTimeout = 0 - cs.on100 = make(chan struct{}, 1) + if continueTimeout != 0 { + if !httpguts.HeaderValuesContainsToken(req.Header["Expect"], "100-continue") { + continueTimeout = 0 + } else { + cs.on100 = make(chan struct{}, 1) + } } // Past this point (where we send request headers), it is possible for @@ -7839,6 +7855,7 @@ func (cs *http2clientStream) writeRequest(req *Request) (err error) { case <-respHeaderTimer: return http2errTimeout case <-respHeaderRecv: + respHeaderRecv = nil respHeaderTimer = nil // keep waiting for END_STREAM case <-cs.abort: return cs.abortErr diff --git a/src/net/http/httptest/server.go b/src/net/http/httptest/server.go index 65165d9eb3..a02a6d64c3 100644 --- a/src/net/http/httptest/server.go +++ b/src/net/http/httptest/server.go @@ -316,6 +316,13 @@ func (s *Server) wrap() { s.Config.ConnState = func(c net.Conn, cs http.ConnState) { s.mu.Lock() defer s.mu.Unlock() + + // Keep Close from returning until the user's ConnState hook + // (if any) finishes. Without this, the call to forgetConn + // below might send the count to 0 before we run the hook. + s.wg.Add(1) + defer s.wg.Done() + switch cs { case http.StateNew: s.wg.Add(1) diff --git a/src/net/http/server.go b/src/net/http/server.go index 198102ffd2..f9e518416d 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -1407,11 +1407,11 @@ func (cw *chunkWriter) writeHeader(p []byte) { hasCL = false } - if w.req.Method == "HEAD" || !bodyAllowedForStatus(code) { - // do nothing - } else if code == StatusNoContent { + if w.req.Method == "HEAD" || !bodyAllowedForStatus(code) || code == StatusNoContent { + // Response has no body. delHeader("Transfer-Encoding") } else if hasCL { + // Content-Length has been provided, so no chunking is to be done. delHeader("Transfer-Encoding") } else if w.req.ProtoAtLeast(1, 1) { // HTTP/1.1 or greater: Transfer-Encoding has been set to identity, and no @@ -1422,6 +1422,7 @@ func (cw *chunkWriter) writeHeader(p []byte) { if hasTE && te == "identity" { cw.chunking = false w.closeAfterReply = true + delHeader("Transfer-Encoding") } else { // HTTP/1.1 or greater: use chunked transfer encoding // to avoid closing the connection at EOF. diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 4a3f2fc453..bf124315df 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -102,28 +102,38 @@ func syscallNoErr() //go:nosplit //go:cgo_unsafe_args func pthread_attr_init(attr *pthreadattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_init_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_getstacksize(attr *pthreadattr, size *uintptr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + KeepAlive(size) + return ret } func pthread_attr_getstacksize_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_setdetachstate(attr *pthreadattr, state int) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_setdetachstate_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_create(attr *pthreadattr, start uintptr, arg unsafe.Pointer) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_create_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_create_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + KeepAlive(arg) // Just for consistency. Arg of course needs to be kept alive for the start function. + return ret } func pthread_create_trampoline() @@ -172,6 +182,7 @@ func mmap_trampoline() //go:cgo_unsafe_args func munmap(addr unsafe.Pointer, n uintptr) { libcCall(unsafe.Pointer(funcPC(munmap_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func munmap_trampoline() @@ -179,6 +190,7 @@ func munmap_trampoline() //go:cgo_unsafe_args func madvise(addr unsafe.Pointer, n uintptr, flags int32) { libcCall(unsafe.Pointer(funcPC(madvise_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func madvise_trampoline() @@ -186,13 +198,16 @@ func madvise_trampoline() //go:cgo_unsafe_args func mlock(addr unsafe.Pointer, n uintptr) { libcCall(unsafe.Pointer(funcPC(mlock_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func mlock_trampoline() //go:nosplit //go:cgo_unsafe_args func read(fd int32, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(funcPC(read_trampoline)), unsafe.Pointer(&fd)) + ret := libcCall(unsafe.Pointer(funcPC(read_trampoline)), unsafe.Pointer(&fd)) + KeepAlive(p) + return ret } func read_trampoline() @@ -230,14 +245,18 @@ func usleep_trampoline() //go:nosplit //go:cgo_unsafe_args func write1(fd uintptr, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(funcPC(write_trampoline)), unsafe.Pointer(&fd)) + ret := libcCall(unsafe.Pointer(funcPC(write_trampoline)), unsafe.Pointer(&fd)) + KeepAlive(p) + return ret } func write_trampoline() //go:nosplit //go:cgo_unsafe_args func open(name *byte, mode, perm int32) (ret int32) { - return libcCall(unsafe.Pointer(funcPC(open_trampoline)), unsafe.Pointer(&name)) + ret = libcCall(unsafe.Pointer(funcPC(open_trampoline)), unsafe.Pointer(&name)) + KeepAlive(name) + return } func open_trampoline() @@ -276,6 +295,8 @@ func walltime_trampoline() //go:cgo_unsafe_args func sigaction(sig uint32, new *usigactiont, old *usigactiont) { libcCall(unsafe.Pointer(funcPC(sigaction_trampoline)), unsafe.Pointer(&sig)) + KeepAlive(new) + KeepAlive(old) } func sigaction_trampoline() @@ -283,6 +304,8 @@ func sigaction_trampoline() //go:cgo_unsafe_args func sigprocmask(how uint32, new *sigset, old *sigset) { libcCall(unsafe.Pointer(funcPC(sigprocmask_trampoline)), unsafe.Pointer(&how)) + KeepAlive(new) + KeepAlive(old) } func sigprocmask_trampoline() @@ -297,6 +320,8 @@ func sigaltstack(new *stackt, old *stackt) { new.ss_size = 32768 } libcCall(unsafe.Pointer(funcPC(sigaltstack_trampoline)), unsafe.Pointer(&new)) + KeepAlive(new) + KeepAlive(old) } func sigaltstack_trampoline() @@ -311,20 +336,32 @@ func raiseproc_trampoline() //go:cgo_unsafe_args func setitimer(mode int32, new, old *itimerval) { libcCall(unsafe.Pointer(funcPC(setitimer_trampoline)), unsafe.Pointer(&mode)) + KeepAlive(new) + KeepAlive(old) } func setitimer_trampoline() //go:nosplit //go:cgo_unsafe_args func sysctl(mib *uint32, miblen uint32, oldp *byte, oldlenp *uintptr, newp *byte, newlen uintptr) int32 { - return libcCall(unsafe.Pointer(funcPC(sysctl_trampoline)), unsafe.Pointer(&mib)) + ret := libcCall(unsafe.Pointer(funcPC(sysctl_trampoline)), unsafe.Pointer(&mib)) + KeepAlive(mib) + KeepAlive(oldp) + KeepAlive(oldlenp) + KeepAlive(newp) + return ret } func sysctl_trampoline() //go:nosplit //go:cgo_unsafe_args func sysctlbyname(name *byte, oldp *byte, oldlenp *uintptr, newp *byte, newlen uintptr) int32 { - return libcCall(unsafe.Pointer(funcPC(sysctlbyname_trampoline)), unsafe.Pointer(&name)) + ret := libcCall(unsafe.Pointer(funcPC(sysctlbyname_trampoline)), unsafe.Pointer(&name)) + KeepAlive(name) + KeepAlive(oldp) + KeepAlive(oldlenp) + KeepAlive(newp) + return ret } func sysctlbyname_trampoline() @@ -346,56 +383,79 @@ func kqueue_trampoline() //go:nosplit //go:cgo_unsafe_args func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 { - return libcCall(unsafe.Pointer(funcPC(kevent_trampoline)), unsafe.Pointer(&kq)) + ret := libcCall(unsafe.Pointer(funcPC(kevent_trampoline)), unsafe.Pointer(&kq)) + KeepAlive(ch) + KeepAlive(ev) + KeepAlive(ts) + return ret } func kevent_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_mutex_init(m *pthreadmutex, attr *pthreadmutexattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_mutex_init_trampoline)), unsafe.Pointer(&m)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_mutex_init_trampoline)), unsafe.Pointer(&m)) + KeepAlive(m) + KeepAlive(attr) + return ret } func pthread_mutex_init_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_mutex_lock(m *pthreadmutex) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_mutex_lock_trampoline)), unsafe.Pointer(&m)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_mutex_lock_trampoline)), unsafe.Pointer(&m)) + KeepAlive(m) + return ret } func pthread_mutex_lock_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_mutex_unlock(m *pthreadmutex) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_mutex_unlock_trampoline)), unsafe.Pointer(&m)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_mutex_unlock_trampoline)), unsafe.Pointer(&m)) + KeepAlive(m) + return ret } func pthread_mutex_unlock_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_cond_init(c *pthreadcond, attr *pthreadcondattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_cond_init_trampoline)), unsafe.Pointer(&c)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_cond_init_trampoline)), unsafe.Pointer(&c)) + KeepAlive(c) + KeepAlive(attr) + return ret } func pthread_cond_init_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_cond_wait(c *pthreadcond, m *pthreadmutex) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_cond_wait_trampoline)), unsafe.Pointer(&c)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_cond_wait_trampoline)), unsafe.Pointer(&c)) + KeepAlive(c) + KeepAlive(m) + return ret } func pthread_cond_wait_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_cond_timedwait_relative_np(c *pthreadcond, m *pthreadmutex, t *timespec) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_cond_timedwait_relative_np_trampoline)), unsafe.Pointer(&c)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_cond_timedwait_relative_np_trampoline)), unsafe.Pointer(&c)) + KeepAlive(c) + KeepAlive(m) + KeepAlive(t) + return ret } func pthread_cond_timedwait_relative_np_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_cond_signal(c *pthreadcond) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_cond_signal_trampoline)), unsafe.Pointer(&c)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_cond_signal_trampoline)), unsafe.Pointer(&c)) + KeepAlive(c) + return ret } func pthread_cond_signal_trampoline() diff --git a/src/runtime/sys_darwin_arm64.go b/src/runtime/sys_darwin_arm64.go index 9c14f33a1c..471e93cb71 100644 --- a/src/runtime/sys_darwin_arm64.go +++ b/src/runtime/sys_darwin_arm64.go @@ -14,7 +14,9 @@ import ( //go:nosplit //go:cgo_unsafe_args func g0_pthread_key_create(k *pthreadkey, destructor uintptr) int32 { - return asmcgocall(unsafe.Pointer(funcPC(pthread_key_create_trampoline)), unsafe.Pointer(&k)) + ret := asmcgocall(unsafe.Pointer(funcPC(pthread_key_create_trampoline)), unsafe.Pointer(&k)) + KeepAlive(k) + return ret } func pthread_key_create_trampoline() diff --git a/src/runtime/sys_openbsd.go b/src/runtime/sys_openbsd.go index fcddf4d6a5..bda8a32ae8 100644 --- a/src/runtime/sys_openbsd.go +++ b/src/runtime/sys_openbsd.go @@ -14,35 +14,47 @@ import "unsafe" //go:nosplit //go:cgo_unsafe_args func pthread_attr_init(attr *pthreadattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_attr_init_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_init_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_destroy(attr *pthreadattr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_destroy_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_attr_destroy_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_destroy_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_getstacksize(attr *pthreadattr, size *uintptr) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_attr_getstacksize_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + KeepAlive(size) + return ret } func pthread_attr_getstacksize_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_attr_setdetachstate(attr *pthreadattr, state int) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_attr_setdetachstate_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + return ret } func pthread_attr_setdetachstate_trampoline() //go:nosplit //go:cgo_unsafe_args func pthread_create(attr *pthreadattr, start uintptr, arg unsafe.Pointer) int32 { - return libcCall(unsafe.Pointer(funcPC(pthread_create_trampoline)), unsafe.Pointer(&attr)) + ret := libcCall(unsafe.Pointer(funcPC(pthread_create_trampoline)), unsafe.Pointer(&attr)) + KeepAlive(attr) + KeepAlive(arg) // Just for consistency. Arg of course needs to be kept alive for the start function. + return ret } func pthread_create_trampoline() diff --git a/src/runtime/sys_openbsd1.go b/src/runtime/sys_openbsd1.go index e2886218db..08a978b4ae 100644 --- a/src/runtime/sys_openbsd1.go +++ b/src/runtime/sys_openbsd1.go @@ -11,7 +11,10 @@ import "unsafe" //go:nosplit //go:cgo_unsafe_args func thrsleep(ident uintptr, clock_id int32, tsp *timespec, lock uintptr, abort *uint32) int32 { - return libcCall(unsafe.Pointer(funcPC(thrsleep_trampoline)), unsafe.Pointer(&ident)) + ret := libcCall(unsafe.Pointer(funcPC(thrsleep_trampoline)), unsafe.Pointer(&ident)) + KeepAlive(tsp) + KeepAlive(abort) + return ret } func thrsleep_trampoline() diff --git a/src/runtime/sys_openbsd2.go b/src/runtime/sys_openbsd2.go index 474e7145e7..5303a68cf5 100644 --- a/src/runtime/sys_openbsd2.go +++ b/src/runtime/sys_openbsd2.go @@ -53,6 +53,7 @@ func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (un ret2 int }{addr, n, prot, flags, fd, off, nil, 0} libcCall(unsafe.Pointer(funcPC(mmap_trampoline)), unsafe.Pointer(&args)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. return args.ret1, args.ret2 } func mmap_trampoline() @@ -61,6 +62,7 @@ func mmap_trampoline() //go:cgo_unsafe_args func munmap(addr unsafe.Pointer, n uintptr) { libcCall(unsafe.Pointer(funcPC(munmap_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func munmap_trampoline() @@ -68,13 +70,16 @@ func munmap_trampoline() //go:cgo_unsafe_args func madvise(addr unsafe.Pointer, n uintptr, flags int32) { libcCall(unsafe.Pointer(funcPC(madvise_trampoline)), unsafe.Pointer(&addr)) + KeepAlive(addr) // Just for consistency. Hopefully addr is not a Go address. } func madvise_trampoline() //go:nosplit //go:cgo_unsafe_args func open(name *byte, mode, perm int32) (ret int32) { - return libcCall(unsafe.Pointer(funcPC(open_trampoline)), unsafe.Pointer(&name)) + ret = libcCall(unsafe.Pointer(funcPC(open_trampoline)), unsafe.Pointer(&name)) + KeepAlive(name) + return } func open_trampoline() @@ -88,14 +93,18 @@ func close_trampoline() //go:nosplit //go:cgo_unsafe_args func read(fd int32, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(funcPC(read_trampoline)), unsafe.Pointer(&fd)) + ret := libcCall(unsafe.Pointer(funcPC(read_trampoline)), unsafe.Pointer(&fd)) + KeepAlive(p) + return ret } func read_trampoline() //go:nosplit //go:cgo_unsafe_args func write1(fd uintptr, p unsafe.Pointer, n int32) int32 { - return libcCall(unsafe.Pointer(funcPC(write_trampoline)), unsafe.Pointer(&fd)) + ret := libcCall(unsafe.Pointer(funcPC(write_trampoline)), unsafe.Pointer(&fd)) + KeepAlive(p) + return ret } func write_trampoline() @@ -118,6 +127,8 @@ func pipe2_trampoline() //go:cgo_unsafe_args func setitimer(mode int32, new, old *itimerval) { libcCall(unsafe.Pointer(funcPC(setitimer_trampoline)), unsafe.Pointer(&mode)) + KeepAlive(new) + KeepAlive(old) } func setitimer_trampoline() @@ -131,7 +142,12 @@ func usleep_trampoline() //go:nosplit //go:cgo_unsafe_args func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32 { - return libcCall(unsafe.Pointer(funcPC(sysctl_trampoline)), unsafe.Pointer(&mib)) + ret := libcCall(unsafe.Pointer(funcPC(sysctl_trampoline)), unsafe.Pointer(&mib)) + KeepAlive(mib) + KeepAlive(out) + KeepAlive(size) + KeepAlive(dst) + return ret } func sysctl_trampoline() @@ -175,7 +191,11 @@ func kqueue_trampoline() //go:nosplit //go:cgo_unsafe_args func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 { - return libcCall(unsafe.Pointer(funcPC(kevent_trampoline)), unsafe.Pointer(&kq)) + ret := libcCall(unsafe.Pointer(funcPC(kevent_trampoline)), unsafe.Pointer(&kq)) + KeepAlive(ch) + KeepAlive(ev) + KeepAlive(ts) + return ret } func kevent_trampoline() @@ -183,6 +203,8 @@ func kevent_trampoline() //go:cgo_unsafe_args func sigaction(sig uint32, new *sigactiont, old *sigactiont) { libcCall(unsafe.Pointer(funcPC(sigaction_trampoline)), unsafe.Pointer(&sig)) + KeepAlive(new) + KeepAlive(old) } func sigaction_trampoline() @@ -190,6 +212,8 @@ func sigaction_trampoline() //go:cgo_unsafe_args func sigprocmask(how uint32, new *sigset, old *sigset) { libcCall(unsafe.Pointer(funcPC(sigprocmask_trampoline)), unsafe.Pointer(&how)) + KeepAlive(new) + KeepAlive(old) } func sigprocmask_trampoline() @@ -197,6 +221,8 @@ func sigprocmask_trampoline() //go:cgo_unsafe_args func sigaltstack(new *stackt, old *stackt) { libcCall(unsafe.Pointer(funcPC(sigaltstack_trampoline)), unsafe.Pointer(&new)) + KeepAlive(new) + KeepAlive(old) } func sigaltstack_trampoline() diff --git a/src/runtime/syscall_solaris.go b/src/runtime/syscall_solaris.go index 094516927f..ed5b7d19f9 100644 --- a/src/runtime/syscall_solaris.go +++ b/src/runtime/syscall_solaris.go @@ -303,6 +303,8 @@ func syscall_wait4(pid uintptr, wstatus *uint32, options uintptr, rusage unsafe. entersyscallblock() asmcgocall(unsafe.Pointer(&asmsysvicall6x), unsafe.Pointer(&call)) exitsyscall() + KeepAlive(wstatus) + KeepAlive(rusage) return int(call.r1), call.err } diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go index 7835b492f7..296f6a39c1 100644 --- a/src/runtime/syscall_windows.go +++ b/src/runtime/syscall_windows.go @@ -276,6 +276,8 @@ func syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (hand } cgocall(asmstdcallAddr, unsafe.Pointer(c)) + KeepAlive(filename) + KeepAlive(absoluteFilepath) handle = c.r1 if handle == 0 { err = c.err @@ -294,6 +296,7 @@ func syscall_loadlibrary(filename *uint16) (handle, err uintptr) { c.n = 1 c.args = uintptr(noescape(unsafe.Pointer(&filename))) cgocall(asmstdcallAddr, unsafe.Pointer(c)) + KeepAlive(filename) handle = c.r1 if handle == 0 { err = c.err @@ -311,6 +314,7 @@ func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uint c.n = 2 c.args = uintptr(noescape(unsafe.Pointer(&handle))) cgocall(asmstdcallAddr, unsafe.Pointer(c)) + KeepAlive(procname) outhandle = c.r1 if outhandle == 0 { err = c.err diff --git a/src/time/time.go b/src/time/time.go index 8ae62308e5..c8f8b9081a 100644 --- a/src/time/time.go +++ b/src/time/time.go @@ -1373,17 +1373,17 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T unix := int64(abs) + (absoluteToInternal + internalToUnix) - // Look for zone offset for t, so we can adjust to UTC. - // The lookup function expects UTC, so we pass t in the + // Look for zone offset for expected time, so we can adjust to UTC. + // The lookup function expects UTC, so first we pass unix in the // hope that it will not be too close to a zone transition, // and then adjust if it is. _, offset, start, end := loc.lookup(unix) if offset != 0 { - switch utc := unix - int64(offset); { - case utc < start: - _, offset, _, _ = loc.lookup(start - 1) - case utc >= end: - _, offset, _, _ = loc.lookup(end) + utc := unix - int64(offset) + // If utc is valid for the time zone we found, then we have the right offset. + // If not, we get the correct offset by looking up utc in the location. + if utc < start || utc >= end { + _, offset, _, _ = loc.lookup(utc) } unix -= int64(offset) } diff --git a/src/time/time_test.go b/src/time/time_test.go index 154198a1ce..d1b9e764f5 100644 --- a/src/time/time_test.go +++ b/src/time/time_test.go @@ -1465,3 +1465,45 @@ func TestConcurrentTimerResetStop(t *testing.T) { } wg.Wait() } + +// Issue 49284: time: ParseInLocation incorrectly because of Daylight Saving Time +func TestTimeWithZoneTransition(t *testing.T) { + ForceZipFileForTesting(true) + defer ForceZipFileForTesting(false) + + loc, err := LoadLocation("Asia/Shanghai") + if err != nil { + t.Fatal(err) + } + + tests := [...]struct { + give Time + want Time + }{ + // 14 Apr 1991 - Daylight Saving Time Started + // When time of "Asia/Shanghai" was about to reach + // Sunday, 14 April 1991, 02:00:00 clocks were turned forward 1 hour to + // Sunday, 14 April 1991, 03:00:00 local daylight time instead. + // The UTC time was 13 April 1991, 18:00:00 + 0: {Date(1991, April, 13, 17, 50, 0, 0, loc), Date(1991, April, 13, 9, 50, 0, 0, UTC)}, + 1: {Date(1991, April, 13, 18, 0, 0, 0, loc), Date(1991, April, 13, 10, 0, 0, 0, UTC)}, + 2: {Date(1991, April, 14, 1, 50, 0, 0, loc), Date(1991, April, 13, 17, 50, 0, 0, UTC)}, + 3: {Date(1991, April, 14, 3, 0, 0, 0, loc), Date(1991, April, 13, 18, 0, 0, 0, UTC)}, + + // 15 Sep 1991 - Daylight Saving Time Ended + // When local daylight time of "Asia/Shanghai" was about to reach + // Sunday, 15 September 1991, 02:00:00 clocks were turned backward 1 hour to + // Sunday, 15 September 1991, 01:00:00 local standard time instead. + // The UTC time was 14 September 1991, 17:00:00 + 4: {Date(1991, September, 14, 16, 50, 0, 0, loc), Date(1991, September, 14, 7, 50, 0, 0, UTC)}, + 5: {Date(1991, September, 14, 17, 0, 0, 0, loc), Date(1991, September, 14, 8, 0, 0, 0, UTC)}, + 6: {Date(1991, September, 15, 0, 50, 0, 0, loc), Date(1991, September, 14, 15, 50, 0, 0, UTC)}, + 7: {Date(1991, September, 15, 2, 00, 0, 0, loc), Date(1991, September, 14, 18, 00, 0, 0, UTC)}, + } + + for i, tt := range tests { + if !tt.give.Equal(tt.want) { + t.Errorf("#%d:: %#v is not equal to %#v", i, tt.give.Format(RFC3339), tt.want.Format(RFC3339)) + } + } +} diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index a3768fd589..652d4d07d2 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519 golang.org/x/crypto/hkdf golang.org/x/crypto/internal/subtle golang.org/x/crypto/poly1305 -# golang.org/x/net v0.0.0-20211101194150-d8c3cde3c676 +# golang.org/x/net v0.0.0-20211201233224-64539c132272 ## explicit golang.org/x/net/dns/dnsmessage golang.org/x/net/http/httpguts diff --git a/test/fixedbugs/issue49249.go b/test/fixedbugs/issue49249.go new file mode 100644 index 0000000000..f152a5a701 --- /dev/null +++ b/test/fixedbugs/issue49249.go @@ -0,0 +1,55 @@ +// compile -l + +// Copyright 2021 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 + +func f() int { + var a, b struct { + s struct { + s struct { + byte + float32 + } + } + } + _ = a + + return func() int { + return func() int { + a = struct { + s struct { + s struct { + byte + float32 + } + } + }{b.s} + return 0 + }() + }() +} + +func g() int { + var a, b struct { + s [1][1]struct { + byte + float32 + } + } + _ = a + + return func() int { + return func() int { + a = struct { + s [1][1]struct { + byte + float32 + } + }{b.s} + return 0 + }() + }() +} diff --git a/test/fixedbugs/issue49378.go b/test/fixedbugs/issue49378.go new file mode 100644 index 0000000000..70f466c929 --- /dev/null +++ b/test/fixedbugs/issue49378.go @@ -0,0 +1,25 @@ +// compile + +// Copyright 2021 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 + +func f(i int) { + var s1 struct { + s struct{ s struct{ i int } } + } + var s2, s3 struct { + a struct{ i int } + b int + } + func() { + i = 1 + 2*i + s3.a.i + func() int { + s2.a, s2.b = s3.a, s3.b + return 0 + }() + func(*int) int { + return s1.s.s.i + }(new(int)) + }() +} |