github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/fuzzing/frames/fuzz.go (about)

     1  package frames
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/protocol"
     7  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/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  		validateFrame(f)
    60  
    61  		startLen := len(b)
    62  		parsedLen := initialLen - len(data)
    63  		b, err = f.Append(b, version)
    64  		if err != nil {
    65  			panic(fmt.Sprintf("error writing frame %#v: %s", f, err))
    66  		}
    67  		frameLen := protocol.ByteCount(len(b) - startLen)
    68  		if f.Length(version) != frameLen {
    69  			panic(fmt.Sprintf("inconsistent frame length for %#v: expected %d, got %d", f, frameLen, f.Length(version)))
    70  		}
    71  		if sf, ok := f.(*wire.StreamFrame); ok {
    72  			sf.PutBack()
    73  		}
    74  		if frameLen > protocol.ByteCount(parsedLen) {
    75  			panic(fmt.Sprintf("serialized length (%d) is longer than parsed length (%d)", len(b), parsedLen))
    76  		}
    77  	}
    78  
    79  	if numFrames == 0 {
    80  		return 0
    81  	}
    82  	return 1
    83  }
    84  
    85  func validateFrame(frame wire.Frame) {
    86  	switch f := frame.(type) {
    87  	case *wire.StreamFrame:
    88  		if protocol.ByteCount(len(f.Data)) != f.DataLen() {
    89  			panic("STREAM frame: inconsistent data length")
    90  		}
    91  	case *wire.AckFrame:
    92  		if f.DelayTime < 0 {
    93  			panic(fmt.Sprintf("invalid ACK delay_time: %s", f.DelayTime))
    94  		}
    95  		if f.LargestAcked() < f.LowestAcked() {
    96  			panic("ACK: largest acknowledged is smaller than lowest acknowledged")
    97  		}
    98  		for _, r := range f.AckRanges {
    99  			if r.Largest < 0 || r.Smallest < 0 {
   100  				panic("ACK range contains a negative packet number")
   101  			}
   102  		}
   103  		if !f.AcksPacket(f.LargestAcked()) {
   104  			panic("ACK frame claims that largest acknowledged is not acknowledged")
   105  		}
   106  		if !f.AcksPacket(f.LowestAcked()) {
   107  			panic("ACK frame claims that lowest acknowledged is not acknowledged")
   108  		}
   109  		_ = f.AcksPacket(100)
   110  		_ = f.AcksPacket((f.LargestAcked() + f.LowestAcked()) / 2)
   111  	case *wire.NewConnectionIDFrame:
   112  		if f.ConnectionID.Len() < 1 || f.ConnectionID.Len() > 20 {
   113  			panic(fmt.Sprintf("invalid NEW_CONNECTION_ID frame length: %s", f.ConnectionID))
   114  		}
   115  	case *wire.NewTokenFrame:
   116  		if len(f.Token) == 0 {
   117  			panic("NEW_TOKEN frame with an empty token")
   118  		}
   119  	case *wire.MaxStreamsFrame:
   120  		if f.MaxStreamNum > protocol.MaxStreamCount {
   121  			panic("MAX_STREAMS frame with an invalid Maximum Streams value")
   122  		}
   123  	case *wire.StreamsBlockedFrame:
   124  		if f.StreamLimit > protocol.MaxStreamCount {
   125  			panic("STREAMS_BLOCKED frame with an invalid Maximum Streams value")
   126  		}
   127  	case *wire.ConnectionCloseFrame:
   128  		if f.IsApplicationError && f.FrameType != 0 {
   129  			panic("CONNECTION_CLOSE for an application error containing a frame type")
   130  		}
   131  	}
   132  }