An Interest In:
Web News this Week
- April 2, 2024
- April 1, 2024
- March 31, 2024
- March 30, 2024
- March 29, 2024
- March 28, 2024
- March 27, 2024
fuzzing Go
Tutorial Go fuzzing
fuzzing Go random test
input
fuzzing SQL injection, buffer overflow, DoS cross-site scripting
fuzzing
- code
- unit test
- fuzz test
Note: built-in types Go Fuzzing docs
- Go 1.18
- Editor
- command terminal OS
- fuzznig AMD64 ARM64
- command prompt home directory
Linux Mac:
$ cd
Windows:
C:\> cd %HOMEPATH%
$ prompt Windows
- command prompt fuzz
$ mkdir fuzz$ cd fuzz
- module
go mod init
$ go mod init example/fuzzgo: creating new go.mod: module example/fuzz
code
reverse string
- text editor main.go fuzz
- main.go package
package main
func Reverse(s string) string { b := []byte(s) for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 { b[i], b[j] = b[j], b[i] } return string(b)}
string byte string
- main
func main() { input := "The quick brown fox jumped over the lazy dog" rev := Reverse(input) doubleRev := Reverse(rev) fmt.Printf("original: %q
", input) fmt.Printf("reversed: %q
", rev) fmt.Printf("reversed again: %q
", doubleRev)}
command line
- main fmt import
package mainimport "fmt"
command line main.go
$ go run .original: "The quick brown fox jumped over the lazy dog"reversed: "god yzal eht revo depmuj xof nworb kciuq ehT"reversed again: "The quick brown fox jumped over the lazy dog"
unit test
unit test Reverse
- text editor reverse_test.go fuzz
- reverse_test.go
package mainimport ( "testing")func TestReverse(t *testing.T) { testcases := []struct { in, want string }{ {"Hello, world", "dlrow ,olleH"}, {" ", " "}, {"!12345", "54321!"}, } for _, tc := range testcases { rev := Reverse(tc.in) if rev != tc.want { t.Errorf("Reverse: %q, want %q", rev, tc.want) } }}
reverse
unit test go test
$ go testPASSok example/fuzz 0.013s
fuzz test
fuzz test
unit test input developer fuzzing input
unit test fuzz test input
Note: unit test benchmark fuzz *_test.go
text editor reverse_test.go
func FuzzReverse(f *testing.F) { testcases := []string{"Hello, world", " ", "!12345"} for _, tc := range testcases { f.Add(tc) // Use f.Add to provide a seed corpus } f.Fuzz(func(t *testing.T, orig string) { rev := Reverse(orig) doubleRev := Reverse(rev) if orig != doubleRev { t.Errorf("Before: %q, after: %q", orig, doubleRev) } if utf8.ValidString(orig) && !utf8.ValidString(rev) { t.Errorf("Reverse produced invalid UTF-8 string %q", rev) } })}
Fuzzing unit test Reverse
Reverse("Hello, world")
"dlrow ,olleH"
fuzzing input
fuzz test 2
- reverse
- reverse UTF-8
Note: unit test fuzz test sysntax :
- TestXxx FuzzXxx *testing.T *testing.F
- t.Run f.Fuzz fuzz *testing.T type fuzz input unit test seed corpus f.Add
import unicode/utf8
package mainimport ( "testing" "unicode/utf8")
fuzz test
- fuzz test fuzzing seed
$ go testPASSok example/fuzz 0.013s
go test -run=FuzzReverse
- FuzzReverse fuzzing input flag -fuzz
$ go test -fuzz=Fuzzfuzz: elapsed: 0s, gathering baseline coverage: 0/3 completedfuzz: elapsed: 0s, gathering baseline coverage: 3/3 completed, now fuzzing with 8 workersfuzz: minimizing 38-byte failing input file...--- FAIL: FuzzReverse (0.01s) --- FAIL: FuzzReverse (0.00s) reverse_test.go:20: Reverse produced invalid UTF-8 string "\x9c\xdd" Failing input written to testdata/fuzz/FuzzReverse/af69258a12129d6cbba438df5d5f25ba0ec050461c116f777e77ea7c9a0d217a To re-run: go test -run=FuzzReverse/af69258a12129d6cbba438df5d5f25ba0ec050461c116f777e77ea7c9a0d217aFAILexit status 1FAIL example/fuzz 0.030s
fuzzing input seed corpus go test flag -fuzz input testdata/fuzz/FuzzReverse
text editor
go test fuzz v1string("")
type input
- go test -fuz seed corpus
$ go test--- FAIL: FuzzReverse (0.00s) --- FAIL: FuzzReverse/af69258a12129d6cbba438df5d5f25ba0ec050461c116f777e77ea7c9a0d217a (0.00s) reverse_test.go:20: Reverse produced invalid stringFAILexit status 1FAIL example/fuzz 0.016s
error
debug
debug VS Code debugger log terminal
utf8.ValidString
ValidString reports whether s consists entirely of valid UTF-8-encoded runes.
Reverse byte byte string UTF-8 rune rune rune
input ( ) Reverse rune
text editor FuzzReverse
f.Fuzz(func(t *testing.T, orig string) { rev := Reverse(orig) doubleRev := Reverse(rev) t.Logf("Number of runes: orig=%d, rev=%d, doubleRev=%d", utf8.RuneCountInString(orig), utf8.RuneCountInString(rev), utf8.RuneCountInString(doubleRev)) if orig != doubleRev { t.Errorf("Before: %q, after: %q", orig, doubleRev) } if utf8.ValidString(orig) && !utf8.ValidString(rev) { t.Errorf("Reverse produced invalid UTF-8 string %q", rev) }})
t.Logf command line error -v
go test
$ go test--- FAIL: FuzzReverse (0.00s) --- FAIL: FuzzReverse/28f36ef487f23e6c7a81ebdaa9feffe2f2b02b4cddaa6252e87f69863046a5e0 (0.00s) reverse_test.go:16: Number of runes: orig=1, rev=3, doubleRev=1 reverse_test.go:21: Reverse produced invalid UTF-8 string "\x83\xb3\xe6"FAILexit status 1FAIL example/fuzz 0.598s
seed corpus
Error
string runes bytes
text editor Reverse
func Reverse(s string) string { r := []rune(s) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r)}
Reverse string rune byte
- go test
$ go testPASSok example/fuzz 0.016s
!
- Fuzz go test -fuzz
$ go test -fuzz=Fuzzfuzz: elapsed: 0s, gathering baseline coverage: 0/37 completedfuzz: minimizing 506-byte failing input file...fuzz: elapsed: 0s, gathering baseline coverage: 5/37 completed--- FAIL: FuzzReverse (0.02s) --- FAIL: FuzzReverse (0.00s) reverse_test.go:33: Before: "\x91", after: "" Failing input written to testdata/fuzz/FuzzReverse/1ffc28f7538e29d79fce69fef20ce5ea72648529a9ca10bea392bcff28cd015c To re-run: go test -run=FuzzReverse/1ffc28f7538e29d79fce69fef20ce5ea72648529a9ca10bea392bcff28cd015cFAILexit status 1FAIL example/fuzz 0.032s
input unicode ?
debug
debug
debug debugger log
- text editor Reverse
func Reverse(s string) string { fmt.Printf("input: %q
", s) r := []rune(s) fmt.Printf("runes: %q
", r) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r)}
log go test -run
$ go test -run=FuzzReverse/28f36ef487f23e6c7a81ebdaa9feffe2f2b02b4cddaa6252e87f69863046a5e0input: "\x91"runes: ['']input: ""runes: ['']--- FAIL: FuzzReverse (0.00s) --- FAIL: FuzzReverse/28f36ef487f23e6c7a81ebdaa9feffe2f2b02b4cddaa6252e87f69863046a5e0 (0.00s) reverse_test.go:16: Number of runes: orig=1, rev=1, doubleRev=1 reverse_test.go:18: Before: "\x91", after: ""FAILexit status 1FAIL example/fuzz 0.145s
corpus FuzzXxx/testdata {FuzzTestName}/{filename}
-run debug
input unicode
error input UTF-8
- text editor Reverse
func Reverse(s string) (string, error) { if !utf8.ValidString(s) { return s, errors.New("input is not valid UTF-8") } r := []rune(s) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r), nil}
input UTF-8 error
- error main
func main() { input := "The quick brown fox jumped over the lazy dog" rev, revErr := Reverse(input) doubleRev, doubleRevErr := Reverse(rev) fmt.Printf("original: %q
", input) fmt.Printf("reversed: %q, err: %v
", rev, revErr) fmt.Printf("reversed again: %q, err: %v
", doubleRev, doubleRevErr)}
Reverse error nil input UTF-8
- import errors unicode/utf8
import ( "errors" "fmt" "unicode/utf8")
- reverse_test.go error error
func FuzzReverse(f *testing.F) { testcases := []string {"Hello, world", " ", "!12345"} for _, tc := range testcases { f.Add(tc) // Use f.Add to provide a seed corpus } f.Fuzz(func(t *testing.T, orig string) { rev, err1 := Reverse(orig) if err1 != nil { return } doubleRev, err2 := Reverse(rev) if err2 != nil { return } if orig != doubleRev { t.Errorf("Before: %q, after: %q", orig, doubleRev) } if utf8.ValidString(orig) && !utf8.ValidString(rev) { t.Errorf("Reverse produced invalid UTF-8 string %q", rev) } })}
return t.Skip() input
- go test
$ go testPASSok example/fuzz 0.019s
- Fuzz go test -fuzz=Fuzz Ctrl-C
$ go test -fuzz=Fuzzfuzz: elapsed: 0s, gathering baseline coverage: 0/38 completedfuzz: elapsed: 0s, gathering baseline coverage: 38/38 completed, now fuzzing with 4 workersfuzz: elapsed: 3s, execs: 86342 (28778/sec), new interesting: 2 (total: 35)fuzz: elapsed: 6s, execs: 193490 (35714/sec), new interesting: 4 (total: 37)fuzz: elapsed: 9s, execs: 304390 (36961/sec), new interesting: 4 (total: 37)...fuzz: elapsed: 3m45s, execs: 7246222 (32357/sec), new interesting: 8 (total: 41)^Cfuzz: elapsed: 3m48s, execs: 7335316 (31648/sec), new interesting: 8 (total: 41)PASSok example/fuzz 228.000s
fuzz flag -fuzztime Ctrl-C
- Fuzz
go test -fuzz=Fuzz -fuzztime 30s
fuzz 30
$ go test -fuzz=Fuzz -fuzztime 30sfuzz: elapsed: 0s, gathering baseline coverage: 0/5 completedfuzz: elapsed: 0s, gathering baseline coverage: 5/5 completed, now fuzzing with 4 workersfuzz: elapsed: 3s, execs: 80290 (26763/sec), new interesting: 12 (total: 12)fuzz: elapsed: 6s, execs: 210803 (43501/sec), new interesting: 14 (total: 14)fuzz: elapsed: 9s, execs: 292882 (27360/sec), new interesting: 14 (total: 14)fuzz: elapsed: 12s, execs: 371872 (26329/sec), new interesting: 14 (total: 14)fuzz: elapsed: 15s, execs: 517169 (48433/sec), new interesting: 15 (total: 15)fuzz: elapsed: 18s, execs: 663276 (48699/sec), new interesting: 15 (total: 15)fuzz: elapsed: 21s, execs: 771698 (36143/sec), new interesting: 15 (total: 15)fuzz: elapsed: 24s, execs: 924768 (50990/sec), new interesting: 16 (total: 16)fuzz: elapsed: 27s, execs: 1082025 (52427/sec), new interesting: 17 (total: 17)fuzz: elapsed: 30s, execs: 1172817 (30281/sec), new interesting: 17 (total: 17)fuzz: elapsed: 31s, execs: 1172817 (0/sec), new interesting: 17 (total: 17)PASSok example/fuzz 31.025s
!
flag -fuzz
go test documentation
fuzzing Go
fuzz ! fuzzing trophy case
Gpher Slack #fuzzing channel
main.go
package mainimport ( "errors" "fmt" "unicode/utf8")func main() { input := "The quick brown fox jumped over the lazy dog" rev, revErr := Reverse(input) doubleRev, doubleRevErr := Reverse(rev) fmt.Printf("original: %q
", input) fmt.Printf("reversed: %q, err: %v
", rev, revErr) fmt.Printf("reversed again: %q, err: %v
", doubleRev, doubleRevErr)}func Reverse(s string) (string, error) { if !utf8.ValidString(s) { return s, errors.New("input is not valid UTF-8") } r := []rune(s) for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] } return string(r), nil}
reverse_test.go
package mainimport ( "testing" "unicode/utf8")func FuzzReverse(f *testing.F) { testcases := []string{"Hello, world", " ", "!12345"} for _, tc := range testcases { f.Add(tc) // Use f.Add to provide a seed corpus } f.Fuzz(func(t *testing.T, orig string) { rev, err1 := Reverse(orig) if err1 != nil { return } doubleRev, err2 := Reverse(rev) if err2 != nil { return } if orig != doubleRev { t.Errorf("Before: %q, after: %q", orig, doubleRev) } if utf8.ValidString(orig) && !utf8.ValidString(rev) { t.Errorf("Reverse produced invalid UTF-8 string %q", rev) } })}
Original Link: https://dev.to/pallat/eriiynruueruueng-fuzzing-ain-go-2jh5
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To