Merge pull request #1895 from Crypt-iQ/lnwire_fuzzing_09_11_2018
fuzz: new fuzz package and lnwire parsing harnesses
This commit is contained in:
commit
462048ae81
54
docs/fuzz.md
Normal file
54
docs/fuzz.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Fuzzing LND #
|
||||||
|
|
||||||
|
The `fuzz` package is organized into subpackages which are named after the `lnd` package they test. Each subpackage has its own set of fuzz targets.
|
||||||
|
|
||||||
|
### Setup and Installation ###
|
||||||
|
This section will cover setup and installation of `go-fuzz` and fuzzing binaries.
|
||||||
|
|
||||||
|
* First, we must get `go-fuzz`.
|
||||||
|
```
|
||||||
|
$ go get -u github.com/dvyukov/go-fuzz/...
|
||||||
|
```
|
||||||
|
* The following is a command to build all fuzzing harnesses for a specific package.
|
||||||
|
```
|
||||||
|
$ cd fuzz/<package>
|
||||||
|
$ find * -maxdepth 1 -regex '[A-Za-z0-9\-_.]'* -not -name fuzz_utils.go | sed 's/\.go$//1' | xargs -I % sh -c 'go-fuzz-build -func Fuzz_% -o <package>-%-fuzz.zip github.com/lightningnetwork/lnd/fuzz/<package>'
|
||||||
|
```
|
||||||
|
|
||||||
|
* This may take a while since this will create zip files associated with each fuzzing target.
|
||||||
|
|
||||||
|
* Now, run `go-fuzz` with `workdir` set as below!
|
||||||
|
```
|
||||||
|
$ go-fuzz -bin=<.zip archive here> -workdir=<harness> -procs=<num workers>
|
||||||
|
```
|
||||||
|
|
||||||
|
`go-fuzz` will print out log lines every couple of seconds. Example output:
|
||||||
|
```
|
||||||
|
2017/09/19 17:44:23 workers: 8, corpus: 23 (3s ago), crashers: 1, restarts: 1/748, execs: 400690 (16694/sec), cover: 394, uptime: 24s
|
||||||
|
```
|
||||||
|
Corpus is the number of items in the corpus. `go-fuzz` may add valid inputs to
|
||||||
|
the corpus in an attempt to gain more coverage. Crashers is the number of inputs
|
||||||
|
resulting in a crash. The inputs, and their outputs are logged in:
|
||||||
|
`fuzz/<package>/<harness>/crashers`. `go-fuzz` also creates a `suppressions` directory
|
||||||
|
of stacktraces to ignore so that it doesn't create duplicate stacktraces.
|
||||||
|
Cover is a number representing edge coverage of the program being fuzzed.
|
||||||
|
|
||||||
|
### Brontide ###
|
||||||
|
The brontide fuzzers need to be run with a `-timeout` flag of 20 seconds or greater since there is a lot of machine state that must be printed on panic.
|
||||||
|
|
||||||
|
### Corpus ###
|
||||||
|
Fuzzing generally works best with a corpus that is of minimal size while achieving the maximum coverage. However, `go-fuzz` automatically minimizes the corpus in-memory before fuzzing so a large corpus shouldn't make a difference - edge coverage is all that really matters.
|
||||||
|
|
||||||
|
### Test Harness ###
|
||||||
|
If you take a look at the test harnesses that are used, you will see that they all consist of one function:
|
||||||
|
```
|
||||||
|
func Fuzz(data []byte) int
|
||||||
|
```
|
||||||
|
If:
|
||||||
|
|
||||||
|
- `-1` is returned, the fuzzing input is ignored
|
||||||
|
- `0` is returned, `go-fuzz` will add the input to the corpus and deprioritize it in future mutations.
|
||||||
|
- `1` is returned, `go-fuzz` will add the input to the corpus and prioritize it in future mutations.
|
||||||
|
|
||||||
|
### Conclusion ###
|
||||||
|
Citizens, do your part and `go-fuzz` `lnd` today!
|
@ -1,106 +0,0 @@
|
|||||||
# How to fuzz the Lightning Network Daemon's wire protocol using go-fuzz #
|
|
||||||
|
|
||||||
This document will describe how to use the fuzz-testing library `go-fuzz` on
|
|
||||||
the `lnd` wire protocol.
|
|
||||||
|
|
||||||
### Introduction ###
|
|
||||||
|
|
||||||
Lnd uses its own wire protocol to send and receive messages of all types. There
|
|
||||||
are 22 different message types, each with their own specific format. If a
|
|
||||||
message is not in the correct format, `lnd` should logically reject the message
|
|
||||||
and throw an error. But what if it doesn't? What if we could sneakily craft a
|
|
||||||
custom message that could pass all the necessary checks and cause an error to
|
|
||||||
go undetected? Chaos would ensue. However, crafting such a message would require
|
|
||||||
an in-depth understanding of the many different cogs that make the wire protocol
|
|
||||||
tick.
|
|
||||||
|
|
||||||
A better solution is fuzz-testing. Fuzz-testing or fuzzing is when a program
|
|
||||||
known as a fuzzer generates many, many inputs to a function or program in an
|
|
||||||
attempt to cause it to crash. Fuzzing is surprisingly effective at finding bugs
|
|
||||||
and a particular fuzzing program `AFL` is well-known for the amount of bugs it
|
|
||||||
has found with its learned approach. The library we will be using, `go-fuzz`, is
|
|
||||||
based on `AFL` and has quite a track record of finding bugs in a diverse set of
|
|
||||||
go programs. `go-fuzz` takes a coverage-guided approach in an attempt to cover
|
|
||||||
as many code paths as possible on an attack surface. We give `go-fuzz` real,
|
|
||||||
valid inputs and it will essentially change bits until it achieves a crash!
|
|
||||||
After reading this document, you too may be able to find errors in `lnd` with
|
|
||||||
`go-fuzz`!
|
|
||||||
|
|
||||||
### Setup and Installation ###
|
|
||||||
This section will cover setup and installation of `go-fuzz`.
|
|
||||||
|
|
||||||
* First, we must get `go-fuzz`:
|
|
||||||
```
|
|
||||||
$ go get github.com/dvyukov/go-fuzz/go-fuzz
|
|
||||||
$ go get github.com/dvyukov/go-fuzz/go-fuzz-build
|
|
||||||
```
|
|
||||||
* Next, create a folder in the `lnwire` package. You can name it whatever.
|
|
||||||
```
|
|
||||||
$ mkdir lnwire/<folder name here>
|
|
||||||
```
|
|
||||||
* Unzip `corpus.tar.gz` in the `docs/go-fuzz` folder and move it to the folder you just made.
|
|
||||||
```
|
|
||||||
$ tar -xzf docs/go-fuzz/corpus.tar.gz
|
|
||||||
$ mv corpus lnwire/<folder name here>
|
|
||||||
```
|
|
||||||
* Now, move `wirefuzz.go` to the same folder you just created.
|
|
||||||
```
|
|
||||||
$ mv docs/go-fuzz/wirefuzz.go lnwire/<folder name here>
|
|
||||||
```
|
|
||||||
* Change the package name in `wirefuzz.go` from `wirefuzz` to `<folder name here>`.
|
|
||||||
* Build the test program - this produces a `<folder name here>-fuzz.zip` (archive) file.
|
|
||||||
```
|
|
||||||
$ go-fuzz-build github.com/lightningnetwork/lnd/lnwire/<folder name here>
|
|
||||||
```
|
|
||||||
* Now, run `go-fuzz`!!!
|
|
||||||
```
|
|
||||||
$ go-fuzz -bin=<.zip archive here> -workdir=lnwire/<folder name here>
|
|
||||||
```
|
|
||||||
|
|
||||||
`go-fuzz` will print out log lines every couple of seconds. Example output:
|
|
||||||
```
|
|
||||||
2017/09/19 17:44:23 slaves: 8, corpus: 23 (3s ago), crashers: 1, restarts: 1/748, execs: 400690 (16694/sec), cover: 394, uptime: 24s
|
|
||||||
```
|
|
||||||
Corpus is the number of items in the corpus. `go-fuzz` may add valid inputs to
|
|
||||||
the corpus in an attempt to gain more coverage. Crashers is the number of inputs
|
|
||||||
resulting in a crash. The inputs, and their outputs are logged in:
|
|
||||||
`<folder name here>/crashers`. `go-fuzz` also creates a `suppressions` directory
|
|
||||||
of stacktraces to ignore so that it doesn't create duplicate stacktraces.
|
|
||||||
Cover is a number representing coverage of the program being fuzzed. When I ran
|
|
||||||
this earlier, `go-fuzz` found two bugs ([#310](https://github.com/lightningnetwork/lnd/pull/310) and [#312](https://github.com/lightningnetwork/lnd/pull/312)) within minutes!
|
|
||||||
|
|
||||||
### Corpus Notes ###
|
|
||||||
You may wonder how I made the corpus that you unzipped in the previous step.
|
|
||||||
It's quite simple really. For every message type that `lnwire_test.go`
|
|
||||||
processed in `TestLightningWireProtocol`, I logged it (in `[]byte` format) to
|
|
||||||
a .txt file. Within minutes, I had a corpus of valid `lnwire` messages that
|
|
||||||
I could use with `go-fuzz`! `go-fuzz` will alter these valid messages to create
|
|
||||||
the sneakily crafted message that I described in the introduction that manages
|
|
||||||
to bypass validation checks and crash the program. I ran `go-fuzz` for several
|
|
||||||
hours on the corpus I generated and found two bugs. I believe I have exhausted
|
|
||||||
the current corpus, but there are still perhaps possible malicious inputs that
|
|
||||||
`go-fuzz` has not yet reached and could reach with a slightly different generated
|
|
||||||
corpus.
|
|
||||||
|
|
||||||
### Test Harness ###
|
|
||||||
If you take a look at the test harness that I used, `wirefuzz.go`, you will see
|
|
||||||
that it consists of one function: `func Fuzz(data []byte) int`. `go-fuzz` requires
|
|
||||||
that each input in the corpus is in `[]byte` format. The test harness is also
|
|
||||||
quite simple. It reads in `[]byte` messages into `lnwire.Message` objects,
|
|
||||||
serializes them into a buffer, deserializes them back into `lnwire.Message` objects
|
|
||||||
and asserts their equality. If the pre-serialization and post-deserialization
|
|
||||||
`lnwire.Message` objects are not equal, the wire protocol has encountered a bug.
|
|
||||||
Wherever a `0` is returned, `go-fuzz` will ignore that input as it has reached
|
|
||||||
an unimportant code path caused by the parser catching the error. If a `1` is
|
|
||||||
returned, the `[]byte` input was parsed successfully and the two `lnwire.Message`
|
|
||||||
objects were indeed equal. This `[]byte` input is then added to the corpus as
|
|
||||||
a valid message. If a `panic` is reached, serialization or deserialization failed
|
|
||||||
and `go-fuzz` may have found a bug.
|
|
||||||
|
|
||||||
### Conclusion ###
|
|
||||||
Fuzzing is a powerful and quick way to find bugs in programs that works especially
|
|
||||||
well with protocols where there is a strict format with validation rules. Fuzzing
|
|
||||||
is important as an automated security tool and can find real bugs in real-world
|
|
||||||
software. The fuzzing of `lnd` is by no means complete and there exist probably
|
|
||||||
many more bugs in the software that may `go` undetected if left unfuzzed. Citizens,
|
|
||||||
do your part and `go-fuzz` `lnd` today!
|
|
Binary file not shown.
@ -1,54 +0,0 @@
|
|||||||
package wirefuzz
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Fuzz is used by go-fuzz to fuzz for potentially malicious input
|
|
||||||
func Fuzz(data []byte) int {
|
|
||||||
// Because go-fuzz requires this function signature with a []byte parameter,
|
|
||||||
// and we want to emulate the behavior of mainScenario in lnwire_test.go,
|
|
||||||
// we first parse the []byte parameter into a Message type.
|
|
||||||
|
|
||||||
// Parsing []byte into Message
|
|
||||||
r := bytes.NewReader(data)
|
|
||||||
msg, err := lnwire.ReadMessage(r, 0)
|
|
||||||
if err != nil {
|
|
||||||
// Ignore this input - go-fuzz generated []byte that cannot be represented as Message
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// We will serialize Message into a new bytes buffer
|
|
||||||
var b bytes.Buffer
|
|
||||||
if _, err := lnwire.WriteMessage(&b, msg, 0); err != nil {
|
|
||||||
// Could not serialize Message into bytes buffer, panic
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure serialized bytes buffer (excluding 2 bytes for message type
|
|
||||||
// is less than max payload size for this specific message,.
|
|
||||||
payloadLen := uint32(b.Len()) - 2
|
|
||||||
if payloadLen > msg.MaxPayloadLength(0) {
|
|
||||||
// Ignore this input - max payload constraint violated
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deserialize the message from the serialized bytes buffer and
|
|
||||||
// assert that the original message is equal to the newly deserialized message.
|
|
||||||
newMsg, err := lnwire.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."))
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
|
135
fuzz/lnwire/accept_channel.go
Normal file
135
fuzz/lnwire/accept_channel.go
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_accept_channel is used by go-fuzz.
|
||||||
|
func Fuzz_accept_channel(data []byte) int {
|
||||||
|
// Prefix with MsgAcceptChannel.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgAcceptChannel)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.AcceptChannel{}
|
||||||
|
|
||||||
|
// We have to do this here instead of in fuzz.Harness so that
|
||||||
|
// reflect.DeepEqual isn't called. Because of the UpfrontShutdownScript
|
||||||
|
// encoding, the first message and second message aren't deeply equal since
|
||||||
|
// the first has a nil slice and the other has an empty slice.
|
||||||
|
|
||||||
|
// 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 := lnwire.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 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will serialize the message into a new bytes buffer.
|
||||||
|
var b bytes.Buffer
|
||||||
|
if _, err := lnwire.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 := lnwire.ReadMessage(&b, 0)
|
||||||
|
if err != nil {
|
||||||
|
// Could not deserialize message from bytes buffer, panic
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now compare every field instead of using reflect.DeepEqual.
|
||||||
|
// For UpfrontShutdownScript, we only compare bytes. This probably takes
|
||||||
|
// up more branches than necessary, but that's fine for now.
|
||||||
|
var shouldPanic bool
|
||||||
|
first := msg.(*lnwire.AcceptChannel)
|
||||||
|
second := newMsg.(*lnwire.AcceptChannel)
|
||||||
|
|
||||||
|
if !bytes.Equal(first.PendingChannelID[:], second.PendingChannelID[:]) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.DustLimit != second.DustLimit {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.MaxValueInFlight != second.MaxValueInFlight {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.ChannelReserve != second.ChannelReserve {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.HtlcMinimum != second.HtlcMinimum {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.MinAcceptDepth != second.MinAcceptDepth {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.CsvDelay != second.CsvDelay {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.MaxAcceptedHTLCs != second.MaxAcceptedHTLCs {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.FundingKey.IsEqual(second.FundingKey) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.RevocationPoint.IsEqual(second.RevocationPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.PaymentPoint.IsEqual(second.PaymentPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.DelayedPaymentPoint.IsEqual(second.DelayedPaymentPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.HtlcPoint.IsEqual(second.HtlcPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.FirstCommitmentPoint.IsEqual(second.FirstCommitmentPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(first.UpfrontShutdownScript, second.UpfrontShutdownScript) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldPanic {
|
||||||
|
panic("original message and deserialized message are not equal")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this input to the corpus.
|
||||||
|
return 1
|
||||||
|
}
|
20
fuzz/lnwire/announce_signatures.go
Normal file
20
fuzz/lnwire/announce_signatures.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_announce_signatures is used by go-fuzz.
|
||||||
|
func Fuzz_announce_signatures(data []byte) int {
|
||||||
|
// Prefix with MsgAnnounceSignatures.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgAnnounceSignatures)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.AnnounceSignatures{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/channel_announcement.go
Normal file
20
fuzz/lnwire/channel_announcement.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_channel_announcement is used by go-fuzz.
|
||||||
|
func Fuzz_channel_announcement(data []byte) int {
|
||||||
|
// Prefix with MsgChannelAnnouncement.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgChannelAnnouncement)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.ChannelAnnouncement{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/channel_reestablish.go
Normal file
20
fuzz/lnwire/channel_reestablish.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_channel_reestablish is used by go-fuzz.
|
||||||
|
func Fuzz_channel_reestablish(data []byte) int {
|
||||||
|
// Prefix with MsgChannelReestablish.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgChannelReestablish)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.ChannelReestablish{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/channel_update.go
Normal file
20
fuzz/lnwire/channel_update.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_channel_update is used by go-fuzz.
|
||||||
|
func Fuzz_channel_update(data []byte) int {
|
||||||
|
// Prefix with MsgChannelUpdate.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgChannelUpdate)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.ChannelUpdate{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/closing_signed.go
Normal file
20
fuzz/lnwire/closing_signed.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_closing_signed is used by go-fuzz.
|
||||||
|
func Fuzz_closing_signed(data []byte) int {
|
||||||
|
// Prefix with MsgClosingSigned.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgClosingSigned)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.ClosingSigned{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/commit_sig.go
Normal file
20
fuzz/lnwire/commit_sig.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_commit_sig is used by go-fuzz.
|
||||||
|
func Fuzz_commit_sig(data []byte) int {
|
||||||
|
// Prefix with MsgCommitSig.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgCommitSig)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.CommitSig{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/error.go
Normal file
20
fuzz/lnwire/error.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_error is used by go-fuzz.
|
||||||
|
func Fuzz_error(data []byte) int {
|
||||||
|
// Prefix with MsgError.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgError)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.Error{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/funding_created.go
Normal file
20
fuzz/lnwire/funding_created.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_funding_created is used by go-fuzz.
|
||||||
|
func Fuzz_funding_created(data []byte) int {
|
||||||
|
// Prefix with MsgFundingCreated.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgFundingCreated)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.FundingCreated{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/funding_locked.go
Normal file
20
fuzz/lnwire/funding_locked.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_funding_locked is used by go-fuzz.
|
||||||
|
func Fuzz_funding_locked(data []byte) int {
|
||||||
|
// Prefix with MsgFundingLocked.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgFundingLocked)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.FundingLocked{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/funding_signed.go
Normal file
20
fuzz/lnwire/funding_signed.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_funding_signed is used by go-fuzz.
|
||||||
|
func Fuzz_funding_signed(data []byte) int {
|
||||||
|
// Prefix with MsgFundingSigned.
|
||||||
|
prefixWithMsgType(data, lnwire.MsgFundingSigned)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.FundingSigned{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
72
fuzz/lnwire/fuzz_utils.go
Normal file
72
fuzz/lnwire/fuzz_utils.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 lnwire.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 lnwire.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 := lnwire.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 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will serialize the message into a new bytes buffer.
|
||||||
|
var b bytes.Buffer
|
||||||
|
if _, err := lnwire.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 := lnwire.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("original message and deserialized message are not deeply equal")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this input to the corpus.
|
||||||
|
return 1
|
||||||
|
}
|
20
fuzz/lnwire/gossip_timestamp_range.go
Normal file
20
fuzz/lnwire/gossip_timestamp_range.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_gossip_timestamp_range is used by go-fuzz.
|
||||||
|
func Fuzz_gossip_timestamp_range(data []byte) int {
|
||||||
|
// Prefix with MsgGossipTimestampRange.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgGossipTimestampRange)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.GossipTimestampRange{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/init.go
Normal file
20
fuzz/lnwire/init.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_init is used by go-fuzz.
|
||||||
|
func Fuzz_init(data []byte) int {
|
||||||
|
// Prefix with MsgInit.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgInit)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.Init{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
112
fuzz/lnwire/node_announcement.go
Normal file
112
fuzz/lnwire/node_announcement.go
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_node_announcement is used by go-fuzz.
|
||||||
|
func Fuzz_node_announcement(data []byte) int {
|
||||||
|
// Prefix with MsgNodeAnnouncement.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgNodeAnnouncement)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.NodeAnnouncement{}
|
||||||
|
|
||||||
|
// We have to do this here instead of in fuzz.Harness so that
|
||||||
|
// reflect.DeepEqual isn't called. Address (de)serialization messes up
|
||||||
|
// the fuzzing assertions.
|
||||||
|
|
||||||
|
// 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 := lnwire.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 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will serialize the message into a new bytes buffer.
|
||||||
|
var b bytes.Buffer
|
||||||
|
if _, err := lnwire.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 := lnwire.ReadMessage(&b, 0)
|
||||||
|
if err != nil {
|
||||||
|
// Could not deserialize message from bytes buffer, panic
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now compare every field instead of using reflect.DeepEqual for the
|
||||||
|
// Addresses field.
|
||||||
|
var shouldPanic bool
|
||||||
|
first := msg.(*lnwire.NodeAnnouncement)
|
||||||
|
second := newMsg.(*lnwire.NodeAnnouncement)
|
||||||
|
if !bytes.Equal(first.Signature[:], second.Signature[:]) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(first.Features, second.Features) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.Timestamp != second.Timestamp {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(first.NodeID[:], second.NodeID[:]) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(first.RGBColor, second.RGBColor) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(first.Alias[:], second.Alias[:]) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(first.Addresses) != len(second.Addresses) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range first.Addresses {
|
||||||
|
if first.Addresses[i].String() != second.Addresses[i].String() {
|
||||||
|
shouldPanic = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(first.ExtraOpaqueData, second.ExtraOpaqueData) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldPanic {
|
||||||
|
panic("original message and deserialized message are not equal")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this input to the corpus.
|
||||||
|
return 1
|
||||||
|
}
|
151
fuzz/lnwire/open_channel.go
Normal file
151
fuzz/lnwire/open_channel.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_open_channel is used by go-fuzz.
|
||||||
|
func Fuzz_open_channel(data []byte) int {
|
||||||
|
// Prefix with MsgOpenChannel.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgOpenChannel)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.OpenChannel{}
|
||||||
|
|
||||||
|
// We have to do this here instead of in fuzz.Harness so that
|
||||||
|
// reflect.DeepEqual isn't called. Because of the UpfrontShutdownScript
|
||||||
|
// encoding, the first message and second message aren't deeply equal since
|
||||||
|
// the first has a nil slice and the other has an empty slice.
|
||||||
|
|
||||||
|
// 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 := lnwire.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 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will serialize the message into a new bytes buffer.
|
||||||
|
var b bytes.Buffer
|
||||||
|
if _, err := lnwire.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 := lnwire.ReadMessage(&b, 0)
|
||||||
|
if err != nil {
|
||||||
|
// Could not deserialize message from bytes buffer, panic
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now compare every field instead of using reflect.DeepEqual.
|
||||||
|
// For UpfrontShutdownScript, we only compare bytes. This probably takes
|
||||||
|
// up more branches than necessary, but that's fine for now.
|
||||||
|
var shouldPanic bool
|
||||||
|
first := msg.(*lnwire.OpenChannel)
|
||||||
|
second := newMsg.(*lnwire.OpenChannel)
|
||||||
|
|
||||||
|
if !first.ChainHash.IsEqual(&second.ChainHash) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(first.PendingChannelID[:], second.PendingChannelID[:]) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.FundingAmount != second.FundingAmount {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.PushAmount != second.PushAmount {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.DustLimit != second.DustLimit {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.MaxValueInFlight != second.MaxValueInFlight {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.ChannelReserve != second.ChannelReserve {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.HtlcMinimum != second.HtlcMinimum {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.FeePerKiloWeight != second.FeePerKiloWeight {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.CsvDelay != second.CsvDelay {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.MaxAcceptedHTLCs != second.MaxAcceptedHTLCs {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.FundingKey.IsEqual(second.FundingKey) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.RevocationPoint.IsEqual(second.RevocationPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.PaymentPoint.IsEqual(second.PaymentPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.DelayedPaymentPoint.IsEqual(second.DelayedPaymentPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.HtlcPoint.IsEqual(second.HtlcPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !first.FirstCommitmentPoint.IsEqual(second.FirstCommitmentPoint) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if first.ChannelFlags != second.ChannelFlags {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(first.UpfrontShutdownScript, second.UpfrontShutdownScript) {
|
||||||
|
shouldPanic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldPanic {
|
||||||
|
panic("original message and deserialized message are not equal")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this input to the corpus.
|
||||||
|
return 1
|
||||||
|
}
|
20
fuzz/lnwire/ping.go
Normal file
20
fuzz/lnwire/ping.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_ping is used by go-fuzz.
|
||||||
|
func Fuzz_ping(data []byte) int {
|
||||||
|
// Prefix with MsgPing.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgPing)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.Ping{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/pong.go
Normal file
20
fuzz/lnwire/pong.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_pong is used by go-fuzz.
|
||||||
|
func Fuzz_pong(data []byte) int {
|
||||||
|
// Prefix with MsgPong.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgPong)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.Pong{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/query_channel_range.go
Normal file
20
fuzz/lnwire/query_channel_range.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_query_channel_range is used by go-fuzz.
|
||||||
|
func Fuzz_query_channel_range(data []byte) int {
|
||||||
|
// Prefix with MsgQueryChannelRange.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgQueryChannelRange)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.QueryChannelRange{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/query_short_chan_ids.go
Normal file
20
fuzz/lnwire/query_short_chan_ids.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_query_short_chan_ids is used by go-fuzz.
|
||||||
|
func Fuzz_query_short_chan_ids(data []byte) int {
|
||||||
|
// Prefix with MsgQueryShortChanIDs.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgQueryShortChanIDs)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.QueryShortChanIDs{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
51
fuzz/lnwire/query_short_chan_ids_zlib.go
Normal file
51
fuzz/lnwire/query_short_chan_ids_zlib.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"compress/zlib"
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_query_short_chan_ids_zlib is used by go-fuzz.
|
||||||
|
func Fuzz_query_short_chan_ids_zlib(data []byte) int {
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
zlibWriter := zlib.NewWriter(&buf)
|
||||||
|
_, err := zlibWriter.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
// Zlib bug?
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := zlibWriter.Close(); err != nil {
|
||||||
|
// Zlib bug?
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
compressedPayload := buf.Bytes()
|
||||||
|
|
||||||
|
chainhash := []byte("00000000000000000000000000000000")
|
||||||
|
numBytesInBody := len(compressedPayload) + 1
|
||||||
|
zlibByte := []byte("\x01")
|
||||||
|
|
||||||
|
bodyBytes := make([]byte, 2)
|
||||||
|
binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody))
|
||||||
|
|
||||||
|
payload := append(chainhash, bodyBytes...)
|
||||||
|
payload = append(payload, zlibByte...)
|
||||||
|
payload = append(payload, compressedPayload...)
|
||||||
|
|
||||||
|
// Prefix with MsgQueryShortChanIDs.
|
||||||
|
payload = prefixWithMsgType(payload, lnwire.MsgQueryShortChanIDs)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.QueryShortChanIDs{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(payload, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/reply_channel_range.go
Normal file
20
fuzz/lnwire/reply_channel_range.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_reply_channel_range is used by go-fuzz.
|
||||||
|
func Fuzz_reply_channel_range(data []byte) int {
|
||||||
|
// Prefix with MsgReplyChannelRange.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgReplyChannelRange)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.ReplyChannelRange{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
59
fuzz/lnwire/reply_channel_range_zlib.go
Normal file
59
fuzz/lnwire/reply_channel_range_zlib.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"compress/zlib"
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_reply_channel_range_zlib is used by go-fuzz.
|
||||||
|
func Fuzz_reply_channel_range_zlib(data []byte) int {
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
zlibWriter := zlib.NewWriter(&buf)
|
||||||
|
_, err := zlibWriter.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
// Zlib bug?
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := zlibWriter.Close(); err != nil {
|
||||||
|
// Zlib bug?
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
compressedPayload := buf.Bytes()
|
||||||
|
|
||||||
|
// Initialize some []byte vars which will prefix our payload
|
||||||
|
chainhash := []byte("00000000000000000000000000000000")
|
||||||
|
firstBlockHeight := []byte("\x00\x00\x00\x00")
|
||||||
|
numBlocks := []byte("\x00\x00\x00\x00")
|
||||||
|
completeByte := []byte("\x00")
|
||||||
|
|
||||||
|
numBytesInBody := len(compressedPayload) + 1
|
||||||
|
zlibByte := []byte("\x01")
|
||||||
|
|
||||||
|
bodyBytes := make([]byte, 2)
|
||||||
|
binary.BigEndian.PutUint16(bodyBytes, uint16(numBytesInBody))
|
||||||
|
|
||||||
|
payload := append(chainhash, firstBlockHeight...)
|
||||||
|
payload = append(payload, numBlocks...)
|
||||||
|
payload = append(payload, completeByte...)
|
||||||
|
payload = append(payload, bodyBytes...)
|
||||||
|
payload = append(payload, zlibByte...)
|
||||||
|
payload = append(payload, compressedPayload...)
|
||||||
|
|
||||||
|
// Prefix with MsgReplyChannelRange.
|
||||||
|
payload = prefixWithMsgType(payload, lnwire.MsgReplyChannelRange)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.ReplyChannelRange{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(payload, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/reply_short_chan_ids_end.go
Normal file
20
fuzz/lnwire/reply_short_chan_ids_end.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_reply_short_chan_ids_end is used by go-fuzz.
|
||||||
|
func Fuzz_reply_short_chan_ids_end(data []byte) int {
|
||||||
|
// Prefix with MsgReplyShortChanIDsEnd.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgReplyShortChanIDsEnd)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.ReplyShortChanIDsEnd{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/revoke_and_ack.go
Normal file
20
fuzz/lnwire/revoke_and_ack.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_revoke_and_ack is used by go-fuzz.
|
||||||
|
func Fuzz_revoke_and_ack(data []byte) int {
|
||||||
|
// Prefix with MsgRevokeAndAck.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgRevokeAndAck)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.RevokeAndAck{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/shutdown.go
Normal file
20
fuzz/lnwire/shutdown.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_shutdown is used by go-fuzz.
|
||||||
|
func Fuzz_shutdown(data []byte) int {
|
||||||
|
// Prefix with MsgShutdown.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgShutdown)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.Shutdown{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/update_add_htlc.go
Normal file
20
fuzz/lnwire/update_add_htlc.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_update_add_htlc is used by go-fuzz.
|
||||||
|
func Fuzz_update_add_htlc(data []byte) int {
|
||||||
|
// Prefix with MsgUpdateAddHTLC.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgUpdateAddHTLC)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.UpdateAddHTLC{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/update_fail_htlc.go
Normal file
20
fuzz/lnwire/update_fail_htlc.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_update_fail_htlc is used by go-fuzz.
|
||||||
|
func Fuzz_update_fail_htlc(data []byte) int {
|
||||||
|
// Prefix with MsgUpdateFailHTLC.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgUpdateFailHTLC)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.UpdateFailHTLC{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/update_fail_malformed_htlc.go
Normal file
20
fuzz/lnwire/update_fail_malformed_htlc.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_update_fail_malformed_htlc is used by go-fuzz.
|
||||||
|
func Fuzz_update_fail_malformed_htlc(data []byte) int {
|
||||||
|
// Prefix with MsgUpdateFailMalformedHTLC.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgUpdateFailMalformedHTLC)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.UpdateFailMalformedHTLC{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/update_fee.go
Normal file
20
fuzz/lnwire/update_fee.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_update_fee is used by go-fuzz.
|
||||||
|
func Fuzz_update_fee(data []byte) int {
|
||||||
|
// Prefix with MsgUpdateFee.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgUpdateFee)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.UpdateFee{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
20
fuzz/lnwire/update_fulfill_htlc.go
Normal file
20
fuzz/lnwire/update_fulfill_htlc.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// +build gofuzz
|
||||||
|
|
||||||
|
package lnwirefuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fuzz_update_fulfill_htlc is used by go-fuzz.
|
||||||
|
func Fuzz_update_fulfill_htlc(data []byte) int {
|
||||||
|
// Prefix with MsgUpdateFulfillHTLC.
|
||||||
|
data = prefixWithMsgType(data, lnwire.MsgUpdateFulfillHTLC)
|
||||||
|
|
||||||
|
// Create an empty message so that the FuzzHarness func can check
|
||||||
|
// if the max payload constraint is violated.
|
||||||
|
emptyMsg := lnwire.UpdateFulfillHTLC{}
|
||||||
|
|
||||||
|
// Pass the message into our general fuzz harness for wire messages!
|
||||||
|
return harness(data, &emptyMsg)
|
||||||
|
}
|
@ -148,13 +148,6 @@ func decodeShortChanIDs(r io.Reader) (ShortChanIDEncoding, []ShortChannelID, err
|
|||||||
// as that was just the encoding type.
|
// as that was just the encoding type.
|
||||||
queryBody = queryBody[1:]
|
queryBody = queryBody[1:]
|
||||||
|
|
||||||
// At this point, if there's no body remaining, then only the encoding
|
|
||||||
// type was specified, meaning that there're no further bytes to be
|
|
||||||
// parsed.
|
|
||||||
if len(queryBody) == 0 {
|
|
||||||
return encodingType, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, depending on the encoding type, we'll decode the encode
|
// Otherwise, depending on the encoding type, we'll decode the encode
|
||||||
// short channel ID's in a different manner.
|
// short channel ID's in a different manner.
|
||||||
switch encodingType {
|
switch encodingType {
|
||||||
@ -210,6 +203,13 @@ func decodeShortChanIDs(r io.Reader) (ShortChanIDEncoding, []ShortChannelID, err
|
|||||||
zlibDecodeMtx.Lock()
|
zlibDecodeMtx.Lock()
|
||||||
defer zlibDecodeMtx.Unlock()
|
defer zlibDecodeMtx.Unlock()
|
||||||
|
|
||||||
|
// At this point, if there's no body remaining, then only the encoding
|
||||||
|
// type was specified, meaning that there're no further bytes to be
|
||||||
|
// parsed.
|
||||||
|
if len(queryBody) == 0 {
|
||||||
|
return encodingType, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Before we start to decode, we'll create a limit reader over
|
// Before we start to decode, we'll create a limit reader over
|
||||||
// the current reader. This will ensure that we can control how
|
// the current reader. This will ensure that we can control how
|
||||||
// much memory we're allocating during the decoding process.
|
// much memory we're allocating during the decoding process.
|
||||||
|
Loading…
Reference in New Issue
Block a user