Go linter以go vet的样式找到reflect.SliceHeader reflect.StringHeader不正确用途。

go-safer报告以下用法模式:
reflect.SliceHeader reflect.StringHeaderstring实例进行了reflect.StringHeader reflect.SliceHeaderint , uint或uintptr模式1标识看起来像这样的代码:
func unsafeFunction ( s string ) [] byte {
sH := ( * reflect . StringHeader )( unsafe . Pointer ( & s ))
bH := & reflect. SliceHeader {
Data : sH . Data ,
Len : sH . Len ,
Cap : sH . Len ,
}
return * ( * [] byte )( unsafe . Pointer ( bH ))
}它还将捕获reflect.SliceHeader已重命名的案例,例如type MysteryType reflect.SliceHeader 。
模式2标识以下代码:
func unsafeFunction ( s string ) [] byte {
strH := ( * reflect . StringHeader )( unsafe . Pointer ( & str ))
sH := ( * reflect . SliceHeader )( unsafe . Pointer ( nil ))
sH . Len = strH . Len
sH . Cap = strH . Len
sH . Data = strH . Data
return
} safer-go将捕捉到类型reflect.SliceHeader的对象的作业。使用函数的控制流程图,可以看到sH不是通过施放真实切片来得出的(这里是nil )。
模式3将演员表确定为以下内容:
type A struct {
x int
}
type B struct {
y int64
}
func unsafeFunction ( a A ) B {
return * ( * B )( unsafe . Pointer ( & a ))
}在passes/*/testdata/src目录中的测试用例中,还有更多有关错误(报告)和安全代码的示例。
如果不是通过施放真实的切片或string创建reflect.SliceHeader或reflect.StringHeader ,则GO运行时不会将这些类型中的Data字段视为对基础数据数组的引用。因此,如果垃圾收集器在从字面的标题实例到真实切片或string之前运行,则可能会收集原始的切片或string 。这可能导致信息泄漏漏洞。
有关更多详细信息,例如概念证明利用和对这些不安全模式的固定版本的建议
要安装go-safer ,请使用以下命令:
go get github.com/jlauinger/go-safer
这将安装到$GOPATH/bin go-safer ,因此请确保它包含在您的$PATH环境变量中。
在这样的软件包上运行GO-SAFER:
$ go-safer example/cmd
或提供多个包裹,由空间隔开:
$ go-safer example/cmd example/util strings
要检查包裹并递归中所有导入,请使用./... ::
$ go-safer example/cmd/...
最后,要检查可以使用的当前目录中的软件包. :
$ go-safer .
go-safer接受与go vet相同的标志:
Flags:
-V print version and exit
-all
no effect (deprecated)
-c int
display offending line with this many lines of context (default -1)
-cpuprofile string
write CPU profile to this file
-debug string
debug flags, any subset of "fpstv"
-fix
apply all suggested fixes
-flags
print analyzer flags in JSON
-json
emit JSON output
-memprofile string
write memory profile to this file
-source
no effect (deprecated)
-tags string
no effect (deprecated)
-trace string
write trace log to this file
-v no effect (deprecated)
提供-help标志为go-safer打印使用信息:
$ go-safer -help
如果您的项目使用go模块和一个go.mod文件, go-safer将在分析它们之前自动获取所有依赖项。它的行为与go build一样。
如果您使用不同形式的依赖关系管理,例如手动go get , go mod vendor或其他任何东西,则需要在运行go-safer之前运行依赖项管理,以便在分析之前对所有依赖关系保持最新。
要获取源代码并编译二进制代码,请运行以下操作:
$ git clone https://github.com/jlauinger/go-safer
$ cd go-safer
$ go build
运行测试用例使用以下命令:
$ go test ./...
go-safer使用golang.org/x/tools/go/analysis/analysistest的测试基础架构。要添加测试用例,请在passes/sliceheader/testdata/src中的bad good中创建一个新软件包。根据需要将尽可能多的GO文件添加到软件包。
然后,通过指定软件包路径在sliceheader_test.go文件中注册新软件包。
在测试案例源文件中,将注释注释添加到应报告(或不报告)的行中。评论必须像这样:
sH.Len = strH.Len // want "assigning to reflect header object" "assigning to reflect header object"
fmt.Println("hello world") // ok
指示应报告的行的注释必须从want开始,然后将所需的消息两次。由于某种原因,测试基础架构将导致go-safer注释两次,因此必须两次通过测试。
structcast通行证的测试用例可以类似地添加。
由于go-safer建立在GO VET标准基础架构上,因此您可以将通行证导入基于Go Vet的Linter。
根据MIT许可(“许可”)许可。除了符合许可外,您不得使用此项目。您可以在此处获得许可证的副本。
版权所有2020 Johannes Lauinger
该工具是在我在TU Darmstadt的软件技术集团上的硕士论文中开发的。