1811ebff32
The function used to sign BOLT 12 messages only takes a message digest. This doesn't allow signers to independently verify the message before signing nor does it allow them to derive the necessary signing keys, if needed. Introduce a TaggedHash wrapper for a message digest, which each unsigned BOLT 12 message type constructs upon initialization. Change the signing function to take AsRef<TaggedHash>, which each unsigned type implements. This allows the signing function to take any unsigned message and obtain its tagged hash. |
||
---|---|---|
.. | ||
src | ||
.gitignore | ||
Cargo.toml | ||
ci-fuzz.sh | ||
README.md | ||
targets.h |
Fuzzing
Fuzz tests generate a ton of random parameter arguments to the program and then validate that none cause it to crash.
How does it work?
Typically, Travis CI will run travis-fuzz.sh
on one of the environments the automated tests are configured for.
This is the most time-consuming component of the continuous integration workflow, so it is recommended that you detect
issues locally, and Travis merely acts as a sanity check. Fuzzing is further only effective with
a lot of CPU time, indicating that if crash scenarios are discovered on Travis with its low
runtime constraints, the crash is caused relatively easily.
How do I run fuzz tests locally?
You typically won't need to run the entire combination of different fuzzing tools. For local execution, honggfuzz
should be more than sufficient.
Setup
To install honggfuzz
, simply run
cargo update
cargo install --force honggfuzz
In some environments, you may want to pin the honggfuzz version to 0.5.52
:
cargo update -p honggfuzz --precise "0.5.52"
cargo install --force honggfuzz --version "0.5.52"
Execution
To run the Hongg fuzzer, do
export CPU_COUNT=1 # replace as needed
export HFUZZ_BUILD_ARGS="--features honggfuzz_fuzz"
export HFUZZ_RUN_ARGS="-n $CPU_COUNT --exit_upon_crash"
export TARGET="msg_ping_target" # replace with the target to be fuzzed
cargo hfuzz run $TARGET
(Or, for a prettier output, replace the last line with cargo --color always hfuzz run $TARGET
.)
To see a list of available fuzzing targets, run:
ls ./src/bin/
A fuzz test failed on Travis, what do I do?
You're trying to create a PR, but need to find the underlying cause of that pesky fuzz failure blocking the merge?
Worry not, for this is easily traced.
If your Travis output log looks like this:
Size:639 (i,b,hw,ed,ip,cmp): 0/0/0/0/0/1, Tot:0/0/0/2036/5/28604
Seen a crash. Terminating all fuzzing threads
… # a lot of lines in between
<0x0000555555565559> [func:UNKNOWN file: line:0 module:/home/travis/build/rust-bitcoin/rust-lightning/fuzz/hfuzz_target/x86_64-unknown-linux-gnu/release/full_stack_target]
<0x0000000000000000> [func:UNKNOWN file: line:0 module:UNKNOWN]
=====================================================================
2d3136383734090101010101010101010101010101010101010101010101
010101010100040101010101010101010101010103010101010100010101
0069d07c319a4961
The command "if [ "$(rustup show | grep default | grep stable)" != "" ]; then cd fuzz && cargo test --verbose && ./travis-fuzz.sh; fi" exited with 1.
Note that the penultimate stack trace line ends in release/full_stack_target]
. That indicates that
the failing target was full_stack
. To reproduce the error locally, simply copy the hex,
and run the following from the fuzz
directory:
export TARGET="full_stack" # adjust for your output
export HEX="2d3136383734090101010101010101010101010101010101010101010101\
010101010100040101010101010101010101010103010101010100010101\
0069d07c319a4961" # adjust for your output
mkdir -p ./test_cases/$TARGET
echo $HEX | xxd -r -p > ./test_cases/$TARGET/any_filename_works
export RUST_BACKTRACE=1
export RUSTFLAGS="--cfg=fuzzing"
cargo test
Note that if the fuzz test failed locally, moving the offending run's trace
to the test_cases
folder should also do the trick; simply replace the echo $HEX |
line above
with (the trace file name is of course a bit longer than in the example):
mv hfuzz_workspace/fuzz_target/SIGABRT.PC.7ffff7e21ce1.STACK.[…].fuzz ./test_cases/$TARGET/
This will reproduce the failing fuzz input and yield a usable stack trace.
How do I add a new fuzz test?
-
The easiest approach is to take one of the files in
fuzz/src/
, such asprocess_network_graph.rs
, and duplicate it, renaming the new file to something more suitable. For the sake of example, let's call the new fuzz target we're creatingmy_fuzzy_experiment
. -
In the newly created file
fuzz/src/my_fuzzy_experiment.rs
, run a string substitution ofprocess_network_graph
tomy_fuzzy_experiment
, such that the three methods in the file aredo_test
,my_fuzzy_experiment_test
, andmy_fuzzy_experiment_run
. -
Adjust the body (not the signature!) of
do_test
as necessary for the new fuzz test. -
In
fuzz/src/bin/gen_target.sh
, add a line readingGEN_TEST my_fuzzy_experiment
to the first group ofGEN_TEST
lines (starting in line 9). -
If your test relies on a new local crate, add that crate as a dependency to
fuzz/Cargo.toml
. -
In
fuzz/src/lib.rs
, add the linepub mod my_fuzzy_experiment
. Additionally, if you added a new crate dependency, add theextern crate […]
import line. -
Run
fuzz/src/bin/gen_target.sh
. -
There is no step eight: happy fuzzing!