Skip to content

Commit 01c413d

Browse files
Bryan C. Millsgopherbot
Bryan C. Mills
authored andcommitted
windows: document the return type mismatch for CommandLineToArgv
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 <[email protected]> Auto-Submit: Bryan Mills <[email protected]> Reviewed-by: Than McIntosh <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent e649453 commit 01c413d

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

windows/exec_windows.go

+19-6
Original file line numberDiff line numberDiff line change
@@ -153,22 +153,35 @@ func DecomposeCommandLine(commandLine string) ([]string, error) {
153153
return nil, errorspkg.New("string with NUL passed to DecomposeCommandLine")
154154
}
155155
var argc int32
156-
argv8192, err := CommandLineToArgv(&utf16CommandLine[0], &argc)
156+
argv, err := commandLineToArgv(&utf16CommandLine[0], &argc)
157157
if err != nil {
158158
return nil, err
159159
}
160-
defer LocalFree(Handle(unsafe.Pointer(argv8192)))
160+
defer LocalFree(Handle(unsafe.Pointer(argv)))
161161

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

169+
// CommandLineToArgv parses a Unicode command line string and sets
170+
// argc to the number of parsed arguments.
171+
//
172+
// The returned memory should be freed using a single call to LocalFree.
173+
//
174+
// Note that although the return type of CommandLineToArgv indicates 8192
175+
// entries of up to 8192 characters each, the actual count of parsed arguments
176+
// may exceed 8192, and the documentation for CommandLineToArgvW does not mention
177+
// any bound on the lengths of the individual argument strings.
178+
// (See https://go.dev/issue/63236.)
179+
func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) {
180+
argp, err := commandLineToArgv(cmd, argc)
181+
argv = (*[8192]*[8192]uint16)(unsafe.Pointer(argp))
182+
return argv, err
183+
}
184+
172185
func CloseOnExec(fd Handle) {
173186
SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
174187
}

windows/syscall_windows.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
238238
//sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW
239239
//sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW
240240
//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
241-
//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW
241+
//sys commandLineToArgv(cmd *uint16, argc *int32) (argv **uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW
242242
//sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0]
243243
//sys LocalAlloc(flags uint32, length uint32) (ptr uintptr, err error)
244244
//sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error)

windows/zsyscall_windows.go

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)