prysm-pulse/fuzz/README.md
Preston Van Loon cebb62997d
Add beacon state unmarshal fuzzer, afl support (#6625)
* Add AFL third_party libraries

* add beacon state fuzzing, add afl fuzz bundle

* rm fuzzing engine

* fix and lint

* Check for array out of bounds when calculating proposer delta

* failing test

* fix

* Checkpoint progress

* Add requirement that inclusion distance is not zero, add regression test

* No need for HTR since that is covered in process slots

* Removing some fuzzit logic, old fuzz tests

* Add ssz encoder test and fix

* Fuzzing checkpoint, adding fuzzing to the p2p layer

* ignore some libfuzzer files

* Full testing of p2p processing of blocks, with some mocked stuff

* use tmpdir and always process blocks

* use checkptr

* Update ethereumapis

* go mod tidy

* benchmarks for ferran's fast ssz hash tree root

* Update fastssz

* fmt

* gaz

* goimports

* Fix

* fix ethereumapis

* fix again

* kafka

* fix gen file

* fix compute signing root

* gofmt

* checkpoint progress

* progress

* checkpoint

* updates

* updates

* merge fix

* WIP

* merge

* fix build

* fix merge related issues

* cleanup

* revert unrelated

* lint

* lint

* lint

* manual tags for fuzz

* Commentary on upload script

* some import fixes, but not all

* fix //fuzz:fuzz_tests

* rm unused test

* update generated ssz

* Set // +build libfuzzer

* remove debug code

* A bit of refactoring ot explain why there is a committee_disabled file

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2020-09-14 11:42:08 -07:00

103 lines
3.3 KiB
Markdown

# Prysm Fuzz Testing
[![fuzzit](https://app.fuzzit.dev/badge?org_id=prysmaticlabs-gh)](https://app.fuzzit.dev/orgs/prysmaticlabs-gh/dashboard)
## Adding a fuzz test
Fuzz testing attempts to find crash level bugs within the tested code paths, but could also be used
as a sanity check certain logic.
### 1) Determining an ideal target
A fuzz test inputs pseudo-random data to a given method and attempts to find input data that tests
as many code branches as possible. When choosing a target to test, consider that the method under
test should be as stateless as possible. While stateful methods (i.e. methods that use a cache),
can be tested, they are often hard to reproduce in a regression test. Consider disabling any caches
or persistence layers if possible.
### 2) Writing a fuzz test
First, you need to determine in your input data. The current test suite uses SSZ encoded bytes to
deserialize to input objects.
_Example: Block header input data_
```go
type InputBlockWithPrestate struct {
StateID uint16
Block *ethpb.BeaconBlock
}
```
You'll also want to add that struct to `//fuzz:ssz_generated_files` to generate the custom fast SSZ
methods for serialization to improve test performance.
Your fuzz test must accept a single argument of type `[]byte`. The return types are ignored by
libfuzzer, but might be useful for other applications such as
[beacon-fuzz](https://github.com/sigp/beacon-fuzz). Be sure to name your test file with the
`_fuzz.go` suffix for consistency.
```go
func MyExampleFuzz(b []byte) {
input := &MyFuzzInputData{}
if err := ssz.Unmarshal(b, input); err != nil {
return // Input bytes doesn't serialize to input object.
}
result, err := somePackage.MethodUnderTest(input)
if err != nil {
// Input was invalid for processing, but the method didn't panic so that's OK.
return
}
// Optional: sanity check the resulting data.
if result < 0 {
panic("MethodUnderTest should never return a negative number") // Fail!
}
}
```
### 3) Add your fuzz target to fuzz/BUILD.bazel
Since we are using some custom rules to generate the fuzz test instrumentation and appropriate
libfuzz testing suite, we cannot rely on gazelle to generate these targets for us.
```starlark
go_fuzz_test(
name = "example_fuzz_test",
srcs = [
"example_fuzz.go",
] + COMMON_SRCS, # common and input type files.
corpus = "example_corpus",
corpus_path = "fuzz/example_corpus", # Path from root of project
func = "MyExampleFuzz",
importpath = IMPORT_PATH,
deps = [
# Deps used in your fuzz test.
] + COMMON_DEPS,
)
```
Be sure to add your target to the test suite at `//fuzz:fuzz_tests`.
### 4) Run your fuzz test
To run your fuzz test you must manually target it with bazel test and run with the config flag
`--config=fuzz`.
```
bazel test //fuzz:example_fuzz_test --config=fuzz
```
## Running fuzzit regression tests
To run fuzzit regression tests, you can run the fuzz test suite with the 1--config=fuzzit`
configuration flag. Note: This requires docker installed on your machine. See
[fuzzitdev/fuzzit#58](https://github.com/fuzzitdev/fuzzit/issues/58).
```
bazel test //fuzz:fuzz_tests --config=fuzzit
```
If the same command above is run with the FUZZIT_API_KEY environment variable set, then the fuzzit
test targets will be uploaded and restarted at https://app.fuzzit.dev.