Structure-aware, in-process, coverage-guided, evolutionary fuzzing engine for Rust functions.

Overview

fuzzcheck

Fuzzcheck is a structure-aware, in-process, coverage-guided, evolutionary fuzzing engine for Rust functions.

Given a function test: (T) -> bool, you can use fuzzcheck to find a value of type T that fails the test or leads to a crash.

Fuzzcheck works by maintaining a pool of test inputs and ranking them using the uniqueness of the code coverage caused by running test(input). From that pool, it selects a high-ranking input, mutates it, and runs the test function again. If the new mutated input has an interesting code coverage then it is added to the pool, otherwise, fuzzcheck tries again with a different input and mutation.

In pseudocode:

loop {
    let input = pool.select();
    mutate(&mut input);

    let analysis = analyze(test, &input);

    match analysis {
        Failed => reportFailure(input),
        Interesting(score) => pool.add(input, score),
        NotInteresting => continue
    }
}

Fuzzcheck is unique because, unlike other coverage-guided fuzzing engines, it doesn't work with bitstrings but instead works with values of any type T directly. The complexity of the inputs and the way to mutate them is given by functions defined by the user.

Usage

The first step is to install the cargo-fuzzcheck executable using cargo nightly.

cargo +nightly install cargo-fuzzcheck

Then, somewhere else, create a new cargo crate. It will contain the library code that you want to fuzz-test. Also do not forget to set the rust version to nightly.

cargo new --lib my_library
cd my_library
rustup override set nightly

Then, run cargo fuzzcheck init to initialize a fuzz folder that will contain all future fuzz tests.

cargo fuzzcheck init

A sample test function was created at fuzz/instrumented/src/lib.rs. The generated file contains an example of a custom data type being fuzzed. The derive proc_macro DefaultMutator automatically generates a mutator that you can give to fuzzcheck.

use decent_serde_json_alternative::{FromJson, ToJson};
use fuzzcheck_mutators::DefaultMutator;

#[derive(Clone, FromJson, ToJson, DefaultMutator)]
pub enum SampleEnum<T> {
    A(u8),
    B { x: bool , y: Option<T> },
    C,
    D
}

#[derive(Clone, FromJson, ToJson, DefaultMutator)]
pub struct SampleStruct<A, B, C> {
    a: A,
    b: Vec<B>,
    c: C
}

The file also contains a sample test function:

pub fn test(input: &[SampleStruct<u8, Option<u8>, SampleEnum<u8>>]) -> bool {
    if 
        input.len() > 5 &&
        input[0].a == 0 &&
        input[0].b == vec![Some(2), None, Some(187)] &&
        matches!(input[0].c, SampleEnum::C) &&
        input[1].a == 189 &&
        input[1].b.len() > 5 &&
        // etc.
    {
        false
    }
    else {
        true
    }
}

And an executable script was created at fuzz/non_instrumented/fuzz_targets/target1.rs. It launches the fuzzing engine on the above test function using the default mutator.

/* Various import statements not included in this example */
fn main() {
    // a vector mutator that uses the default mutator generated by the derive proc_macro
    let mutator = Vec::<SampleStruct<u8, Option<u8>, SampleEnum<u8>>>::default_mutator();
    // a lightweight serializer is used to save the interesting inputs to the file system,
    // you can also use a serde-based serializer if you prefer
    let serializer = JsonSerializer::default();
    // launch fuzzcheck on the test function
    let _ = fuzzcheck::launch(test, mutator, serializer);
}

You can already try launching this test:

cargo fuzzcheck run target1 fuzz

This starts a loop that will stop when a failing test has been found.

A line will be printed whenever a newsworthy event happened, along with some statistics. For example:

NEW     1004619 score: 34.30    pool: 29        exec/s: 1832012 cplx: 110.55
  • NEW means that a new input was added to the pool of interesting inputs
  • 1,004,619 is the number of iterations that were performed so far
  • score: 34.30 is a measure of the total code coverage caused by all inputs in the pool
  • pool: 29 is the number of inputs in the pool
  • exec/s: 1,832,012 is the average number of iterations performed every second
  • cplx: 128.94 is the average complexity of the inputs in the pool

When a failing test has been found, the following is printed:

================ TEST FAILED ================
2828995 score: 57.80    pool: 50        exec/s: 1745441 cplx: 141.34	
Saving at "fuzz/artifacts/target1/2a71aa786f3e552b.json"

Here, the path to the artifact file is fuzz/artifacts/target1/2a71aa786f3e552b.json. It contains the JSON-encoded input that failed the test.

[
    {
    "a": 0,
    "b": [
      2,
      null,
      187
    ],
    "c": {
      "kind": "C"
    }
  },
  {
    "a": 189,
    "b": [
      89,
      null,
      213,
      189,
      null,
      32
    ],
    "c": {
      "kind": "A",
      "payload": {
        "0": 7
      }
    }
  },
  ...
]

Moreover, the fuzzer can maintain a copy of its input pool in the file system, which is located by default at fuzz/corpora/<target>. Fuzzing corpora are useful to kick-start a fuzzing process by providing a list of known interesting inputs. If you try to run the fuzzer again, you will see that it finds the problematic input instantly. This is because it first read the values written inside the fuzz corpus and used them as starting points.

Structure of the fuzz folder

The fuzz folder is a bit difficult to understand, because fuzzcheck needs to compile your crate and the fuzz test in two different ways. This is why it contains an instrumented and a non-instrumented folder.

The instrumented folder contains all the test functions and their helper functions. It can use your library as a dependency but not fuzzcheck or non_instrumented. Every piece of code written there will be instrumented such that its code coverage can be recorded.

The non-instrumented folder contains the code that launches the fuzzer (called the fuzz_targets). It uses your library, fuzzcheck, and instrumented as dependencies. The code there is not instrumented.

.
├── Cargo.toml
├── fuzz                     # everything inside `fuzz` is to be used by fuzzcheck
│  ├── fuzzcheck.toml        # fuzzcheck configuration file
│  ├── instrumented          # a crate that contains the test functions
│  │  ├── Cargo.toml
│  │  └── src
│  │     └── lib.rs
│  └── non_instrumented      # a crate to compile fuzzcheck and launch the fuzz tests 
│     ├── build.rs
│     ├── Cargo.toml
│     └── fuzz_targets
│        ├── target1.rs      # a fuzz-test
│        └── target2.rs      # another fuzz-test
└── src
   └── lib.rs                # your library code

Note that if instrumented and non_instrumented both depend on a common crate A, then that crate will be compiled twice and the two versions of it will live in the resulting binary. These two versions will have different, incompatible versions of the types and traits defined by A.

Minifying failing test inputs

Fuzzcheck can also be used to minify a large input that fails a test.

Let's say you have a file crash.json containing an input that you would like to minify:

[
  {
    "a": 0,
    "b": [2, null, 187],
    "c": 9
  },
  {
    "a": 189,
    "b": [89, null, 213, 189, null, 32],
    "c": 19
  },
  ...
]

Launch cargo-fuzzcheck run on your target with the tmin command and an --input-file option.

cargo fuzzcheck run target1 tmin --input-file "artifacts/crash.json"

This will repeatedly launch the fuzzer in “minify” mode and save the artifacts in the folder artifacts/crash.minified. The name of each artifact will be prefixed with the complexity of its input. For example, crash.minified/800--fe958d4f003bd4f5.json has a complexity of 8.00.

You can stop the minifying fuzzer at any point and look for the least complex input in the crash.minified folder.

Creating a Mutator

If you would like to fuzz-test your own custom type T without the DefaultMutator derive attribute, you will have to create a type that conforms to the Mutator<T> trait.

This trait can be a bit difficult to implement, but it is very powerful and it is possible to write efficient and composable mutators with it. For example, fuzzcheck implements U8Mutator (u8), OptionMutator (Option), and VecMutator (Vec). They compose such that it possible to use a VecMutator<VecMutator<OptionMutator<U8Mutator>>> to fuzz values of type Vec<Vec<Option<u8>>>. A number of other mutators are already defined: TupleMutator for all types that have a tuple-like structure as well as EnumNPayloadMutator for all types that have an enum-like structure containing N items that have associated data.

Furthermore, the fuzzcheck_mutators_derive crate offers a proc_macro that can choose a default mutator for user-defined types automatically.

I would like to write a guide to fuzzcheck to explain the trait and how to work with it. But in the meantime, if you have questions, please send me an email or create an issue on GitHub.

My goal is to write more mutators for common types and building blocks for composability such that a custom implementation of Mutator<T> is rarely needed.

Configuration and Instrumentation

The file located at fuzz/fuzzcheck.toml can be used to configure fuzzcheck. It can be used to:

  • change the type of coverage instrumentation that is used to guide the fuzzer
  • choose default arguments to the cargo fuzzcheck command
  • change how the instrumented library is compiled

All settings can be configured globally or per fuzz target.

For example, you can disable the trace-compares coverage instrumentation globally by setting:

[default]
trace-compares = false

This will significantly speed up the fuzzing iteration speed and reduce the size of the internal pool of inputs, but wil miss code coverage information, which may negatively affect the overall performance of the fuzzer.

If you would like to enable stack depth tracing for a specific fuzz target, which can be used to find stack overflows, you can set:

[targets.my_target]
stack_depth = true

Note that stack depth tracing is currently experimental.

You can change the default command line arguments of cargo-fuzzcheck as follows:

[default]
# by default, do not generate inputs of complexity more than 4096
max_cplx = 4096
[targets.target1]
# but for target1, reduce the default maximum complexity to 256
max_cplx = 256
# and use a custom folder to save the artifacts
artifacts = "fuzz/different_artifacts_folder"

This will allow you to simply run:

cargo fuzzcheck run target1 fuzz

instead of:

cargo fuzzcheck run target1 fuzz -max-cplx 256 -artifacts "fuzz/different_artifacts_folder"

Finally, you can specify which features of the (non-)instrumented library you would like to enable via the instrumented_default_features (bool) and instrumented_features (vector of strings) settings.

Previous work on fuzzing engines

As far as I know, evolutionary, coverage-guided fuzzing engines were popularized by American Fuzzy Lop (AFL).
Fuzzcheck is also evolutionary and coverage-guided.

Later on, LLVM released its own fuzzing engine, libFuzzer, which is based on the same ideas as AFL, but it uses Clang’s SanitizerCoverage and is in-process (it lives in the same process as the program being fuzz-tested.
Fuzzcheck is also in-process and also uses SanitizerCoverage.

Both AFL and libFuzzer work by manipulating bitstrings (e.g. 1011101011). However, many programs work on structured data, and mutations at the bitstring level may not map to meaningful mutations at the level of the structured data. This problem can be partially addressed by using a compact binary encoding such as protobuf and providing custom mutation functions to libFuzzer that work on the structured data itself. This is a way to perform “structure-aware fuzzing” (talk, tutorial).

An alternative way to deal with structured data is to use generators just like QuickCheck’s Arbitrary trait. And then to “treat the raw byte buffer input provided by the coverage-guided fuzzer as a sequence of random values and implement a “random” number generator around it.” (cited blog post by @fitzgen). The tool cargo-fuzz has recently implemented that approach.

Fuzzcheck is also structure-aware, but unlike previous attempts at structure-aware fuzzing, it doesn't use an intermediary binary encoding such as protobuf nor does it use Quickcheck-like generators. Instead, it directly mutates the typed values in-process. This is better many ways. First, it is faster because there is no need to encode and decode inputs at each iteration. Second, the complexity of the input is given by a user-defined function, which will be more accurate than counting the bytes of the protobuf encoding. Finally, and most importantly, the mutations are faster and more meaningful than those done on protobuf or Arbitrary’s byte buffer-based RNG. A detail that I particularly like about fuzzcheck, and that is possible only because it mutates typed values, is that every mutation is done in-place and is reversable. That means that generating a new test case is super fast, and can often even be done with zero allocations.

As I was developing Fuzzcheck for Swift, a few researchers developed Fuzzchick for Coq (paper). It is a coverage-guided property-based testing tool implemented as an extension to Quickchick. As far as I know, it is the only other tool with the same philosophy as fuzzcheck. The similarity between the names fuzzcheck and Fuzzchick is a coincidence.

Comments
  • Crash while trying to read LLVM covmap

    Crash while trying to read LLVM covmap

    I encountered this crash while trying to run cargo-fuzzcheck.

    This is using the nightly-x86_64-apple-darwin toolchain (rustc 1.56.0-nightly (b70888601 2021-07-28))

    I'm currently experimenting with different rustc versions to see if that makes a difference.

    I'm using the latest version of both fuzzcheck and cargo-fuzzcheck (0.7.0)

    The command I'm using is cargo fuzzcheck leaderboard::test::fuzz_id_encoding fuzz --artifacts fuzz/artifacts (leaderboard::test::fuzz_id_encoding is the path to the test)

    running 1 test
    test leaderboard::test::fuzz_id_encoding ... thread 'main' panicked at 'assertion failed: `(left == right)`
      left: `156`,
     right: `0`', /Users/teymouraldridge/.cargo/registry/src/github.com-1ecc6299db9ec823/fuzzcheck-0.7.0/src/code_coverage_sensor/llvm_coverage.rs:306:5
    stack backtrace:
       0:        0x1031b3df4 - std::backtrace_rs::backtrace::libunwind::trace::h32ef383823110ea5
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5
       1:        0x1031b3df4 - std::backtrace_rs::backtrace::trace_unsynchronized::h39cafb439612ba84
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
       2:        0x1031b3df4 - std::sys_common::backtrace::_print_fmt::h57709926472a5d5c
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/sys_common/backtrace.rs:67:5
       3:        0x1031b3df4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hbf0f7aeb2a01393a
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/sys_common/backtrace.rs:46:22
       4:        0x1031d7ffc - core::fmt::write::h8160330c41daaf61
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/core/src/fmt/mod.rs:1115:17
       5:        0x1031ab8da - std::io::Write::write_fmt::haa5623a2a8d2ec9f
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/io/mod.rs:1665:15
       6:        0x1031b620f - std::sys_common::backtrace::_print::ha01b9c824fd26115
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/sys_common/backtrace.rs:49:5
       7:        0x1031b620f - std::sys_common::backtrace::print::hd6de520bd6e67ce7
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/sys_common/backtrace.rs:36:9
       8:        0x1031b620f - std::panicking::default_hook::{{closure}}::h5fe994d86d862da0
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:208:50
       9:        0x1031b5d0d - std::panicking::default_hook::hba89cfe1e23145fb
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:225:9
      10:        0x1031b6910 - std::panicking::rust_panic_with_hook::h674e3a191f056728
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:622:17
      11:        0x1031b63b5 - std::panicking::begin_panic_handler::{{closure}}::hc97521b9fa6c7ab0
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:519:13
      12:        0x1031b4298 - std::sys_common::backtrace::__rust_end_short_backtrace::h9a967faa138ad029
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/sys_common/backtrace.rs:141:18
      13:        0x1031b631a - rust_begin_unwind
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:515:5
      14:        0x10321e58f - core::panicking::panic_fmt::h2e3306ce37bd7247
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/core/src/panicking.rs:92:14
      15:        0x1031d5697 - core::panicking::assert_failed_inner::h4e794867b3d5f849
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/core/src/panicking.rs:160:17
      16:        0x1031f090e - core[1037ddd5376118b]::panicking::assert_failed::<usize, usize>
      17:        0x102a4abed - fuzzcheck[8eebe5071d6b1a76]::code_coverage_sensor::llvm_coverage::read_covmap
      18:        0x1028c8dde - <fuzzcheck[8eebe5071d6b1a76]::code_coverage_sensor::CodeCoverageSensor>::new::<<fuzzcheck[8eebe5071d6b1a76]::builder::FuzzerBuilder4<[i32], main[4da33c02eb1296a4]::leaderboard::test::predicate, fuzzcheck[8eebe5071d6b1a76]::mutators::vector::VecMutator<i32, fuzzcheck[8eebe5071d6b1a76]::mutators::integer::I32Mutator>, alloc[7bd5eaea06473e33]::vec::Vec<i32>, fuzzcheck[8eebe5071d6b1a76]::serializers::serde_serializer::SerdeSerializer<alloc[7bd5eaea06473e33]::vec::Vec<i32>>>>::observe_only_files_from_current_dir::{closure#0}, <fuzzcheck[8eebe5071d6b1a76]::builder::FuzzerBuilder4<[i32], main[4da33c02eb1296a4]::leaderboard::test::predicate, fuzzcheck[8eebe5071d6b1a76]::mutators::vector::VecMutator<i32, fuzzcheck[8eebe5071d6b1a76]::mutators::integer::I32Mutator>, alloc[7bd5eaea06473e33]::vec::Vec<i32>, fuzzcheck[8eebe5071d6b1a76]::serializers::serde_serializer::SerdeSerializer<alloc[7bd5eaea06473e33]::vec::Vec<i32>>>>::observe_only_files_from_current_dir::{closure#1}>
      19:        0x10268ff3c - fuzzcheck[8eebe5071d6b1a76]::fuzzer::launch::<alloc[7bd5eaea06473e33]::vec::Vec<i32>, [i32], main[4da33c02eb1296a4]::leaderboard::test::predicate, fuzzcheck[8eebe5071d6b1a76]::mutators::vector::VecMutator<i32, fuzzcheck[8eebe5071d6b1a76]::mutators::integer::I32Mutator>, fuzzcheck[8eebe5071d6b1a76]::serializers::serde_serializer::SerdeSerializer<alloc[7bd5eaea06473e33]::vec::Vec<i32>>, <fuzzcheck[8eebe5071d6b1a76]::builder::FuzzerBuilder4<[i32], main[4da33c02eb1296a4]::leaderboard::test::predicate, fuzzcheck[8eebe5071d6b1a76]::mutators::vector::VecMutator<i32, fuzzcheck[8eebe5071d6b1a76]::mutators::integer::I32Mutator>, alloc[7bd5eaea06473e33]::vec::Vec<i32>, fuzzcheck[8eebe5071d6b1a76]::serializers::serde_serializer::SerdeSerializer<alloc[7bd5eaea06473e33]::vec::Vec<i32>>>>::observe_only_files_from_current_dir::{closure#0}, <fuzzcheck[8eebe5071d6b1a76]::builder::FuzzerBuilder4<[i32], main[4da33c02eb1296a4]::leaderboard::test::predicate, fuzzcheck[8eebe5071d6b1a76]::mutators::vector::VecMutator<i32, fuzzcheck[8eebe5071d6b1a76]::mutators::integer::I32Mutator>, alloc[7bd5eaea06473e33]::vec::Vec<i32>, fuzzcheck[8eebe5071d6b1a76]::serializers::serde_serializer::SerdeSerializer<alloc[7bd5eaea06473e33]::vec::Vec<i32>>>>::observe_only_files_from_current_dir::{closure#1}>
      20:        0x1026eaba5 - <fuzzcheck[8eebe5071d6b1a76]::builder::FuzzerBuilder5<[i32], main[4da33c02eb1296a4]::leaderboard::test::predicate, fuzzcheck[8eebe5071d6b1a76]::mutators::vector::VecMutator<i32, fuzzcheck[8eebe5071d6b1a76]::mutators::integer::I32Mutator>, alloc[7bd5eaea06473e33]::vec::Vec<i32>, fuzzcheck[8eebe5071d6b1a76]::serializers::serde_serializer::SerdeSerializer<alloc[7bd5eaea06473e33]::vec::Vec<i32>>, <fuzzcheck[8eebe5071d6b1a76]::builder::FuzzerBuilder4<[i32], main[4da33c02eb1296a4]::leaderboard::test::predicate, fuzzcheck[8eebe5071d6b1a76]::mutators::vector::VecMutator<i32, fuzzcheck[8eebe5071d6b1a76]::mutators::integer::I32Mutator>, alloc[7bd5eaea06473e33]::vec::Vec<i32>, fuzzcheck[8eebe5071d6b1a76]::serializers::serde_serializer::SerdeSerializer<alloc[7bd5eaea06473e33]::vec::Vec<i32>>>>::observe_only_files_from_current_dir::{closure#0}, <fuzzcheck[8eebe5071d6b1a76]::builder::FuzzerBuilder4<[i32], main[4da33c02eb1296a4]::leaderboard::test::predicate, fuzzcheck[8eebe5071d6b1a76]::mutators::vector::VecMutator<i32, fuzzcheck[8eebe5071d6b1a76]::mutators::integer::I32Mutator>, alloc[7bd5eaea06473e33]::vec::Vec<i32>, fuzzcheck[8eebe5071d6b1a76]::serializers::serde_serializer::SerdeSerializer<alloc[7bd5eaea06473e33]::vec::Vec<i32>>>>::observe_only_files_from_current_dir::{closure#1}>>::launch
      21:        0x1027555a9 - main[4da33c02eb1296a4]::leaderboard::test::fuzz_id_encoding
      22:        0x102a39cba - core::ops::function::FnOnce::call_once::h864fb8cb65c82ad0
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/core/src/ops/function.rs:227:5
      23:        0x102a39cba - test::__rust_begin_short_backtrace::h7ec90dbafd078692
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/test/src/lib.rs:578:5
      24:        0x102a38974 - <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once::h22c35b1fd1591729
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/alloc/src/boxed.rs:1572:9
      25:        0x102a38974 - <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once::he01aa01c6784e37c
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panic.rs:347:9
      26:        0x102a38974 - std::panicking::try::do_call::hc677fc05d38b16ff
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:401:40
      27:        0x102a38974 - std::panicking::try::h506c53c09d46da41
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:365:19
      28:        0x102a38974 - std::panic::catch_unwind::h9a8b52d6ea7a527e
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panic.rs:434:14
      29:        0x102a38974 - test::run_test_in_process::hcd24ff6bb028ff0a
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/test/src/lib.rs:601:18
      30:        0x102a38974 - test::run_test::run_test_inner::{{closure}}::hf60c537148a26f88
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/test/src/lib.rs:493:39
      31:        0x102a37e2d - test::run_test::run_test_inner::h0aa267bb56c93a74
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/test/src/lib.rs:531:13
      32:        0x102a36c1b - test::run_test::hbe8950e7a5e1d1f2
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/test/src/lib.rs:565:28
      33:        0x102a31bc7 - test::run_tests::ha378b857ae47dc9b
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/test/src/lib.rs:306:17
      34:        0x102a1a997 - test::console::run_tests_console::h2b48bcd5822b3fee
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/test/src/console.rs:290:5
      35:        0x102a2fdd5 - test::test_main::hff95eeeba4a6e4b1
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/test/src/lib.rs:123:15
      36:        0x102a30f5f - test::test_main_static::h6e9cc4a43b2aa36a
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/test/src/lib.rs:142:5
      37:        0x10288a22a - std[4656eb4d6ec895b4]::sys_common::backtrace::__rust_begin_short_backtrace::<fn(), ()>
      38:        0x10258d39c - std[4656eb4d6ec895b4]::rt::lang_start::<()>::{closure#0}
      39:        0x1031b6e39 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::he18e274b8ec42070
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/core/src/ops/function.rs:259:13
      40:        0x1031b6e39 - std::panicking::try::do_call::hea026a8f5852112e
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:401:40
      41:        0x1031b6e39 - std::panicking::try::h5a1bca372ac4c528
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:365:19
      42:        0x1031b6e39 - std::panic::catch_unwind::h4245da8e2d8cbf9a
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panic.rs:434:14
      43:        0x1031b6e39 - std::rt::lang_start_internal::{{closure}}::h64dd899fdea61a58
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/rt.rs:45:48
      44:        0x1031b6e39 - std::panicking::try::do_call::h25d01982e49ebd9a
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:401:40
      45:        0x1031b6e39 - std::panicking::try::hb40c0d004f245d35
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panicking.rs:365:19
      46:        0x1031b6e39 - std::panic::catch_unwind::hc4bddc94710aa7ee
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/panic.rs:434:14
      47:        0x1031b6e39 - std::rt::lang_start_internal::hdfe6c30fb8c47cc9
                                   at /rustc/b70888601af92f6cdc0364abab3446e418b91d36/library/std/src/rt.rs:45:20
      48:        0x10266a639 - _main
    FAILED
    
    failures:
    
    failures:
        leaderboard::test::fuzz_id_encoding
    
    opened by teymour-aldridge 12
  • fix out-of-bounds access bug

    fix out-of-bounds access bug

    Unsafe access to the first vector element when the vector was empty was causing a segmentation fault when using fuzzcheck. This patch fixes it.

    Thread 3.1 "action_fuzz-b00" received signal SIGSEGV, Segmentation fault.
    
    [Switching to Thread 0x7ffff7a453c0 (LWP 574366)]
    0x0000555555bb1c7c in <fuzzcheck::code_coverage_sensor::CodeCoverageSensor as fuzzcheck::traits::Sensor>::iterate_over_observations ()
    (gdb) bt
    #0  0x0000555555bb1c7c in <fuzzcheck::code_coverage_sensor::CodeCoverageSensor as fuzzcheck::traits::Sensor>::iterate_over_observations ()
    #1  0x00005555557d487a in <fuzzcheck::sensors_and_pools::and_sensor_and_pool::AndPool<fuzzcheck::sensors_and_pools::simplest_to_activate_counter_pool::SimplestToActivateCounterPool, fuzzcheck::sensors_and_pools::and_sensor_and_pool::AndPool<fuzzcheck::sensors_and_pools::and_sensor_and_pool::AndPool<fuzzcheck::sensors_and_pools::most_n_diverse_pool::MostNDiversePool, fuzzcheck::sensors_and_pools::optimise_aggregate_stat_pool::OptimiseAggregateStatPool<fuzzcheck::sensors_and_pools::optimise_aggregate_stat_pool::NumberOfActivatedCounters>>, fuzzcheck::sensors_and_pools::and_sensor_and_pool::AndPool<fuzzcheck::sensors_and_pools::maximise_counter_value_pool::MaximiseCounterValuePool, fuzzcheck::sensors_and_pools::optimise_aggregate_stat_pool::OptimiseAggregateStatPool<fuzzcheck::sensors_and_pools::optimise_aggregate_stat_pool::SumOfCounterValues>>>> as fuzzcheck::traits::CompatibleWithSensor<fuzzcheck::code_coverage_sensor::CodeCoverageSensor>>::process ()
    
    opened by dkuehr 8
  • Error minifying an input

    Error minifying an input

    I found a failing test case, however, trying to minify it fails:

    error: linking with `cc` failed: exit status: 1
    
      = note: Undefined symbols for architecture x86_64:
                "___llvm_profile_runtime", referenced from:
                    ___llvm_profile_runtime_user in fuzz_parser-10a0a12e83348750.fuzz_parser.6cb7562a-cgu.0.rcgu.o
                   (maybe you meant: ___llvm_profile_runtime_user)
              ld: symbol(s) not found for architecture x86_64
              clang: error: linker command failed with exit code 1 (use -v to see invocation)
    

    I'm on MacOS Catalina, x86_64.

    opened by teymour-aldridge 7
  • Recurrence of recursive mutator bug

    Recurrence of recursive mutator bug

    Unfortunately I think that #31 is still here: I tried writing a recursive JSON generator recently, but this crashes pretty quickly after being launched. I thought this might be because I modify the fuzzcheck generated types before converting them to the serde_json::Value enum (stripping invalid characters from the strings), but I removed that code and it didn't seem to fix the problem. The code is at https://git.sr.ht/~teymour/fuzzcheck_generators/tree/ (in fuzzcheck_serde_json_generator), and I get this error output (using the latest commit in the fuzzcheck repository)

    thread 'main' panicked at 'The mutator used by the fuzz test does not evaluate the complexity of the test cases consistently.
                        This is a bug in the implementation of fuzzcheck::mutators::map::MapMutator<fuzzcheck_serde_json_generator::InternalJsonValue, serde_json::value::Value, fuzzcheck::mutators::recursive::RecursiveMutator<fuzzcheck_serde_json_generator::InternalJsonValueMutator>, fuzzcheck_serde_json_generator::json_value_mutator::{{closure}}, fuzzcheck_serde_json_generator::json_value_mutator::{{closure}}, fuzzcheck_serde_json_generator::json_value_mutator::{{closure}}>
                        =============
                        
                        {"":[]}
    
                        =============
                        ', /Users/teymour/.cargo/git/checkouts/fuzzcheck-rs-531eb3f95f61a5dd/2bfa9f0/fuzzcheck/src/fuzzer.rs:445:17
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    FAILED
    
    opened by teymour-aldridge 6
  • Avoid constructing a specific variant of an enum when using `DefaultMutator`

    Avoid constructing a specific variant of an enum when using `DefaultMutator`

    Is it possible to instruct Fuzzcheck not to use a specific variant of an enum?

    e.g.

    #[derive(DefaultMutator)]
    pub enum X {
      // fuzzcheck should construct this one
      SimpleType(String),
      // fuzzcheck should also construct this one
      AlsoSimpleType(i32),
      // fuzzcheck should not construct this one
      DoNotConstruct(HashMap<String, Vec<(usize, i32, String)>>
    }
    

    If it isn't, I'd be happy to implement this.

    opened by teymour-aldridge 6
  • Errors running fuzzcheck

    Errors running fuzzcheck

    I hope you're well :)

    (relevant code at the bottom of this issue)

    I'm trying to test a small parser with fuzzcheck, and I am running into a couple of errors.

    The first error I found was (everything running on MacOS Catalina, x86_64):

    teymouraldridge@Teymours-MBP tmp-XVrRgj % cargo +nightly fuzzcheck fuzz::test_fuzz_parser fuzz
    error: failed to run `rustc` to learn about target-specific information
    
    Caused by:
      process didn't exit successfully: `rustc - --crate-name ___ --print=file-names -Zinstrument-coverage=except-unused-functions -Zno-profiler-runtime --cfg fuzzing --target x86_64-apple-darwin --crate-type bin --crate-type rlib --crate-type dylib --crate-type cdylib --crate-type staticlib --crate-type proc-macro --print=sysroot --print=cfg` (exit status: 1)
      --- stderr
      error: unknown debugging option: `no-profiler-runtime`
    

    I updated everything (rust toolchain – so running the latest nightly – and fuzzcheck) and that issue went away (yay!) but instead this issue appears:

    teymouraldridge@Teymours-MBP tmp-XVrRgj % cargo +nightly fuzzcheck fuzz::test_fuzz_parser fuzz
    error: no library targets found in package `tmp-xvrrgj`
    

    My code is as follows:

    use std::mem;
    
    fn main() {}
    
    fn exec(mut instruction: String) -> Vec<u8> {
        let shuffles = Shuffles::parse(&mut instruction);
        let mut vec: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8];
        shuffles.execute(&mut vec)
    }
    
    /// Formal grammar:
    /// ```
    /// instructions ::= (instruction)+
    /// instruction ::= 'b'
    ///                 'i'
    ///                 'o'
    ///                 '(' + instruction+ + ')'
    ///                 '0'..='9' + instruction
    /// ```
    
    #[derive(Debug)]
    struct Shuffles(Vec<Shuffle>);
    
    impl Shuffles {
        fn parse(input: &mut String) -> Self {
            let mut output = vec![];
    
            loop {
                if input.starts_with(')') || input.is_empty() {
                    return Self(output);
                }
                output.push(Shuffle::parse(input))
            }
        }
    
        fn execute(&self, sequence: &mut Vec<u8>) -> Vec<u8> {
            for shuffle in &self.0 {
                shuffle.execute(sequence);
            }
            sequence.to_vec()
        }
    }
    
    #[derive(Debug)]
    enum Shuffle {
        Break,
        InRiffle,
        OutRiffle,
        Group(Shuffles),
        Repeat(u8, Box<Shuffle>),
    }
    
    impl Shuffle {
        fn execute(&self, sequence: &mut Vec<u8>) {
            match self {
                Shuffle::Break => {
                    let character = sequence.remove(0);
                    sequence.push(character);
                }
                Shuffle::InRiffle => {
                    let mut new = vec![];
                    let top_half = &sequence[0..sequence.len() / 2];
                    let bottom_half = &sequence[sequence.len() / 2..];
                    assert_eq!(top_half.len(), bottom_half.len());
                    for (top, bottom) in top_half.into_iter().zip(bottom_half) {
                        new.push(*bottom);
                        new.push(*top);
                    }
                    mem::swap(&mut new, sequence);
                }
                Shuffle::OutRiffle => {
                    let mut new = vec![];
                    let top_half = &sequence[0..sequence.len() / 2];
                    let bottom_half = &sequence[sequence.len() / 2..];
                    assert_eq!(top_half.len(), bottom_half.len());
                    for (top, bottom) in top_half.into_iter().zip(bottom_half) {
                        new.push(*top);
                        new.push(*bottom);
                    }
                    mem::swap(&mut new, sequence);
                }
                Shuffle::Group(shuffles) => {
                    shuffles.execute(sequence);
                }
                Shuffle::Repeat(n, shuffle) => {
                    for _ in 0..*n {
                        shuffle.execute(sequence)
                    }
                }
            }
        }
    
        fn parse(input: &mut String) -> Self {
            let character = input.remove(0);
            match character {
                'b' => Shuffle::Break,
                'i' => Shuffle::InRiffle,
                'o' => Shuffle::OutRiffle,
                '(' => {
                    let shuffles = Shuffles::parse(input);
                    assert_eq!(input.remove(0), ')');
                    Shuffle::Group(shuffles)
                }
                '0'..='9' => {
                    let mut string = String::from(character);
                    loop {
                        let next = input.chars().next().unwrap();
                        match next {
                            '1'..='9' => {
                                string.push(next);
                                input.remove(0);
                            }
                            _ => {
                                break;
                            }
                        }
                    }
                    let n = string.parse::<u8>().unwrap();
                    let shuffle = Shuffle::parse(input);
                    Shuffle::Repeat(n, Box::new(shuffle))
                }
                _ => panic!(),
            }
        }
    }
    
    #[cfg(test)]
    mod fuzz {
        use fuzzcheck::{
            alternation, concatenation, literal, mutators::grammar::grammar_based_string_mutator,
            recurse, recursive, repetition, FuzzerBuilder, SerdeSerializer,
        };
    
        use crate::Shuffles;
    
        #[test]
        fn test_fuzz_parser() {
            let grammar = repetition! {
                recursive! {
                    g in alternation! {
                        literal!('b'),
                        literal!('i'),
                        literal!('o'),
                        concatenation! {
                            literal!('('),
                            recurse!(g),
                            literal!(')')
                        },
                        concatenation! {
                            repetition!(literal!('0'..='9'), 0..1000),
                            recurse!(g)
                        }
                    }
                },
                0..1000
            };
    
            fn test(input: &String) {
                Shuffles::parse(&mut input.clone());
            }
    
            FuzzerBuilder::test(test)
                .mutator(grammar_based_string_mutator(grammar))
                .serializer(SerdeSerializer::default())
                .arguments_from_cargo_fuzzcheck()
                .observe_only_files_from_current_dir()
                .launch()
        }
    }
    
    opened by teymour-aldridge 6
  • Using `#[field_mutator(...)]` attribute with `DefaultMutator` derive macro.

    Using `#[field_mutator(...)]` attribute with `DefaultMutator` derive macro.

    At the moment you can only use #[field_mutator(...)] with make_mutator!(...) macro.

    Is it possible to allow that attribute for DefaultMutator macro as well to avoid duplicate struct definitions?

    opened by binier 6
  • Allow specific enum variants to be avoided.

    Allow specific enum variants to be avoided.

    This adds an attribute called #[ignore_variant], usable on enums which instructs Fuzzcheck to not construct that variant of the enumeration.

    I haven't yet solved this for generic types.

    opened by teymour-aldridge 5
  • Error

    Error "the mutator used by the fuzz test does not evaluate the complexity of the test cases consistently"

    I encountered this error, and I think it might be a bug in fuzzcheck because I have not implemented any mutators myself (I've only used Fuzzcheck's macros).

    Sorry for the lack of specificity, I'm not really sure about how fuzzcheck's internals work.

    The code in question can be found at these two URLs:

    • https://github.com/bailion/compiler/blob/2b94c2461e91c45724657eaa5e2716b2260858b8/tests/generator/src/lib.rs
    • https://github.com/bailion/compiler/blob/2b94c2461e91c45724657eaa5e2716b2260858b8/tests/fuzzer/src/lib.rs
    opened by teymour-aldridge 4
  • AddressSanitizer complains when stopping fuzzer w/ CTRL+C

    AddressSanitizer complains when stopping fuzzer w/ CTRL+C

    When canceling a running fuzzer with CTRL+C, I get a big ASAN dump regardless of the fuzzing target. The repro command below uses the usage_tests crate, but any test function will do, even an empty one. I haven't spent any time debugging whether this is a real issue or just some ASAN false positive. Unfortunately I'm not getting symbols from AddressSanitizer on where the issue might be : (

    ~/dev/fuzzcheck/usage_tests/basic_crate$ RUST_BACKTRACE=1 cargo +nightly-2022-07-21 fuzzcheck --address-sanitizer tests::fuzz
    
        Finished release [optimized] target(s) in 12.65s
         Running unittests src/lib.rs (target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335)
    
    running 1 test
    test tests::fuzz ... 0ms  START
    29ms  1 simplest_cov(0 cov: 0/46 cplx: 0.00) diverse_cov_20(0) max_each_cov_hits(0 sum: 0) diverse_cov_1(0) max_total_cov_hits(0) iter/s 38461
    30ms  2 simplest_cov(1 cov: 6/46 cplx: 25.00) diverse_cov_20(6) max_each_cov_hits(1 sum: 16) diverse_cov_1(6) max_total_cov_hits(16) iter/s 4192
    30ms  3 simplest_cov(2 cov: 7/46 cplx: 24.00) diverse_cov_20(7) max_each_cov_hits(2 sum: 22) diverse_cov_1(6) max_total_cov_hits(16) iter/s 3911
    34ms  FINISHED READING CORPUS
    35ms  PULSE 292 simplest_cov(2 cov: 7/46 cplx: 24.00) diverse_cov_20(7) max_each_cov_hits(2 sum: 22) diverse_cov_1(6) max_total_cov_hits(16) iter/s 570312
    36ms  PULSE 584 simplest_cov(2 cov: 7/46 cplx: 24.00) diverse_cov_20(7) max_each_cov_hits(2 sum: 22) diverse_cov_1(6) max_total_cov_hits(16) iter/s 422270
    37ms  PULSE 1168 simplest_cov(2 cov: 7/46 cplx: 24.00) diverse_cov_20(7) max_each_cov_hits(2 sum: 22) diverse_cov_1(6) max_total_cov_hits(16) iter/s 387267
    41ms  PULSE 2336 simplest_cov(2 cov: 7/46 cplx: 24.00) diverse_cov_20(7) max_each_cov_hits(2 sum: 22) diverse_cov_1(6) max_total_cov_hits(16) iter/s 343832
    49ms  PULSE 4672 simplest_cov(2 cov: 7/46 cplx: 24.00) diverse_cov_20(7) max_each_cov_hits(2 sum: 22) diverse_cov_1(6) max_total_cov_hits(16) iter/s 326348
    
    ^C
    
    ~/dev/fuzzcheck/usage_tests/basic_crate$ =================================================================
    ==428240==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x625000013fa0 at pc 0x55c662d3d0c2 bp 0x625000013f80 sp 0x625000013750
    WRITE of size 16 at 0x625000013fa0 thread T0
        #0 0x55c662d3d0c1  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x1290c1) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #1 0x55c662ff7ab7  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x3e3ab7) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #2 0x55c662f46c98  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x332c98) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #3 0x55c662e441b6  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x2301b6) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #4 0x55c662e20f56  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x20cf56) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #5 0x55c662f1e3b4  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x30a3b4) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #6 0x55c662f0b6de  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x2f76de) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #7 0x7f4d5eee651f  (/lib/x86_64-linux-gnu/libc.so.6+0x4251f) (BuildId: 89c3cb85f9e55046776471fed05ec441581d1969)
        #8 0x55c662d8d419  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x179419) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #9 0x55c662d8d30d  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x17930d) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #10 0x55c662dd430e  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x1c030e) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #11 0x55c662e4a668  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x236668) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #12 0x55c662e3e717  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x22a717) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #13 0x55c662e00498  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x1ec498) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #14 0x55c662e392ea  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x2252ea) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #15 0x55c662e8e0c2  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x27a0c2) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #16 0x55c662e8cdfb  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x278dfb) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #17 0x55c662e8bfbf  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x277fbf) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #18 0x55c662e8a735  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x276735) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #19 0x55c662e84fdb  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x270fdb) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #20 0x55c662e6da8f  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x259a8f) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #21 0x55c662e82ede  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x26eede) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #22 0x55c662e83dc3  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x26fdc3) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #23 0x55c662dd9a72  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x1c5a72) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #24 0x55c662dfd118  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x1e9118) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #25 0x55c662fee0b9  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x3da0b9) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #26 0x55c662df8e91  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x1e4e91) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
        #27 0x7f4d5eecdd8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: 89c3cb85f9e55046776471fed05ec441581d1969)
        #28 0x7f4d5eecde3f  (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: 89c3cb85f9e55046776471fed05ec441581d1969)
        #29 0x55c662d1b144  (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x107144) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
    
    Address 0x625000013fa0 is a wild pointer inside of access range of size 0x000000000010.
    SUMMARY: AddressSanitizer: heap-buffer-overflow (~/dev/fuzzcheck/usage_tests/basic_crate/target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/basic_crate-355b4a7b4d1de335+0x1290c1) (BuildId: faf06c4db8d903caa5edfc5b0ddaf8fc28b78ab2)
    Shadow bytes around the buggy address:
      0x0c4a7fffa7a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c4a7fffa7b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c4a7fffa7c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c4a7fffa7d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
      0x0c4a7fffa7e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
    =>0x0c4a7fffa7f0: fa fa fa fa[fa]fa fa fa fa fa fa fa f1 f1 f1 f1
      0x0c4a7fffa800: f8 f2 f2 f2 f8 f8 f8 f2 f2 f2 f2 f2 f8 f8 f8 f2
      0x0c4a7fffa810: f2 f2 f2 f2 f8 f8 f2 f2 f8 f8 f8 f2 f2 f2 f2 f2
      0x0c4a7fffa820: f8 f8 f8 f8 f2 f2 f2 f2 f8 f8 f8 f8 f8 f8 f2 f2
      0x0c4a7fffa830: f2 f2 f8 f8 f2 f2 f8 f8 f8 f2 f2 f2 f2 f2 f8 f8
      0x0c4a7fffa840: f8 f8 f2 f2 f2 f2 f8 f8 f8 f8 f8 f8 f2 f2 f2 f2
    Shadow byte legend (one shadow byte represents 8 application bytes):
      Addressable:           00
      Partially addressable: 01 02 03 04 05 06 07
      Heap left redzone:       fa
      Freed heap region:       fd
      Stack left redzone:      f1
      Stack mid redzone:       f2
      Stack right redzone:     f3
      Stack after return:      f5
      Stack use after scope:   f8
      Global redzone:          f9
      Global init order:       f6
      Poisoned by user:        f7
      Container overflow:      fc
      Array cookie:            ac
      Intra object redzone:    bb
      ASan internal:           fe
      Left alloca redzone:     ca
      Right alloca redzone:    cb
    ==428240==ABORTING
    

    possibly relevant platform details:

    $ uname -a
    Linux XXX 5.17.15-76051715-generic #202206141358~1655919116~22.04~1db9e34 SMP PREEMPT Wed Jun 22 19 x86_64 x86_64 x86_64 GNU/Linux
    
    opened by phlip9 4
  • Linking issue with example fuzzer code

    Linking issue with example fuzzer code

    error: linking with `cc` failed: exit code: 1
      |
      = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-Wl,--eh-frame-hdr" "-Wl,-plugin=1" "-Wl,-plugin-opt=O3" "-Wl,-plugin-opt=mcpu=skylake" "-L" "/home/christophe/.rustup/toolchains/nightly-2021-02-20-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps/query_optimization.query_optimization.8ylrw7si-cgu.0.rcgu.o" "-o" "/home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps/libquery_optimization.so" "-Wl,--version-script=/tmp/rustctTGZXv/list" "/home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps/query_optimization.4vv4bvlcpeqs8lta.rcgu.o" "-shared" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-L" "/home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps" "-L" "/home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/release/deps" "-L" "/home/christophe/.rustup/toolchains/nightly-2021-02-20-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "/tmp/rustctTGZXv/libitertools-11c0588956c1a9e9.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustctTGZXv/libeither-9c441606e1522bc4.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustctTGZXv/libmemory_usage-a9daf975c5269191.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustctTGZXv/libpetgraph-d4a1ca2a4584a6ac.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustctTGZXv/libordermap-9ae9dcc2fa2a157d.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustctTGZXv/libfixedbitset-d5c84f681dbdfbe2.rlib" "-Wl,--no-whole-archive" "-Wl,--start-group" "-L" "/home/christophe/.rustup/toolchains/nightly-2021-02-20-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bdynamic" "-lstd-6f5658153d127ddd" "-Wl,--end-group" "-Wl,-Bstatic" "/tmp/rustctTGZXv/libcompiler_builtins-ea377e9224b11a8a.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-fuse-ld=gold"
      = note: /usr/bin/ld.gold: error: 1: could not load plugin library: 1: cannot open shared object file: No such file or directory
              /usr/bin/ld.gold: error: /home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps/query_optimization.query_optimization.8ylrw7si-cgu.0.rcgu.o:1:3: invalid character
              /usr/bin/ld.gold: error: /home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps/query_optimization.query_optimization.8ylrw7si-cgu.0.rcgu.o:1:3: syntax error, unexpected $end
              /usr/bin/ld.gold: error: /home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps/query_optimization.query_optimization.8ylrw7si-cgu.0.rcgu.o: not an object or archive
              /usr/bin/ld.gold: error: /home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps/query_optimization.4vv4bvlcpeqs8lta.rcgu.o:1:3: invalid character
              /usr/bin/ld.gold: error: /home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps/query_optimization.4vv4bvlcpeqs8lta.rcgu.o:1:3: syntax error, unexpected $end
              /usr/bin/ld.gold: error: /home/christophe/Code/encircle/query-optimization/fuzz/instrumented/target/x86_64-unknown-linux-gnu/release/deps/query_optimization.4vv4bvlcpeqs8lta.rcgu.o: not an object or archive
              /usr/bin/ld.gold: error: /tmp/rustctTGZXv/libitertools-11c0588956c1a9e9.rlib: plugin failed to claim member itertools-11c0588956c1a9e9.itertools.6c2ysjm2-cgu.0.rcgu.o at 956
              /usr/bin/ld.gold: error: /tmp/rustctTGZXv/libeither-9c441606e1522bc4.rlib: plugin failed to claim member either-9c441606e1522bc4.either.e7ks6amo-cgu.0.rcgu.o at 190
              /usr/bin/ld.gold: error: /tmp/rustctTGZXv/libmemory_usage-a9daf975c5269191.rlib: plugin failed to claim member memory_usage-a9daf975c5269191.memory_usage.6iqros1j-cgu.0.rcgu.o at 506
              /usr/bin/ld.gold: error: /tmp/rustctTGZXv/libpetgraph-d4a1ca2a4584a6ac.rlib: plugin failed to claim member petgraph-d4a1ca2a4584a6ac.petgraph.80g7g297-cgu.0.rcgu.o at 2304
              /usr/bin/ld.gold: error: /tmp/rustctTGZXv/libordermap-9ae9dcc2fa2a157d.rlib: plugin failed to claim member ordermap-9ae9dcc2fa2a157d.ordermap.ctam39c9-cgu.0.rcgu.o at 364
              /usr/bin/ld.gold: error: /tmp/rustctTGZXv/libfixedbitset-d5c84f681dbdfbe2.rlib: plugin failed to claim member fixedbitset-d5c84f681dbdfbe2.fixedbitset.8vnrbsqo-cgu.0.rcgu.o at 920
              collect2: error: ld returned 1 exit status
    

    The part -Wl,-plugin=1 seems to be the cause, but I can't find whether it is the expected name for an actual linker plugin, or is the root cause of the bug. I've tried a few versions of nightly in case the issue was due to breakage with newer versions, but 2021-02-20 (used here) is basically from when the last release went out.

    opened by christophebiocca 4
Owner
Loïc Lecrenier
Loïc Lecrenier
Rewind is a snapshot-based coverage-guided fuzzer targeting Windows kernel components.

Rewind is a snapshot-based coverage-guided fuzzer targeting Windows kernel components.

Quarkslab 259 Dec 26, 2022
A snapshotting, coverage-guided fuzzer for software (UEFI, Kernel, firmware, BIOS) built on SIMICS

TSFFS: Target Software Fuzzer For SIMICS TSFFS is a snapshotting, coverage-guided fuzzer built on the SIMICS full system simulator. TSFFS makes it eas

Intel Corporation 194 Oct 9, 2023
Hopper is a tool for generating fuzzing test cases for libraries automatically using interpretative fuzzing.

Hopper Hopper is an tool for generating fuzzing test cases for libraries automatically using interpretative fuzzing. It transforms the problem of libr

FuzzAnything 118 Nov 15, 2023
Hopper is a tool for generating fuzzing test cases for libraries automatically using interpretative fuzzing.

Hopper Hopper is an tool for generating fuzzing test cases for libraries automatically using interpretative fuzzing. It transforms the problem of libr

FuzzAnything 124 Nov 24, 2023
An example fuzzer about how to fuzz a JS engine combinign Nautilus with Token-level fuzzing

LibAFL QuickJS Fuzzing Example An example fuzzer about how to fuzz a JS engine combinign Nautilus with Token-level fuzzing. Prepare Make sure to have

Andrea Fioraldi 32 Dec 21, 2022
A symbolic-model-guided fuzzer for TLS

tlspuffin TLS Protocol Under FuzzINg A symbolic-model-guided fuzzer for TLS Master Thesis | Thesis Presentation | Documentation Description Fuzzing im

null 69 Dec 20, 2022
🐇 Fuzzing Rust code with American Fuzzy Lop

afl.rs Fuzzing Rust code with AFLplusplus What is it? Fuzz testing is a software testing technique used to find security and stability issues by provi

Rust Fuzzing Authority 1.3k Jan 5, 2023
Advanced Fuzzing Library - Slot your Fuzzer together in Rust! Scales across cores and machines. For Windows, Android, MacOS, Linux, no_std, ...

LibAFL, the fuzzer library. Advanced Fuzzing Library - Slot your own fuzzers together and extend their features using Rust. LibAFL is written and main

Advanced Fuzzing League ++ 1.2k Dec 29, 2022
A self-hosted Fuzzing-As-A-Service platform

OneFuzz A self-hosted Fuzzing-As-A-Service platform Project OneFuzz enables continuous developer-driven fuzzing to proactively harden software prior t

Microsoft 2.6k Dec 30, 2022
Pre-Silicon Hardware Fuzzing Toolkit

Disclaimer All components are provided for research and validation purposes only. Use at your own risk. Pre-Silicon Hardware Fuzzing Toolkit From CPU

Intel Labs 12 Dec 13, 2022
µFUZZ: Redesign of Parallel Fuzzing using Microservice Architecture

mufuzz, a parallel fuzzing framework TODO: Add reference Build Install cargo and protoc curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Software Systems Security Team at Penn State University 7 May 15, 2023
A fuzzer setup to fuzz libc functions.

libc-fuzzer This does what it sounds like! It attempts to, as automatically as possible, generate and run fuzzers for up to the entire set of libc (in

null 9 Nov 30, 2022
Handle some lichess.org/tournament load with Rust, while learning Rust

lila-http Take some of the HTTP load away from lila. WIP! Arena tournaments Clients connected to a tournament page request new data about the tourname

Lichess 22 Jan 2, 2023
HTTP mocking library for Rust.

httpmock HTTP mocking library for Rust. Documentation · Crate · Report Bug · Request Feature · Changelog Features Simple, expressive, fluent API. Many

Alexander Liesenfeld 320 Dec 21, 2022
Testing Framework for Rust

Polish Polish is Test-Driven Development done right Getting Started Installing the Package The crates.io package is kept up-to-date with all the major

Fadi Hanna Al-Kass 49 Dec 18, 2022
Travis CI and AppVeyor template to test your Rust crate on 5 architectures and publish binary releases of it for Linux, macOS and Windows

trust Travis CI and AppVeyor template to test your Rust crate on 5 architectures and publish binary releases of it for Linux, macOS and Windows Featur

Jorge Aparicio 1.2k Dec 30, 2022
A library for generating fake data in Rust.

Fake A Rust library for generating fake data. Installation Default (rand is required): [dependencies] fake = "2.4" rand = "0.8" If you want to use #[d

cksac 552 Dec 25, 2022
Benchmarks for rust serialization frameworks

Rust serialization benchmark The goal of these benchmarks is to provide thorough and complete benchmarks for various rust serialization frameworks. Th

David Koloski 187 Jan 4, 2023
Playwright is a rust library to automate Chromium, Firefox and WebKit built on top of Node.js library.

?? Playwright for Rust Playwright is a rust library to automate Chromium, Firefox and WebKit built on top of Node.js library. Installation [dependenci

octaltree 132 Jan 6, 2023