github.com/decred/dcrlnd@v0.7.6/fuzz/wtwire/fuzz_utils.go (about)

     1  //go:build gofuzz
     2  // +build gofuzz
     3  
     4  package wtwirefuzz
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/binary"
     9  	"fmt"
    10  	"reflect"
    11  
    12  	"github.com/decred/dcrlnd/watchtower/wtwire"
    13  )
    14  
    15  // prefixWithMsgType takes []byte and adds a wire protocol prefix
    16  // to make the []byte into an actual message to be used in fuzzing.
    17  func prefixWithMsgType(data []byte, prefix wtwire.MessageType) []byte {
    18  	var prefixBytes [2]byte
    19  	binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix))
    20  	data = append(prefixBytes[:], data...)
    21  	return data
    22  }
    23  
    24  // harness performs the actual fuzz testing of the appropriate wire message.
    25  // This function will check that the passed-in message passes wire length checks,
    26  // is a valid message once deserialized, and passes a sequence of serialization
    27  // and deserialization checks. Returns an int that determines whether the input
    28  // is unique or not.
    29  func harness(data []byte, emptyMsg wtwire.Message) int {
    30  	// Create a reader with the byte array.
    31  	r := bytes.NewReader(data)
    32  
    33  	// Make sure byte array length (excluding 2 bytes for message type) is
    34  	// less than max payload size for the wire message. We check this because
    35  	// otherwise `go-fuzz` will keep creating inputs that crash on ReadMessage
    36  	// due to a large message size.
    37  	payloadLen := uint32(len(data)) - 2
    38  	if payloadLen > emptyMsg.MaxPayloadLength(0) {
    39  		// Ignore this input - max payload constraint violated.
    40  		return 1
    41  	}
    42  
    43  	msg, err := wtwire.ReadMessage(r, 0)
    44  	if err != nil {
    45  		// go-fuzz generated []byte that cannot be represented as a
    46  		// wire message but we will return 0 so go-fuzz can modify the
    47  		// input.
    48  		return 1
    49  	}
    50  
    51  	// We will serialize the message into a new bytes buffer.
    52  	var b bytes.Buffer
    53  	if _, err := wtwire.WriteMessage(&b, msg, 0); err != nil {
    54  		// Could not serialize message into bytes buffer, panic.
    55  		panic(err)
    56  	}
    57  
    58  	// Deserialize the message from the serialized bytes buffer, and then
    59  	// assert that the original message is equal to the newly deserialized
    60  	// message.
    61  	newMsg, err := wtwire.ReadMessage(&b, 0)
    62  	if err != nil {
    63  		// Could not deserialize message from bytes buffer, panic.
    64  		panic(err)
    65  	}
    66  
    67  	if !reflect.DeepEqual(msg, newMsg) {
    68  		// Deserialized message and original message are not
    69  		// deeply equal.
    70  		panic(fmt.Errorf("deserialized message and original message " +
    71  			"are not deeply equal."))
    72  	}
    73  
    74  	// Add this input to the corpus.
    75  	return 1
    76  }