Skip to content

Latest commit

 

History

History
119 lines (85 loc) · 4.01 KB

getting_started.md

File metadata and controls

119 lines (85 loc) · 4.01 KB

Getting Started with Libfuzzer in Chrome

*** note Prerequisites: libfuzzer in chrome is supported with GN on Linux only.


This document will walk you through:

  • setting up your build enviroment.
  • creating your first fuzzer.
  • running the fuzzer and verifying its vitals.

Check Out ToT Clang

Libfuzzer relies heavily on compile-time instrumentation. Because it is still under heavy development you need to use tot clang with libfuzzer:

# In chrome/src
LLVM_FORCE_HEAD_REVISION=1 ./tools/clang/scripts/update.py --force-local-build --without-android

To revert this run the same script without specifying LLVM_FORCE_HEAD_REVISION.

Configure Build

Use use_libfuzzer GN argument together with sanitizer to generate build files:

# With address sanitizer
gn gen out/libfuzzer '--args=use_libfuzzer=true is_asan=true enable_nacl=false' --check

Supported sanitizer configurations are:

GN Argument Description
is_asan=true enables Address Sanitizer to catch problems like buffer overruns.
is_msan=true enables Memory Sanitizer to catch problems like uninitialed reads.

Write Fuzzer Function

Create a new .cc file and define a LLVMFuzzerTestOneInput function:

extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
  // put your fuzzing code here and use data+size as input.
  return 0;
}

[url_parse_fuzzer.cc] is a simple example of real-world fuzzer.

Define GN Target

Define fuzzer_test GN target:

import("//testing/libfuzzer/fuzzer_test.gni")
fuzzer_test("my_fuzzer") {
  sources = [ "my_fuzzer.cc" ]
  deps = [ ... ]
}

Build and Run Fuzzer Locally

Build with ninja as usual and run:

ninja -C out/libfuzzer url_parse_fuzzer
./out/libfuzzer url_parse_fuzzer

Your fuzzer should produce output like this:

INFO: Seed: 1787335005
INFO: -max_len is not provided, using 64
INFO: PreferSmall: 1
#0      READ   units: 1 exec/s: 0
#1      INITED cov: 2361 bits: 95 indir: 29 units: 1 exec/s: 0
#2      NEW    cov: 2710 bits: 359 indir: 36 units: 2 exec/s: 0 L: 64 MS: 0 
#3      NEW    cov: 2715 bits: 371 indir: 37 units: 3 exec/s: 0 L: 64 MS: 1 ShuffleBytes-
#5      NEW    cov: 2728 bits: 375 indir: 38 units: 4 exec/s: 0 L: 63 MS: 3 ShuffleBytes-ShuffleBytes-EraseByte-
#6      NEW    cov: 2729 bits: 384 indir: 38 units: 5 exec/s: 0 L: 10 MS: 4 ShuffleBytes-ShuffleBytes-EraseByte-CrossOver-
#7      NEW    cov: 2733 bits: 424 indir: 39 units: 6 exec/s: 0 L: 63 MS: 1 ShuffleBytes-
#8      NEW    cov: 2733 bits: 426 indir: 39 units: 7 exec/s: 0 L: 63 MS: 2 ShuffleBytes-ChangeByte-
#11     NEW    cov: 2733 bits: 447 indir: 39 units: 8 exec/s: 0 L: 33 MS: 5 ShuffleBytes-ChangeByte-ChangeASCIIInt-ChangeBit-CrossOver-
#12     NEW    cov: 2733 bits: 451 indir: 39 units: 9 exec/s: 0 L: 62 MS: 1 CrossOver-
#16     NEW    cov: 2733 bits: 454 indir: 39 units: 10 exec/s: 0 L: 61 MS: 5 CrossOver-ChangeBit-ChangeBit-EraseByte-ChangeBit-
#18     NEW    cov: 2733 bits: 458 indir: 39 units: 11 exec/s: 0 L: 24 MS: 2 CrossOver-CrossOver-

The ... NEW ... line appears when libfuzzer finds new and interesting input. The efficient fuzzer should be able to finds lots of them rather quickly.

The ... pulse ... line will appear periodically to show the current status.

Submitting Fuzzer to ClusterFuzz

ClusterFuzz builds and executes all fuzzer_test targets in the source tree. The only thing you should do is to submit a fuzzer into Chrome.

Next Steps