3 Commits

Author SHA1 Message Date
Vorapol Rinsatitnon
98c5110178 Update to go1.25.1 2025-09-08 17:34:02 +07:00
Vorapol Rinsatitnon
59840a035a Update README.md 2025-08-26 16:03:58 +07:00
Vorapol Rinsatitnon
ada6955fd4 Add patch 6 2025-08-26 15:29:17 +07:00
16 changed files with 315 additions and 73 deletions

View File

@@ -31,6 +31,7 @@ Every release includes the following modifications:
- Added back Windows 7 console handle workaround (reverted [48042aa](https://github.com/golang/go/commit/48042aa09c2f878c4faa576948b07fe625c4707a))
- Added back 5ms sleep on Windows 7/8 in (\*Process).Wait (reverted [f0894a0](https://github.com/golang/go/commit/f0894a00f4b756d4b9b4078af2e686b359493583))
- Restored deprecated `go get` behavior for use outside modules (reverted [de4d503](https://github.com/golang/go/commit/de4d50316fb5c6d1529aa5377dc93b26021ee843))
- Reverted to the previous `removeall_noat` variant for Windows (fixed [issue #2](https://github.com/thongtech/go-legacy-win7/issues/2))
- Includes all improvements and bug fixes from the corresponding upstream Go release
The Windows binary provided here also supports Windows 7 and Windows Server 2008 R2
@@ -41,15 +42,15 @@ The Windows binary provided here also supports Windows 7 and Windows Server 2008
| OS | Architecture | Filename | SHA256 Hash |
|----|--------------|----------|--------------|
| **macOS** | Intel (amd64) | [go-legacy-win7-1.25.0-1.darwin_amd64.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-1/go-legacy-win7-1.25.0-1.darwin_amd64.tar.gz) | `b5f0946d1c4c686e4569de062f23c015be6fe6d18fea424fb05c27f4ebd412aa` |
| macOS | Apple (ARM64) | [go-legacy-win7-1.25.0-1.darwin_arm64.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-1/go-legacy-win7-1.25.0-1.darwin_arm64.tar.gz) | `6888f1e1bb4436f5478abbf609313f242abe3810c2e77b8184a266e5e21fc8dc` |
| **Linux** | x86 (386) | [go-legacy-win7-1.25.0-1.linux_386.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-1/go-legacy-win7-1.25.0-1.linux_386.tar.gz) | `00e733607ea4ebb031eb0db12f72ff3e9c082477d5a23de5098cf13449e73090` |
| Linux | x64 (amd64) | [go-legacy-win7-1.25.0-1.linux_amd64.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-1/go-legacy-win7-1.25.0-1.linux_amd64.tar.gz) | `9cd208562e00ca0fd4244b59a0e2fb27e332688a21ef45b33a64c297aba33c2f` |
| Linux | ARM (32bit) | [go-legacy-win7-1.25.0-1.linux_arm.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-1/go-legacy-win7-1.25.0-1.linux_arm.tar.gz) | `f5367fbfee04259d259d0667bb0caeff5c21c8661e00756c6a399ccbbf00ad0f` |
| Linux | ARM64 | [go-legacy-win7-1.25.0-1.linux_arm64.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-1/go-legacy-win7-1.25.0-1.linux_arm64.tar.gz) | `21b38c51be22d5a26769602bf1d0646f3953840313f0c6ab2dd8d622960e1f3e` |
| **Windows** | x86 (386) | [go-legacy-win7-1.25.0-1.windows_386.zip](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-1/go-legacy-win7-1.25.0-1.windows_386.zip) | `43c1b46dbaf462a16a7cd33d258fa095e34a7a570299a4f6cf95d2fb511974d8` |
| Windows | x64 (amd64) | [go-legacy-win7-1.25.0-1.windows_amd64.zip](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-1/go-legacy-win7-1.25.0-1.windows_amd64.zip) | `cfd5538cd914c393d5fa90d2cb6054a478e588dcb29d86f6442c080310094773` |
| Windows | ARM64 | [go-legacy-win7-1.25.0-1.windows_arm64.zip](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-1/go-legacy-win7-1.25.0-1.windows_arm64.zip) | `a998931fa385261f50fc48ab1131a3ed420d5e800dc9022a16944af51282db78` |
| **macOS** | Intel (amd64) | [go-legacy-win7-1.25.0-2.darwin_amd64.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-2/go-legacy-win7-1.25.0-2.darwin_amd64.tar.gz) | `2f3d1089b1770f2ea5f803cb95841da7a08a7f4b8f5c8cbe8889372fd29ca7fa` |
| macOS | Apple (ARM64) | [go-legacy-win7-1.25.0-2.darwin_arm64.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-2/go-legacy-win7-1.25.0-2.darwin_arm64.tar.gz) | `f56f5bf1dc7e41aa7af16cdfa6829292ce46a1ed32b3d481528670a9fafd78d7` |
| **Linux** | x86 (386) | [go-legacy-win7-1.25.0-2.linux_386.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-2/go-legacy-win7-1.25.0-2.linux_386.tar.gz) | `6fceeb092e1f30661bf50f20a7c671e893b3cd6de5aa566a4a4ef672fd12c5b0` |
| Linux | x64 (amd64) | [go-legacy-win7-1.25.0-2.linux_amd64.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-2/go-legacy-win7-1.25.0-2.linux_amd64.tar.gz) | `21546d98267d4650096d9ec447480b516e0242bcec8de95a18b0f28ed53e393e` |
| Linux | ARM (32bit) | [go-legacy-win7-1.25.0-2.linux_arm.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-2/go-legacy-win7-1.25.0-2.linux_arm.tar.gz) | `3b5465afa3cd011926b7168dd4abe5d75c55ef03ce165c7b88e07a79b3dca6cc` |
| Linux | ARM64 | [go-legacy-win7-1.25.0-2.linux_arm64.tar.gz](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-2/go-legacy-win7-1.25.0-2.linux_arm64.tar.gz) | `b103720b046a88e826df741bc979daa3343c95d734f36b8d556897a5acda1c84` |
| **Windows** | x86 (386) | [go-legacy-win7-1.25.0-2.windows_386.zip](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-2/go-legacy-win7-1.25.0-2.windows_386.zip) | `0f0a8f4e68ffbadb99ee60779efed148e629410208633ff59bfc2bf7de988aa8` |
| Windows | x64 (amd64) | [go-legacy-win7-1.25.0-2.windows_amd64.zip](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-2/go-legacy-win7-1.25.0-2.windows_amd64.zip) | `ce54380d04fc395ed0eeaec49ebcad049d92d4d274d23d1d192cb7e897ad4be2` |
| Windows | ARM64 | [go-legacy-win7-1.25.0-2.windows_arm64.zip](https://github.com/thongtech/go-legacy-win7/releases/download/v1.25.0-2/go-legacy-win7-1.25.0-2.windows_arm64.zip) | `35fdd7d381377d34e019d66795574379b4da8634a5ce3d226e0d8d2a5d9d101c` |
### Before you begin
To avoid PATH/GOROOT conflicts and mixed toolchains, uninstall any existing Go installation first.

View File

@@ -1,2 +1,2 @@
go1.25.0
time 2025-08-08T19:33:32Z
go1.25.1
time 2025-08-27T15:49:40Z

View File

@@ -0,0 +1,130 @@
From c0f79a96a0262b2dd69d1a85e20b481d03cba8f2 Mon Sep 17 00:00:00 2001
From: Vorapol Rinsatitnon <vorapol.r@pm.me>
Date: Tue, 26 Aug 2025 15:07:25 +0700
Subject: [PATCH] Use removeall_noat variant on Windows
---
src/os/removeall_at.go | 2 +-
src/os/removeall_noat.go | 2 +-
src/os/root.go | 6 ------
src/os/root_noopenat.go | 20 --------------------
src/os/root_openat.go | 22 ----------------------
5 files changed, 2 insertions(+), 50 deletions(-)
diff --git a/src/os/removeall_at.go b/src/os/removeall_at.go
index 5ddc1ade..61298a46 100644
--- a/src/os/removeall_at.go
+++ b/src/os/removeall_at.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix || wasip1 || windows
+//go:build unix || wasip1
package os
diff --git a/src/os/removeall_noat.go b/src/os/removeall_noat.go
index 395a1503..02f6fca7 100644
--- a/src/os/removeall_noat.go
+++ b/src/os/removeall_noat.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (js && wasm) || plan9
+//go:build (js && wasm) || plan9 || windows
package os
diff --git a/src/os/root.go b/src/os/root.go
index d759727c..1ecbcc09 100644
--- a/src/os/root.go
+++ b/src/os/root.go
@@ -189,12 +189,6 @@ func (r *Root) Remove(name string) error {
return rootRemove(r, name)
}
-// RemoveAll removes the named file or directory and any children that it contains.
-// See [RemoveAll] for more details.
-func (r *Root) RemoveAll(name string) error {
- return rootRemoveAll(r, name)
-}
-
// Stat returns a [FileInfo] describing the named file in the root.
// See [Stat] for more details.
func (r *Root) Stat(name string) (FileInfo, error) {
diff --git a/src/os/root_noopenat.go b/src/os/root_noopenat.go
index 59f1abe9..ecdf264f 100644
--- a/src/os/root_noopenat.go
+++ b/src/os/root_noopenat.go
@@ -11,7 +11,6 @@ import (
"internal/filepathlite"
"internal/stringslite"
"sync/atomic"
- "syscall"
"time"
)
@@ -186,25 +185,6 @@ func rootRemove(r *Root, name string) error {
return nil
}
-func rootRemoveAll(r *Root, name string) error {
- if endsWithDot(name) {
- // Consistency with os.RemoveAll: Return EINVAL when trying to remove .
- return &PathError{Op: "RemoveAll", Path: name, Err: syscall.EINVAL}
- }
- if err := checkPathEscapesLstat(r, name); err != nil {
- if err == syscall.ENOTDIR {
- // Some intermediate path component is not a directory.
- // RemoveAll treats this as success (since the target doesn't exist).
- return nil
- }
- return &PathError{Op: "RemoveAll", Path: name, Err: err}
- }
- if err := RemoveAll(joinPath(r.root.name, name)); err != nil {
- return &PathError{Op: "RemoveAll", Path: name, Err: underlyingError(err)}
- }
- return nil
-}
-
func rootReadlink(r *Root, name string) (string, error) {
if err := checkPathEscapesLstat(r, name); err != nil {
return "", &PathError{Op: "readlinkat", Path: name, Err: err}
diff --git a/src/os/root_openat.go b/src/os/root_openat.go
index e433bd50..cfc6d906 100644
--- a/src/os/root_openat.go
+++ b/src/os/root_openat.go
@@ -194,28 +194,6 @@ func rootRemove(r *Root, name string) error {
return nil
}
-func rootRemoveAll(r *Root, name string) error {
- // Consistency with os.RemoveAll: Strip trailing /s from the name,
- // so RemoveAll("not_a_directory/") succeeds.
- for len(name) > 0 && IsPathSeparator(name[len(name)-1]) {
- name = name[:len(name)-1]
- }
- if endsWithDot(name) {
- // Consistency with os.RemoveAll: Return EINVAL when trying to remove .
- return &PathError{Op: "RemoveAll", Path: name, Err: syscall.EINVAL}
- }
- _, err := doInRoot(r, name, nil, func(parent sysfdType, name string) (struct{}, error) {
- return struct{}{}, removeAllFrom(parent, name)
- })
- if IsNotExist(err) {
- return nil
- }
- if err != nil {
- return &PathError{Op: "RemoveAll", Path: name, Err: underlyingError(err)}
- }
- return err
-}
-
func rootRename(r *Root, oldname, newname string) error {
_, err := doInRoot(r, oldname, nil, func(oldparent sysfdType, oldname string) (struct{}, error) {
_, err := doInRoot(r, newname, nil, func(newparent sysfdType, newname string) (struct{}, error) {
--
2.50.1.windows.1

View File

@@ -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) != ""

View File

@@ -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.

View File

@@ -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

View File

@@ -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
})
})
}
}

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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{

View File

@@ -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")
}
}

View File

@@ -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}
}

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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

View File

@@ -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)
}