Go linter dalam gaya go vet untuk menemukan penggunaan yang salah dari reflect.SliceHeader dan reflect.StringHeader , dan gips yang tidak aman antara struct dengan bidang seukuran arsitektur.

go-safer melaporkan pola penggunaan berikut:
reflect.StringHeader literal gabungan dari tipe yang reflect.SliceHeader .reflect.StringHeader tugas untuk instance tipe reflect.SliceHeader stringint , uint , atau uintptrPola 1 mengidentifikasi kode yang terlihat seperti ini:
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 ))
} Ini juga akan menangkap kasus di mana reflect.SliceHeader type MysteryType reflect.SliceHeader
Pola 2 mengidentifikasi kode seperti berikut:
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 akan menangkap tugas ke objek tipe reflect.SliceHeader . Menggunakan grafik aliran kontrol fungsi, ia dapat melihat bahwa sH tidak diturunkan dengan melemparkan irisan nyata (di sini nil sebagai gantinya).
Pola 3 gips yang diidentifikasi sebagai berikut:
type A struct {
x int
}
type B struct {
y int64
}
func unsafeFunction ( a A ) B {
return * ( * B )( unsafe . Pointer ( & a ))
} Ada lebih banyak contoh tentang salah (dilaporkan) dan kode aman dalam kasus uji pada direktori passes/*/testdata/src .
Jika reflect.SliceHeader atau reflect.StringHeader tidak dibuat dengan melemparkan irisan atau string nyata, maka runtime go tidak akan memperlakukan bidang Data dalam jenis ini sebagai referensi ke array data yang mendasarinya. Oleh karena itu, jika pengumpul sampah berjalan tepat sebelum pemain terakhir dari instance header literal ke irisan atau string nyata, itu dapat mengumpulkan irisan atau string asli. Ini dapat menyebabkan kerentanan kebocoran informasi.
Untuk detail lebih lanjut, seperti eksploitasi pembuktian konsep dan saran untuk versi tetap dari pola yang tidak aman ini, baca posting blog ini: Golang Slice Header Berbasis Data Kebingungan pada Kode Dunia Nyata
Untuk menginstal go-safer , gunakan perintah berikut:
go get github.com/jlauinger/go-safer
Ini akan menginstal go-safer ke $GOPATH/bin , jadi pastikan itu termasuk dalam variabel lingkungan $PATH Anda.
Jalankan Go-Safer pada paket seperti ini:
$ go-safer example/cmd
Atau menyediakan beberapa paket, dipisahkan oleh spasi:
$ go-safer example/cmd example/util strings
Untuk memeriksa paket dan, secara rekursif, semua impornya, gunakan ./... :
$ go-safer example/cmd/...
Akhirnya, untuk memeriksa paket di direktori saat ini yang dapat Anda gunakan . :
$ go-safer .
go-safer menerima bendera yang sama dengan 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)
Menyediakan bendera -help mencetak informasi penggunaan untuk go-safer :
$ go-safer -help
Jika proyek Anda menggunakan modul GO dan file go.mod , go-safer akan mengambil semua dependensi secara otomatis sebelum menganalisisnya. Perilaku itu persis seperti go build .
Jika Anda menggunakan bentuk manajemen ketergantungan yang berbeda, misalnya manual go get , go mod vendor atau apa pun, Anda perlu menjalankan manajemen ketergantungan Anda sebelum menjalankan go-safer agar semua ketergantungan up-muted sebelum analisis.
Untuk mendapatkan kode sumber dan menyusun biner, jalankan ini:
$ git clone https://github.com/jlauinger/go-safer
$ cd go-safer
$ go build
Untuk menjalankan kasus uji, gunakan perintah berikut:
$ go test ./...
go-safer menggunakan infrastruktur pengujian dari golang.org/x/tools/go/analysis/analysistest . Untuk menambahkan test case, buat paket baru di dalam direktori bad atau good di passes/sliceheader/testdata/src . Tambahkan banyak file GO ke paket sesuai kebutuhan.
Kemudian, daftarkan paket baru di file sliceheader_test.go dengan menentukan jalur paket.
Dalam file sumber kasus uji, tambahkan komentar anotasi ke baris yang harus dilaporkan (atau tidak). Komentar harus terlihat seperti ini:
sH.Len = strH.Len // want "assigning to reflect header object" "assigning to reflect header object"
fmt.Println("hello world") // ok
Anotasi yang menunjukkan garis yang harus dilaporkan harus dimulai dengan want dan kemudian memiliki pesan yang diinginkan dua kali. Untuk beberapa alasan, infrastruktur pengujian akan menyebabkan go-safer untuk menghasilkan anotasi dua kali, oleh karena itu harus diharapkan dua kali lebih baik untuk lulus tes.
Kasus uji untuk Pass structcast dapat ditambahkan dengan cara yang sama.
Karena go-safer dibangun di atas infrastruktur standar VET GO, Anda dapat mengimpor lintasan ke liner berbasis dokter hewan Anda sendiri.
Dilisensikan di bawah lisensi MIT ("lisensi"). Anda tidak boleh menggunakan proyek ini kecuali sesuai dengan lisensi. Anda dapat memperoleh salinan lisensi di sini.
Hak Cipta 2020 Johannes Lauinger
Alat ini telah dikembangkan sebagai bagian dari tesis master saya di Grup Teknologi Perangkat Lunak di TU Darmstadt.