From 78546090efd77ceb64572d31143ebd6931ded846 Mon Sep 17 00:00:00 2001 From: zi0Black <13380579+zi0Black@users.noreply.github.com> Date: Tue, 14 Jan 2025 18:34:10 +0000 Subject: [PATCH 1/3] Enhance fuzz.sh script with 'cmin' functionality for corpus minimization. Introduce debug panic mechanism in errors.rs for improved error handling during fuzzing and update README.md for usage instructions. --- testsuite/fuzzer/README.md | 11 ++++++++++ testsuite/fuzzer/fuzz.sh | 19 ++++++++++++++++- .../move/move-binary-format/src/errors.rs | 21 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/testsuite/fuzzer/README.md b/testsuite/fuzzer/README.md index d948c5cc611a0..5bf3425f6eb25 100644 --- a/testsuite/fuzzer/README.md +++ b/testsuite/fuzzer/README.md @@ -25,6 +25,10 @@ The script includes several functions to manage and execute fuzz tests: ```bash ./fuzz.sh build-oss-fuzz ``` +- `cmin`: Distillate corpora + ```bash + ./fuzz.sh cmin [corpora_directory] + ``` - `coverage`: Generates coverage report in HTML format ```bash ./fuzz.sh coverage @@ -124,6 +128,13 @@ The CSV file is structured as follows: - Column 2: Module address - Column 3: Base64-encoded bytecode of the module +## Debug Crashes +Flamegraph and GDB are integrated into fuzz.sh for advanced metrics and debugging. A more rudimentary option is also available: since we have symbolized binaries, we can directly use the stack trace produced by the fuzzer. However, for INVARIANT_VIOLATIONS, the stack trace is incorrect. To obtain the correct stack trace, you can use the following command: +```bash +DEBUG_VM_STATUS= ./fuzz.sh run +``` +This command is selective, so only the specified, comma-separated statuses will trigger the panic in PartialVMError. + ## References - [Rust Fuzz Book](https://rust-fuzz.github.io/book/) - [Google OSS-Fuzz](https://google.github.io/oss-fuzz/) diff --git a/testsuite/fuzzer/fuzz.sh b/testsuite/fuzzer/fuzz.sh index 355d1a548d5df..9db5ae978fd84 100755 --- a/testsuite/fuzzer/fuzz.sh +++ b/testsuite/fuzzer/fuzz.sh @@ -53,6 +53,9 @@ function usage() { "build-oss-fuzz") echo "Usage: $0 build-oss-fuzz " ;; + "cmin") + echo "Usage: $0 cmin [corpus_dir]" + ;; "coverage") echo "Usage: $0 coverage " ;; @@ -80,6 +83,7 @@ function usage() { echo " block-builder runs rust tool to hel build fuzzers" echo " build builds fuzz targets" echo " build-oss-fuzz builds fuzz targets for oss-fuzz" + echo " cmin minimizes a corpus for a target" echo " coverage generates coverage for a fuzz target" echo " clean-coverage clean coverage for a fuzz target" echo " debug debugs a fuzz target with a testcase" @@ -166,6 +170,15 @@ function build-oss-fuzz() { done } +function cmin() { + if [ -z "$1" ]; then + usage cmin + fi + fuzz_target=$1 + corpus_dir=${2:-./fuzz/corpus/$fuzz_target} + cargo_fuzz cmin $fuzz_target $corpus_dir +} + function install-coverage-tools() { cargo +$NIGHTLY_VERSION install cargo-binutils cargo +$NIGHTLY_VERSION install rustfilt @@ -271,7 +284,7 @@ function run() { fi fi info "Running $fuzz_target" - cargo_fuzz run --sanitizer none -O $fuzz_target $testcase -- -fork=10 + cargo_fuzz run --sanitizer none -O $fuzz_target $testcase -- -fork=15 #-ignore_crashes=1 } function test() { @@ -340,6 +353,10 @@ case "$1" in shift build-oss-fuzz "$@" ;; + "cmin") + shift + cmin "$@" + ;; "coverage") shift coverage "$@" diff --git a/third_party/move/move-binary-format/src/errors.rs b/third_party/move/move-binary-format/src/errors.rs index a5f5e447786b1..d275daaab8b4f 100644 --- a/third_party/move/move-binary-format/src/errors.rs +++ b/third_party/move/move-binary-format/src/errors.rs @@ -16,6 +16,23 @@ pub type VMResult = ::std::result::Result; pub type BinaryLoaderResult = ::std::result::Result; pub type PartialVMResult = ::std::result::Result; +/// This macro is used to panic while debugging fuzzing crashes obtaining the right stack trace. +/// e.g. DEBUG_VM_STATUS=ABORTED,UNKNOWN_INVARIANT_VIOLATION_ERROR ./fuzz.sh run move_aptosvm_publish_and_run +/// third_party/move/move-core/types/src/vm_status.rs:506 for the list of status codes. +#[cfg(feature = "fuzzing")] +macro_rules! maybe_debug_panic { + ($major_status:expr, $message:expr) => {{ + if let Ok(debug_statuses) = std::env::var("DEBUG_VM_STATUS") { + let status_strings: Vec<&str> = debug_statuses.split(',').collect(); + if status_strings.iter().any(|s| { + s.trim() == format!("{:?}", $major_status) + }) { + panic!("PartialVMError: {:?} {:?}", $major_status, $message); + } + } + }}; +} + #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum Location { Undefined, @@ -438,6 +455,10 @@ impl PartialVMError { } else { None }; + + #[cfg(feature = "fuzzing")] + maybe_debug_panic!(major_status, message); + Self(Box::new(PartialVMError_ { major_status, sub_status: None, From e251e4900cb325840e3d9f213378088eae78e961 Mon Sep 17 00:00:00 2001 From: zi0Black <13380579+zi0Black@users.noreply.github.com> Date: Wed, 15 Jan 2025 10:02:18 +0000 Subject: [PATCH 2/3] fmt --- third_party/move/move-binary-format/src/errors.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/third_party/move/move-binary-format/src/errors.rs b/third_party/move/move-binary-format/src/errors.rs index d275daaab8b4f..5dee9ab89be7b 100644 --- a/third_party/move/move-binary-format/src/errors.rs +++ b/third_party/move/move-binary-format/src/errors.rs @@ -24,9 +24,10 @@ macro_rules! maybe_debug_panic { ($major_status:expr, $message:expr) => {{ if let Ok(debug_statuses) = std::env::var("DEBUG_VM_STATUS") { let status_strings: Vec<&str> = debug_statuses.split(',').collect(); - if status_strings.iter().any(|s| { - s.trim() == format!("{:?}", $major_status) - }) { + if status_strings + .iter() + .any(|s| s.trim() == format!("{:?}", $major_status)) + { panic!("PartialVMError: {:?} {:?}", $major_status, $message); } } From 4f6bcc20265524c5b5072977bf1e4d58d6f0983d Mon Sep 17 00:00:00 2001 From: zi0Black <13380579+zi0Black@users.noreply.github.com> Date: Thu, 16 Jan 2025 09:59:46 +0000 Subject: [PATCH 3/3] rename remove useless collect --- testsuite/fuzzer/fuzz.sh | 2 +- third_party/move/move-binary-format/src/errors.rs | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/testsuite/fuzzer/fuzz.sh b/testsuite/fuzzer/fuzz.sh index 9db5ae978fd84..88c4b8891d00d 100755 --- a/testsuite/fuzzer/fuzz.sh +++ b/testsuite/fuzzer/fuzz.sh @@ -284,7 +284,7 @@ function run() { fi fi info "Running $fuzz_target" - cargo_fuzz run --sanitizer none -O $fuzz_target $testcase -- -fork=15 #-ignore_crashes=1 + cargo_fuzz run --sanitizer address -O $fuzz_target $testcase -- -fork=15 #-ignore_crashes=1 } function test() { diff --git a/third_party/move/move-binary-format/src/errors.rs b/third_party/move/move-binary-format/src/errors.rs index 5dee9ab89be7b..5fe9af70b5a1d 100644 --- a/third_party/move/move-binary-format/src/errors.rs +++ b/third_party/move/move-binary-format/src/errors.rs @@ -20,12 +20,11 @@ pub type PartialVMResult = ::std::result::Result; /// e.g. DEBUG_VM_STATUS=ABORTED,UNKNOWN_INVARIANT_VIOLATION_ERROR ./fuzz.sh run move_aptosvm_publish_and_run /// third_party/move/move-core/types/src/vm_status.rs:506 for the list of status codes. #[cfg(feature = "fuzzing")] -macro_rules! maybe_debug_panic { +macro_rules! fuzzing_maybe_panic { ($major_status:expr, $message:expr) => {{ if let Ok(debug_statuses) = std::env::var("DEBUG_VM_STATUS") { - let status_strings: Vec<&str> = debug_statuses.split(',').collect(); - if status_strings - .iter() + if debug_statuses + .split(',') .any(|s| s.trim() == format!("{:?}", $major_status)) { panic!("PartialVMError: {:?} {:?}", $major_status, $message); @@ -458,7 +457,7 @@ impl PartialVMError { }; #[cfg(feature = "fuzzing")] - maybe_debug_panic!(major_status, message); + fuzzing_maybe_panic!(major_status, message); Self(Box::new(PartialVMError_ { major_status,