Skip to content

Commit

Permalink
windows: fix EnumProcesses to pass the correct array size
Browse files Browse the repository at this point in the history
Implementation generated directly with mkwinsyscall has a wrong
assumption about the expected value for PIDs buffer size.

This change adds some small manual code that converts the input
slice length to the number of bytes of the array backing the slice.

A test is also added. It fails with the previous implementation.

Fixes golang/go#60223

Change-Id: I5e2414acb29c6c949e5e6acd328043f8a8883887
Reviewed-on: https://go-review.googlesource.com/c/sys/+/495995
Commit-Queue: Quim Muntal <quimmuntal@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
  • Loading branch information
roman-mazur authored and qmuntal committed May 19, 2023
1 parent 352d833 commit c8ea6b0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 7 deletions.
13 changes: 12 additions & 1 deletion windows/syscall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys VerQueryValue(block unsafe.Pointer, subBlock string, pointerToBufferPointer unsafe.Pointer, bufSize *uint32) (err error) = version.VerQueryValueW

// Process Status API (PSAPI)
//sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
//sys enumProcesses(processIds *uint32, nSize uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses
//sys EnumProcessModules(process Handle, module *Handle, cb uint32, cbNeeded *uint32) (err error) = psapi.EnumProcessModules
//sys EnumProcessModulesEx(process Handle, module *Handle, cb uint32, cbNeeded *uint32, filterFlag uint32) (err error) = psapi.EnumProcessModulesEx
//sys GetModuleInformation(process Handle, module Handle, modinfo *ModuleInfo, cb uint32) (err error) = psapi.GetModuleInformation
Expand Down Expand Up @@ -1354,6 +1354,17 @@ func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) {
return syscall.EWINDOWS
}

func EnumProcesses(processIds []uint32, bytesReturned *uint32) error {
// EnumProcesses syscall expects the size parameter to be in bytes, but the code generated with mksyscall uses
// the length of the processIds slice instead. Hence, this wrapper function is added to fix the discrepancy.
var p *uint32
if len(processIds) > 0 {
p = &processIds[0]
}
size := uint32(len(processIds) * 4)
return enumProcesses(p, size, bytesReturned)
}

func Getpid() (pid int) { return int(GetCurrentProcessId()) }

func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
Expand Down
22 changes: 22 additions & 0 deletions windows/syscall_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,28 @@ func TestWinVerifyTrust(t *testing.T) {

}

func TestEnumProcesses(t *testing.T) {
var (
pids [2]uint32
outSize uint32
)
err := windows.EnumProcesses(pids[:], &outSize)
if err != nil {
t.Fatalf("unable to enumerate processes: %v", err)
}

// Regression check for go.dev/issue/60223
if outSize != 8 {
t.Errorf("unexpected bytes returned: %d", outSize)
}
// Most likely, this should be [0, 4].
// 0 is the system idle pseudo-process. 4 is the initial system process ID.
// This test expects that at least one of the PIDs is not 0.
if pids[0] == 0 && pids[1] == 0 {
t.Errorf("all PIDs are 0")
}
}

func TestProcessModules(t *testing.T) {
process, err := windows.GetCurrentProcess()
if err != nil {
Expand Down
8 changes: 2 additions & 6 deletions windows/zsyscall_windows.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c8ea6b0

Please sign in to comment.