[libFuzzer] Make -merge=1 to reuse coverage information from the control file.
authorMax Moroz <mmoroz@chromium.org>
Wed, 11 Sep 2019 14:11:08 +0000 (14:11 +0000)
committerMax Moroz <mmoroz@chromium.org>
Wed, 11 Sep 2019 14:11:08 +0000 (14:11 +0000)
commitf054067f276d8951e5a0a8dbd009a16fa666d736
tree632de622361de4796a980dceb17313813ca62c4c
parent9c4047f26724b89f5ae9f5915a044d65afb9477b
[libFuzzer] Make -merge=1 to reuse coverage information from the control file.

Summary:
This change allows to perform corpus merging in two steps. This is useful when
the user wants to address the following two points simultaneously:

1) Get trustworthy incremental stats for the coverage and corpus size changes
    when adding new corpus units.
2) Make sure the shorter units will be preferred when two or more units give the
    same unique signal (equivalent to the `REDUCE` logic).

This solution was brainstormed together with @kcc, hopefully it looks good to
the other people too. The proposed use case scenario:

1) We have a `fuzz_target` binary and `existing_corpus` directory.
2) We do fuzzing and write new units into the `new_corpus` directory.
3) We want to merge the new corpus into the existing corpus and satisfy the
    points mentioned above.
4) We create an empty directory `merged_corpus` and run the first merge step:

    `
    ./fuzz_target -merge=1 -merge_control_file=MCF ./merged_corpus ./existing_corpus
    `

    this provides the initial stats for `existing_corpus`, e.g. from the output:

    `
    MERGE-OUTER: 3 new files with 11 new features added; 11 new coverage edges
    `

5) We recreate `merged_corpus` directory and run the second merge step:

    `
    ./fuzz_target -merge=1 -merge_control_file=MCF ./merged_corpus ./existing_corpus ./new_corpus
    `

    this provides the final stats for the merged corpus, e.g. from the output:

    `
    MERGE-OUTER: 6 new files with 14 new features added; 14 new coverage edges
    `

Alternative solutions to this approach are:

A) Store precise coverage information for every unit (not only unique signal).
B) Execute the same two steps without reusing the control file.

Either of these would be suboptimal as it would impose an extra disk or CPU load
respectively, which is bad given the quadratic complexity in the worst case.

Tested on Linux, Mac, Windows.

Reviewers: morehouse, metzman, hctim, kcc

Reviewed By: morehouse

Subscribers: JDevlieghere, delcypher, mgrang, #sanitizers, llvm-commits, kcc

Tags: #llvm, #sanitizers

Differential Revision: https://reviews.llvm.org/D66107

llvm-svn: 371620
compiler-rt/lib/fuzzer/FuzzerDefs.h
compiler-rt/lib/fuzzer/FuzzerMerge.cpp
compiler-rt/test/fuzzer/merge.test
compiler-rt/test/fuzzer/merge_two_step.test [new file with mode: 0644]