This pull request adds 2 fuzz testing targets for the Crockford32 codec. These fuzz testing targets are built on top of cargo fuzz, described in the Rust Fuzzing Book.
cargo fuzz itself is a wrapper around LibFuzzer, adapted for use with Rust code.
After you install the cargo-fuzz component, you can build these targets with cargo +nightly fuzz build. (By default, cargo fuzz builds with Address Sanitizer, which currently requires Rust's Nightly release, hence the +nightly.)
At this point, you can list the fuzz testing targets that cargo fuzz knows about using its list subcommand:
$ cargo +nightly fuzz list
c32_address_decode
c32_address_roundtrip
You can run one of these fuzz testing targets, for example, with a command line like this, which will fuzz until a crash is detected or until 10m have elapsed:
$ cargo +nightly fuzz run c32_address_roundtrip fuzz/fuzz_corpora/encoded_c32_addresses -- -max_total_time=600
INFO: Seed: 3480189470
INFO: Loaded 1 modules (699596 inline 8-bit counters): 699596 [0x5633595ed762, 0x56335969842e),
INFO: Loaded 1 PC tables (699596 PCs): 699596 [0x563359698430,0x56335a1450f0),
INFO: 286 files found in fuzz/fuzz_corpora/encoded_c32_addresses
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: seed corpus: files: 286 min: 3b max: 289b total: 23111b rss: 86Mb
#287 INITED cov: 3320 ft: 11918 corp: 213/18Kb exec/s: 0 rss: 104Mb
#1628 REDUCE cov: 3320 ft: 11918 corp: 213/18Kb lim: 305 exec/s: 814 rss: 115Mb L: 12/289 MS: 1 EraseBytes-
#1974 REDUCE cov: 3320 ft: 11918 corp: 213/18Kb lim: 305 exec/s: 987 rss: 117Mb L: 38/289 MS: 1 EraseBytes-
#2048 pulse cov: 3320 ft: 11918 corp: 213/18Kb lim: 305 exec/s: 1024 rss: 118Mb
#2061 REDUCE cov: 3320 ft: 11918 corp: 213/18Kb lim: 305 exec/s: 1030 rss: 118Mb L: 99/289 MS: 2 ChangeASCIIInt-EraseBytes-
# ...
thread '<unnamed>' panicked at 'byte index 1 is not a char boundary; it is inside '\u{f1c7}' (bytes 0..3) of `T<;&`', src/libcore/str/mod.rs:2154:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
==10224== ERROR: libFuzzer: deadly signal
#0 0x563353478a91 in __sanitizer_print_stack_trace /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_stack.cc:86:3
#1 0x5633585e3be3 in fuzzer::PrintStackTrace() /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerUtil.cpp:205
#2 0x5633585f20a4 in fuzzer::Fuzzer::CrashCallback() /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerLoop.cpp:232
#3 0x5633585f1f45 in fuzzer::Fuzzer::StaticCrashSignalCallback() /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerLoop.cpp:203
#4 0x5633585d730c in fuzzer::CrashHandler(int, siginfo_t*, void*) /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerUtilPosix.cpp:47
#5 0x7fc0735d688f (/lib/x86_64-linux-gnu/libpthread.so.0+0x1288f)
#6 0x7fc072ff9e96 in __libc_signal_restore_set /build/glibc-OTsEL5/glibc-2.27/signal/../sysdeps/unix/sysv/linux/nptl-signals.h:80
#7 0x7fc072ff9e96 in raise /build/glibc-OTsEL5/glibc-2.27/signal/../sysdeps/unix/sysv/linux/raise.c:48
#8 0x7fc072ffb800 in abort /build/glibc-OTsEL5/glibc-2.27/stdlib/abort.c:79
#9 0x5633587f0196 in std::sys::unix::abort_internal::hff6a16ca4fa621fd /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libstd/sys/unix/mod.rs:165:4
#10 0x5633587d8455 in std::process::abort::h08c97a0f33fabd92 /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libstd/process.rs:1609:13
#11 0x5633585b2f58 in libfuzzer_sys::initialize::_$u7b$$u7b$closure$u7d$$u7d$::h88ffd6041b89fe59 /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/src/lib.rs:51:8
#12 0x5633587df8f4 in std::panicking::rust_panic_with_hook::hb4c33a16e88d4aec /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libstd/panicking.rs:474:16
#13 0x5633587df40a in rust_begin_unwind /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libstd/panicking.rs:378:4
#14 0x56335880f780 in core::panicking::panic_fmt::h04c74b112bd3e021 /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libcore/panicking.rs:85:13
#15 0x563358816b63 in core::str::slice_error_fail::h6e7a7b57c771f669 /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libcore/str/mod.rs
#16 0x56335446c189 in core::str::_$LT$impl$u20$str$GT$::split_at::hb9cf0d21239621e4 /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libcore/str/mod.rs:2600:12
#17 0x563354952f62 in blockstack_lib::address::c32::c32_check_decode::hc6fa5b085cdfab98 /home/blarsen/x-audit-blockstack-core/src/address/c32.rs:183:26
#18 0x5633549556be in blockstack_lib::address::c32::c32_address_decode::hba764231c39deafb /home/blarsen/x-audit-blockstack-core/src/address/c32.rs:221:8
#19 0x5633534a29ad in rust_fuzzer_test_input /home/blarsen/x-audit-blockstack-core/fuzz/fuzz_targets/c32_address_roundtrip.rs:12:37
#20 0x5633585b2952 in libfuzzer_sys::test_input_wrap::_$u7b$$u7b$closure$u7d$$u7d$::h67f379890ee9b448 /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/src/lib.rs:27:8
#21 0x56335860a884 in std::panicking::try::do_call::hd98d16f17f6424ac /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libstd/panicking.rs:303:39
#22 0x5633587f11a6 in __rust_maybe_catch_panic /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libpanic_unwind/lib.rs:86:7
#23 0x56335860a275 in std::panicking::try::hd96947203c69f5a1 /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libstd/panicking.rs:281:12
#24 0x563358609d1c in std::panic::catch_unwind::hfda6656cc8f1b8d6 /rustc/e620d0f337d0643c757bab791fc7d88d63217704/src/libstd/panic.rs:394:13
#25 0x5633585b2299 in LLVMFuzzerTestOneInput /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/src/lib.rs:25:21
#26 0x5633585f3be2 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerLoop.cpp:553
#27 0x5633585f3423 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerLoop.cpp:469
#28 0x5633585f4788 in fuzzer::Fuzzer::MutateAndTestOne() /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerLoop.cpp:696
#29 0x5633585f5433 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerLoop.cpp:831
#30 0x5633585ba185 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerDriver.cpp:825
#31 0x5633585b1f9a in main /home/blarsen/.cargo/registry/src/github.com-1ecc6299db9ec823/libfuzzer-sys-0.3.0/libfuzzer/FuzzerMain.cpp:19
#32 0x7fc072fdcb96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
#33 0x5633533f82b9 in _start (/home/blarsen/x-audit-blockstack-core/fuzz/target/x86_64-unknown-linux-gnu/debug/c32_address_roundtrip+0x136d2b9)
NOTE: libFuzzer has rudimentary signal handlers.
Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 5 PersAutoDict-CopyPart-ChangeBinInt-ChangeByte-EraseBytes- DE: "\x01\x10\xff\xff"-; base unit: d48a023381a0891df74c3d6da46f2c3452f278f4
0x31,0xef,0x87,0x87,0x6,0x54,0x0,0xef,0x87,0x87,0x6,0x0,0xef,0x87,0x87,0x6,0x3c,0x0,0x3b,0x0,0x26,
1\xef\x87\x87\x06T\x00\xef\x87\x87\x06\x00\xef\x87\x87\x06<\x00;\x00&
artifact_prefix='/home/blarsen/x-audit-blockstack-core/fuzz/artifacts/c32_address_roundtrip/'; Test unit written to /home/blarsen/x-audit-blockstack-core/fuzz/artifacts/c32_address_roundtrip/crash-b72e22175a08a6cfdf3f058320d757924d19a865
Base64: Me+HhwZUAO+HhwYA74eHBjwAOwAm
────────────────────────────────────────────────────────────────────────────────
Failing input:
fuzz/artifacts/c32_address_roundtrip/crash-b72e22175a08a6cfdf3f058320d757924d19a865
Output of `std::fmt::Debug`:
[49, 239, 135, 135, 6, 84, 0, 239, 135, 135, 6, 0, 239, 135, 135, 6, 60, 0, 59, 0, 38]
Reproduce with:
cargo fuzz run c32_address_roundtrip fuzz/artifacts/c32_address_roundtrip/crash-b72e22175a08a6cfdf3f058320d757924d19a865
Minimize test case with:
cargo fuzz tmin c32_address_roundtrip fuzz/artifacts/c32_address_roundtrip/crash-b72e22175a08a6cfdf3f058320d757924d19a865
────────────────────────────────────────────────────────────────────────────────
(The crash revealed here looks to be an instance of #11)
This pull request adds 2 fuzz testing targets for the Crockford32 codec. These fuzz testing targets are built on top of
cargo fuzz
, described in the Rust Fuzzing Book.cargo fuzz
itself is a wrapper around LibFuzzer, adapted for use with Rust code.After you install the
cargo-fuzz
component, you can build these targets withcargo +nightly fuzz build
. (By default,cargo fuzz
builds with Address Sanitizer, which currently requires Rust's Nightly release, hence the+nightly
.)At this point, you can list the fuzz testing targets that
cargo fuzz
knows about using itslist
subcommand:You can run one of these fuzz testing targets, for example, with a command line like this, which will fuzz until a crash is detected or until 10m have elapsed:
(The crash revealed here looks to be an instance of #11)