Giter Site home page Giter Site logo

loiclec / fuzzcheck-rs Goto Github PK

View Code? Open in Web Editor NEW
421.0 10.0 13.0 3.11 MB

Modular, structure-aware, and feedback-driven fuzzing engine for Rust functions

License: MIT License

Rust 99.74% C 0.22% Shell 0.04%
rust fuzzing property-based-testing fuzzer coverage-guided-fuzzing testing grammar-fuzzer

fuzzcheck-rs's Introduction

Fuzzcheck

CI Docs MIT licensed crates.io

Fuzzcheck is a modular, structure-aware, and feedback-driven 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.

The tool fuzzcheck-view is available to visualise the code coverage of each/all test cases generated by fuzzcheck. It is still just a prototype though.

Follow the guide at fuzzcheck.neocities.org to get started or read the documentation on docs.rs.

Setup

Linux or macOS is required. Windows support is planned but I need help with it.

Rust nightly is also required. You can install it with:

rustup toolchain install nightly

While it is not strictly necessary, installing the cargo-fuzzcheck executable will make it easier to run fuzzcheck.

cargo install cargo-fuzzcheck

In your Cargo.toml file, add fuzzcheck as a dev-dependency:

[dev-dependencies]
fuzzcheck = "0.12"

Then, we need a way to serialize values. By default, fuzzcheck uses serde_json for that purpose (but it can be changed). That means our data types should implement serde's traits. In Cargo.toml, add:

[dependencies]
serde = { version = "1.0", features = ["derive"] }

Usage

Below is an example of how to use fuzz test. Note:

  1. every code related to fuzzcheck is conditional on #[cfg(test)] because we don't want to carry the fuzzcheck dependency in normal builds
  2. the #![cfg_attr(test, feature(no_coverage))] is required by fuzzcheck’s procedural macros
  3. the use of derive(fuzzcheck::DefaultMutator) makes a custom type fuzzable
#![cfg_attr(fuzzing, feature(no_coverage))]
use serde::{Deserialize, Serialize};

#[cfg_attr(fuzzing, derive(fuzzcheck::DefaultMutator))]
#[derive(Clone, Serialize, Deserialize)]
struct SampleStruct<T, U> {
    x: T,
    y: U,
}

#[cfg_attr(fuzzing, derive(fuzzcheck::DefaultMutator))]
#[derive(Clone, Serialize, Deserialize)]
enum SampleEnum {
    A(u16),
    B,
    C { x: bool, y: bool },
}

fn should_not_crash(xs: &[SampleStruct<u8, SampleEnum>]) {
    if xs.len() > 3
        && xs[0].x == 100
        && matches!(xs[0].y, SampleEnum::C { x: false, y: true })
        && xs[1].x == 55
        && matches!(xs[1].y, SampleEnum::C { x: true, y: false })
        && xs[2].x == 87
        && matches!(xs[2].y, SampleEnum::C { x: false, y: false })
        && xs[3].x == 24
        && matches!(xs[3].y, SampleEnum::C { x: true, y: true })
    {
        panic!()
    }
}

// fuzz tests reside along your other tests and have the #[test] attribute
#[cfg(all(fuzzing, test))]
mod tests {
    #[test]
    fn test_function_shouldn_t_crash() {
        let result = fuzzcheck::fuzz_test(super::should_not_crash) // the test function to fuzz
            .default_mutator() // the mutator to generate values of &[SampleStruct<u8, SampleEnum>]
            .serde_serializer() // save the test cases to the file system using serde
            .default_sensor_and_pool() // gather observations using the default sensor (i.e. recording code coverage)
            .arguments_from_cargo_fuzzcheck() // take arguments from the cargo-fuzzcheck command line tool
            .stop_after_first_test_failure(true) // stop the fuzzer as soon as a test failure is found
            .launch();
        assert!(!result.found_test_failure);
    }
}

We can now use cargo-fuzzcheck to launch the test, using Rust nightly:

rustup override set nightly
# the argument is the *exact* path to the test function
cargo fuzzcheck tests::test_function_shouldn_t_crash

This starts a loop that will stop when a failing test has been found. After about ~50ms of fuzz-testing on my machine, the following line is printed:

Failing test case found. Saving at "fuzz/tests::test_function_shouldn_t_crash/artifacts/59886edc1de2dcc1.json"

The file 59886edc1de2dcc1.json contains the JSON-encoded input that failed the test.

[
  {
    "x": 100,
    "y": {
      "C": {
        "x": false,
        "y": true
      }
    }
  },
  {
    "x": 55,
    "y": {
      "C": {
        "x": true,
        "y": false
      }
    }
  },
  ..
]

Minifying failing test inputs

Fuzzcheck can also be used to minify a large input that fails a test. If the failure is recoverable (i.e. it is not a segfault/stack overflow), and the fuzzer is not instructed to stop after the first failure, then the failing test cases will be minified automatically. Otherwise, you can use the minify command.

Let's say you have a file crash.json containing an input that you would like to minify. Launch cargo fuzzcheck <exact name of fuzz test> with the minify command and an --input-file option.

cargo fuzzcheck "tests::test_function_shouldn_t_crash" --command minify --input-file "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.

Alternatives

Other crates with the same goal are quickcheck and proptest. Fuzzcheck can be more powerful than these because it guides the generation of test cases based on feedback generated from running the test function. This feedback is most often code coverage, but can be different.

Another similar crate is cargo-fuzz, often paired with arbitrary. In this case, fuzzcheck has an advantage by being easier to use, more modular, and being more fundamentally structure-aware and thus potentially more efficient.

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. It uses rustc’s -Z instrument-coverage option instead of SanitizerCoverage for code coverage instrumentation.

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.

LibAFL is another modular fuzzer written in Rust. It was released relatively recently.

fuzzcheck-rs's People

Contributors

binier avatar loiclec avatar teymour-aldridge avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fuzzcheck-rs's Issues

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

Default mutators for `String`/`str` types?

This would be a nice addition :)

(I am currently using a Vec<u8>, and then converting this into Strings, but I suspect that this is suboptimal)

If you could suggest how to do this (just the general approach) I would also be happy to try to implement this.

Fuzzcheck can't run on NixOS

I tried to run FuzzCheck on NixOS to see if it had the same problems as I have on my Ubuntu desktop.

Predictably, the build instead failed due to completely unrelated errors.

Mostly it's looking for system libs and not finding them. I'm not sure how you could solve that with cargo install. Maybe I could try making a NixOS package directly.

My system:

  • OS version: NixOS, nix-env (Nix) 2.3.10
  • Rust version: 1.60
  • Fuzzcheck version: 0.12.0

failed to parse LLVM covmap: InvalidVersion(6)

The version of LLVM covmap was updated to version 6, hence fuzzcheck-rs does no longer work with the latest rust version.

This results in the error

failed to parse LLVM covmap: InvalidVersion(6)

when trying to run fuzzcheck.

Linking failure

Unfortunately, the linking failure of #16 seems to have reappeared.

When trying to fuzz the parser in https://github.com/bailion/compiler (cd logic and then cargo make fuzz_parser), I get the following error:

error: linking with `cc` failed: exit status: 1
  |
  = note: "cc" "-m64" "-arch" "x86_64" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/logic-7ac7bc4893af41b9.logic.0e5fb5ab-cgu.0.rcgu.o" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/logic-7ac7bc4893af41b9.4yaop7vyo3oi4jwd.rcgu.o" "-L" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps" "-L" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/release/deps" "-L" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libtest-a4a9d6dfc3cb7d1f.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libgetopts-55c643af53b487f5.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libunicode_width-8c1befd68a350645.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_std-dec7a406a59f4fba.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcodespan_reporting-82c8e7395ad6fdf4.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libunicode_width-31ad6be4b3da7d47.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libtermcolor-227b2033f8af4be6.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libinsta-5b30e4f2c07d2ff2.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libserde_yaml-23eb7e8bf528de33.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libdtoa-f08731f63527036f.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libyaml_rust-1ec932a87c92770b.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/liblinked_hash_map-f64af7936bb0c6af.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libserde_json-7707b3a258d2c0b1.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libryu-084f98775f2bcd47.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libitoa-968cb5afac804c6e.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libconsole-b1d29735e93c7139.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libterminal_size-364f620309169771.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/liblibc-9ed5cae0a36ea3b0.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libonce_cell-8350a75654ff790b.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libsimilar-0ad18ca182410cf5.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/liblazy_static-d17e8e322d532086.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libserde-bdaafaf0e8ea3cc6.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcranelift_native-1298c3d89661444d.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcranelift_object-5b5a31ca4774c87b.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libobject-b923024a54506e05.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcrc32fast-276a9bd7e70c6f77.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcranelift_module-98c1a9163fdd9094.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libanyhow-11983f43fb507c02.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcranelift_frontend-c8345ff42c355adf.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcranelift_codegen-daff7c9a26795d87.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcranelift_codegen_shared-d00b75645acd2a37.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libtarget_lexicon-a03bebfee3d29059.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libregalloc-b65994f28308d55e.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/librustc_hash-4fd02005b8127820.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libsmallvec-aeba58bbd836ea6f.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/liblog-ca81a8a9c5dfefe4.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcfg_if-52dced1ddfaa61ad.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libgimli-43b2a080cee38cfc.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libindexmap-514a508969108009.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libhashbrown-26648b9b20b392d9.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcranelift_bforest-2e7f1541a75ed107.rlib" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/libcranelift_entity-a339fc096e338d99.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libstd-e0d1108e51bfb0d5.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-b302e9efd55d58df.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libobject-8d60cc1207aa0389.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libmemchr-e6496f81ac614178.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libaddr2line-6fe0ca55ac7c684e.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libgimli-6251ec83c25e2fdb.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libstd_detect-3724da203e764788.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_demangle-12f49b029d72fd67.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libhashbrown-46cc73ae324c4251.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_alloc-6365dfa364b30124.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libunwind-5e590d4590629f98.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcfg_if-31e558d6f4ce9e06.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liblibc-7ea8daf78864f633.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liballoc-e206da7209af9420.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_core-7454d006639b0b9c.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcore-07b1a016408f5808.rlib" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcompiler_builtins-0f6214b7ec76071f.rlib" "-liconv" "-lSystem" "-lresolv" "-lc" "-lm" "-liconv" "-L" "/Users/teymouraldridge/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "-o" "/Users/teymouraldridge/Desktop/tmp/compiler/logic/target/fuzzcheck/x86_64-apple-darwin/release/deps/logic-7ac7bc4893af41b9" "-Wl,-dead_strip" "-nodefaultlibs"
  = note: Undefined symbols for architecture x86_64:
            "___llvm_profile_runtime", referenced from:
                ___llvm_profile_runtime_user in logic-7ac7bc4893af41b9.logic.0e5fb5ab-cgu.0.rcgu.o
                ___llvm_profile_runtime_user in libcodespan_reporting-82c8e7395ad6fdf4.rlib(codespan_reporting-82c8e7395ad6fdf4.codespan_reporting.bc7a71ab-cgu.0.rcgu.o)
                ___llvm_profile_runtime_user in libtermcolor-227b2033f8af4be6.rlib(termcolor-227b2033f8af4be6.termcolor.82ddc2c6-cgu.0.rcgu.o)
                ___llvm_profile_runtime_user in libinsta-5b30e4f2c07d2ff2.rlib(insta-5b30e4f2c07d2ff2.insta.a67da457-cgu.0.rcgu.o)
                ___llvm_profile_runtime_user in libserde_yaml-23eb7e8bf528de33.rlib(serde_yaml-23eb7e8bf528de33.serde_yaml.3f5d8c86-cgu.0.rcgu.o)
                ___llvm_profile_runtime_user in libsimilar-0ad18ca182410cf5.rlib(similar-0ad18ca182410cf5.similar.489981ad-cgu.0.rcgu.o)
                ___llvm_profile_runtime_user in libserde_json-7707b3a258d2c0b1.rlib(serde_json-7707b3a258d2c0b1.serde_json.1500859e-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 an Intel x86_64 processor, MacOS Catalina.

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.

Update fuzzcheck to new Coverage Mapping format version

The coverage mapping format used by newer versions of rustc is Version 6, while fuzzcheck only supports Version 4. This means that fuzzcheck will not work at all.

This is rather urgent and I am hoping to publish a fix very soon :)

Minify crashes while fuzz works

Hi I am trying to use my fuzz harness and had a crash which I would like to minify.

Code is at https://gitlab.com/MTRNord/conduit-fuzz-harness/-/tree/03cade7d643a6cf28ba93c966ae77f5cec82c1a8 (Note there is a file reference in the cargo toml. the rev and url in there however should work though)

The setup is a little funky tbh as I had link failures when trying to do the verification tests so the cfg flags are all over the place. It however compiles just fine (expect ~10-20m compile times due to the upstream package conduit that I am fuzzing. Its annoying but it is due to codegen sadly.)

Running it with cargo fuzzcheck tests::register --command minify --input-file "fuzz/tests::register/artifacts/35056055153a44e5.json" fails with the following for me:

➜  conduit-fuzz-harness git:(main) ✗ cargo fuzzcheck tests::register --command minify --input-file "fuzz/tests::register/artifacts/35056055153a44e5.json"
launch with config: "--command read --input-file fuzz/tests::register/artifacts/35056055153a44e5.json --no-in-corpus  --no-out-corpus  --artifacts fuzz/tests::register/artifacts/35056055153a44e5.minified  --no-stats  --max-cplx 4096 --stop-after-duration 18446744073709551615 --stop-after-iterations 18446744073709551615 --stop-after-first-failure "
warning: `-Z instrument-coverage` is deprecated; use `-C instrument-coverage`

warning: field is never read: `exp`
  --> /opt/dev_env/conduit/src/client_server/session.rs:19:5
   |
19 |     exp: usize,
   |     ^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default
note: `Claims` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
  --> /opt/dev_env/conduit/src/client_server/session.rs:16:10
   |
16 | #[derive(Debug, Deserialize)]
   |          ^^^^^
   = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: field is never read: `statement_ref`
  --> /opt/dev_env/conduit/src/database/abstraction/sqlite.rs:22:5
   |
22 |     pub statement_ref: NonAliasingBox<rusqlite::Statement<'a>>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: `conduit` (lib) generated 3 warnings
   Compiling conduit-fuzz-harness v0.1.0 (/opt/dev_env/conduit-fuzz-harness)
warning: `conduit-fuzz-harness` (lib test) generated 1 warning (1 duplicate)
    Finished release [optimized + debuginfo] target(s) in 12m 35s
     Running unittests (target/fuzzcheck/x86_64-unknown-linux-gnu/release/deps/conduit_fuzz_harness-05780ade5151ccef)

running 1 test
test tests::register ... thread 'main' panicked at 'assertion failed: !o.status.success()', /root/.cargo/registry/src/github.com-1ecc6299db9ec823/cargo-fuzzcheck-0.10.0/src/lib.rs:175:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

The json file I input is:

{"kind":"user","auth":{"session":"","type":"m.login.dummy"},"device_id":"�\u001b���I%b","inhibit_login":false,"initial_device_display_name":"��\u0000���Ŧ.�Oo�JyE1�","password":"��\u000f��","username":"��� }"}

I am not sure why this may be happening. any tips would help.

Linking issue when building sample fuzzer

Hi,

I ran into the following linking error while trying to build the sample fuzzer from the README.

   Compiling fuzzcheck_input v0.1.0 (https://github.com/loiclec/fuzzcheck-rs#f94d9484)
   Compiling my_library-fuzz v0.0.0 (/home/ekse/my_library/fuzz)
error: linking with `cc` failed: exit code: 1

[I removed the command line as it is very long ]

  = note: /usr/bin/ld: __sancov_guards has both ordered [`__sancov_guards[_ZN102_$LT$fuzzcheck_input..vector..VectorGenerator$LT$G$GT$$u20$as$u20$fuzzcheck..input..InputGenerator$GT$9new_input17ha1bc96293fe05b0eE]' in /home/ekse/my_library/fuzz/target/x86_64-unknown-linux-gnu/release/deps/target1-95582bd24b3c88fb.26joefc9aoybq9f0.rcgu.o] and unordered [`__sancov_guards' in /home/ekse/my_library/fuzz/target/x86_64-unknown-linux-gnu/release/deps/target1-95582bd24b3c88fb.26joefc9aoybq9f0.rcgu.o] sections
          /usr/bin/ld: final link failed: bad value
          collect2: error: ld returned 1 exit status

My system:

Ubuntu 19.04
Rust nightly 2019-09-08

There is an open ticket for similar error in cargo-fuzz, it seems to be apearing when compiling with optimizations.

rust-fuzz/cargo-fuzz#161
rust-lang/rust#53945

I did a test where I removed the --release flag in cargo-fuzz/main.rs, but then I get segfaults of child processes when trying to start the fuzzer.

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

Use of static mut and &'static mut has a high risk of undefined behaviour

static mut (and similarly &'static mut) is quite dangerous, because they make it very easy to trigger undefined behaviour in any unsafe using them (rust-lang/rust#53639, rust-lang/unsafe-code-guidelines#269), both in multi-threaded programs (due to unsynchronised mutation) and in single threaded ones too (due to, for instance, aliasing of &mut).

The code_coverage_sensor module contains many of these, and exposes the shared_sensor function:

pub fn shared_sensor() -> &'static mut CodeCoverageSensor {
unsafe { &mut *SHARED_SENSOR.as_mut_ptr() }
}

which is particularly dangerous: if this is called in multiple stack frames, I believe it is considered undefined behaviour (and so, 'seems to work' is unreliable, if anything is changed about the environment/code) instantly, even if the references aren't used/mutated. As an example:

fn f() {
    let sensor_f = shared_sensor();
    g()
}

fn g() {
    let sensor_g = shared_sensor(); // Undefined behaviour: sensor_g and sensor_f alias
}

https://github.com/rust-lang/miri may be able to detect errors like this, and in particular may highlight if this occurs in practice within fuzzcheck.

Notably, the &'static mut lifetime bounds makes this particularly easy, because those &mut references can be returned from any function returning a reference, meaning it's easy to accidentally (and non-obviously) have the aliasing. For instance, I believe the following would compile:

struct SomeStruct;

impl SomeStruct {
    fn some_method(&mut self) -> &mut bool { // implicitly &'a mut self -> &'a mut bool
        &mut shared_sensor().is_recording // 'static > the implicit &mut self lifetime, so this is okay
    }
}

fn h() {
    let mut struct_a = SomeStruct;
    let a = struct_a.some_method();

    let mut struct_b = SomeStruct;
    let b = struct_b.some_method();
    // undefined behaviour: b and a alias, despite seeming to come from entirely separate structs
}

Alternative designs that would minimise the risk here might be:

  • instead of exposing a mutable global singleton as a &mut ... reference with methods, only expose free functions like start_recording directly. These can be implemented in terms of a mutable global singleton, at least to start with (to be able to progressively reduce the risk of undefined behaviour rather than have to do major refactoring to see any benefit), as long as no reference are exposed from the module (and it looks like this would be fine: I think the only reference currently exposed by the module is the shared_sensor function). For instance,

    impl CodeCoverageSensor {
    pub fn start_recording(&mut self) {
    self.is_recording = true;
    self.lowest_stack = usize::MAX;
    *self._lowest_stack = usize::MAX;
    }

    could become a top level function (this first refactoring does require pushing unsafe into each of the methods, but this is somewhat more 'honest': each of these functions is (thread) unsafe):

    pub fn start_recording() {
        unsafe {
            let sensor = SHARED_SENSOR.as_mut_ptr();
            sensor.is_recording = true;
            sensor.lowest_stack = usize::MAX;
            *sensor._lowest_stack = usize::MAX;
        }
    }

    The use-sites like would also need changing. For instance,

    let sensor = shared_sensor();
    sensor.clear();
    if timeout != 0 {
    set_timer(timeout);
    }
    sensor.start_recording();
    let cell = NotUnwindSafe { value: test };
    let input_cell = NotUnwindSafe {
    value: input.value.borrow(),
    };
    let result = catch_unwind(|| (cell.value)(input_cell.value));
    sensor.stop_recording();

    could become

          code_coverage_sensor::clear();
    
          if timeout != 0 {
              set_timer(timeout);
          }
    
          code_coverage_sensor::start_recording();
    
          let cell = NotUnwindSafe { value: test };
          let input_cell = NotUnwindSafe {
              value: input.value.borrow(),
          };
          let result = catch_unwind(|| (cell.value)(input_cell.value));
    
          code_coverage_sensor::stop_recording();
  • use *mut (or maybe &raw mut?) instead of &mut, to avoid undefined behaviour due to aliasing of &mut. There's still danger here (like needing synchronisation in multi-threaded code, and the risk of dangling pointers), but there's no risk of violating aliasing rules.

  • use atomics instead of static mut and &mut/*mut. For instance, static mut X: uintptr_t becomes static X: AtomicUsize and &'static mut uintptr_t becomes &'static AtomicUsize. If the program isn't multithreaded, one can use relaxed orderings to have reduced cost but still be correct in the face of re-entrancy, and let the compiler help ensure safety more.

These are somewhat in order, in that they build on each other.

I hope this makes sense!

Windows Support

I think it is very important that fuzzcheck runs on Windows. Unfortunately, I know nothing about Windows and I don't have a computer to test it.

I expect that there are three parts that need to change to support Windows:

  1. the C file that gives pointers to the __llvm_prf_cnts and __llvm_prf_data sections of the executable object (the sections have a different name on Windows, but otherwise I think the file should be roughly the same)
  2. the signal handler
  3. there may be some problems with Paths

The one that I need the most help with is the signal handling. Please let me know if you are available to help out 😊

Thank you!

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.

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.

error: unsupported operation: can't call foreign function `sigaltstack` on OS `linux`

  • Command: FUZZCHECK_ARGS="my test" MIRIFLAGS=-Zmiri-disable-isolation cargo +miri2 miri run
  • Environment: Linux G22L059 5.19.0-50-generic #50-Ubuntu SMP PREEMPT_DYNAMIC Mon Jul 10 18:24:29 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

  1. Error 1: I got the following error when trying to execute the above command using my custom Rustc toolchain (named miri2)."
thread 'main' panicked at 'could not find all relevant LLVM coverage sections: CannotFindSection { section: CovMap }', /home/y23kim/rust/fuzzcheck-rs/fuzzcheck/src/code_coverage_sensor/mod.rs:55:57
  1. Error 2: When I modified this part(/home/y23kim/rust/fuzzcheck-rs/fuzzcheck/src/code_coverage_sensor/mod.rs:55:57) to return an empty CoverageSensor struct, above error was disappeared but another error occurred.
error: unsupported operation: can't call foreign function `sigaltstack` on OS `linux`
  --> /home/y23kim/rust/fuzzcheck-rs/fuzzcheck/src/signals_handler.rs:46:17
   |
46 |     let stack = libc::sigaltstack(&signal_stack, std::ptr::null_mut());
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't call foreign function `sigaltstack` on OS `linux`
   |
   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support

Are these two errors caused by using my custom RustC and MIRI Toolchain? The second one seems like an obvious bug, but I'm unable to speculate on the cause of the first one.


I attached my main function for your information.

  1 #![allow(unused_attributes)]
  2 #![feature(no_coverage)]
  3 #![feature(impl_trait_in_assoc_type)]
  4 use std::fmt::Debug;
  5 use serde::{Deserialize, Serialize};
  6 use fuzzcheck::{DefaultMutator, Mutator};
  7 use fuzzcheck::mutators::tuples::TupleStructure;
  8 use fuzzcheck::mutators::testing_utilities::test_mutator;
  9 
 10 #[derive(Serialize, Deserialize)]
 11 #[derive(Clone, Debug, PartialEq, Eq, Hash, DefaultMutator)]
 12 struct SampleStruct2<T, U> {
 13     x: T,
 14     y: U,
 15     z: U,
 16 }
 17 
 18 
 19 fn fuzz_target(s: &SampleStruct2<u16, u16>) {
 20     if s.x > 3 {
 21         return;
 22     } else {
 23         let _tmp = s.x + s.y + s.z;
 24     }
 25 }
 26 
 27 
 28 fn main() {
 29 
 30     let m = SampleStruct2::<u8, u8>::default_mutator();
 31     test_mutator(m, 1000., 1000., false, true, 100, 100);
 32     let result = fuzzcheck::fuzz_test(fuzz_target)
 33         .default_mutator()
 34         .serde_serializer()
 35         .default_sensor_and_pool()
 36         .arguments_from_cargo_fuzzcheck()
 37         .stop_after_first_test_failure(true)
 38         .launch();
 39     println!("after result");
 40 }

"A crash was detected, but the fuzzer cannot recover the crashing input."

I've recently been trying to write a fairly complex grammar using the grammar-based AST mutator, but I've run into a bug where Fuzzcheck outputs an error message stating that

running 1 test
test expr::fuzz_expr ... 0ms  START
2ms  
================ SIGNAL 11 ================
0 simplest_cov(0 cov: 0/58 cplx: 0.00) diverse_cov_20(0) max_each_cov_hits(0 sum: 0) diverse_cov_1(0) max_total_cov_hits(0) failures(0) iter/s 0 
2ms  
=================== CRASH DETECTED ===================
A crash was detected, but the fuzzer cannot recover the crashing input.
This should never happen, and is probably a bug in fuzzcheck. Sorry :(
error: test failed, to rerun pass '--lib'

I've also encountered a series of other errors (sometimes with different grammars the tests do work, but it uses ~2-3 GB of RAM to generate the mutator, and then runs as expected using 40-50MB or so, and sometimes the code to build the Rc<Grammar> hangs forever - no stack overflows though, so I'm not really sure what the problem is there). Unfortunately I struggled to produce a minimal reproduction of those, so I've just reported this error.

// This works (just calls `test_mutator` with a timeout of 60s)
#[cfg(test)]
#[test]
fn simple_expression_language() {
    use std::{sync::mpsc::channel, time::Duration};

    use fuzzcheck::mutators::{
        grammar::grammar_based_ast_mutator, testing_utilities::test_mutator,
    };

    #[derive(cgisf::Grammar)]
    #[cgisf_file = "src/expr.grammar"]
    struct ExprLang;

    enum Status<E> {
        Ok,
        Err(E),
    }

    let (sender, receiver) = channel();

    let t1 = std::thread::spawn(move || {
        let grammar = ExprLang::top();
        let mutator = grammar_based_ast_mutator(grammar);
        test_mutator(mutator, 1024.0, 1024.0, false, true, 1024, 1024);
    });

    std::thread::spawn(move || match t1.join() {
        Ok(_) => sender.send(Status::Ok),
        Err(e) => sender.send(Status::Err(e)),
    });

    match receiver.recv_timeout(Duration::from_secs(60)) {
        Ok(_) => (),
        Err(e) => {
            panic!("test failed with: {e:?}");
        }
    }
}

// This fails with error output:
// running 1 test
// test expr::fuzz_expr ... 0ms  START
// 2ms  
// ================ SIGNAL 11 ================
// 0 simplest_cov(0 cov: 0/58 cplx: 0.00) diverse_cov_20(0) // max_each_cov_hits(0 sum: 0) diverse_cov_1(0) max_total_cov_hits(0) // failures(0) iter/s 0 
// 2ms  
// =================== CRASH DETECTED ===================
// A crash was detected, but the fuzzer cannot recover the crashing input.
// This should never happen, and is probably a bug in fuzzcheck. Sorry :(
// error: test failed, to rerun pass '--lib'
#[cfg(test)]
#[test]
fn try_fuzz() {
    let grammar = ExprLang::top();
    let mutator = grammar_based_ast_mutator(grammar).with_string();

    let s1: fuzzcheck::builder::FuzzerBuilder1<(String, AST), _> =
        fuzz_test(|(string, _): &(String, AST)| {
            true
        });
    let s2: fuzzcheck::builder::FuzzerBuilder2<_, _, (String, AST)> = s1.mutator(mutator);
    let s3: fuzzcheck::builder::FuzzerBuilder3<_, _, (String, AST)> = s2.serde_serializer();
    let s4 = s3.default_sensor_and_pool();
    let s5 = s4.arguments_from_cargo_fuzzcheck();
    let res = s5.launch();
    assert!(!res.found_test_failure);
}

// Recursive expansion of cgisf::Grammar! macro
// =============================================

#[derive(Clone)]
struct __GrammarCtx {
    rules: ::std::collections::BTreeMap<
        ::std::string::String,
        ::std::rc::Weak<::fuzzcheck::mutators::grammar::Grammar>,
    >,
}
impl ExprLang {
    pub fn top() -> ::std::rc::Rc<::fuzzcheck::mutators::grammar::Grammar> {
        let ctx = __GrammarCtx {
            rules: ::std::collections::BTreeMap::new(),
        };
        Self::Expr(ctx.clone())
    }
    fn Expr(mut ctx: __GrammarCtx) -> ::std::rc::Rc<::fuzzcheck::mutators::grammar::Grammar> {
        ::fuzzcheck::mutators::grammar::recursive(|Expr| {
            let mut ctx: __GrammarCtx = ctx.clone();
            ctx.rules.insert("Expr".to_string(), Expr.clone());
            ::fuzzcheck::mutators::grammar::alternation([
                ::fuzzcheck::mutators::grammar::alternation([
                    ::fuzzcheck::mutators::grammar::alternation([
                        Self::Term(ctx.clone()),
                        Self::Factorial(ctx.clone()),
                    ]),
                    Self::Addition(ctx.clone()),
                ]),
                Self::Multiplication(ctx.clone()),
            ])
        })
    }
    fn Factorial(ctx: __GrammarCtx) -> ::std::rc::Rc<::fuzzcheck::mutators::grammar::Grammar> {
        ::fuzzcheck::mutators::grammar::concatenation([
            ::fuzzcheck::mutators::grammar::concatenation([
                ::fuzzcheck::mutators::grammar::literal('!'),
            ]),
            ::fuzzcheck::mutators::grammar::recurse(ctx.rules.get("Expr").expect(
                "failed to retrieve element to \
                        recurse to (this is a bug in `cgisf`!)",
            )),
        ])
    }
    fn Addition(ctx: __GrammarCtx) -> ::std::rc::Rc<::fuzzcheck::mutators::grammar::Grammar> {
        ::fuzzcheck::mutators::grammar::concatenation([
            ::fuzzcheck::mutators::grammar::concatenation([
                ::fuzzcheck::mutators::grammar::recurse(ctx.rules.get("Expr").expect(
                    "failed to retrieve element to \
                        recurse to (this is a bug in `cgisf`!)",
                )),
                ::fuzzcheck::mutators::grammar::concatenation([
                    ::fuzzcheck::mutators::grammar::literal('+'),
                ]),
            ]),
            ::fuzzcheck::mutators::grammar::recurse(ctx.rules.get("Expr").expect(
                "failed to retrieve element to \
                        recurse to (this is a bug in `cgisf`!)",
            )),
        ])
    }
    fn Multiplication(ctx: __GrammarCtx) -> ::std::rc::Rc<::fuzzcheck::mutators::grammar::Grammar> {
        ::fuzzcheck::mutators::grammar::concatenation([
            ::fuzzcheck::mutators::grammar::concatenation([
                ::fuzzcheck::mutators::grammar::recurse(ctx.rules.get("Expr").expect(
                    "failed to retrieve element to \
                        recurse to (this is a bug in `cgisf`!)",
                )),
                ::fuzzcheck::mutators::grammar::concatenation([
                    ::fuzzcheck::mutators::grammar::literal('*'),
                ]),
            ]),
            ::fuzzcheck::mutators::grammar::recurse(ctx.rules.get("Expr").expect(
                "failed to retrieve element to \
                        recurse to (this is a bug in `cgisf`!)",
            )),
        ])
    }
    fn Term(ctx: __GrammarCtx) -> ::std::rc::Rc<::fuzzcheck::mutators::grammar::Grammar> {
        ::fuzzcheck::mutators::grammar::alternation([
            ::fuzzcheck::mutators::grammar::concatenation([
                ::fuzzcheck::mutators::grammar::literal('0'),
            ]),
            ::fuzzcheck::mutators::grammar::concatenation([
                ::fuzzcheck::mutators::grammar::literal('1'),
            ]),
        ])
    }
}

Is there a way to construct mutually recursive structs?

e.g. trying to derive DefaultMutator fails (not unexpectedly) on the following structs.

struct MutuallyRecursiveA {
  b: Vec<MutuallyRecursiveB>,
  data: Vec<u64>
}

struct MutuallyRecursiveB {
  a: Option<A>,
  data: bool
}

I tried using make_mutator, but I couldn't get the recursion to work.

Is this possible?

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()
    }
}

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

Documentation typo

(sorry if this me being pedantic; I couldn't find the source code of the docs to submit a PR, so I opened this issue instead)

This is quite large! To understand why this particular test case was saved, we create a new test function that runs the operations and then print the resulting tree.

I think this should say "prints the resulting tree" instead

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:

Please provide sponsorship information

Alternatively, you could sponsor me 🥳 Then I can set aside some time every week to write fuzzcheck.

If someone were interested in this, it’s not clear where, what, or how much is being discussed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.