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的軟件技術集團上的碩士論文中開發的。