Merge pull request #2713 from lucas-clemente/fuzz-tps

add fuzzing for transport parameters
This commit is contained in:
Marten Seemann
2020-08-18 12:10:23 +07:00
committed by GitHub
23 changed files with 153 additions and 3 deletions

View File

@@ -0,0 +1,92 @@
package main
import (
"fmt"
"log"
"math"
"math/rand"
"net"
"os"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/wire"
)
func getRandomData(l int) []byte {
b := make([]byte, l)
rand.Read(b)
return b
}
func getRandomValue() uint64 {
maxVals := []int64{math.MaxUint8 / 4, math.MaxUint16 / 4, math.MaxUint32 / 4, math.MaxUint64 / 4}
return uint64(rand.Int63n(maxVals[int(rand.Int31n(4))]))
}
func main() {
rand.Seed(1337)
for i := 0; i < 20; i++ {
tp := &wire.TransportParameters{
InitialMaxStreamDataBidiLocal: protocol.ByteCount(getRandomValue()),
InitialMaxStreamDataBidiRemote: protocol.ByteCount(getRandomValue()),
InitialMaxStreamDataUni: protocol.ByteCount(getRandomValue()),
InitialMaxData: protocol.ByteCount(getRandomValue()),
MaxAckDelay: time.Duration(getRandomValue()),
AckDelayExponent: uint8(getRandomValue()),
DisableActiveMigration: getRandomValue()%2 == 0,
MaxUDPPayloadSize: protocol.ByteCount(getRandomValue()),
MaxUniStreamNum: protocol.StreamNum(getRandomValue()),
MaxBidiStreamNum: protocol.StreamNum(getRandomValue()),
MaxIdleTimeout: time.Duration(getRandomValue()),
ActiveConnectionIDLimit: getRandomValue(),
}
if rand.Int()%2 == 0 {
tp.OriginalDestinationConnectionID = protocol.ConnectionID(getRandomData(rand.Intn(50)))
}
if rand.Int()%2 == 0 {
tp.InitialSourceConnectionID = protocol.ConnectionID(getRandomData(rand.Intn(50)))
}
if rand.Int()%2 == 0 {
connID := protocol.ConnectionID(getRandomData(rand.Intn(50)))
tp.RetrySourceConnectionID = &connID
}
if rand.Int()%2 == 0 {
var token protocol.StatelessResetToken
rand.Read(token[:])
tp.StatelessResetToken = &token
}
if rand.Int()%2 == 0 {
var token protocol.StatelessResetToken
rand.Read(token[:])
tp.PreferredAddress = &wire.PreferredAddress{
IPv4: net.IPv4(uint8(rand.Int()), uint8(rand.Int()), uint8(rand.Int()), uint8(rand.Int())),
IPv4Port: uint16(rand.Int()),
IPv6: net.IP(getRandomData(16)),
IPv6Port: uint16(rand.Int()),
ConnectionID: protocol.ConnectionID(getRandomData(rand.Intn(25))),
StatelessResetToken: token,
}
}
pers := protocol.PerspectiveServer
if rand.Int()%2 == 0 {
pers = protocol.PerspectiveClient
}
if err := writeCorpusFile(fmt.Sprintf("tp%d", i), tp.Marshal(pers)); err != nil {
log.Fatal(err)
}
}
}
func writeCorpusFile(name string, data []byte) error {
file, err := os.Create("corpus/" + name)
if err != nil {
return err
}
data = append(getRandomData(2), data...)
if _, err := file.Write(data); err != nil {
return err
}
return file.Close()
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,56 @@
package transportparameters
import (
"bytes"
"fmt"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/wire"
)
//go:generate go run ./cmd/corpus.go
func Fuzz(data []byte) int {
if len(data) <= 1 {
return 0
}
if data[0]%2 == 0 {
return fuzzTransportParametersForSessionTicket(data[1:])
}
return fuzzTransportParameters(data[1:])
}
func fuzzTransportParameters(data []byte) int {
perspective := protocol.PerspectiveServer
if data[0]%2 == 1 {
perspective = protocol.PerspectiveServer
}
data = data[1:]
tp := &wire.TransportParameters{}
if err := tp.Unmarshal(data, perspective); err != nil {
return 0
}
_ = tp.String()
tp2 := &wire.TransportParameters{}
if err := tp2.Unmarshal(tp.Marshal(perspective), perspective); err != nil {
fmt.Printf("%#v\n", tp)
panic(err)
}
return 1
}
func fuzzTransportParametersForSessionTicket(data []byte) int {
tp := &wire.TransportParameters{}
if err := tp.UnmarshalFromSessionTicket(bytes.NewReader(data)); err != nil {
return 0
}
buf := &bytes.Buffer{}
tp.MarshalForSessionTicket(buf)
tp2 := &wire.TransportParameters{}
if err := tp2.UnmarshalFromSessionTicket(bytes.NewReader(buf.Bytes())); err != nil {
panic(err)
}
return 1
}

View File

@@ -358,9 +358,11 @@ func (p *TransportParameters) Marshal(pers protocol.Perspective) []byte {
}
if pers == protocol.PerspectiveServer {
// stateless_reset_token
utils.WriteVarInt(b, uint64(statelessResetTokenParameterID))
utils.WriteVarInt(b, 16)
b.Write(p.StatelessResetToken[:])
if p.StatelessResetToken != nil {
utils.WriteVarInt(b, uint64(statelessResetTokenParameterID))
utils.WriteVarInt(b, 16)
b.Write(p.StatelessResetToken[:])
}
// original_destination_connection_id
utils.WriteVarInt(b, uint64(originalDestinationConnectionIDParameterID))
utils.WriteVarInt(b, uint64(p.OriginalDestinationConnectionID.Len()))