Update to go1.25.1
This commit is contained in:
4
VERSION
4
VERSION
@@ -1,2 +1,2 @@
|
||||
go1.25.0
|
||||
time 2025-08-08T19:33:32Z
|
||||
go1.25.1
|
||||
time 2025-08-27T15:49:40Z
|
||||
|
||||
@@ -109,6 +109,9 @@ func ModIsPrefix(path, vers string) bool {
|
||||
// The caller is assumed to have checked that ModIsValid(path, vers) is true.
|
||||
func ModIsPrerelease(path, vers string) bool {
|
||||
if IsToolchain(path) {
|
||||
if path == "toolchain" {
|
||||
return IsPrerelease(FromToolchain(vers))
|
||||
}
|
||||
return IsPrerelease(vers)
|
||||
}
|
||||
return semver.Prerelease(vers) != ""
|
||||
|
||||
10
src/cmd/go/testdata/script/mod_get_toolchain.txt
vendored
10
src/cmd/go/testdata/script/mod_get_toolchain.txt
vendored
@@ -94,12 +94,14 @@ stderr '^go: added toolchain go1.24rc1$'
|
||||
grep 'go 1.22.9' go.mod # no longer implied
|
||||
grep 'toolchain go1.24rc1' go.mod
|
||||
|
||||
# go get toolchain@latest finds go1.999testmod.
|
||||
# go get toolchain@latest finds go1.23.9.
|
||||
cp go.mod.orig go.mod
|
||||
go get toolchain@latest
|
||||
stderr '^go: added toolchain go1.999testmod$'
|
||||
stderr '^go: added toolchain go1.23.9$'
|
||||
grep 'go 1.21' go.mod
|
||||
grep 'toolchain go1.999testmod' go.mod
|
||||
grep 'toolchain go1.23.9' go.mod
|
||||
|
||||
|
||||
|
||||
# Bug fixes.
|
||||
|
||||
@@ -115,7 +117,7 @@ stderr '^go: upgraded go 1.19 => 1.21.0'
|
||||
|
||||
# go get toolchain@1.24rc1 is OK too.
|
||||
go get toolchain@1.24rc1
|
||||
stderr '^go: downgraded toolchain go1.999testmod => go1.24rc1$'
|
||||
stderr '^go: upgraded toolchain go1.23.9 => go1.24rc1$'
|
||||
|
||||
# go get go@1.21 should work if we are the Go 1.21 language version,
|
||||
# even though there's no toolchain for it.
|
||||
|
||||
@@ -1106,6 +1106,12 @@ func (fd *FD) Seek(offset int64, whence int) (int64, error) {
|
||||
fd.l.Lock()
|
||||
defer fd.l.Unlock()
|
||||
|
||||
if !fd.isBlocking && whence == io.SeekCurrent {
|
||||
// Windows doesn't keep the file pointer for overlapped file handles.
|
||||
// We do it ourselves in case to account for any read or write
|
||||
// operations that may have occurred.
|
||||
offset += fd.offset
|
||||
}
|
||||
n, err := syscall.Seek(fd.Sysfd, offset, whence)
|
||||
fd.setOffset(n)
|
||||
return n, err
|
||||
|
||||
@@ -383,34 +383,34 @@ func TestChannelMovedOutOfBubble(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
desc string
|
||||
f func(chan struct{})
|
||||
wantPanic string
|
||||
wantFatal string
|
||||
}{{
|
||||
desc: "receive",
|
||||
f: func(ch chan struct{}) {
|
||||
<-ch
|
||||
},
|
||||
wantPanic: "receive on synctest channel from outside bubble",
|
||||
wantFatal: "receive on synctest channel from outside bubble",
|
||||
}, {
|
||||
desc: "send",
|
||||
f: func(ch chan struct{}) {
|
||||
ch <- struct{}{}
|
||||
},
|
||||
wantPanic: "send on synctest channel from outside bubble",
|
||||
wantFatal: "send on synctest channel from outside bubble",
|
||||
}, {
|
||||
desc: "close",
|
||||
f: func(ch chan struct{}) {
|
||||
close(ch)
|
||||
},
|
||||
wantPanic: "close of synctest channel from outside bubble",
|
||||
wantFatal: "close of synctest channel from outside bubble",
|
||||
}} {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
// Bubbled channel accessed from outside any bubble.
|
||||
t.Run("outside_bubble", func(t *testing.T) {
|
||||
wantFatal(t, test.wantFatal, func() {
|
||||
donec := make(chan struct{})
|
||||
ch := make(chan chan struct{})
|
||||
go func() {
|
||||
defer close(donec)
|
||||
defer wantPanic(t, test.wantPanic)
|
||||
test.f(<-ch)
|
||||
}()
|
||||
synctest.Run(func() {
|
||||
@@ -418,15 +418,16 @@ func TestChannelMovedOutOfBubble(t *testing.T) {
|
||||
})
|
||||
<-donec
|
||||
})
|
||||
})
|
||||
// Bubbled channel accessed from a different bubble.
|
||||
t.Run("different_bubble", func(t *testing.T) {
|
||||
wantFatal(t, test.wantFatal, func() {
|
||||
donec := make(chan struct{})
|
||||
ch := make(chan chan struct{})
|
||||
go func() {
|
||||
defer close(donec)
|
||||
c := <-ch
|
||||
synctest.Run(func() {
|
||||
defer wantPanic(t, test.wantPanic)
|
||||
test.f(c)
|
||||
})
|
||||
}()
|
||||
@@ -436,6 +437,7 @@ func TestChannelMovedOutOfBubble(t *testing.T) {
|
||||
<-donec
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,32 +445,32 @@ func TestTimerFromInsideBubble(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
desc string
|
||||
f func(tm *time.Timer)
|
||||
wantPanic string
|
||||
wantFatal string
|
||||
}{{
|
||||
desc: "read channel",
|
||||
f: func(tm *time.Timer) {
|
||||
<-tm.C
|
||||
},
|
||||
wantPanic: "receive on synctest channel from outside bubble",
|
||||
wantFatal: "receive on synctest channel from outside bubble",
|
||||
}, {
|
||||
desc: "Reset",
|
||||
f: func(tm *time.Timer) {
|
||||
tm.Reset(1 * time.Second)
|
||||
},
|
||||
wantPanic: "reset of synctest timer from outside bubble",
|
||||
wantFatal: "reset of synctest timer from outside bubble",
|
||||
}, {
|
||||
desc: "Stop",
|
||||
f: func(tm *time.Timer) {
|
||||
tm.Stop()
|
||||
},
|
||||
wantPanic: "stop of synctest timer from outside bubble",
|
||||
wantFatal: "stop of synctest timer from outside bubble",
|
||||
}} {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
wantFatal(t, test.wantFatal, func() {
|
||||
donec := make(chan struct{})
|
||||
ch := make(chan *time.Timer)
|
||||
go func() {
|
||||
defer close(donec)
|
||||
defer wantPanic(t, test.wantPanic)
|
||||
test.f(<-ch)
|
||||
}()
|
||||
synctest.Run(func() {
|
||||
@@ -477,6 +479,7 @@ func TestTimerFromInsideBubble(t *testing.T) {
|
||||
})
|
||||
<-donec
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,13 +77,21 @@ func (c *CrossOriginProtection) AddTrustedOrigin(origin string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var noopHandler = HandlerFunc(func(w ResponseWriter, r *Request) {})
|
||||
type noopHandler struct{}
|
||||
|
||||
func (noopHandler) ServeHTTP(ResponseWriter, *Request) {}
|
||||
|
||||
var sentinelHandler Handler = &noopHandler{}
|
||||
|
||||
// AddInsecureBypassPattern permits all requests that match the given pattern.
|
||||
// The pattern syntax and precedence rules are the same as [ServeMux].
|
||||
//
|
||||
// AddInsecureBypassPattern can be called concurrently with other methods
|
||||
// or request handling, and applies to future requests.
|
||||
// The pattern syntax and precedence rules are the same as [ServeMux]. Only
|
||||
// requests that match the pattern directly are permitted. Those that ServeMux
|
||||
// would redirect to a pattern (e.g. after cleaning the path or adding a
|
||||
// trailing slash) are not.
|
||||
//
|
||||
// AddInsecureBypassPattern can be called concurrently with other methods or
|
||||
// request handling, and applies to future requests.
|
||||
func (c *CrossOriginProtection) AddInsecureBypassPattern(pattern string) {
|
||||
var bypass *ServeMux
|
||||
|
||||
@@ -99,7 +107,7 @@ func (c *CrossOriginProtection) AddInsecureBypassPattern(pattern string) {
|
||||
}
|
||||
}
|
||||
|
||||
bypass.Handle(pattern, noopHandler)
|
||||
bypass.Handle(pattern, sentinelHandler)
|
||||
}
|
||||
|
||||
// SetDenyHandler sets a handler to invoke when a request is rejected.
|
||||
@@ -172,7 +180,7 @@ var (
|
||||
// be deferred until the last moment.
|
||||
func (c *CrossOriginProtection) isRequestExempt(req *Request) bool {
|
||||
if bypass := c.bypass.Load(); bypass != nil {
|
||||
if _, pattern := bypass.Handler(req); pattern != "" {
|
||||
if h, _ := bypass.Handler(req); h == sentinelHandler {
|
||||
// The request matches a bypass pattern.
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -113,6 +113,11 @@ func TestCrossOriginProtectionPatternBypass(t *testing.T) {
|
||||
protection := http.NewCrossOriginProtection()
|
||||
protection.AddInsecureBypassPattern("/bypass/")
|
||||
protection.AddInsecureBypassPattern("/only/{foo}")
|
||||
protection.AddInsecureBypassPattern("/no-trailing")
|
||||
protection.AddInsecureBypassPattern("/yes-trailing/")
|
||||
protection.AddInsecureBypassPattern("PUT /put-only/")
|
||||
protection.AddInsecureBypassPattern("GET /get-only/")
|
||||
protection.AddInsecureBypassPattern("POST /post-only/")
|
||||
handler := protection.Handler(okHandler)
|
||||
|
||||
tests := []struct {
|
||||
@@ -126,13 +131,23 @@ func TestCrossOriginProtectionPatternBypass(t *testing.T) {
|
||||
{"non-bypass path without sec-fetch-site", "/api/", "", http.StatusForbidden},
|
||||
{"non-bypass path with cross-site", "/api/", "cross-site", http.StatusForbidden},
|
||||
|
||||
{"redirect to bypass path without ..", "/foo/../bypass/bar", "", http.StatusOK},
|
||||
{"redirect to bypass path with trailing slash", "/bypass", "", http.StatusOK},
|
||||
{"redirect to bypass path without ..", "/foo/../bypass/bar", "", http.StatusForbidden},
|
||||
{"redirect to bypass path with trailing slash", "/bypass", "", http.StatusForbidden},
|
||||
{"redirect to non-bypass path with ..", "/foo/../api/bar", "", http.StatusForbidden},
|
||||
{"redirect to non-bypass path with trailing slash", "/api", "", http.StatusForbidden},
|
||||
|
||||
{"wildcard bypass", "/only/123", "", http.StatusOK},
|
||||
{"non-wildcard", "/only/123/foo", "", http.StatusForbidden},
|
||||
|
||||
// https://go.dev/issue/75054
|
||||
{"no trailing slash exact match", "/no-trailing", "", http.StatusOK},
|
||||
{"no trailing slash with slash", "/no-trailing/", "", http.StatusForbidden},
|
||||
{"yes trailing slash exact match", "/yes-trailing/", "", http.StatusOK},
|
||||
{"yes trailing slash without slash", "/yes-trailing", "", http.StatusForbidden},
|
||||
|
||||
{"method-specific hit", "/post-only/", "", http.StatusOK},
|
||||
{"method-specific miss (PUT)", "/put-only/", "", http.StatusForbidden},
|
||||
{"method-specific miss (GET)", "/get-only/", "", http.StatusForbidden},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
||||
@@ -237,8 +237,12 @@ func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, e
|
||||
func addrPortToSockaddrInet4(ap netip.AddrPort) (syscall.SockaddrInet4, error) {
|
||||
// ipToSockaddrInet4 has special handling here for zero length slices.
|
||||
// We do not, because netip has no concept of a generic zero IP address.
|
||||
//
|
||||
// addr is allowed to be an IPv4-mapped IPv6 address.
|
||||
// As4 will unmap it to an IPv4 address.
|
||||
// The error message is kept consistent with ipToSockaddrInet4.
|
||||
addr := ap.Addr()
|
||||
if !addr.Is4() {
|
||||
if !addr.Is4() && !addr.Is4In6() {
|
||||
return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: addr.String()}
|
||||
}
|
||||
sa := syscall.SockaddrInet4{
|
||||
|
||||
@@ -705,3 +705,35 @@ func TestIPv6WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion verifies that
|
||||
// WriteMsgUDPAddrPort accepts IPv4 and IPv4-mapped IPv6 destination addresses,
|
||||
// and rejects IPv6 destination addresses on a "udp4" connection.
|
||||
func TestIPv4WriteMsgUDPAddrPortTargetAddrIPVersion(t *testing.T) {
|
||||
if !testableNetwork("udp4") {
|
||||
t.Skipf("skipping: udp4 not available")
|
||||
}
|
||||
|
||||
conn, err := ListenUDP("udp4", &UDPAddr{IP: IPv4(127, 0, 0, 1)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
daddr4 := netip.AddrPortFrom(netip.MustParseAddr("127.0.0.1"), 12345)
|
||||
daddr4in6 := netip.AddrPortFrom(netip.MustParseAddr("::ffff:127.0.0.1"), 12345)
|
||||
daddr6 := netip.AddrPortFrom(netip.MustParseAddr("::1"), 12345)
|
||||
buf := make([]byte, 8)
|
||||
|
||||
if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4); err != nil {
|
||||
t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4) failed: %v", err)
|
||||
}
|
||||
|
||||
if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6); err != nil {
|
||||
t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr4in6) failed: %v", err)
|
||||
}
|
||||
|
||||
if _, _, err = conn.WriteMsgUDPAddrPort(buf, nil, daddr6); err == nil {
|
||||
t.Errorf("conn.WriteMsgUDPAddrPort(buf, nil, daddr6) should have failed, but got no error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func findExecutable(file string) error {
|
||||
// As of Go 1.19, LookPath will instead return that path along with an error satisfying
|
||||
// [errors.Is](err, [ErrDot]). See the package documentation for more details.
|
||||
func LookPath(file string) (string, error) {
|
||||
if err := validateLookPath(file); err != nil {
|
||||
if err := validateLookPath(filepath.Clean(file)); err != nil {
|
||||
return "", &Error{file, err}
|
||||
}
|
||||
|
||||
|
||||
@@ -1845,6 +1845,44 @@ func TestFile(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileOverlappedSeek(t *testing.T) {
|
||||
t.Parallel()
|
||||
name := filepath.Join(t.TempDir(), "foo")
|
||||
f := newFileOverlapped(t, name, true)
|
||||
content := []byte("foo")
|
||||
if _, err := f.Write(content); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Check that the file pointer is at the expected offset.
|
||||
n, err := f.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != int64(len(content)) {
|
||||
t.Errorf("expected file pointer to be at offset %d, got %d", len(content), n)
|
||||
}
|
||||
// Set the file pointer to the start of the file.
|
||||
if _, err := f.Seek(0, io.SeekStart); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Read the first byte.
|
||||
var buf [1]byte
|
||||
if _, err := f.Read(buf[:]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(buf[:], content[:len(buf)]) {
|
||||
t.Errorf("expected %q, got %q", content[:len(buf)], buf[:])
|
||||
}
|
||||
// Check that the file pointer is at the expected offset.
|
||||
n, err = f.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != int64(len(buf)) {
|
||||
t.Errorf("expected file pointer to be at offset %d, got %d", len(buf), n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipe(t *testing.T) {
|
||||
t.Parallel()
|
||||
r, w, err := os.Pipe()
|
||||
|
||||
@@ -191,7 +191,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
|
||||
}
|
||||
|
||||
if c.bubble != nil && getg().bubble != c.bubble {
|
||||
panic(plainError("send on synctest channel from outside bubble"))
|
||||
fatal("send on synctest channel from outside bubble")
|
||||
}
|
||||
|
||||
// Fast path: check for failed non-blocking operation without acquiring the lock.
|
||||
@@ -318,7 +318,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
|
||||
func send(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func(), skip int) {
|
||||
if c.bubble != nil && getg().bubble != c.bubble {
|
||||
unlockf()
|
||||
panic(plainError("send on synctest channel from outside bubble"))
|
||||
fatal("send on synctest channel from outside bubble")
|
||||
}
|
||||
if raceenabled {
|
||||
if c.dataqsiz == 0 {
|
||||
@@ -416,7 +416,7 @@ func closechan(c *hchan) {
|
||||
panic(plainError("close of nil channel"))
|
||||
}
|
||||
if c.bubble != nil && getg().bubble != c.bubble {
|
||||
panic(plainError("close of synctest channel from outside bubble"))
|
||||
fatal("close of synctest channel from outside bubble")
|
||||
}
|
||||
|
||||
lock(&c.lock)
|
||||
@@ -538,7 +538,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
|
||||
}
|
||||
|
||||
if c.bubble != nil && getg().bubble != c.bubble {
|
||||
panic(plainError("receive on synctest channel from outside bubble"))
|
||||
fatal("receive on synctest channel from outside bubble")
|
||||
}
|
||||
|
||||
if c.timer != nil {
|
||||
@@ -702,7 +702,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
|
||||
func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func(), skip int) {
|
||||
if c.bubble != nil && getg().bubble != c.bubble {
|
||||
unlockf()
|
||||
panic(plainError("receive on synctest channel from outside bubble"))
|
||||
fatal("receive on synctest channel from outside bubble")
|
||||
}
|
||||
if c.dataqsiz == 0 {
|
||||
if raceenabled {
|
||||
|
||||
@@ -178,7 +178,7 @@ func selectgo(cas0 *scase, order0 *uint16, pc0 *uintptr, nsends, nrecvs int, blo
|
||||
|
||||
if cas.c.bubble != nil {
|
||||
if getg().bubble != cas.c.bubble {
|
||||
panic(plainError("select on synctest channel from outside bubble"))
|
||||
fatal("select on synctest channel from outside bubble")
|
||||
}
|
||||
} else {
|
||||
allSynctest = false
|
||||
|
||||
@@ -415,7 +415,7 @@ func newTimer(when, period int64, f func(arg any, seq uintptr, delay int64), arg
|
||||
//go:linkname stopTimer time.stopTimer
|
||||
func stopTimer(t *timeTimer) bool {
|
||||
if t.isFake && getg().bubble == nil {
|
||||
panic("stop of synctest timer from outside bubble")
|
||||
fatal("stop of synctest timer from outside bubble")
|
||||
}
|
||||
return t.stop()
|
||||
}
|
||||
@@ -430,7 +430,7 @@ func resetTimer(t *timeTimer, when, period int64) bool {
|
||||
racerelease(unsafe.Pointer(&t.timer))
|
||||
}
|
||||
if t.isFake && getg().bubble == nil {
|
||||
panic("reset of synctest timer from outside bubble")
|
||||
fatal("reset of synctest timer from outside bubble")
|
||||
}
|
||||
return t.reset(when, period)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user