Skip to content

Commit

Permalink
windows: document the return type mismatch for CommandLineToArgv
Browse files Browse the repository at this point in the history
For golang/go#63236.

Change-Id: Id6c458e2ee2291e28685d24e86c05702d9fd132a
Cq-Include-Trybots: luci.golang.try:x_sys-gotip-windows-amd64-longtest
Reviewed-on: https://go-review.googlesource.com/c/sys/+/531175
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
Bryan C. Mills authored and gopherbot committed Sep 26, 2023
1 parent e649453 commit 01c413d
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 9 deletions.
25 changes: 19 additions & 6 deletions windows/exec_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,22 +153,35 @@ func DecomposeCommandLine(commandLine string) ([]string, error) {
return nil, errorspkg.New("string with NUL passed to DecomposeCommandLine")
}
var argc int32
argv8192, err := CommandLineToArgv(&utf16CommandLine[0], &argc)
argv, err := commandLineToArgv(&utf16CommandLine[0], &argc)
if err != nil {
return nil, err
}
defer LocalFree(Handle(unsafe.Pointer(argv8192)))
defer LocalFree(Handle(unsafe.Pointer(argv)))

var args []string
// Note: CommandLineToArgv hard-codes an incorrect return type
// (see https://go.dev/issue/63236).
// We use an unsafe.Pointer conversion here to work around it.
for _, p := range unsafe.Slice((**uint16)(unsafe.Pointer(argv8192)), argc) {
for _, p := range unsafe.Slice(argv, argc) {
args = append(args, UTF16PtrToString(p))
}
return args, nil
}

// CommandLineToArgv parses a Unicode command line string and sets
// argc to the number of parsed arguments.
//
// The returned memory should be freed using a single call to LocalFree.
//
// Note that although the return type of CommandLineToArgv indicates 8192
// entries of up to 8192 characters each, the actual count of parsed arguments
// may exceed 8192, and the documentation for CommandLineToArgvW does not mention
// any bound on the lengths of the individual argument strings.
// (See https://go.dev/issue/63236.)
func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) {
argp, err := commandLineToArgv(cmd, argc)
argv = (*[8192]*[8192]uint16)(unsafe.Pointer(argp))
return argv, err
}

func CloseOnExec(fd Handle) {
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
}
Expand Down
2 changes: 1 addition & 1 deletion windows/syscall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
//sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW
//sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW
//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW
//sys commandLineToArgv(cmd *uint16, argc *int32) (argv **uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW
//sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0]
//sys LocalAlloc(flags uint32, length uint32) (ptr uintptr, err error)
//sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error)
Expand Down
4 changes: 2 additions & 2 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 01c413d

Please sign in to comment.