From 2fe9304d62661c0603323351a2654e26515a9b6b Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Fri, 29 Apr 2016 18:49:55 +0000 Subject: [PATCH] [libFuzzer] enable detect_leaks=1, add proper docs llvm-svn: 268088 --- llvm/docs/LibFuzzer.rst | 33 ++++++++++++++++++++++----------- llvm/lib/Fuzzer/FuzzerFlags.def | 2 +- llvm/lib/Fuzzer/FuzzerInternal.h | 2 +- llvm/lib/Fuzzer/test/fuzzer-leak.test | 2 +- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/llvm/docs/LibFuzzer.rst b/llvm/docs/LibFuzzer.rst index 00d77ec..8ad961b 100644 --- a/llvm/docs/LibFuzzer.rst +++ b/llvm/docs/LibFuzzer.rst @@ -147,7 +147,8 @@ will be added to the corpus directory. By default, the fuzzing process will continue indefinitely – at least until a bug is found. Any crashes or sanitizer failures will be reported as usual, stopping the fuzzing process, and the particular input that triggered the bug -will be written to disk (typically as ``crash-`` or ``timeout-``). +will be written to disk (typically as ``crash-``, ``leak-``, +or ``timeout-``). Parallel Fuzzing @@ -246,6 +247,9 @@ The most important command line options are: Indicate output streams to close at startup. Be careful, this will also remove diagnostic output from the tools in use; for example the messages AddressSanitizer_ sends to ``stderr``/``stdout`` will also be lost. +``-detect-leaks`` + If 1 (default) and if LeakSanitizer is enabled + try to detect memory leaks during fuzzing (i.e. not only at shut down). - 0 (default): close neither ``stdout`` nor ``stderr`` - 1 : close ``stdout`` @@ -631,16 +635,22 @@ the program arguments that you can read and modify: Leaks ----- -Code that has been built with AddressSanitizer_ will report memory leaks, -but only when the process exits. If you suspect memory leaks in the code -under test, you will therefore need to use the ``-runs=N`` or -``-max_total_time=N`` command line options to ensure that the fuzzing -process completes and gives AddressSanitizer_ a chance to report leaks. -Because the leak is only reported at the end of the process, this also means -that it is not clear which input triggered the leak. To narrow this down, -re-run each input file in the corpus separately through the target function. - -If your target has massive leaks you will eventually run out of RAM. +Binaries built with AddressSanitizer_ or LeakSanitizer_ will try to detect +memory leaks at the process shutdown. +For in-process fuzzing this is inconvenient +since the fuzzer needs to report a leak with a reproducer as soon as the leaky +mutation is found. However, running full leak detection after every mutation +is expensive. + +By default (``-detect_leaks=1``) libFuzzer will count the number of +``malloc`` and ``free`` calls when executing every mutation. +If the numbers don't match (which by itself doesn't mean there is a leak) +libFuzzer will invoke the more expensive LeakSanitizer_ +pass and if the actual leak is found, it will be reported with the reproducer +and the process will exit. + +If your target has massive leaks and the leak detection is disabled +you will eventually run out of RAM. To protect your machine from OOM death you may use e.g. ``ASAN_OPTIONS=hard_rss_limit_mb=2000`` (with AddressSanitizer_). @@ -806,6 +816,7 @@ Trophies .. _SanitizerCoverageTraceDataFlow: http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow .. _DataFlowSanitizer: http://clang.llvm.org/docs/DataFlowSanitizer.html .. _AddressSanitizer: http://clang.llvm.org/docs/AddressSanitizer.html +.. _LeakSanitizer: http://clang.llvm.org/docs/LeakSanitizer.html .. _Heartbleed: http://en.wikipedia.org/wiki/Heartbleed .. _FuzzerInterface.h: https://github.com/llvm-mirror/llvm/blob/master/lib/Fuzzer/FuzzerInterface.h .. _3.7.0: http://llvm.org/releases/3.7.0/docs/LibFuzzer.html diff --git a/llvm/lib/Fuzzer/FuzzerFlags.def b/llvm/lib/Fuzzer/FuzzerFlags.def index 2616232..86b203c 100644 --- a/llvm/lib/Fuzzer/FuzzerFlags.def +++ b/llvm/lib/Fuzzer/FuzzerFlags.def @@ -79,7 +79,7 @@ FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.") FUZZER_FLAG_INT(close_fd_mask, 0, "If 1, close stdout at startup; " "if 2, close stderr; if 3, close both. " "Be careful, this will also close e.g. asan's stderr/stdout.") -FUZZER_FLAG_INT(detect_leaks, 0, "If 1, and if LeakSanitizer is enabled " +FUZZER_FLAG_INT(detect_leaks, 1, "If 1, and if LeakSanitizer is enabled " "try to detect memory leaks during fuzzing (i.e. not only at shut down).") FUZZER_DEPRECATED_FLAG(exit_on_first) diff --git a/llvm/lib/Fuzzer/FuzzerInternal.h b/llvm/lib/Fuzzer/FuzzerInternal.h index a6c8678..169536b 100644 --- a/llvm/lib/Fuzzer/FuzzerInternal.h +++ b/llvm/lib/Fuzzer/FuzzerInternal.h @@ -304,7 +304,7 @@ public: bool OutputCSV = false; bool PrintNewCovPcs = false; bool PrintFinalStats = false; - bool DetectLeaks = false; + bool DetectLeaks = true; }; Fuzzer(UserCallback CB, MutationDispatcher &MD, FuzzingOptions Options); void AddToCorpus(const Unit &U) { diff --git a/llvm/lib/Fuzzer/test/fuzzer-leak.test b/llvm/lib/Fuzzer/test/fuzzer-leak.test index d86a8f6..48e9ca6 100644 --- a/llvm/lib/Fuzzer/test/fuzzer-leak.test +++ b/llvm/lib/Fuzzer/test/fuzzer-leak.test @@ -11,7 +11,7 @@ LEAK_IN_CORPUS: ERROR: libFuzzer: initial corpus triggers memory leaks. RUN: not LLVMFuzzer-LeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER -RUN: not LLVMFuzzer-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER +RUN: not LLVMFuzzer-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING LEAK_AFTER: Done 100000 runs in LEAK_AFTER: ERROR: LeakSanitizer: detected memory leaks LEAK_AFTER-NOT: DEATH: -- 2.7.4