github.com/tumi8/quic-go@v0.37.4-tum/fuzzing/frames/fuzz.go (about)

     1  package frames
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/tumi8/quic-go/noninternal/protocol"
     7  	"github.com/tumi8/quic-go/noninternal/wire"
     8  )
     9  
    10  const version = protocol.Version1
    11  
    12  // PrefixLen is the number of bytes used for configuration
    13  const PrefixLen = 1
    14  
    15  func toEncLevel(v uint8) protocol.EncryptionLevel {
    16  	switch v % 3 {
    17  	default:
    18  		return protocol.EncryptionInitial
    19  	case 1:
    20  		return protocol.EncryptionHandshake
    21  	case 2:
    22  		return protocol.Encryption1RTT
    23  	}
    24  }
    25  
    26  // Fuzz fuzzes the QUIC frames.
    27  //
    28  //go:generate go run ./cmd/corpus.go
    29  func Fuzz(data []byte) int {
    30  	if len(data) < PrefixLen {
    31  		return 0
    32  	}
    33  	encLevel := toEncLevel(data[0])
    34  	data = data[PrefixLen:]
    35  
    36  	parser := wire.NewFrameParser(true)
    37  	parser.SetAckDelayExponent(protocol.DefaultAckDelayExponent)
    38  
    39  	var numFrames int
    40  	var b []byte
    41  	for len(data) > 0 {
    42  		initialLen := len(data)
    43  		l, f, err := parser.ParseNext(data, encLevel, version)
    44  		if err != nil {
    45  			break
    46  		}
    47  		data = data[l:]
    48  		numFrames++
    49  		if f == nil { // PADDING frame
    50  			continue
    51  		}
    52  		// We accept empty STREAM frames, but we don't write them.
    53  		if sf, ok := f.(*wire.StreamFrame); ok {
    54  			if sf.DataLen() == 0 {
    55  				sf.PutBack()
    56  				continue
    57  			}
    58  		}
    59  
    60  		startLen := len(b)
    61  		parsedLen := initialLen - len(data)
    62  		b, err = f.Append(b, version)
    63  		if err != nil {
    64  			panic(fmt.Sprintf("Error writing frame %#v: %s", f, err))
    65  		}
    66  		frameLen := protocol.ByteCount(len(b) - startLen)
    67  		if f.Length(version) != frameLen {
    68  			panic(fmt.Sprintf("Inconsistent frame length for %#v: expected %d, got %d", f, frameLen, f.Length(version)))
    69  		}
    70  		if sf, ok := f.(*wire.StreamFrame); ok {
    71  			sf.PutBack()
    72  		}
    73  		if frameLen > protocol.ByteCount(parsedLen) {
    74  			panic(fmt.Sprintf("Serialized length (%d) is longer than parsed length (%d)", len(b), parsedLen))
    75  		}
    76  	}
    77  
    78  	if numFrames == 0 {
    79  		return 0
    80  	}
    81  	return 1
    82  }