你正在使用的Go版本是什么(go version
)?
https://pkg.go.dev/golang.org/x/sys@v0.12.0/windows#CommandLineToArgv
你做了什么?
对windows.DecomposeCommandLine
进行模糊测试,它以前使用windows.CommandLineToArgv
如下:
var argc int32
argv, err := CommandLineToArgv(&utf16CommandLine[0], &argc)
if err != nil {
return nil, err
}
defer LocalFree(Handle(unsafe.Pointer(argv)))
var args []string
for _, v := range (*argv)[:argc] {
args = append(args, UTF16ToString((*v)[:]))
}
return args, nil
你期望看到什么?
从CommandLineToArgv
返回一个与它的argc
返回值一致的返回类型,并与在https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-commandlinetoargvw中记录的签名匹配。
你看到了什么?
Go的CommandLineToArgv
Package 器硬编码了返回值的边界,每个边界有8192个条目,每个条目有8192个字符:
func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error)
硬编码的边界是错误的,当调用者尝试通过argc
索引到argv
时,可能会导致调用者恐慌。(注意@golang/windows)
7条答案
按热度按时间jtw3ybtb1#
https://go.dev/cl/530275提到了这个问题:
windows: convert TestCommandLineRecomposition to a fuzz test and fix discrepancies
kxxlusnw2#
我不确定我们应该如何解决这个问题。可选方案包括:
CommandLineToArgv
,并记录调用者应该使用DecomposeCommandLine
代替。CommandLineToArgv
并用具有更正确签名的新函数(名称待定)替换它。CommandLineToArgv
进行重大更改,使其返回值具有正确的类型。调用者可以使用类似argp := (**uint64)(unsafe.Pointer(argv))
的东西,以便他们的代码在无论使用哪个签名的情况下都能编译通过。oogrdqng3#
https://go.dev/cl/531175提到了这个问题:
windows: document the return type mismatch for CommandLineToArgv
xuo3flqw4#
我不确定我们应该如何解决这个问题。选项包括:
我更喜欢选项2。当前的
CommandLineToArgv
调用者应该被警告API是错误的,并且废弃它是实现这一目标的好方法。在大多数情况下,DecomposeCommandLine
应该是更好的选择。我也喜欢这样的设计,即寻找
CommandLineToArgv
的用户会被重定向到DecomposeCommandLine
,这在一般情况下更难发现,因为通常人们会尝试用鸭子类型来识别Windows API名称。另一方面,如果我们遵循选项3,即导出CommandLineToArgv2
,那么用户在花了一些时间确保他们没有调用不同的Windows API后,就会坚持使用这个API。pzfprimi5#
https://go.dev/cl/531176提到了这个问题:
windows: remove the 8192-codepoint arg limit in FuzzComposeCommandLine
yyhrrdl86#
这也影响了具有相同 Package 器的
syscall
包:https://pkg.go.dev/syscall?GOOS=windows#CommandLineToArgv
l2osamch7#
将内容转换为基于选项(2)的提案。该提案具体如下:
syscall.CommandLineToArgv
和windows.CommandLineToArgv
,并建议使用windows.DecomposeCommandLine
作为替代方案。