From: Bryan C. Mills Date: Tue, 12 Dec 2023 21:26:45 +0000 (-0500) Subject: internal/syscall/windows: fix the signature of SetFileInformationByHandle X-Git-Tag: go1.22rc1~2^2~12 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a7097243e462802f3055da9f843013e450a75092;p=gostls13.git internal/syscall/windows: fix the signature of SetFileInformationByHandle Also fix its call site in internal/poll to pass the length of the actual buffer instead of an unrelated variable, and update the definition of FILE_BASIC_INFO to match the documented field types and add padding that is empirically needed on the 386 architecture. Passing a pointer to a Go-allocated buffer as type uintptr violates the unsafe.Pointer conversion rules, which allow such a conversion only in the call expression itself for a call to syscall.Syscall or equivalent. That can allow the buffer to be corrupted arbitrarily if the Go runtime happens to garbage-collect it while the call to SetFileInformationByHandle is in progress. The Microsoft documentation for SetFileInformationByHandle specifies its third argument type as LPVOID, which corresponds to Go's unsafe.Pointer, not uintptr. Fixes #58933 (maybe). Change-Id: If577b57adea9922f5fcca55e46030c703d8f035c Cq-Include-Trybots: luci.golang.try:gotip-windows-amd64-longtest Reviewed-on: https://go-review.googlesource.com/c/go/+/549256 LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh Auto-Submit: Bryan Mills Reviewed-by: Quim Muntal Reviewed-by: Alex Brainman --- diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 9df39edced..2095a6aa29 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -1037,8 +1037,7 @@ func (fd *FD) Fchmod(mode uint32) error { var du windows.FILE_BASIC_INFO du.FileAttributes = attrs - l := uint32(unsafe.Sizeof(d)) - return windows.SetFileInformationByHandle(fd.Sysfd, windows.FileBasicInfo, uintptr(unsafe.Pointer(&du)), l) + return windows.SetFileInformationByHandle(fd.Sysfd, windows.FileBasicInfo, unsafe.Pointer(&du), uint32(unsafe.Sizeof(du))) } // Fchdir wraps syscall.Fchdir. diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go index 5854ca60b5..d10e30cb68 100644 --- a/src/internal/syscall/windows/syscall_windows.go +++ b/src/internal/syscall/windows/syscall_windows.go @@ -129,11 +129,22 @@ type SecurityAttributes struct { } type FILE_BASIC_INFO struct { - CreationTime syscall.Filetime - LastAccessTime syscall.Filetime - LastWriteTime syscall.Filetime - ChangedTime syscall.Filetime + CreationTime int64 + LastAccessTime int64 + LastWriteTime int64 + ChangedTime int64 FileAttributes uint32 + + // Pad out to 8-byte alignment. + // + // Without this padding, TestChmod fails due to an argument validation error + // in SetFileInformationByHandle on windows/386. + // + // https://learn.microsoft.com/en-us/cpp/build/reference/zp-struct-member-alignment?view=msvc-170 + // says that “The C/C++ headers in the Windows SDK assume the platform's + // default alignment is used.” What we see here is padding rather than + // alignment, but maybe it is related. + _ uint32 } const ( @@ -150,7 +161,7 @@ const ( //sys GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW //sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW //sys GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW -//sys SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle +//sys SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf unsafe.Pointer, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle //sys VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery //sys GetTempPath2(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPath2W diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go index 5a587ad4f1..931f157cf1 100644 --- a/src/internal/syscall/windows/zsyscall_windows.go +++ b/src/internal/syscall/windows/zsyscall_windows.go @@ -342,7 +342,7 @@ func RtlVirtualUnwind(handlerType uint32, baseAddress uintptr, pc uintptr, entry return } -func SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) { +func SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf unsafe.Pointer, bufsize uint32) (err error) { r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(fileInformationClass), uintptr(buf), uintptr(bufsize), 0, 0) if r1 == 0 { err = errnoErr(e1)