From 1ed2a1bc283a746e9da40fe76d1760ef2c407efa Mon Sep 17 00:00:00 2001 From: Conner Date: Fri, 29 Jul 2022 18:19:01 -0400 Subject: [PATCH] wtwire: migrate fuzz tests --- fuzz/wtwire/create_session.go | 21 ---- fuzz/wtwire/create_session_reply.go | 21 ---- fuzz/wtwire/delete_session.go | 21 ---- fuzz/wtwire/delete_session_reply.go | 21 ---- fuzz/wtwire/error.go | 21 ---- fuzz/wtwire/fuzz_utils.go | 76 ------------ fuzz/wtwire/init.go | 21 ---- fuzz/wtwire/state_update.go | 21 ---- fuzz/wtwire/state_update_reply.go | 21 ---- watchtower/wtwire/fuzz_test.go | 183 ++++++++++++++++++++++++++++ 10 files changed, 183 insertions(+), 244 deletions(-) delete mode 100644 fuzz/wtwire/create_session.go delete mode 100644 fuzz/wtwire/create_session_reply.go delete mode 100644 fuzz/wtwire/delete_session.go delete mode 100644 fuzz/wtwire/delete_session_reply.go delete mode 100644 fuzz/wtwire/error.go delete mode 100644 fuzz/wtwire/fuzz_utils.go delete mode 100644 fuzz/wtwire/init.go delete mode 100644 fuzz/wtwire/state_update.go delete mode 100644 fuzz/wtwire/state_update_reply.go create mode 100644 watchtower/wtwire/fuzz_test.go diff --git a/fuzz/wtwire/create_session.go b/fuzz/wtwire/create_session.go deleted file mode 100644 index b2bd3e705..000000000 --- a/fuzz/wtwire/create_session.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package wtwirefuzz - -import ( - "github.com/lightningnetwork/lnd/watchtower/wtwire" -) - -// Fuzz_create_session is used by go-fuzz. -func Fuzz_create_session(data []byte) int { - // Prefix with MsgCreateSession. - data = prefixWithMsgType(data, wtwire.MsgCreateSession) - - // Create an empty message so that the FuzzHarness func can check if the - // max payload constraint is violated. - emptyMsg := wtwire.CreateSession{} - - // Pass the message into our general fuzz harness for wire messages! - return harness(data, &emptyMsg) -} diff --git a/fuzz/wtwire/create_session_reply.go b/fuzz/wtwire/create_session_reply.go deleted file mode 100644 index e862e3e36..000000000 --- a/fuzz/wtwire/create_session_reply.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package wtwirefuzz - -import ( - "github.com/lightningnetwork/lnd/watchtower/wtwire" -) - -// Fuzz_create_session_reply is used by go-fuzz. -func Fuzz_create_session_reply(data []byte) int { - // Prefix with MsgCreateSessionReply. - data = prefixWithMsgType(data, wtwire.MsgCreateSessionReply) - - // Create an empty message so that the FuzzHarness func can check if the - // max payload constraint is violated. - emptyMsg := wtwire.CreateSessionReply{} - - // Pass the message into our general fuzz harness for wire messages! - return harness(data, &emptyMsg) -} diff --git a/fuzz/wtwire/delete_session.go b/fuzz/wtwire/delete_session.go deleted file mode 100644 index cca278093..000000000 --- a/fuzz/wtwire/delete_session.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package wtwirefuzz - -import ( - "github.com/lightningnetwork/lnd/watchtower/wtwire" -) - -// Fuzz_delete_session is used by go-fuzz. -func Fuzz_delete_session(data []byte) int { - // Prefix with MsgDeleteSession. - data = prefixWithMsgType(data, wtwire.MsgDeleteSession) - - // Create an empty message so that the FuzzHarness func can check if the - // max payload constraint is violated. - emptyMsg := wtwire.DeleteSession{} - - // Pass the message into our general fuzz harness for wire messages! - return harness(data, &emptyMsg) -} diff --git a/fuzz/wtwire/delete_session_reply.go b/fuzz/wtwire/delete_session_reply.go deleted file mode 100644 index ec890aa11..000000000 --- a/fuzz/wtwire/delete_session_reply.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package wtwirefuzz - -import ( - "github.com/lightningnetwork/lnd/watchtower/wtwire" -) - -// Fuzz_delete_session_reply is used by go-fuzz. -func Fuzz_delete_session_reply(data []byte) int { - // Prefix with MsgDeleteSessionReply. - data = prefixWithMsgType(data, wtwire.MsgDeleteSessionReply) - - // Create an empty message so that the FuzzHarness func can check if the - // max payload constraint is violated. - emptyMsg := wtwire.DeleteSessionReply{} - - // Pass the message into our general fuzz harness for wire messages! - return harness(data, &emptyMsg) -} diff --git a/fuzz/wtwire/error.go b/fuzz/wtwire/error.go deleted file mode 100644 index 7d73e1f30..000000000 --- a/fuzz/wtwire/error.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package wtwirefuzz - -import ( - "github.com/lightningnetwork/lnd/watchtower/wtwire" -) - -// Fuzz_error is used by go-fuzz. -func Fuzz_error(data []byte) int { - // Prefix with MsgError. - data = prefixWithMsgType(data, wtwire.MsgError) - - // Create an empty message so that the FuzzHarness func can check if the - // max payload constraint is violated. - emptyMsg := wtwire.Error{} - - // Pass the message into our general fuzz harness for wire messages! - return harness(data, &emptyMsg) -} diff --git a/fuzz/wtwire/fuzz_utils.go b/fuzz/wtwire/fuzz_utils.go deleted file mode 100644 index 06a00a2de..000000000 --- a/fuzz/wtwire/fuzz_utils.go +++ /dev/null @@ -1,76 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package wtwirefuzz - -import ( - "bytes" - "encoding/binary" - "fmt" - "reflect" - - "github.com/lightningnetwork/lnd/watchtower/wtwire" -) - -// prefixWithMsgType takes []byte and adds a wire protocol prefix -// to make the []byte into an actual message to be used in fuzzing. -func prefixWithMsgType(data []byte, prefix wtwire.MessageType) []byte { - var prefixBytes [2]byte - binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix)) - data = append(prefixBytes[:], data...) - return data -} - -// harness performs the actual fuzz testing of the appropriate wire message. -// This function will check that the passed-in message passes wire length checks, -// is a valid message once deserialized, and passes a sequence of serialization -// and deserialization checks. Returns an int that determines whether the input -// is unique or not. -func harness(data []byte, emptyMsg wtwire.Message) int { - // Create a reader with the byte array. - r := bytes.NewReader(data) - - // Make sure byte array length (excluding 2 bytes for message type) is - // less than max payload size for the wire message. We check this because - // otherwise `go-fuzz` will keep creating inputs that crash on ReadMessage - // due to a large message size. - payloadLen := uint32(len(data)) - 2 - if payloadLen > emptyMsg.MaxPayloadLength(0) { - // Ignore this input - max payload constraint violated. - return 1 - } - - msg, err := wtwire.ReadMessage(r, 0) - if err != nil { - // go-fuzz generated []byte that cannot be represented as a - // wire message but we will return 0 so go-fuzz can modify the - // input. - return 1 - } - - // We will serialize the message into a new bytes buffer. - var b bytes.Buffer - if _, err := wtwire.WriteMessage(&b, msg, 0); err != nil { - // Could not serialize message into bytes buffer, panic. - panic(err) - } - - // Deserialize the message from the serialized bytes buffer, and then - // assert that the original message is equal to the newly deserialized - // message. - newMsg, err := wtwire.ReadMessage(&b, 0) - if err != nil { - // Could not deserialize message from bytes buffer, panic. - panic(err) - } - - if !reflect.DeepEqual(msg, newMsg) { - // Deserialized message and original message are not - // deeply equal. - panic(fmt.Errorf("deserialized message and original message " + - "are not deeply equal.")) - } - - // Add this input to the corpus. - return 1 -} diff --git a/fuzz/wtwire/init.go b/fuzz/wtwire/init.go deleted file mode 100644 index ea157a646..000000000 --- a/fuzz/wtwire/init.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package wtwirefuzz - -import ( - "github.com/lightningnetwork/lnd/watchtower/wtwire" -) - -// Fuzz_init is used by go-fuzz. -func Fuzz_init(data []byte) int { - // Prefix with MsgInit. - data = prefixWithMsgType(data, wtwire.MsgInit) - - // Create an empty message so that the FuzzHarness func can check if the - // max payload constraint is violated. - emptyMsg := wtwire.Init{} - - // Pass the message into our general fuzz harness for wire messages! - return harness(data, &emptyMsg) -} diff --git a/fuzz/wtwire/state_update.go b/fuzz/wtwire/state_update.go deleted file mode 100644 index 82323e146..000000000 --- a/fuzz/wtwire/state_update.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package wtwirefuzz - -import ( - "github.com/lightningnetwork/lnd/watchtower/wtwire" -) - -// Fuzz_state_update is used by go-fuzz. -func Fuzz_state_update(data []byte) int { - // Prefix with MsgStateUpdate. - data = prefixWithMsgType(data, wtwire.MsgStateUpdate) - - // Create an empty message so that the FuzzHarness func can check if the - // max payload constraint is violated. - emptyMsg := wtwire.StateUpdate{} - - // Pass the message into our general fuzz harness for wire messages! - return harness(data, &emptyMsg) -} diff --git a/fuzz/wtwire/state_update_reply.go b/fuzz/wtwire/state_update_reply.go deleted file mode 100644 index c645031d4..000000000 --- a/fuzz/wtwire/state_update_reply.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -package wtwirefuzz - -import ( - "github.com/lightningnetwork/lnd/watchtower/wtwire" -) - -// Fuzz_state_update_reply is used by go-fuzz. -func Fuzz_state_update_reply(data []byte) int { - // Prefix with MsgStateUpdateReply. - data = prefixWithMsgType(data, wtwire.MsgStateUpdateReply) - - // Create an empty message so that the FuzzHarness func can check if the - // max payload constraint is violated. - emptyMsg := wtwire.StateUpdateReply{} - - // Pass the message into our general fuzz harness for wire messages! - return harness(data, &emptyMsg) -} diff --git a/watchtower/wtwire/fuzz_test.go b/watchtower/wtwire/fuzz_test.go new file mode 100644 index 000000000..7a6004013 --- /dev/null +++ b/watchtower/wtwire/fuzz_test.go @@ -0,0 +1,183 @@ +package wtwire + +import ( + "bytes" + "encoding/binary" + "reflect" + "testing" +) + +// prefixWithMsgType takes []byte and adds a wire protocol prefix +// to make the []byte into an actual message to be used in fuzzing. +func prefixWithMsgType(data []byte, prefix MessageType) []byte { + var prefixBytes [2]byte + binary.BigEndian.PutUint16(prefixBytes[:], uint16(prefix)) + data = append(prefixBytes[:], data...) + return data +} + +// harness performs the actual fuzz testing of the appropriate wire message. +// This function will check that the passed-in message passes wire length +// checks, is a valid message once deserialized, and passes a sequence of +// serialization and deserialization checks. Returns an int that determines +// whether the input is unique or not. +func harness(t *testing.T, data []byte, emptyMsg Message) { + // Create a reader with the byte array. + r := bytes.NewReader(data) + + // Make sure byte array length (excluding 2 bytes for message type) is + // less than max payload size for the wire message. + payloadLen := uint32(len(data)) - 2 + if payloadLen > emptyMsg.MaxPayloadLength(0) { + // Ignore this input - max payload constraint violated. + return + } + + msg, err := ReadMessage(r, 0) + if err != nil { + return + } + + // We will serialize the message into a new bytes buffer. + var b bytes.Buffer + if _, err := WriteMessage(&b, msg, 0); err != nil { + // Could not serialize message into bytes buffer, panic. + t.Fatal(err) + } + + // Deserialize the message from the serialized bytes buffer, and then + // assert that the original message is equal to the newly deserialized + // message. + newMsg, err := ReadMessage(&b, 0) + if err != nil { + // Could not deserialize message from bytes buffer, panic. + t.Fatal(err) + } + + if !reflect.DeepEqual(msg, newMsg) { + // Deserialized message and original message are not + // deeply equal. + t.Fatal("deserialized message and original message " + + "are not deeply equal.") + } +} + +func Fuzz_create_session_reply(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + // Prefix with MsgCreateSessionReply. + data = prefixWithMsgType(data, MsgCreateSessionReply) + + // Create an empty message so that the FuzzHarness func can + // check if the max payload constraint is violated. + emptyMsg := CreateSessionReply{} + + // Pass the message into our general fuzz harness for wire + // messages! + harness(t, data, &emptyMsg) + }) +} + +func Fuzz_create_session(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + // Prefix with MsgCreateSession. + data = prefixWithMsgType(data, MsgCreateSession) + + // Create an empty message so that the FuzzHarness func can + // check if the max payload constraint is violated. + emptyMsg := CreateSession{} + + // Pass the message into our general fuzz harness for wire + // messages! + harness(t, data, &emptyMsg) + }) +} + +func Fuzz_delete_session_reply(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + // Prefix with MsgDeleteSessionReply. + data = prefixWithMsgType(data, MsgDeleteSessionReply) + + // Create an empty message so that the FuzzHarness func can + // check if the max payload constraint is violated. + emptyMsg := DeleteSessionReply{} + + // Pass the message into our general fuzz harness for wire + // messages! + harness(t, data, &emptyMsg) + }) +} + +func Fuzz_delete_session(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + // Prefix with MsgDeleteSession. + data = prefixWithMsgType(data, MsgDeleteSession) + + // Create an empty message so that the FuzzHarness func can + // check if the max payload constraint is violated. + emptyMsg := DeleteSession{} + + // Pass the message into our general fuzz harness for wire + // messages! + harness(t, data, &emptyMsg) + }) +} + +func Fuzz_error(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + // Prefix with MsgError. + data = prefixWithMsgType(data, MsgError) + + // Create an empty message so that the FuzzHarness func can + // check if the max payload constraint is violated. + emptyMsg := Error{} + + // Pass the message into our general fuzz harness for wire + // messages! + harness(t, data, &emptyMsg) + }) +} + +func Fuzz_init(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + // Prefix with MsgInit. + data = prefixWithMsgType(data, MsgInit) + + // Create an empty message so that the FuzzHarness func can + // check if the max payload constraint is violated. + emptyMsg := Init{} + + // Pass the message into our general fuzz harness for wire + // messages! + harness(t, data, &emptyMsg) + }) +} + +func Fuzz_state_update_reply(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + // Prefix with MsgStateUpdateReply. + data = prefixWithMsgType(data, MsgStateUpdateReply) + + // Create an empty message so that the FuzzHarness func can + // check if the max payload constraint is violated. + emptyMsg := StateUpdateReply{} + + // Pass the message into our general fuzz harness for wire + // messages! + harness(t, data, &emptyMsg) + }) +} + +func Fuzz_state_update(f *testing.F) { + f.Fuzz(func(t *testing.T, data []byte) { + // Prefix with MsgStateUpdate. + data = prefixWithMsgType(data, MsgStateUpdate) + + // Create an empty message so that the FuzzHarness func can + // check if the max payload constraint is violated. + emptyMsg := StateUpdate{} + + // Pass the message into our general fuzz harness for wire + // messages! + harness(t, data, &emptyMsg) + }) +}