From 911211578c25fd86fca7d1a967453ed8c8d85789 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sun, 21 Dec 2025 00:12:03 +0800 Subject: [PATCH] action: add Go 1.26rc1 to test --- .github/patch/go1.26.patch | 842 +++++++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 9 +- 2 files changed, 850 insertions(+), 1 deletion(-) create mode 100644 .github/patch/go1.26.patch diff --git a/.github/patch/go1.26.patch b/.github/patch/go1.26.patch new file mode 100644 index 00000000..29dab4d0 --- /dev/null +++ b/.github/patch/go1.26.patch @@ -0,0 +1,842 @@ +Subject: [PATCH] Fix os.RemoveAll not working on Windows7 +Revert "runtime: always use LoadLibraryEx to load system libraries" +Revert "syscall: remove Windows 7 console handle workaround" +Revert "net: remove sysSocket fallback for Windows 7" +Revert "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng" +--- +Index: src/crypto/internal/sysrand/rand_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/crypto/internal/sysrand/rand_windows.go b/src/crypto/internal/sysrand/rand_windows.go +--- a/src/crypto/internal/sysrand/rand_windows.go (revision c599a8f2385849a225d02843b3c6389dbfc5aa69) ++++ b/src/crypto/internal/sysrand/rand_windows.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) +@@ -7,5 +7,26 @@ + import "internal/syscall/windows" + + func read(b []byte) error { +- return windows.ProcessPrng(b) ++ // RtlGenRandom only returns 1<<32-1 bytes at a time. We only read at ++ // most 1<<31-1 bytes at a time so that this works the same on 32-bit ++ // and 64-bit systems. ++ return batched(windows.RtlGenRandom, 1<<31-1)(b) ++} ++ ++// batched returns a function that calls f to populate a []byte by chunking it ++// into subslices of, at most, readMax bytes. ++func batched(f func([]byte) error, readMax int) func([]byte) error { ++ return func(out []byte) error { ++ for len(out) > 0 { ++ read := len(out) ++ if read > readMax { ++ read = readMax ++ } ++ if err := f(out[:read]); err != nil { ++ return err ++ } ++ out = out[read:] ++ } ++ return nil ++ } + } +Index: src/crypto/rand/rand.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/crypto/rand/rand.go b/src/crypto/rand/rand.go +--- a/src/crypto/rand/rand.go (revision c599a8f2385849a225d02843b3c6389dbfc5aa69) ++++ b/src/crypto/rand/rand.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) +@@ -25,7 +25,7 @@ + // - On legacy Linux (< 3.17), Reader opens /dev/urandom on first use. + // - On macOS, iOS, and OpenBSD Reader, uses arc4random_buf(3). + // - On NetBSD, Reader uses the kern.arandom sysctl. +-// - On Windows, Reader uses the ProcessPrng API. ++// - On Windows systems, Reader uses the RtlGenRandom API. + // - On js/wasm, Reader uses the Web Crypto API. + // - On wasip1/wasm, Reader uses random_get. + // +Index: src/internal/syscall/windows/syscall_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go +--- a/src/internal/syscall/windows/syscall_windows.go (revision c599a8f2385849a225d02843b3c6389dbfc5aa69) ++++ b/src/internal/syscall/windows/syscall_windows.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) +@@ -421,7 +421,7 @@ + //sys DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock + //sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle syscall.Handle, err error) = kernel32.CreateEventW + +-//sys ProcessPrng(buf []byte) (err error) = bcryptprimitives.ProcessPrng ++//sys RtlGenRandom(buf []byte) (err error) = advapi32.SystemFunction036 + + type FILE_ID_BOTH_DIR_INFO struct { + NextEntryOffset uint32 +Index: src/internal/syscall/windows/zsyscall_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go +--- a/src/internal/syscall/windows/zsyscall_windows.go (revision c599a8f2385849a225d02843b3c6389dbfc5aa69) ++++ b/src/internal/syscall/windows/zsyscall_windows.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) +@@ -38,7 +38,6 @@ + + var ( + modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) +- modbcryptprimitives = syscall.NewLazyDLL(sysdll.Add("bcryptprimitives.dll")) + modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll")) + modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll")) + modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll")) +@@ -63,7 +62,7 @@ + procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") + procRevertToSelf = modadvapi32.NewProc("RevertToSelf") + procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") +- procProcessPrng = modbcryptprimitives.NewProc("ProcessPrng") ++ procSystemFunction036 = modadvapi32.NewProc("SystemFunction036") + procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") + procCreateEventW = modkernel32.NewProc("CreateEventW") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") +@@ -244,12 +243,12 @@ + return + } + +-func ProcessPrng(buf []byte) (err error) { ++func RtlGenRandom(buf []byte) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } +- r1, _, e1 := syscall.SyscallN(procProcessPrng.Addr(), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf))) ++ r1, _, e1 := syscall.SyscallN(procSystemFunction036.Addr(), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0) + if r1 == 0 { + err = errnoErr(e1) + } +Index: src/runtime/os_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go +--- a/src/runtime/os_windows.go (revision c599a8f2385849a225d02843b3c6389dbfc5aa69) ++++ b/src/runtime/os_windows.go (revision ea2726a6fa25fbfa1092e696e522eafca544d24c) +@@ -40,7 +40,8 @@ + //go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll" + //go:cgo_import_dynamic runtime._GetThreadContext GetThreadContext%2 "kernel32.dll" + //go:cgo_import_dynamic runtime._SetThreadContext SetThreadContext%2 "kernel32.dll" +-//go:cgo_import_dynamic runtime._LoadLibraryExW LoadLibraryExW%3 "kernel32.dll" ++//go:cgo_import_dynamic runtime._LoadLibraryW LoadLibraryW%1 "kernel32.dll" ++//go:cgo_import_dynamic runtime._LoadLibraryA LoadLibraryA%1 "kernel32.dll" + //go:cgo_import_dynamic runtime._PostQueuedCompletionStatus PostQueuedCompletionStatus%4 "kernel32.dll" + //go:cgo_import_dynamic runtime._QueryPerformanceCounter QueryPerformanceCounter%1 "kernel32.dll" + //go:cgo_import_dynamic runtime._QueryPerformanceFrequency QueryPerformanceFrequency%1 "kernel32.dll" +@@ -74,7 +75,6 @@ + // Following syscalls are available on every Windows PC. + // All these variables are set by the Windows executable + // loader before the Go program starts. +- _AddVectoredContinueHandler, + _AddVectoredExceptionHandler, + _CloseHandle, + _CreateEventA, +@@ -97,7 +97,8 @@ + _GetSystemInfo, + _GetThreadContext, + _SetThreadContext, +- _LoadLibraryExW, ++ _LoadLibraryW, ++ _LoadLibraryA, + _PostQueuedCompletionStatus, + _QueryPerformanceCounter, + _QueryPerformanceFrequency, +@@ -126,8 +127,23 @@ + _WriteFile, + _ stdFunction + +- // Use ProcessPrng to generate cryptographically random data. +- _ProcessPrng stdFunction ++ // Following syscalls are only available on some Windows PCs. ++ // We will load syscalls, if available, before using them. ++ _AddDllDirectory, ++ _AddVectoredContinueHandler, ++ _LoadLibraryExA, ++ _LoadLibraryExW, ++ _ stdFunction ++ ++ // Use RtlGenRandom to generate cryptographically random data. ++ // This approach has been recommended by Microsoft (see issue ++ // 15589 for details). ++ // The RtlGenRandom is not listed in advapi32.dll, instead ++ // RtlGenRandom function can be found by searching for SystemFunction036. ++ // Also some versions of Mingw cannot link to SystemFunction036 ++ // when building executable as Cgo. So load SystemFunction036 ++ // manually during runtime startup. ++ _RtlGenRandom stdFunction + + // Load ntdll.dll manually during startup, otherwise Mingw + // links wrong printf function to cgo executable (see issue +@@ -144,13 +160,6 @@ + _ stdFunction + ) + +-var ( +- bcryptprimitivesdll = [...]uint16{'b', 'c', 'r', 'y', 'p', 't', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 's', '.', 'd', 'l', 'l', 0} +- ntdlldll = [...]uint16{'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0} +- powrprofdll = [...]uint16{'p', 'o', 'w', 'r', 'p', 'r', 'o', 'f', '.', 'd', 'l', 'l', 0} +- winmmdll = [...]uint16{'w', 'i', 'n', 'm', 'm', '.', 'd', 'l', 'l', 0} +-) +- + // Function to be called by windows CreateThread + // to start new os thread. + func tstart_stdcall(newm *m) +@@ -242,9 +251,40 @@ + return unsafe.String(&sysDirectory[0], sysDirectoryLen) + } + +-func windowsLoadSystemLib(name []uint16) uintptr { +- const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 +- return stdcall(_LoadLibraryExW, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32) ++//go:linkname syscall_getSystemDirectory syscall.getSystemDirectory ++func syscall_getSystemDirectory() string { ++ return unsafe.String(&sysDirectory[0], sysDirectoryLen) ++} ++ ++func windowsLoadSystemLib(name []byte) uintptr { ++ if useLoadLibraryEx { ++ return stdcall(_LoadLibraryExA, uintptr(unsafe.Pointer(&name[0])), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32) ++ } else { ++ absName := append(sysDirectory[:sysDirectoryLen], name...) ++ return stdcall(_LoadLibraryA, uintptr(unsafe.Pointer(&absName[0]))) ++ } ++} ++ ++const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 ++ ++// When available, this function will use LoadLibraryEx with the filename ++// parameter and the important SEARCH_SYSTEM32 argument. But on systems that ++// do not have that option, absoluteFilepath should contain a fallback ++// to the full path inside of system32 for use with vanilla LoadLibrary. ++// ++//go:linkname syscall_loadsystemlibrary syscall.loadsystemlibrary ++func syscall_loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle, err uintptr) { ++ if useLoadLibraryEx { ++ handle, _, err = syscall_syscalln(uintptr(unsafe.Pointer(_LoadLibraryExW)), 3, uintptr(unsafe.Pointer(filename)), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32) ++ } else { ++ handle, _, err = syscall_syscalln(uintptr(unsafe.Pointer(_LoadLibraryW)), 1, uintptr(unsafe.Pointer(absoluteFilepath))) ++ } ++ KeepAlive(filename) ++ KeepAlive(absoluteFilepath) ++ if handle != 0 { ++ err = 0 ++ } ++ return + } + + //go:linkname windows_QueryPerformanceCounter internal/syscall/windows.QueryPerformanceCounter +@@ -262,13 +302,28 @@ + } + + func loadOptionalSyscalls() { +- bcryptPrimitives := windowsLoadSystemLib(bcryptprimitivesdll[:]) +- if bcryptPrimitives == 0 { +- throw("bcryptprimitives.dll not found") ++ var kernel32dll = []byte("kernel32.dll\000") ++ k32 := stdcall(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0]))) ++ if k32 == 0 { ++ throw("kernel32.dll not found") + } +- _ProcessPrng = windowsFindfunc(bcryptPrimitives, []byte("ProcessPrng\000")) ++ _AddDllDirectory = windowsFindfunc(k32, []byte("AddDllDirectory\000")) ++ _AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000")) ++ _LoadLibraryExA = windowsFindfunc(k32, []byte("LoadLibraryExA\000")) ++ _LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000")) ++ useLoadLibraryEx = (_LoadLibraryExW != nil && _LoadLibraryExA != nil && _AddDllDirectory != nil) ++ ++ initSysDirectory() + +- n32 := windowsLoadSystemLib(ntdlldll[:]) ++ var advapi32dll = []byte("advapi32.dll\000") ++ a32 := windowsLoadSystemLib(advapi32dll) ++ if a32 == 0 { ++ throw("advapi32.dll not found") ++ } ++ _RtlGenRandom = windowsFindfunc(a32, []byte("SystemFunction036\000")) ++ ++ var ntdll = []byte("ntdll.dll\000") ++ n32 := windowsLoadSystemLib(ntdll) + if n32 == 0 { + throw("ntdll.dll not found") + } +@@ -297,7 +352,7 @@ + context uintptr + } + +- powrprof := windowsLoadSystemLib(powrprofdll[:]) ++ powrprof := windowsLoadSystemLib([]byte("powrprof.dll\000")) + if powrprof == 0 { + return // Running on Windows 7, where we don't need it anyway. + } +@@ -351,6 +406,22 @@ + // in sys_windows_386.s and sys_windows_amd64.s: + func getlasterror() uint32 + ++// When loading DLLs, we prefer to use LoadLibraryEx with ++// LOAD_LIBRARY_SEARCH_* flags, if available. LoadLibraryEx is not ++// available on old Windows, though, and the LOAD_LIBRARY_SEARCH_* ++// flags are not available on some versions of Windows without a ++// security patch. ++// ++// https://msdn.microsoft.com/en-us/library/ms684179(v=vs.85).aspx says: ++// "Windows 7, Windows Server 2008 R2, Windows Vista, and Windows ++// Server 2008: The LOAD_LIBRARY_SEARCH_* flags are available on ++// systems that have KB2533623 installed. To determine whether the ++// flags are available, use GetProcAddress to get the address of the ++// AddDllDirectory, RemoveDllDirectory, or SetDefaultDllDirectories ++// function. If GetProcAddress succeeds, the LOAD_LIBRARY_SEARCH_* ++// flags can be used with LoadLibraryEx." ++var useLoadLibraryEx bool ++ + var timeBeginPeriodRetValue uint32 + + // osRelaxMinNS indicates that sysmon shouldn't osRelax if the next +@@ -417,7 +488,8 @@ + // Only load winmm.dll if we need it. + // This avoids a dependency on winmm.dll for Go programs + // that run on new Windows versions. +- m32 := windowsLoadSystemLib(winmmdll[:]) ++ var winmmdll = []byte("winmm.dll\000") ++ m32 := windowsLoadSystemLib(winmmdll) + if m32 == 0 { + print("runtime: LoadLibraryExW failed; errno=", getlasterror(), "\n") + throw("winmm.dll not found") +@@ -458,6 +530,28 @@ + canUseLongPaths = true + } + ++var osVersionInfo struct { ++ majorVersion uint32 ++ minorVersion uint32 ++ buildNumber uint32 ++} ++ ++func initOsVersionInfo() { ++ info := windows.OSVERSIONINFOW{} ++ info.OSVersionInfoSize = uint32(unsafe.Sizeof(info)) ++ stdcall(_RtlGetVersion, uintptr(unsafe.Pointer(&info))) ++ osVersionInfo.majorVersion = info.MajorVersion ++ osVersionInfo.minorVersion = info.MinorVersion ++ osVersionInfo.buildNumber = info.BuildNumber ++} ++ ++//go:linkname rtlGetNtVersionNumbers syscall.rtlGetNtVersionNumbers ++func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) { ++ *majorVersion = osVersionInfo.majorVersion ++ *minorVersion = osVersionInfo.minorVersion ++ *buildNumber = osVersionInfo.buildNumber ++} ++ + func osinit() { + asmstdcallAddr = unsafe.Pointer(windows.AsmStdCallAddr()) + +@@ -470,8 +564,8 @@ + initHighResTimer() + timeBeginPeriodRetValue = osRelax(false) + +- initSysDirectory() + initLongPathSupport() ++ initOsVersionInfo() + + numCPUStartup = getCPUCount() + +@@ -487,7 +581,7 @@ + //go:nosplit + func readRandom(r []byte) int { + n := 0 +- if stdcall(_ProcessPrng, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { ++ if stdcall(_RtlGenRandom, uintptr(unsafe.Pointer(&r[0])), uintptr(len(r)))&0xff != 0 { + n = len(r) + } + return n +Index: src/net/hook_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/net/hook_windows.go b/src/net/hook_windows.go +--- a/src/net/hook_windows.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) ++++ b/src/net/hook_windows.go (revision 44e76f7cf1bc6e04b5da724e0b2e48f393713506) +@@ -13,6 +13,7 @@ + hostsFilePath = windows.GetSystemDirectory() + "/Drivers/etc/hosts" + + // Placeholders for socket system calls. ++ socketFunc func(int, int, int) (syscall.Handle, error) = syscall.Socket + wsaSocketFunc func(int32, int32, int32, *syscall.WSAProtocolInfo, uint32, uint32) (syscall.Handle, error) = windows.WSASocket + connectFunc func(syscall.Handle, syscall.Sockaddr) error = syscall.Connect + listenFunc func(syscall.Handle, int) error = syscall.Listen +Index: src/net/internal/socktest/main_test.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/net/internal/socktest/main_test.go b/src/net/internal/socktest/main_test.go +--- a/src/net/internal/socktest/main_test.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) ++++ b/src/net/internal/socktest/main_test.go (revision 44e76f7cf1bc6e04b5da724e0b2e48f393713506) +@@ -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 && !plan9 && !wasip1 && !windows ++//go:build !js && !plan9 && !wasip1 + + package socktest_test + +Index: src/net/internal/socktest/main_windows_test.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/net/internal/socktest/main_windows_test.go b/src/net/internal/socktest/main_windows_test.go +new file mode 100644 +--- /dev/null (revision 44e76f7cf1bc6e04b5da724e0b2e48f393713506) ++++ b/src/net/internal/socktest/main_windows_test.go (revision 44e76f7cf1bc6e04b5da724e0b2e48f393713506) +@@ -0,0 +1,22 @@ ++// Copyright 2015 The Go Authors. All rights reserved. ++// Use of this source code is governed by a BSD-style ++// license that can be found in the LICENSE file. ++ ++package socktest_test ++ ++import "syscall" ++ ++var ( ++ socketFunc func(int, int, int) (syscall.Handle, error) ++ closeFunc func(syscall.Handle) error ++) ++ ++func installTestHooks() { ++ socketFunc = sw.Socket ++ closeFunc = sw.Closesocket ++} ++ ++func uninstallTestHooks() { ++ socketFunc = syscall.Socket ++ closeFunc = syscall.Closesocket ++} +Index: src/net/internal/socktest/sys_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/net/internal/socktest/sys_windows.go b/src/net/internal/socktest/sys_windows.go +--- a/src/net/internal/socktest/sys_windows.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) ++++ b/src/net/internal/socktest/sys_windows.go (revision 44e76f7cf1bc6e04b5da724e0b2e48f393713506) +@@ -9,6 +9,38 @@ + "syscall" + ) + ++// Socket wraps [syscall.Socket]. ++func (sw *Switch) Socket(family, sotype, proto int) (s syscall.Handle, err error) { ++ sw.once.Do(sw.init) ++ ++ so := &Status{Cookie: cookie(family, sotype, proto)} ++ sw.fmu.RLock() ++ f, _ := sw.fltab[FilterSocket] ++ sw.fmu.RUnlock() ++ ++ af, err := f.apply(so) ++ if err != nil { ++ return syscall.InvalidHandle, err ++ } ++ s, so.Err = syscall.Socket(family, sotype, proto) ++ if err = af.apply(so); err != nil { ++ if so.Err == nil { ++ syscall.Closesocket(s) ++ } ++ return syscall.InvalidHandle, err ++ } ++ ++ sw.smu.Lock() ++ defer sw.smu.Unlock() ++ if so.Err != nil { ++ sw.stats.getLocked(so.Cookie).OpenFailed++ ++ return syscall.InvalidHandle, so.Err ++ } ++ nso := sw.addLocked(s, family, sotype, proto) ++ sw.stats.getLocked(nso.Cookie).Opened++ ++ return s, nil ++} ++ + // WSASocket wraps [syscall.WSASocket]. + func (sw *Switch) WSASocket(family, sotype, proto int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (s syscall.Handle, err error) { + sw.once.Do(sw.init) +Index: src/net/main_windows_test.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/net/main_windows_test.go b/src/net/main_windows_test.go +--- a/src/net/main_windows_test.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) ++++ b/src/net/main_windows_test.go (revision 44e76f7cf1bc6e04b5da724e0b2e48f393713506) +@@ -12,6 +12,7 @@ + + var ( + // Placeholders for saving original socket system calls. ++ origSocket = socketFunc + origWSASocket = wsaSocketFunc + origClosesocket = poll.CloseFunc + origConnect = connectFunc +@@ -21,6 +22,7 @@ + ) + + func installTestHooks() { ++ socketFunc = sw.Socket + wsaSocketFunc = sw.WSASocket + poll.CloseFunc = sw.Closesocket + connectFunc = sw.Connect +@@ -30,6 +32,7 @@ + } + + func uninstallTestHooks() { ++ socketFunc = origSocket + wsaSocketFunc = origWSASocket + poll.CloseFunc = origClosesocket + connectFunc = origConnect +Index: src/net/sock_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/net/sock_windows.go b/src/net/sock_windows.go +--- a/src/net/sock_windows.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) ++++ b/src/net/sock_windows.go (revision 44e76f7cf1bc6e04b5da724e0b2e48f393713506) +@@ -20,6 +20,21 @@ + func sysSocket(family, sotype, proto int) (syscall.Handle, error) { + s, err := wsaSocketFunc(int32(family), int32(sotype), int32(proto), + nil, 0, windows.WSA_FLAG_OVERLAPPED|windows.WSA_FLAG_NO_HANDLE_INHERIT) ++ if err == nil { ++ return s, nil ++ } ++ // WSA_FLAG_NO_HANDLE_INHERIT flag is not supported on some ++ // old versions of Windows, see ++ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx ++ // for details. Just use syscall.Socket, if windows.WSASocket failed. ++ ++ // See ../syscall/exec_unix.go for description of ForkLock. ++ syscall.ForkLock.RLock() ++ s, err = socketFunc(family, sotype, proto) ++ if err == nil { ++ syscall.CloseOnExec(s) ++ } ++ syscall.ForkLock.RUnlock() + if err != nil { + return syscall.InvalidHandle, os.NewSyscallError("socket", err) + } +Index: src/syscall/exec_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go +--- a/src/syscall/exec_windows.go (revision b0d48afabb9fd14976c27221cb525c5d2ebbfe79) ++++ b/src/syscall/exec_windows.go (revision b4aece36e51ecce81c3ee9fe03e31db552e90018) +@@ -15,7 +15,6 @@ + "unsafe" + ) + +-// ForkLock is not used on Windows. + var ForkLock sync.RWMutex + + // EscapeArg rewrites command line argument s as prescribed +@@ -304,6 +303,9 @@ + var zeroProcAttr ProcAttr + var zeroSysProcAttr SysProcAttr + ++//go:linkname rtlGetNtVersionNumbers ++func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) ++ + func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle uintptr, err error) { + if len(argv0) == 0 { + return 0, 0, EWINDOWS +@@ -367,6 +369,17 @@ + } + } + ++ var maj, min, build uint32 ++ rtlGetNtVersionNumbers(&maj, &min, &build) ++ isWin7 := maj < 6 || (maj == 6 && min <= 1) ++ // NT kernel handles are divisible by 4, with the bottom 3 bits left as ++ // a tag. The fully set tag correlates with the types of handles we're ++ // concerned about here. Except, the kernel will interpret some ++ // special handle values, like -1, -2, and so forth, so kernelbase.dll ++ // checks to see that those bottom three bits are checked, but that top ++ // bit is not checked. ++ isLegacyWin7ConsoleHandle := func(handle Handle) bool { return isWin7 && handle&0x10000003 == 3 } ++ + p, _ := GetCurrentProcess() + parentProcess := p + if sys.ParentProcess != 0 { +@@ -375,7 +388,15 @@ + fd := make([]Handle, len(attr.Files)) + for i := range attr.Files { + if attr.Files[i] > 0 { +- err := DuplicateHandle(p, Handle(attr.Files[i]), parentProcess, &fd[i], 0, true, DUPLICATE_SAME_ACCESS) ++ destinationProcessHandle := parentProcess ++ ++ // On Windows 7, console handles aren't real handles, and can only be duplicated ++ // into the current process, not a parent one, which amounts to the same thing. ++ if parentProcess != p && isLegacyWin7ConsoleHandle(Handle(attr.Files[i])) { ++ destinationProcessHandle = p ++ } ++ ++ err := DuplicateHandle(p, Handle(attr.Files[i]), destinationProcessHandle, &fd[i], 0, true, DUPLICATE_SAME_ACCESS) + if err != nil { + return 0, 0, err + } +@@ -406,6 +427,14 @@ + + fd = append(fd, sys.AdditionalInheritedHandles...) + ++ // On Windows 7, console handles aren't real handles, so don't pass them ++ // through to PROC_THREAD_ATTRIBUTE_HANDLE_LIST. ++ for i := range fd { ++ if isLegacyWin7ConsoleHandle(fd[i]) { ++ fd[i] = 0 ++ } ++ } ++ + // The presence of a NULL handle in the list is enough to cause PROC_THREAD_ATTRIBUTE_HANDLE_LIST + // to treat the entire list as empty, so remove NULL handles. + j := 0 +Index: src/syscall/dll_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/syscall/dll_windows.go b/src/syscall/dll_windows.go +--- a/src/syscall/dll_windows.go (revision b4aece36e51ecce81c3ee9fe03e31db552e90018) ++++ b/src/syscall/dll_windows.go (revision ea2726a6fa25fbfa1092e696e522eafca544d24c) +@@ -119,14 +119,7 @@ + } + + //go:linkname loadsystemlibrary +-func loadsystemlibrary(filename *uint16) (uintptr, Errno) { +- const _LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800 +- handle, _, err := SyscallN(uintptr(__LoadLibraryExW), uintptr(unsafe.Pointer(filename)), 0, _LOAD_LIBRARY_SEARCH_SYSTEM32) +- if handle != 0 { +- err = 0 +- } +- return handle, err +-} ++func loadsystemlibrary(filename *uint16, absoluteFilepath *uint16) (handle uintptr, err Errno) + + //go:linkname getprocaddress + func getprocaddress(handle uintptr, procname *uint8) (uintptr, Errno) { +@@ -143,6 +136,9 @@ + Handle Handle + } + ++//go:linkname getSystemDirectory ++func getSystemDirectory() string // Implemented in runtime package. ++ + // LoadDLL loads the named DLL file into memory. + // + // If name is not an absolute path and is not a known system DLL used by +@@ -159,7 +155,11 @@ + var h uintptr + var e Errno + if sysdll.IsSystemDLL[name] { +- h, e = loadsystemlibrary(namep) ++ absoluteFilepathp, err := UTF16PtrFromString(getSystemDirectory() + name) ++ if err != nil { ++ return nil, err ++ } ++ h, e = loadsystemlibrary(namep, absoluteFilepathp) + } else { + h, e = loadlibrary(namep) + } +Index: src/os/removeall_at.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/os/removeall_at.go b/src/os/removeall_at.go +--- a/src/os/removeall_at.go (revision ea2726a6fa25fbfa1092e696e522eafca544d24c) ++++ b/src/os/removeall_at.go (revision d47e0d22130d597dcf9daa6b41fd9501274f0cb2) +@@ -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 + +@@ -175,3 +175,25 @@ + } + return newDirFile(fd, name) + } ++ ++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 ++} +Index: src/os/removeall_noat.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/os/removeall_noat.go b/src/os/removeall_noat.go +--- a/src/os/removeall_noat.go (revision ea2726a6fa25fbfa1092e696e522eafca544d24c) ++++ b/src/os/removeall_noat.go (revision d47e0d22130d597dcf9daa6b41fd9501274f0cb2) +@@ -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 + +@@ -140,3 +140,22 @@ + } + return err + } ++ ++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 ++} +Index: src/os/root_noopenat.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/os/root_noopenat.go b/src/os/root_noopenat.go +--- a/src/os/root_noopenat.go (revision ea2726a6fa25fbfa1092e696e522eafca544d24c) ++++ b/src/os/root_noopenat.go (revision d47e0d22130d597dcf9daa6b41fd9501274f0cb2) +@@ -11,7 +11,6 @@ + "internal/filepathlite" + "internal/stringslite" + "sync/atomic" +- "syscall" + "time" + ) + +@@ -185,25 +184,6 @@ + } + 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 { +Index: src/os/root_openat.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/os/root_openat.go b/src/os/root_openat.go +--- a/src/os/root_openat.go (revision ea2726a6fa25fbfa1092e696e522eafca544d24c) ++++ b/src/os/root_openat.go (revision d47e0d22130d597dcf9daa6b41fd9501274f0cb2) +@@ -196,28 +196,6 @@ + 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) { +Index: src/os/root_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/os/root_windows.go b/src/os/root_windows.go +--- a/src/os/root_windows.go (revision ea2726a6fa25fbfa1092e696e522eafca544d24c) ++++ b/src/os/root_windows.go (revision d47e0d22130d597dcf9daa6b41fd9501274f0cb2) +@@ -402,3 +402,14 @@ + } + return fi.Mode(), nil + } ++ ++func checkPathEscapes(r *Root, name string) error { ++ if !filepathlite.IsLocal(name) { ++ return errPathEscapes ++ } ++ return nil ++} ++ ++func checkPathEscapesLstat(r *Root, name string) error { ++ return checkPathEscapes(r, name) ++} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ddddb5ee..af3ae18f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,6 +24,7 @@ jobs: - 'ubuntu-24.04-arm' # arm64 linux - 'macos-15-intel' # amd64 macos go-version: + - '1.26.0-rc.1' - '1.25' - '1.24' - '1.23' @@ -49,11 +50,17 @@ jobs: go-version: ${{ matrix.go-version }} - name: Revert Golang commit for Windows7/8 - if: ${{ runner.os == 'Windows' && matrix.go-version != '1.20' }} + if: ${{ runner.os == 'Windows' && matrix.go-version != '1.20' && matrix.go-version != '1.26.0-rc.1' }} run: | cd $(go env GOROOT) patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/go${{matrix.go-version}}.patch + - name: Revert Golang commit for Windows7/8 + if: ${{ runner.os == 'Windows' && matrix.go-version == '1.26.0-rc.1' }} + run: | + cd $(go env GOROOT) + patch --verbose -p 1 < $GITHUB_WORKSPACE/.github/patch/go1.26.patch + - name: Remove inbound test for macOS if: ${{ runner.os == 'macOS' }} run: |