Skip to content

Commit

Permalink
feat: add fuzzing (#651)
Browse files Browse the repository at this point in the history
* macro docs improvements

* wip

* fuzz experiments

* macro errors

* wip

* add fuzz makefile & docs

* add generative fuzz for account module implementation

This commit introduces a generative model for the accounts module
implementation that will generate valid messages to update the account
address.

It also fixes a bug where a prefix with an unaligned vector could be
created by declaring an API module, combining its prefixes, and
generating a vec would result in potentially unaligned vectors.

* fix statemap arbitrary generation

* fix lint nits

* rollback aligned vec assertion for tests

* fix native requirement for arbitrary implementation

* fix arbitrary workset to use genesis

* fix merge generated errors

* remove cargo.lock from fuzz directory

---------

Co-authored-by: Filippo Costa <[email protected]>
  • Loading branch information
vlopes11 and neysofu authored Aug 29, 2023
1 parent 693ecb6 commit b06c98b
Show file tree
Hide file tree
Showing 48 changed files with 648 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.idea/

target/
fuzz/Cargo.lock

.DS_Store

Expand Down
23 changes: 23 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ jmt = { git = "https://github.com/penumbra-zone/jmt", commit = "46b4b00" }
# External dependencies
async-trait = "0.1.71"
anyhow = "1.0.68"
arbitrary = { version = "1.3.0", features = ["derive"] }
borsh = { version = "0.10.3", features = ["rc", "bytes"] }
# TODO: Consider replacing this serialization format
# https://github.com/Sovereign-Labs/sovereign-sdk/issues/283
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ lint-fix: ## cargo fmt, fix and clippy
check-features: ## Checks that project compiles with all combinations of features. default is not needed because we never check `cfg(default)`, we only use it as an alias.
cargo hack check --workspace --feature-powerset --exclude-features default

check-fuzz: ## Checks that fuzz member compiles
$(MAKE) -C fuzz check

find-unused-deps: ## Prints unused dependencies for project. Note: requires nightly
cargo udeps --all-targets --all-features

Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ to have adapters for almost all Data Availability Layers and LLVM-compatible pro
maintain adapters for [`Risc0`](https://www.risczero.com) (a ZKVM) and [`Celestia`](https://www.celestia.org) a (DA layer).
The Avail project also maintains an adapter for their DA layer, which can be found [here](https://github.com/availproject/avail-sovereign-da-adapter).

## Testing

An implementation of LLVM's libFUZZER is available under [fuzz/README.md](./fuzz/README.md).

## Warning

The Sovereign SDK is Alpha software. It has not been audited and should not be used in production under any circumstances.
Expand Down
6 changes: 6 additions & 0 deletions adapters/celestia/src/shares.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,13 @@ impl std::error::Error for ShareParsingError {}

impl NamespaceGroup {
pub fn from_b64(b64: &str) -> Result<Self, ShareParsingError> {
if b64.is_empty() {
error!("Empty input");
return Err(ShareParsingError::ErrWrongLength);
}

let mut decoded = Vec::with_capacity((b64.len() + 3) / 4 * 3);

// unsafe { decoded.set_len((b64.len() / 4 * 3)) }
if let Err(err) = B64_ENGINE.decode_slice(b64, &mut decoded) {
info!("Error decoding NamespaceGroup from base64: {}", err);
Expand Down
91 changes: 91 additions & 0 deletions fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
[package]
name = "sovereign-sdk-fuzz"
version = "0.1.0"
publish = false
edition = "2021"

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.4"
serde_json = "1"
tempfile = "3"
rand = "0.8"

# Sovereign-maintained dependencies.
celestia = { path = "../adapters/celestia" }
sov-modules-api = { path = "../module-system/sov-modules-api", features = ["arbitrary", "native"] }
sov-accounts = { path = "../module-system/module-implementations/sov-accounts", features = ["arbitrary", "native"] }
sov-bank = { path = "../module-system/module-implementations/sov-bank", features = ["native"] }
sov-state = { path = "../module-system/sov-state" }

# Prevent this from interfering with workspaces.
[workspace]
members = ["."]

[[bin]]
name = "namespace_group_from_b64"
path = "fuzz_targets/namespace_group_from_b64.rs"
test = false
doc = false

[[bin]]
name = "parse_address"
path = "fuzz_targets/parse_address.rs"
test = false
doc = false

[[bin]]
name = "address_bech_32_parse_serde"
path = "fuzz_targets/address_bech_32_parse_serde.rs"
test = false
doc = false

[[bin]]
name = "address_bech_32_try_from_bytes"
path = "fuzz_targets/address_bech_32_try_from_bytes.rs"
test = false
doc = false

[[bin]]
name = "share_deserialize"
path = "fuzz_targets/share_deserialize.rs"
test = false
doc = false

[[bin]]
name = "bank_call"
path = "fuzz_targets/bank_call.rs"
test = false
doc = false

[[bin]]
name = "accounts_call"
path = "fuzz_targets/accounts_call.rs"
test = false
doc = false

[[bin]]
name = "accounts_call_random"
path = "fuzz_targets/accounts_call_random.rs"
test = false
doc = false

[[bin]]
name = "bank_parse_call_message"
path = "fuzz_targets/bank_parse_call_message.rs"
test = false
doc = false

[[bin]]
name = "accounts_parse_call_message"
path = "fuzz_targets/accounts_parse_call_message.rs"
test = false
doc = false

[[bin]]
name = "accounts_parse_call_message_random"
path = "fuzz_targets/accounts_parse_call_message_random.rs"
test = false
doc = false
33 changes: 33 additions & 0 deletions fuzz/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.PHONY: help

BINARIES := $(shell sed -n '/^\[\[bin\]\]/,/^$$/ { /name\s*=\s*"\(.*\)"/s//\1/p }' Cargo.toml)
PROFILE ?= debug
ARGS ?=

help: ## Display this help message
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

check: ## Checks that fuzz member compiles
cargo check

build-target: ## Build the target fuzz
cargo rustc --bin $(TARGET) $(ARGS) -- \
-C debuginfo=full \
-C debug-assertions \
-C passes='sancov-module' \
-C llvm-args='-sanitizer-coverage-level=3' \
-C llvm-args='-sanitizer-coverage-inline-8bit-counters' \
-Z sanitizer=address

build: ## Build the fuzz targets
@for t in $(BINARIES); do \
$(MAKE) build-target TARGET=$$t; \
done

targets: ## Prints all fuzz targets
@for t in $(BINARIES); do \
echo $$t; \
done

run: build-target ## Run the fuzz target
./target/$(PROFILE)/$(TARGET) -artifact_prefix=artifacts/
66 changes: 66 additions & 0 deletions fuzz/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# LLVM's libFuzzer

This implementation is built upon [libfuzzer-sys](https://crates.io/crates/libfuzzer-sys). For more information, check [LLVM](https://llvm.org/docs/LibFuzzer.html) documentation.

## Build

To build the fuzz target, run the following command:

```sh
make build
```

You can build in release mode via:

```sh
make build ARGS=--release
```

Some special parameters are required to build the fuzz target. As example, let's build the `namespace_group_from_b64` fuzz target:

```sh
cargo rustc --bin namespace_group_from_b64 \
--manifest-path fuzz/Cargo.toml -- \
-C debuginfo=full \
-C debug-assertions \
-C passes='sancov-module' \
-C llvm-args='-sanitizer-coverage-level=3' \
-C llvm-args='-sanitizer-coverage-inline-8bit-counters' \
-Z sanitizer=address
```

We don't default these options as they depend on the `rustc` version and might change in the future. For the list of available targets, check [Cargo.toml](./fuzz/Cargo.toml) under the `bin` section. We are currently not using optimized binaries as it might impact on how rocksdb is built. If you want to activate optimization, add `--release` after `rustc`.

Unfortunately, rustc doesn't support the `--bins` argument to build multiple binaries with custom compiler directives. We have to build every target individually. Below is a convenience [sed](https://www.gnu.org/software/sed/) script to build all targets.

```sh
for t in `sed -n '/^\[\[bin\]\]/,/^$/ { /name\s*=\s*"\(.*\)"/s//\1/p }' fuzz/Cargo.toml` ; do cargo rustc --bin $t --manifest-path fuzz/Cargo.toml -- -C debuginfo=full -C debug-assertions -C passes='sancov-module' -C llvm-args='-sanitizer-coverage-level=3' -C llvm-args='-sanitizer-coverage-inline-8bit-counters' -Z sanitizer=address ; done
```

## Run

Here is a sample command to fuzz a `namespace_group_from_b64`:

```sh
make run TARGET=namespace_group_from_b64
```

To run in release mode:

```sh
make run TARGET=namespace_group_from_b64 PROFILE=release
```

To list the available targets, run:

```sh
make targets
```

Once built, you can run the targets under the `fuzz/target/<profile>` directory.

```sh
./fuzz/target/debug/namespace_group_from_b64
```

It will run the fuzz until you interrupt the command (i.e. `CTRL-C`), and will record crashes under `fuzz/artifacts/*/crash-*`. If you find a crash, please report a new [bug](https://github.com/Sovereign-Labs/sovereign-sdk/issues/new?assignees=&labels=&projects=&template=bug_report.md&title=).
Empty file.
Binary file not shown.
2 changes: 2 additions & 0 deletions fuzz/artifacts/crash-03ff9dbf9c64fb7c125f0aec0b8b80a972907eb8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@


Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
��������������������������������ˊe'
2 changes: 2 additions & 0 deletions fuzz/artifacts/crash-1f039bacf8f860eb5507d9ee3a9879dfe316cf5e
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
���
����������������������������������
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
2 changes: 2 additions & 0 deletions fuzz/artifacts/crash-5e665cf3759c0aabfc3e898f6294840582421b32
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

888888888888888�88888888888888888888
2 changes: 2 additions & 0 deletions fuzz/artifacts/crash-6929e000e5891085cf17a75de96dd505b6499083
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
����~����������������������������
Binary file not shown.
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions fuzz/artifacts/crash-e5f45f193d720ae7264383fcc0763cd945120fc1
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@



��������������������������������
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
zgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRzggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggegggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggRRRRggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg4
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
zggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggeggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggRRRRRRRRRRRRRRRRRRRRRRRRRRRgggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg4
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

��ﱱ�����������������������������
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
R����
Loading

0 comments on commit b06c98b

Please sign in to comment.