rust-fuzz / cargo-fuzz

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

`cargo fuzz` fails, but compiling directly works. #328

Closed bhansconnect closed 1 year ago

bhansconnect commented 1 year ago

Hi, this may not exactly be a bug. It may just be some difference in configuration, but I am trying to get to the root of what is going on.

I have a rust app that links with a static library. I am trying to fuzz both together. I compile the static library with fuzzing enable and asan. Then I compile and run a fuzz target with cargo fuzz run.

I get an output of:

INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 2415826112
INFO: Loaded 1 modules   (5179 inline 8-bit counters): 5179 [0x102bc0f10, 0x102bc234b), 
INFO: Loaded 1 PC tables (5152 PCs): 5152 [0x102bc2350,0x102bd6550), 
ERROR: The size of coverage PC tables does not match the
number of instrumented PCs. This might be a compiler bug,
please contact the libFuzzer developers.
Also check https://bugs.llvm.org/show_bug.cgi?id=34636
for possible workarounds (tl;dr: don't use the old GNU ld)
────────────────────────────────────────────────────────────────────────────────

Error: Fuzz target exited with exit status: 1

This is probably caused by linking against the static library, but I am not fully sure why. I have tried changing my linker for rust, but it does not change anything.

If instead, I compile the fuzz target directly, as suggested by the libFuzzer-sys crate:

cargo rustc -- \       
    -C passes='sancov-module' \
    -C llvm-args='-sanitizer-coverage-level=3' \
    -C llvm-args='-sanitizer-coverage-inline-8bit-counters' \
    -Z sanitizer=address

And then run it directly ./target/debug/fuzz-target. Everything will run as expected:

INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 2653975677
INFO: Loaded 1 modules   (1274 inline 8-bit counters): 1274 [0x1044f1520, 0x1044f1a1a), 
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 ft: 93 corp: 1/1b exec/s: 0 rss: 67Mb
#8  NEW    ft: 174 corp: 2/3b lim: 4 exec/s: 0 rss: 70Mb L: 2/2 MS: 3 CrossOver-ChangeBit-CrossOver-
#18 NEW    ft: 215 corp: 3/7b lim: 4 exec/s: 0 rss: 71Mb L: 4/4 MS: 5 ChangeByte-ChangeByte-InsertByte-ChangeBit-CopyPart-
#20 NEW    ft: 294 corp: 4/11b lim: 4 exec/s: 0 rss: 71Mb L: 4/4 MS: 1 ChangeBit-
...

Any ideas what could be causing the difference here? Would be really useful to able to use cargo fuzz to fuzz a rust + static library combination. Maybe there are extra llvm options/passes that should be run when generating the static library. Any pointers in general would be greatly appreciated. Even if it is just to docs about the llvm configuration that cargo fuzz uses.

fitzgen commented 1 year ago

They generally do the same thing so this is a bit surprising.

You could try logging the commands the cargo fuzz is executing to see what other flags are getting passed: https://github.com/rust-fuzz/cargo-fuzz/blob/bb2de3ece0564fd8d2410f74837f9d23e602f78d/src/project.rs#L312

bhansconnect commented 1 year ago

Thanks for the hint. I'll take a look and try to do some debugging to figure out the differences.

bhansconnect commented 1 year ago

Oh, figured it out. Your library also uses: -sanitizer-coverage-pc-table. I missed that. Add that configuration when building my static library and everything is good now.