Enable testing with go-fuzz
This commit is contained in:
parent
a693698279
commit
c6f5075721
|
@ -0,0 +1,70 @@
|
|||
// Copyright (C) 2015 The Protocol Authors.
|
||||
|
||||
// +build gofuzz
|
||||
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
// Regenerate the length, or we'll most commonly exit quickly due to an
|
||||
// unexpected eof which is unintestering.
|
||||
if len(data) > 8 {
|
||||
binary.BigEndian.PutUint32(data[4:], uint32(len(data))-8)
|
||||
}
|
||||
|
||||
// Setup a rawConnection we'll use to parse the message.
|
||||
c := rawConnection{
|
||||
cr: &countingReader{Reader: bytes.NewReader(data)},
|
||||
closed: make(chan struct{}),
|
||||
pool: sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, BlockSize)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Attempt to parse the message.
|
||||
hdr, msg, err := c.readMessage()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
// If parsing worked, attempt to encode it again.
|
||||
newBs, err := msg.AppendXDR(nil)
|
||||
if err != nil {
|
||||
panic("not encodable")
|
||||
}
|
||||
|
||||
// Create an appriate header for the re-encoding.
|
||||
newMsg := make([]byte, 8)
|
||||
binary.BigEndian.PutUint32(newMsg, encodeHeader(hdr))
|
||||
binary.BigEndian.PutUint32(newMsg[4:], uint32(len(newBs)))
|
||||
newMsg = append(newMsg, newBs...)
|
||||
|
||||
// Use the rawConnection to parse the re-encoding.
|
||||
c.cr = &countingReader{Reader: bytes.NewReader(newMsg)}
|
||||
hdr2, msg2, err := c.readMessage()
|
||||
if err != nil {
|
||||
fmt.Println("Initial:\n" + hex.Dump(data))
|
||||
fmt.Println("New:\n" + hex.Dump(newMsg))
|
||||
panic("not parseable after re-encode: " + err.Error())
|
||||
}
|
||||
|
||||
// Make sure the data is the same as it was before.
|
||||
if hdr != hdr2 {
|
||||
panic("headers differ")
|
||||
}
|
||||
if !reflect.DeepEqual(msg, msg2) {
|
||||
panic("contents differ")
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright (C) 2015 The Protocol Authors.
|
||||
|
||||
// +build gofuzz
|
||||
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/quick"
|
||||
)
|
||||
|
||||
// This can be used to generate a corpus of valid messages as a starting point
|
||||
// for the fuzzer.
|
||||
func TestGenerateCorpus(t *testing.T) {
|
||||
t.Skip("Use to generate initial corpus only")
|
||||
|
||||
n := 0
|
||||
check := func(idx IndexMessage) bool {
|
||||
for i := range idx.Options {
|
||||
if len(idx.Options[i].Key) > 64 {
|
||||
idx.Options[i].Key = idx.Options[i].Key[:64]
|
||||
}
|
||||
}
|
||||
hdr := header{
|
||||
version: 0,
|
||||
msgID: 42,
|
||||
msgType: messageTypeIndex,
|
||||
compression: false,
|
||||
}
|
||||
|
||||
msgBs := idx.MustMarshalXDR()
|
||||
|
||||
buf := make([]byte, 8)
|
||||
binary.BigEndian.PutUint32(buf, encodeHeader(hdr))
|
||||
binary.BigEndian.PutUint32(buf[4:], uint32(len(msgBs)))
|
||||
buf = append(buf, msgBs...)
|
||||
|
||||
ioutil.WriteFile(fmt.Sprintf("testdata/corpus/test-%03d.xdr", n), buf, 0644)
|
||||
n++
|
||||
return true
|
||||
}
|
||||
|
||||
if err := quick.Check(check, &quick.Config{MaxCount: 1000}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests any crashers found by the fuzzer, for closer investigation.
|
||||
func TestCrashers(t *testing.T) {
|
||||
testFiles(t, "testdata/crashers")
|
||||
}
|
||||
|
||||
// Tests the entire corpus, which should PASS before the fuzzer starts
|
||||
// fuzzing.
|
||||
func TestCorpus(t *testing.T) {
|
||||
testFiles(t, "testdata/corpus")
|
||||
}
|
||||
|
||||
func testFiles(t *testing.T, dir string) {
|
||||
fd, err := os.Open(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
crashers, err := fd.Readdirnames(-1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, name := range crashers {
|
||||
if strings.HasSuffix(name, ".output") {
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(name, ".quoted") {
|
||||
continue
|
||||
}
|
||||
|
||||
t.Log(name)
|
||||
crasher, err := ioutil.ReadFile(dir + "/" + name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Fuzz(crasher)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue