forked from ElementsProject/elements-miniscript
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fuzz: bring in new scripts and CI stuff from rust-bitcoin
- Loading branch information
Showing
11 changed files
with
409 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Automatically generated by fuzz/generate-files.sh | ||
name: Fuzz | ||
|
||
on: | ||
push: | ||
branches: | ||
- master | ||
- 'test-ci/**' | ||
pull_request: | ||
|
||
jobs: | ||
fuzz: | ||
if: ${{ !github.event.act }} | ||
runs-on: ubuntu-20.04 | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
fuzz_target: [ | ||
roundtrip_miniscript_str, | ||
roundtrip_miniscript_script, | ||
parse_descriptor, | ||
roundtrip_semantic, | ||
parse_descriptor_secret, | ||
roundtrip_descriptor, | ||
roundtrip_concrete, | ||
compile_descriptor, | ||
] | ||
steps: | ||
- name: Install test dependencies | ||
run: sudo apt-get update -y && sudo apt-get install -y binutils-dev libunwind8-dev libcurl4-openssl-dev libelf-dev libdw-dev cmake gcc libiberty-dev | ||
- uses: actions/checkout@v2 | ||
- uses: actions/cache@v2 | ||
id: cache-fuzz | ||
with: | ||
path: | | ||
~/.cargo/bin | ||
fuzz/target | ||
target | ||
key: cache-${{ matrix.target }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} | ||
- uses: actions-rs/toolchain@v1 | ||
with: | ||
toolchain: 1.58 | ||
override: true | ||
profile: minimal | ||
- name: fuzz | ||
run: | | ||
if [[ "${{ matrix.fuzz_target }}" =~ ^bitcoin ]]; then | ||
export RUSTFLAGS='--cfg=hashes_fuzz --cfg=secp256k1_fuzz' | ||
fi | ||
echo "Using RUSTFLAGS $RUSTFLAGS" | ||
cd fuzz && ./fuzz.sh "${{ matrix.fuzz_target }}" | ||
- run: echo "${{ matrix.fuzz_target }}" >executed_${{ matrix.fuzz_target }} | ||
- uses: actions/upload-artifact@v2 | ||
with: | ||
name: executed_${{ matrix.fuzz_target }} | ||
path: executed_${{ matrix.fuzz_target }} | ||
|
||
verify-execution: | ||
if: ${{ !github.event.act }} | ||
needs: fuzz | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/download-artifact@v2 | ||
- name: Display structure of downloaded files | ||
run: ls -R | ||
- run: find executed_* -type f -exec cat {} + | sort > executed | ||
- run: source ./fuzz/fuzz-util.sh && listTargetNames | sort | diff - executed |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,115 @@ | ||
# Fuzz Tests | ||
# Fuzzing | ||
|
||
Repository for fuzz testing Miniscript. | ||
`bitcoin` and `bitcoin_hashes` have fuzzing harnesses setup for use with | ||
honggfuzz. | ||
|
||
## How to reproduce crashes? | ||
To run the fuzz-tests as in CI -- briefly fuzzing every target -- simply | ||
run | ||
|
||
Travis should output a offending hex("048531e80700ae6400670000af5168" in the example) | ||
which you can use as shown. Copy and paste the following code lines into file reporting crashes and | ||
replace the hex with the offending hex. | ||
Refer to file [roundtrip_concrete.rs](./fuzz_targets/roundtrip_concrete.rs) for an example. | ||
./fuzz.sh | ||
|
||
in this directory. | ||
|
||
To build honggfuzz, you must have libunwind on your system, as well as | ||
libopcodes and libbfd from binutils **2.38** on your system. The most | ||
recently-released binutils 2.39 has changed their API in a breaking way. | ||
|
||
On Nix, you can obtain these libraries by running | ||
|
||
nix-shell -p libopcodes_2_38 -p libunwind | ||
|
||
and then run fuzz.sh as above. | ||
|
||
# Fuzzing with weak cryptography | ||
|
||
You may wish to replace the hashing and signing code with broken crypto, | ||
which will be faster and enable the fuzzer to do otherwise impossible | ||
things such as forging signatures or finding preimages to hashes. | ||
|
||
Doing so may result in spurious bug reports since the broken crypto does | ||
not respect the encoding or algebraic invariants upheld by the real crypto. We | ||
would like to improve this but it's a nontrivial problem -- though not | ||
beyond the abilities of a motivated student with a few months of time. | ||
Please let us know if you are interested in taking this on! | ||
|
||
Meanwhile, to use the broken crypto, simply compile (and run the fuzzing | ||
scripts) with | ||
|
||
RUSTFLAGS="--cfg=hashes_fuzz --cfg=secp256k1_fuzz" | ||
|
||
which will replace the hashing library with broken hashes, and the | ||
secp256k1 library with broken cryptography. | ||
|
||
Needless to say, NEVER COMPILE REAL CODE WITH THESE FLAGS because if a | ||
fuzzer can break your crypto, so can anybody. | ||
|
||
# Long-term fuzzing | ||
|
||
To see the full list of targets, the most straightforward way is to run | ||
|
||
source ./fuzz-util.sh | ||
listTargetNames | ||
|
||
To run each of them for an hour, run | ||
|
||
./cycle.sh | ||
|
||
To run a single fuzztest indefinitely, run | ||
|
||
HFUZZ_BUILD_ARGS='--features honggfuzz_fuzz' cargo hfuzz run <target> | ||
|
||
This script uses the `chrt` utility to try to reduce the priority of the | ||
jobs. If you would like to run for longer, the most straightforward way | ||
is to edit `cycle.sh` before starting. To run the fuzz-tests in parallel, | ||
you will need to implement a custom harness. | ||
|
||
# Adding fuzz tests | ||
|
||
All fuzz tests can be found in the `fuzz_target/` directory. Adding a new | ||
one is as simple as copying an existing one and editing the `do_test` | ||
function to do what you want. | ||
|
||
If your test clearly belongs to a specific crate, please put it in that | ||
crate's directory. Otherwise you can put it directly in `fuzz_target/`. | ||
|
||
If you need to add dependencies, edit the file `generate-files.sh` to add | ||
it to the generated `Cargo.toml`. | ||
|
||
Once you've added a fuzztest, regenerate the `Cargo.toml` and CI job by | ||
running | ||
|
||
./generate-files.sh | ||
|
||
Then to test your fuzztest, run | ||
|
||
./fuzz.sh <target> | ||
|
||
If it is working, you will see a rapid stream of data for many seconds | ||
(you can hit Ctrl+C to stop it early). If not, you should quickly see | ||
an error. | ||
|
||
# Reproducing Failures | ||
|
||
If a fuzztest fails, it will exit with a summary which looks something like | ||
|
||
``` | ||
#[cfg(test)] | ||
mod tests { | ||
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) { | ||
let mut b = 0; | ||
for (idx, c) in hex.as_bytes().iter().enumerate() { | ||
b <<= 4; | ||
match *c { | ||
b'A'...b'F' => b |= c - b'A' + 10, | ||
b'a'...b'f' => b |= c - b'a' + 10, | ||
b'0'...b'9' => b |= c - b'0', | ||
_ => panic!("Bad hex"), | ||
} | ||
if (idx & 1) == 1 { | ||
out.push(b); | ||
b = 0; | ||
} | ||
} | ||
} | ||
#[test] | ||
fn duplicate_crash() { | ||
let mut a = Vec::new(); | ||
extend_vec_from_hex("048531e80700ae6400670000af5168", &mut a); | ||
super::do_test(&a); | ||
} | ||
} | ||
... | ||
fuzzTarget : hfuzz_target/x86_64-unknown-linux-gnu/release/hashes_sha256 | ||
CRASH: | ||
DESCRIPTION: | ||
ORIG_FNAME: 00000000000000000000000000000000.00000000.honggfuzz.cov | ||
FUZZ_FNAME: hfuzz_workspace/hashes_sha256/SIGABRT.PC.7ffff7c8abc7.STACK.18826d9b64.CODE.-6.ADDR.0.INSTR.mov____%eax,%ebp.fuzz | ||
... | ||
===================================================================== | ||
fff400610004 | ||
``` | ||
|
||
The final line is a hex-encoded version of the input that caused the crash. You | ||
can test this directly by editing the `duplicate_crash` test to copy/paste the | ||
hex output into the call to `Vec::<u8>::from_hex`. Then run the test with | ||
|
||
cargo test | ||
|
||
Note that if you set your `RUSTFLAGS` while fuzzing (see above) you must make | ||
sure they are set the same way when running `cargo test`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Continuosly cycle over fuzz targets running each for 1 hour. | ||
# It uses chrt SCHED_IDLE so that other process takes priority. | ||
# | ||
# For hfuzz options see https://github.com/google/honggfuzz/blob/master/docs/USAGE.md | ||
|
||
set -e | ||
REPO_DIR=$(git rev-parse --show-toplevel) | ||
# shellcheck source=./fuzz-util.sh | ||
source "$REPO_DIR/fuzz/fuzz-util.sh" | ||
|
||
while : | ||
do | ||
for targetFile in $(listTargetFiles); do | ||
targetName=$(targetFileToName "$targetFile") | ||
echo "Fuzzing target $targetName ($targetFile)" | ||
|
||
# fuzz for one hour | ||
HFUZZ_RUN_ARGS='--run_time 3600' chrt -i 0 cargo hfuzz run "$targetName" | ||
# minimize the corpus | ||
HFUZZ_RUN_ARGS="-i hfuzz_workspace/$targetName/input/ -P -M" chrt -i 0 cargo hfuzz run "$targetName" | ||
done | ||
done | ||
|
Oops, something went wrong.