Skip to content

Commit

Permalink
token-swap: Add fuzzer for swap / withdraw / deposit (#875)
Browse files Browse the repository at this point in the history
* token-swap: Add fuzzer for swap / withdraw / deposit

* Run cargo fmt

* Make end-to-end testing work

* Fix test failures

* Cleanup for review

* Remove Clone trait for Initialize

* Fix building fuzz targets

* Fix fuzz withdraw logic to avoid ZeroTradingTokens error

* Cargo fmt

* Clippy / fmt again

* Integrate fuzzer in main workspace to share clippy / fmt

* Fix clippy

* Switch to stable honggfuzz that could work with BPF

* Update to most recent honggfuzz

* Add build / run requirements

* Add fuzz CI and cleanup for honggfuzz

* Revert to using fuzz feature to integrate with workspace

* Make fuzz script executable

* Refactor and cleanup

* Add nightly run

* Fix workflow typo

* Add runtime for pull request fuzz workflow

* Fix unrelated new clippy errors
  • Loading branch information
joncinque committed Nov 30, 2020
1 parent ac20c5d commit b40e0dd
Show file tree
Hide file tree
Showing 19 changed files with 1,350 additions and 180 deletions.
64 changes: 64 additions & 0 deletions .github/workflows/fuzz-nightly.yml
@@ -0,0 +1,64 @@
name: Fuzz Nightly

on:
schedule:
- cron: '0 3 * * *'

jobs:
fuzz-nightly:
runs-on: ubuntu-latest
strategy:
matrix:
fuzz_target: [token-swap-instructions]
fail-fast: false
steps:
- uses: actions/checkout@v2

- name: Set env vars
run: |
source ci/rust-version.sh
echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
source ci/solana-version.sh
echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ env.RUST_STABLE }}
override: true
profile: minimal

- uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: cargo-fuzz-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
cargo-fuzz-
- uses: actions/cache@v2
with:
path: |
~/.cargo/bin/cargo-hfuzz
~/.cargo/bin/cargo-honggfuzz
key: cargo-fuzz-bins-${{ runner.os }}
restore-keys: |
cargo-fuzz-bins-${{ runner.os }}-
- uses: actions/cache@v2
with:
path: |
~/.cache
key: solana-${{ env.SOLANA_VERSION }}
restore-keys: |
solana-
- name: Install dependencies
run: |
./ci/install-build-deps.sh
./ci/install-program-deps.sh
echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
- name: Run fuzz target
run: ./ci/fuzz.sh ${{ matrix.fuzz_target }} 18000 # 5 hours, jobs max out at 6
58 changes: 58 additions & 0 deletions .github/workflows/pull-request.yml
Expand Up @@ -15,6 +15,7 @@ jobs:
- js-test-token
- js-test-token-swap
- js-test-token-lending
- fuzz
steps:
- run: echo "Done"

Expand Down Expand Up @@ -200,3 +201,60 @@ jobs:
name: programs
path: target/bpfel-unknown-unknown/release
- run: ./ci/js-test-token-lending.sh

fuzz:
runs-on: ubuntu-latest
strategy:
matrix:
fuzz_target: [token-swap-instructions]
steps:
- uses: actions/checkout@v2

- name: Set env vars
run: |
source ci/rust-version.sh
echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
source ci/solana-version.sh
echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
- uses: actions-rs/toolchain@v1
with:
toolchain: ${{ env.RUST_STABLE }}
override: true
profile: minimal

- uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: cargo-fuzz-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
cargo-fuzz-
- uses: actions/cache@v2
with:
path: |
~/.cargo/bin/cargo-hfuzz
~/.cargo/bin/cargo-honggfuzz
key: cargo-fuzz-bins-${{ runner.os }}
restore-keys: |
cargo-fuzz-bins-${{ runner.os }}-
- uses: actions/cache@v2
with:
path: |
~/.cache
key: solana-${{ env.SOLANA_VERSION }}
restore-keys: |
solana-
- name: Install dependencies
run: |
./ci/install-build-deps.sh
./ci/install-program-deps.sh
echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
- name: Run fuzz target
run: ./ci/fuzz.sh ${{ matrix.fuzz_target }} 30 # 30 seconds, just to check everything is ok
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -5,3 +5,5 @@ bin
config.json
node_modules
./package-lock.json
hfuzz_target
hfuzz_workspace
53 changes: 48 additions & 5 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
Expand Up @@ -15,6 +15,7 @@ members = [
"themis/program_ristretto",
"token-lending/program",
"token-swap/program",
"token-swap/program/fuzz",
"token/cli",
"token/perf-monitor",
"token/program",
Expand Down
39 changes: 39 additions & 0 deletions ci/fuzz.sh
@@ -0,0 +1,39 @@
#!/usr/bin/env bash

set -e

usage() {
exitcode=0
if [[ -n "$1" ]]; then
exitcode=1
echo "Error: $*"
fi
echo "Usage: $0 [fuzz-target] [run-time-in-seconds]"
exit $exitcode
}

fuzz_target=$1
if [[ -z $fuzz_target ]]; then
usage "No fuzz target provided"
fi

run_time=$2
if [[ -z $2 ]]; then
usage "No runtime provided"
fi

set -x

HFUZZ_RUN_ARGS="--run_time $run_time --exit_upon_crash" cargo hfuzz run $fuzz_target

# Until https://github.com/rust-fuzz/honggfuzz-rs/issues/16 is resolved,
# hfuzz does not return an error code on crash, so look for a crash artifact
for crash_file in ./hfuzz_workspace/"$fuzz_target"/*.fuzz; do
# Check if the glob gets expanded to existing files.
if [[ -e "$crash_file" ]]; then
echo ".fuzz file $crash_file found, meaning some error occurred, exiting"
exit 1
fi
# Break early -- we just need one iteration to see if a failure occurred
break
done
2 changes: 2 additions & 0 deletions ci/install-build-deps.sh
Expand Up @@ -10,4 +10,6 @@ sudo apt-get install -y openssl --allow-unauthenticated
sudo apt-get install -y libssl-dev --allow-unauthenticated
sudo apt-get install -y libssl1.1 --allow-unauthenticated
sudo apt-get install -y libudev-dev
sudo apt-get install -y binutils-dev
sudo apt-get install -y libunwind-dev
clang-7 --version
1 change: 1 addition & 0 deletions ci/install-program-deps.sh
Expand Up @@ -9,6 +9,7 @@ set -x

cargo --version
cargo install rustfilt || true
cargo install honggfuzz || true

export PATH="$HOME"/.local/share/solana/install/active_release/bin:"$PATH"
solana --version
Expand Down
2 changes: 2 additions & 0 deletions token-swap/program/Cargo.toml
Expand Up @@ -10,6 +10,7 @@ edition = "2018"
[features]
no-entrypoint = []
production = []
fuzz = ["arbitrary"]

[dependencies]
arrayref = "0.3.6"
Expand All @@ -19,6 +20,7 @@ solana-program = "1.4.9"
spl-token = { version = "3.0", path = "../../token/program", features = [ "no-entrypoint" ] }
thiserror = "1.0"
uint = "0.8"
arbitrary = { version = "0.4", features = ["derive"], optional = true }

[dev-dependencies]
solana-sdk = "1.4.9"
Expand Down
22 changes: 22 additions & 0 deletions token-swap/program/fuzz/Cargo.toml
@@ -0,0 +1,22 @@
[package]
name = "spl-token-swap-fuzz"
version = "0.0.1"
description = "Solana Program Library Token Swap Fuzzer"
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
repository = "https://github.com/solana-labs/solana-program-library"
license = "Apache-2.0"
edition = "2018"
publish = false

[dependencies]
honggfuzz = { version = "0.5" }
arbitrary = { version = "0.4", features = ["derive"] }
solana-program = "1.4.8"
spl-token = { version = "3.0", path = "../../../token/program", features = [ "no-entrypoint" ] }
spl-token-swap = { path = "..", features = ["fuzz", "no-entrypoint"] }

[[bin]]
name = "token-swap-instructions"
path = "src/instructions.rs"
test = false
doc = false

0 comments on commit b40e0dd

Please sign in to comment.