rust-fuzz / cargo-fuzz

Command line helpers for fuzzing
https://rust-fuzz.github.io/book/cargo-fuzz.html
Apache License 2.0
1.56k stars 109 forks source link

Add option to ignore panics #173

Open Shnatsel opened 5 years ago

Shnatsel commented 5 years ago

I'm looking into fuzzing parts of Rust standard library to detect bugs such as CVE-2018-1000810. See also: the fix.

However, this is currently impossible with cargo-fuzz because it passes -Cpanic=abort during compilation, while for this function panic on overflow is the expected behavior. I need a way to disable that.

Shnatsel commented 5 years ago

In an ideal world I'd like to toggle this behavior persistently for each fuzzing target, but unconditional -Cpanic=abort makes it impossible. The best way forward that I see is --ignore-panics flag for cargo fuzz run

Manishearth commented 5 years ago

I think the panic infrastructure messes with fuzzing somehow so it's disabled for that reason too. You're free to try it and if it works, make a PR with the flag.

The expected thing to do with such cases is to filter the input beforehand

Shnatsel commented 5 years ago

For future reference, I currently have no plans to implement this feature by myself because use of libfuzzer in my project is blocked by #174 anyway.

douglas-raillard-arm commented 11 months ago

I was also looking into fuzzing but my only goal is to find hard crashes (segfaults). I know my API can panic in some circumstances, so cargo fuzz stopping on them is not very useful to me.

EDIT: for reference, I'm trying to fuzz a file format parser, so filtering the input is basically impossible

kpcyrd commented 11 months ago

I was wondering if maybe std::panic::catch_unwind would work for this, but it didn't:

#![no_main]

use libfuzzer_sys::fuzz_target;

fn this_panics(buf: &[u8]) {
    if buf.len() > 5 {
        panic!("oh no");
    }
}

fuzz_target!(|data: &[u8]| {
    std::panic::catch_unwind(|| {
        this_panics(data);
    }).ok();
});
``` % cargo new fuzz-test Created binary (application) `fuzz-test` package % cd fuzz-test % cargo fuzz init % cat > fuzz/fuzz_targets/fuzz_target_1.rs #![no_main] use libfuzzer_sys::fuzz_target; fn this_panics(buf: &[u8]) { if buf.len() > 5 { panic!("oh no"); } } fuzz_target!(|data: &[u8]| { std::panic::catch_unwind(|| { this_panics(data); }).ok(); }); % RUSTC_BOOTSTRAP=1 cargo fuzz run fuzz_target_1 -s none Updating crates.io index warning: fuzz-test-fuzz v0.0.0 (/.../fuzz-test/fuzz) ignoring invalid dependency `fuzz-test` which is missing a lib target Compiling libc v0.2.151 Compiling arbitrary v1.3.2 Compiling once_cell v1.19.0 Compiling jobserver v0.1.27 Compiling cc v1.0.83 Compiling libfuzzer-sys v0.4.7 Compiling fuzz-test-fuzz v0.0.0 (/.../fuzz-test/fuzz) Finished release [optimized + debuginfo] target(s) in 15.15s warning: fuzz-test-fuzz v0.0.0 (/.../fuzz-test/fuzz) ignoring invalid dependency `fuzz-test` which is missing a lib target Finished release [optimized + debuginfo] target(s) in 0.01s Running `fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1 -artifact_prefix=/.../fuzz-test/fuzz/artifacts/fuzz_target_1/ /.../fuzz-test/fuzz/corpus/fuzz_target_1` WARNING: Failed to find function "__sanitizer_acquire_crash_state". WARNING: Failed to find function "__sanitizer_print_stack_trace". WARNING: Failed to find function "__sanitizer_set_death_callback". INFO: Running with entropic power schedule (0xFF, 100). INFO: Seed: 1058425890 INFO: Loaded 1 modules (789 inline 8-bit counters): 789 [0x7ffb2d5cbb0, 0x7ffb2d5cec5), INFO: Loaded 1 PC tables (789 PCs): 789 [0x7ffb2d5cec8,0x7ffb2d60018), INFO: 0 files found in /.../fuzz-test/fuzz/corpus/fuzz_target_1 INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes INFO: A corpus is not provided, starting from an empty corpus #2 INITED cov: 6 ft: 7 corp: 1/1b exec/s: 0 rss: 27Mb thread '' panicked at fuzz_targets/fuzz_target_1.rs:7:9: oh no note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ==1224546== ERROR: libFuzzer: deadly signal NOTE: libFuzzer has rudimentary signal handlers. Combine libFuzzer with AddressSanitizer or similar for better crash reports. SUMMARY: libFuzzer: deadly signal MS: 3 ChangeByte-CMP-InsertByte- DE: "\377\377\377\377"-; base unit: adc83b19e793491b1c6ea0fd8b46cd9f32e592fc 0xff,0xff,0xff,0xff,0x27,0x2b, \377\377\377\377'+ artifact_prefix='/.../fuzz-test/fuzz/artifacts/fuzz_target_1/'; Test unit written to /.../fuzz-test/fuzz/artifacts/fuzz_target_1/crash-b4b0af687a34ed0e2f21ff234bdd63867e108f74 Base64: /////ycr ──────────────────────────────────────────────────────────────────────────────── Failing input: fuzz/artifacts/fuzz_target_1/crash-b4b0af687a34ed0e2f21ff234bdd63867e108f74 Output of `std::fmt::Debug`: [255, 255, 255, 255, 39, 43] Reproduce with: cargo fuzz run --sanitizer=none fuzz_target_1 fuzz/artifacts/fuzz_target_1/crash-b4b0af687a34ed0e2f21ff234bdd63867e108f74 Minimize test case with: cargo fuzz tmin --sanitizer=none fuzz_target_1 fuzz/artifacts/fuzz_target_1/crash-b4b0af687a34ed0e2f21ff234bdd63867e108f74 ──────────────────────────────────────────────────────────────────────────────── Error: Fuzz target exited with exit status: 77 % ```