<div dir="ltr">Attempted in r238086.</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, May 22, 2015 at 4:16 PM, Justin Bogner <span dir="ltr"><<a href="mailto:mail@justinbogner.com" target="_blank">mail@justinbogner.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">Kostya Serebryany <<a href="mailto:kcc@google.com">kcc@google.com</a>> writes:<br>
> Author: kcc<br>
> Date: Fri May 22 17:35:31 2015<br>
> New Revision: 238059<br>
><br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D238059-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=kgSIWfqC2gb1zUxA5IvMAVolagBwLGOHvYRLDidrlnw&e=" target="_blank">http://llvm.org/viewvc/llvm-project?rev=238059&view=rev</a><br>
> Log:<br>
> [lib/Fuzzer] extend the fuzzer interface to allow user-supplied mutators<br>
><br>
> Added:<br>
>     llvm/trunk/lib/Fuzzer/FuzzerInterface.cpp<br>
>     llvm/trunk/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp<br>
> Modified:<br>
>     llvm/trunk/lib/Fuzzer/CMakeLists.txt<br>
>     llvm/trunk/lib/Fuzzer/FuzzerCrossOver.cpp<br>
>     llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp<br>
>     llvm/trunk/lib/Fuzzer/FuzzerInterface.h<br>
>     llvm/trunk/lib/Fuzzer/FuzzerInternal.h<br>
>     llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp<br>
>     llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp<br>
>     llvm/trunk/lib/Fuzzer/test/CMakeLists.txt<br>
>     llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp<br>
>     llvm/trunk/lib/Fuzzer/test/fuzzer.test<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/CMakeLists.txt<br>
> URL:<br>
> <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_CMakeLists.txt-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=u3t-sArJnAEI_PRL83ZYP7G8JMjPrnt7FfuURJMgFo0&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/CMakeLists.txt?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/CMakeLists.txt (original)<br>
> +++ llvm/trunk/lib/Fuzzer/CMakeLists.txt Fri May 22 17:35:31 2015<br>
> @@ -2,8 +2,9 @@ set(LIBFUZZER_FLAGS_BASE "${CMAKE_CXX_FL<br>
>  # Disable the coverage and sanitizer instrumentation for the fuzzer itself.<br>
>  set(CMAKE_CXX_FLAGS_RELEASE "${LIBFUZZER_FLAGS_BASE} -O2 -fno-sanitize=all")<br>
>  if( LLVM_USE_SANITIZE_COVERAGE )<br>
> -  add_library(LLVMFuzzerNoMain OBJECT<br>
> +  add_library(LLVMFuzzerNoMainObjects OBJECT<br>
>      FuzzerCrossOver.cpp<br>
> +    FuzzerInterface.cpp<br>
>      FuzzerTraceState.cpp<br>
>      FuzzerDriver.cpp<br>
>      FuzzerIO.cpp<br>
> @@ -13,9 +14,12 @@ if( LLVM_USE_SANITIZE_COVERAGE )<br>
>      FuzzerSHA1.cpp<br>
>      FuzzerUtil.cpp<br>
>      )<br>
> +  add_library(LLVMFuzzerNoMain STATIC<br>
> +    $<TARGET_OBJECTS:LLVMFuzzerNoMainObjects><br>
> +    )<br>
>    add_library(LLVMFuzzer STATIC<br>
>      FuzzerMain.cpp<br>
> -    $<TARGET_OBJECTS:LLVMFuzzerNoMain><br>
> +    $<TARGET_OBJECTS:LLVMFuzzerNoMainObjects><br>
>      )<br>
><br>
>    if( LLVM_INCLUDE_TESTS )<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/FuzzerCrossOver.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_FuzzerCrossOver.cpp-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=7q2_VLthhwKuvjpPWv45jze2bJMbIcVcaKpwrSj59vA&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerCrossOver.cpp?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/FuzzerCrossOver.cpp (original)<br>
> +++ llvm/trunk/lib/Fuzzer/FuzzerCrossOver.cpp Fri May 22 17:35:31 2015<br>
> @@ -9,39 +9,42 @@<br>
>  // Cross over test inputs.<br>
>  //===----------------------------------------------------------------------===//<br>
><br>
> +#include <cstring><br>
> +<br>
>  #include "FuzzerInternal.h"<br>
> -#include <algorithm><br>
><br>
>  namespace fuzzer {<br>
><br>
> -// Cross A and B, store the result (ap to MaxLen bytes) in U.<br>
> -void CrossOver(const Unit &A, const Unit &B, Unit *U, size_t MaxLen) {<br>
> -  size_t Size = rand() % MaxLen + 1;<br>
> -  U->clear();<br>
> -  const Unit *V = &A;<br>
> -  size_t PosA = 0;<br>
> -  size_t PosB = 0;<br>
> -  size_t *Pos = &PosA;<br>
> -  while (U->size() < Size && (PosA < A.size() || PosB < B.size())) {<br>
> -    // Merge a part of V into U.<br>
> -    size_t SizeLeftU = Size - U->size();<br>
> -    if (*Pos < V->size()) {<br>
> -      size_t SizeLeftV = V->size() - *Pos;<br>
> -      size_t MaxExtraSize = std::min(SizeLeftU, SizeLeftV);<br>
> +// Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out.<br>
> +size_t CrossOver(const uint8_t *Data1, size_t Size1,<br>
> +                 const uint8_t *Data2, size_t Size2,<br>
> +                 uint8_t *Out, size_t MaxOutSize) {<br>
> +  MaxOutSize = rand() % MaxOutSize + 1;<br>
> +  size_t OutPos = 0;<br>
> +  size_t Pos1 = 0;<br>
> +  size_t Pos2 = 0;<br>
> +  size_t *InPos = &Pos1;<br>
> +  size_t InSize = Size1;<br>
> +  const uint8_t *Data = Data1;<br>
> +  bool CurrentlyUsingFirstData = true;<br>
> +  while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) {<br>
> +    // Merge a part of Data into Out.<br>
> +    size_t OutSizeLeft = MaxOutSize - OutPos;<br>
> +    if (*InPos < InSize) {<br>
> +      size_t InSizeLeft = InSize - *InPos;<br>
> +      size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft);<br>
>        size_t ExtraSize = rand() % MaxExtraSize + 1;<br>
> -      U->insert(U->end(), V->begin() + *Pos, V->begin() + *Pos + ExtraSize);<br>
> -      (*Pos) += ExtraSize;<br>
> -    }<br>
> -<br>
> -    // Use the other Unit on the next iteration.<br>
> -    if (Pos == &PosA) {<br>
> -      Pos = &PosB;<br>
> -      V = &B;<br>
> -    } else {<br>
> -      Pos = &PosA;<br>
> -      V = &A;<br>
> +      memcpy(Out + OutPos, Data + *InPos, ExtraSize);<br>
> +      OutPos += ExtraSize;<br>
> +      (*InPos) += ExtraSize;<br>
>      }<br>
> +    // Use the other input data on the next iteration.<br>
> +    InPos  = CurrentlyUsingFirstData ? &Pos2 : &Pos1;<br>
> +    InSize = CurrentlyUsingFirstData ? Size2 : Size1;<br>
> +    Data   = CurrentlyUsingFirstData ? Data2 : Data1;<br>
> +    CurrentlyUsingFirstData = !CurrentlyUsingFirstData;<br>
>    }<br>
> +  return OutPos;<br>
>  }<br>
><br>
>  }  // namespace fuzzer<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_FuzzerDriver.cpp-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=7nrYbAO6j9LOWg1z2miDrSH1DnPnWG_mQySuJ45GHzI&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp (original)<br>
> +++ llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp Fri May 22 17:35:31 2015<br>
> @@ -204,6 +204,11 @@ int ApplyTokens(const Fuzzer &F, const c<br>
>  }<br>
><br>
>  int FuzzerDriver(int argc, char **argv, UserCallback Callback) {<br>
> +  SimpleUserSuppliedFuzzer SUSF(Callback);<br>
> +  return FuzzerDriver(argc, argv, SUSF);<br>
> +}<br>
> +<br>
> +int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF) {<br>
>    using namespace fuzzer;<br>
><br>
>    ProgName = argv[0];<br>
> @@ -244,7 +249,7 @@ int FuzzerDriver(int argc, char **argv,<br>
>    if (Flags.sync_command)<br>
>      Options.SyncCommand = Flags.sync_command;<br>
>    Options.SyncTimeout = Flags.sync_timeout;<br>
> -  Fuzzer F(Callback, Options);<br>
> +  Fuzzer F(USF, Options);<br>
><br>
>    unsigned seed = Flags.seed;<br>
>    // Initialize seed.<br>
><br>
> Added: llvm/trunk/lib/Fuzzer/FuzzerInterface.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_FuzzerInterface.cpp-3Frev-3D238059-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=BHEXA1GAwuIrUUodKZ_r84hL35dQAbNpDttB9nYqdDw&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInterface.cpp?rev=238059&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/FuzzerInterface.cpp (added)<br>
> +++ llvm/trunk/lib/Fuzzer/FuzzerInterface.cpp Fri May 22 17:35:31 2015<br>
> @@ -0,0 +1,27 @@<br>
> +//===- FuzzerInterface.cpp - Mutate a test input --------------------------===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +// Parts of public interface for libFuzzer.<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +<br>
> +#include "FuzzerInterface.h"<br>
> +#include "FuzzerInternal.h"<br>
> +<br>
> +namespace fuzzer {<br>
> +size_t UserSuppliedFuzzer::BasicMutate(uint8_t *Data, size_t Size,<br>
> +                                       size_t MaxSize) {<br>
> +  return ::fuzzer::Mutate(Data, Size, MaxSize);<br>
> +}<br>
> +size_t UserSuppliedFuzzer::BasicCrossOver(const uint8_t *Data1, size_t Size1,<br>
> +                                          const uint8_t *Data2, size_t Size2,<br>
> +                                          uint8_t *Out, size_t MaxOutSize) {<br>
> +  return ::fuzzer::CrossOver(Data1, Size1, Data2, Size2, Out, MaxOutSize);<br>
> +}<br>
> +<br>
> +}  // namespace fuzzer.<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/FuzzerInterface.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_FuzzerInterface.h-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=qEVAA68tBFV7-qgPJ9AoMjLRHM4bUHGyghtNEDSs6lE&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInterface.h?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/FuzzerInterface.h (original)<br>
> +++ llvm/trunk/lib/Fuzzer/FuzzerInterface.h Fri May 22 17:35:31 2015<br>
> @@ -9,6 +9,10 @@<br>
>  // Define the interface between the Fuzzer and the library being tested.<br>
>  //===----------------------------------------------------------------------===//<br>
><br>
> +// WARNING: keep the interface free of STL or any other header-based C++ lib,<br>
> +// to avoid bad interactions between the code used in the fuzzer and<br>
> +// the code used in the target function.<br>
> +<br>
>  #ifndef LLVM_FUZZER_INTERFACE_H<br>
>  #define LLVM_FUZZER_INTERFACE_H<br>
><br>
> @@ -17,9 +21,69 @@<br>
><br>
>  namespace fuzzer {<br>
><br>
> -typedef void (*UserCallback)(const uint8_t *data, size_t size);<br>
> +// Simple C-like interface with a single user-supplied callback.<br>
> +/* Usage: ---------------------------------------------------------------------<br>
> +#include "FuzzerInterface.h"<br>
> +<br>
> +void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {<br>
> +  DoStuffWithData(Data, Size);<br>
> +}<br>
> +<br>
> +// Implement your own main() or use the one from FuzzerMain.cpp.<br>
> +int main(int argc, char **argv) {<br>
> +  InitializeMeIfNeeded();<br>
> +  return fuzzer::FuzzerDriver(argc, argv, LLVMFuzzerTestOneInput);<br>
> +}<br>
> +----------------------------------------------------------------------------- */<br>
> +typedef void (*UserCallback)(const uint8_t *Data, size_t Size);<br>
>  int FuzzerDriver(int argc, char **argv, UserCallback Callback);<br>
><br>
> +// An abstract class that allows to use user-supplied mutators with libFuzzer.<br>
> +/* Usage: ---------------------------------------------------------------------<br>
> +#include "FuzzerInterface.h"<br>
> +class MyFuzzer : public fuzzer::UserSuppliedFuzzer {<br>
> + public:<br>
> +  // Must define the target function.<br>
> +  void TargetFunction(...) { ... }<br>
> +  // Optionally define the mutator.<br>
> +  size_t Mutate(...) { ... }<br>
> +  // Optionally define the CrossOver method.<br>
> +  size_t CrossOver(...) { ... }<br>
> +};<br>
> +<br>
> +int main(int argc, char **argv) {<br>
> +  MyFuzzer F;<br>
> +  fuzzer::FuzzerDriver(argc, argv, F);<br>
> +}<br>
> +-----------------------------------------------------------------------------<br>
> */<br>
<br>
</div></div>Please use doxygen comments (///) for these, so the examples show up on<br>
<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_doxygen&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=eoUHLu-SdQJfTmsukXt9CBvlH2eCmTXL60Llm83STvI&e=" target="_blank">llvm.org/doxygen</a>.<br>
<div class="HOEnZb"><div class="h5"><br>
> +class UserSuppliedFuzzer {<br>
> + public:<br>
> +  // Executes the target function on 'Size' bytes of 'Data'.<br>
> +  virtual void TargetFunction(const uint8_t *Data, size_t Size) = 0;<br>
> +  // Mutates 'Size' bytes of data in 'Data' inplace into up to 'MaxSize' bytes,<br>
> +  // returns the new size of the data.<br>
> +  virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {<br>
> +    return BasicMutate(Data, Size, MaxSize);<br>
> +  }<br>
> +  // Crosses 'Data1' and 'Data2', writes up to 'MaxOutSize' bytes into Out,<br>
> +  // returns the number of bytes written.<br>
> +  virtual size_t CrossOver(const uint8_t *Data1, size_t Size1,<br>
> +                           const uint8_t *Data2, size_t Size2,<br>
> +                           uint8_t *Out, size_t MaxOutSize) {<br>
> +    return BasicCrossOver(Data1, Size1, Data2, Size2, Out, MaxOutSize);<br>
> +  }<br>
> +  virtual ~UserSuppliedFuzzer() {}<br>
> +<br>
> + protected:<br>
> +  // These can be called internally by Mutate and CrossOver.<br>
> +  size_t BasicMutate(uint8_t *Data, size_t Size, size_t MaxSize);<br>
> +  size_t BasicCrossOver(const uint8_t *Data1, size_t Size1,<br>
> +                        const uint8_t *Data2, size_t Size2,<br>
> +                        uint8_t *Out, size_t MaxOutSize);<br>
> +};<br>
> +<br>
> +int FuzzerDriver(int argc, char **argv, UserSuppliedFuzzer &USF);<br>
> +<br>
>  }  // namespace fuzzer<br>
><br>
>  #endif  // LLVM_FUZZER_INTERFACE_H<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_FuzzerInternal.h-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=2BQ79BY94vAeqZUBI5OCznJuGzBKk33XdNoPPlLiWhU&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)<br>
> +++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Fri May 22 17:35:31 2015<br>
> @@ -33,9 +33,10 @@ void CopyFileToErr(const std::string &Pa<br>
>  std::string DirPlusFile(const std::string &DirPath,<br>
>                          const std::string &FileName);<br>
><br>
> -void Mutate(Unit *U, size_t MaxLen);<br>
> +size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);<br>
><br>
> -void CrossOver(const Unit &A, const Unit &B, Unit *U, size_t MaxLen);<br>
> +size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2,<br>
> +                 size_t Size2, uint8_t *Out, size_t MaxOutSize);<br>
><br>
>  void Print(const Unit &U, const char *PrintAfter = "");<br>
>  void PrintASCII(const Unit &U, const char *PrintAfter = "");<br>
> @@ -72,7 +73,7 @@ class Fuzzer {<br>
>      std::string SyncCommand;<br>
>      std::vector<std::string> Tokens;<br>
>    };<br>
> -  Fuzzer(UserCallback Callback, FuzzingOptions Options);<br>
> +  Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options);<br>
>    void AddToCorpus(const Unit &U) { Corpus.push_back(U); }<br>
>    void Loop(size_t NumIterations);<br>
>    void ShuffleAndMinimize();<br>
> @@ -144,7 +145,7 @@ class Fuzzer {<br>
>      return Res;<br>
>    }<br>
><br>
> -  UserCallback Callback;<br>
> +  UserSuppliedFuzzer &USF;<br>
>    FuzzingOptions Options;<br>
>    system_clock::time_point ProcessStartTime = system_clock::now();<br>
>    system_clock::time_point LastExternalSync = system_clock::now();<br>
> @@ -153,4 +154,15 @@ class Fuzzer {<br>
>    long EpochOfLastReadOfOutputCorpus = 0;<br>
>  };<br>
><br>
> +class SimpleUserSuppliedFuzzer: public UserSuppliedFuzzer {<br>
> + public:<br>
> +  SimpleUserSuppliedFuzzer(UserCallback Callback) : Callback(Callback) {}<br>
> +  virtual void TargetFunction(const uint8_t *Data, size_t Size) {<br>
> +    return Callback(Data, Size);<br>
> +  }<br>
> +<br>
> + private:<br>
> +  UserCallback Callback;<br>
> +};<br>
> +<br>
>  };  // namespace fuzzer<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_FuzzerLoop.cpp-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=o9Q8o6sVmnvu4sIVODJeEcqODNqJDsR2Lx3ZDNO3Zyo&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)<br>
> +++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Fri May 22 17:35:31 2015<br>
> @@ -19,8 +19,8 @@ namespace fuzzer {<br>
>  // Only one Fuzzer per process.<br>
>  static Fuzzer *F;<br>
><br>
> -Fuzzer::Fuzzer(UserCallback Callback, FuzzingOptions Options)<br>
> -    : Callback(Callback), Options(Options) {<br>
> +Fuzzer::Fuzzer(UserSuppliedFuzzer &USF, FuzzingOptions Options)<br>
> +    : USF(USF), Options(Options) {<br>
>    SetDeathCallback();<br>
>    InitializeTraceState();<br>
>    assert(!F);<br>
> @@ -207,10 +207,10 @@ Unit Fuzzer::SubstituteTokens(const Unit<br>
><br>
>  void Fuzzer::ExecuteCallback(const Unit &U) {<br>
>    if (Options.Tokens.empty()) {<br>
> -    Callback(U.data(), U.size());<br>
> +    USF.TargetFunction(U.data(), U.size());<br>
>    } else {<br>
>      auto T = SubstituteTokens(U);<br>
> -    Callback(T.data(), T.size());<br>
> +    USF.TargetFunction(T.data(), T.size());<br>
>    }<br>
>  }<br>
><br>
> @@ -321,7 +321,11 @@ void Fuzzer::ReportNewCoverage(size_t Ne<br>
>  void Fuzzer::MutateAndTestOne(Unit *U) {<br>
>    for (int i = 0; i < Options.MutateDepth; i++) {<br>
>      StartTraceRecording();<br>
> -    Mutate(U, Options.MaxLen);<br>
> +    size_t Size = U->size();<br>
> +    U->resize(Options.MaxLen);<br>
> +    size_t NewSize = USF.Mutate(U->data(), Size, U->size());<br>
> +    assert(NewSize > 0 && NewSize <= Options.MaxLen);<br>
> +    U->resize(NewSize);<br>
>      RunOneAndUpdateCorpus(*U);<br>
>      size_t NumTraceBasedMutations = StopTraceRecording();<br>
>      for (size_t j = 0; j < NumTraceBasedMutations; j++) {<br>
> @@ -344,8 +348,12 @@ void Fuzzer::Loop(size_t NumIterations)<br>
>        // Now, cross with others.<br>
>        if (Options.DoCrossOver) {<br>
>          for (size_t J2 = 0; J2 < Corpus.size(); J2++) {<br>
> -          CurrentUnit.clear();<br>
> -          CrossOver(Corpus[J1], Corpus[J2], &CurrentUnit, Options.MaxLen);<br>
> +          CurrentUnit.resize(Options.MaxLen);<br>
> +          size_t NewSize = USF.CrossOver(<br>
> +              Corpus[J1].data(), Corpus[J1].size(), Corpus[J2].data(),<br>
> +              Corpus[J2].size(), CurrentUnit.data(), CurrentUnit.size());<br>
> +          assert(NewSize > 0 && NewSize <= Options.MaxLen);<br>
> +          CurrentUnit.resize(NewSize);<br>
>            MutateAndTestOne(&CurrentUnit);<br>
>          }<br>
>        }<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_FuzzerMutate.cpp-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=iB0jN828_XjgpBy0LzVeoUenaeHTgA-c5OoA4cXNNEw&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp (original)<br>
> +++ llvm/trunk/lib/Fuzzer/FuzzerMutate.cpp Fri May 22 17:35:31 2015<br>
> @@ -9,6 +9,8 @@<br>
>  // Mutate a test input.<br>
>  //===----------------------------------------------------------------------===//<br>
><br>
> +#include <cstring><br>
> +<br>
>  #include "FuzzerInternal.h"<br>
><br>
>  namespace fuzzer {<br>
> @@ -31,40 +33,39 @@ static char RandCh() {<br>
>    return Special[rand() % (sizeof(Special) - 1)];<br>
>  }<br>
><br>
> -// Mutate U in place.<br>
> -void Mutate(Unit *U, size_t MaxLen) {<br>
> -  assert(MaxLen > 0);<br>
> -  assert(U->size() <= MaxLen);<br>
> -  if (U->empty()) {<br>
> -    for (size_t i = 0; i < MaxLen; i++)<br>
> -      U->push_back(RandCh());<br>
> -    return;<br>
> +// Mutates Data in place, returns new size.<br>
> +size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {<br>
> +  assert(MaxSize > 0);<br>
> +  assert(Size <= MaxSize);<br>
> +  if (Size == 0) {<br>
> +    for (size_t i = 0; i < MaxSize; i++)<br>
> +      Data[i] = RandCh();<br>
> +    return MaxSize;<br>
>    }<br>
> -  assert(!U->empty());<br>
> +  assert(Size > 0);<br>
> +  size_t Idx = rand() % Size;<br>
>    switch (rand() % 3) {<br>
>    case 0:<br>
> -    if (U->size() > 1) {<br>
> -      U->erase(U->begin() + rand() % U->size());<br>
> -      break;<br>
> +    if (Size > 1) {<br>
> +      // Erase Data[Idx].<br>
> +      memmove(Data + Idx, Data + Idx + 1, Size - Idx - 1);<br>
> +      Size = Size - 1;<br>
>      }<br>
>      [[clang::fallthrough]];<br>
>    case 1:<br>
> -    if (U->size() < MaxLen) {<br>
> -      U->insert(U->begin() + rand() % U->size(), RandCh());<br>
> -    } else { // At MaxLen.<br>
> -      uint8_t Ch = RandCh();<br>
> -      size_t Idx = rand() % U->size();<br>
> -      (*U)[Idx] = Ch;<br>
> +    if (Size < MaxSize) {<br>
> +      // Insert new value at Data[Idx].<br>
> +      memmove(Data + Idx + 1, Data + Idx, Size - Idx);<br>
> +      Data[Idx] = RandCh();<br>
>      }<br>
> +    Data[Idx] = RandCh();<br>
>      break;<br>
> -  default:<br>
> -    {<br>
> -      size_t Idx = rand() % U->size();<br>
> -      (*U)[Idx] = FlipRandomBit((*U)[Idx]);<br>
> -    }<br>
> +  case 2:<br>
> +    Data[Idx] = FlipRandomBit(Data[Idx]);<br>
>      break;<br>
>    }<br>
> -  assert(!U->empty());<br>
> +  assert(Size > 0);<br>
> +  return Size;<br>
>  }<br>
><br>
>  }  // namespace fuzzer<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/test/CMakeLists.txt<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_test_CMakeLists.txt-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=aBQeiJWlPyBfu83q_lyJYVhKP8MAol2ErK0g7RhmEUA&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/CMakeLists.txt?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/test/CMakeLists.txt (original)<br>
> +++ llvm/trunk/lib/Fuzzer/test/CMakeLists.txt Fri May 22 17:35:31 2015<br>
> @@ -21,6 +21,10 @@ set(Tests<br>
>    ${DFSanTests}<br>
>    )<br>
><br>
> +set(CustomMainTests<br>
> +  UserSuppliedFuzzerTest<br>
> +  )<br>
> +<br>
><br>
>  set(TestBinaries)<br>
><br>
> @@ -34,6 +38,17 @@ foreach(Test ${Tests})<br>
>    set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test})<br>
>  endforeach()<br>
><br>
> +foreach(Test ${CustomMainTests})<br>
> +  add_executable(LLVMFuzzer-${Test}<br>
> +    ${Test}.cpp<br>
> +    )<br>
> +  target_link_libraries(LLVMFuzzer-${Test}<br>
> +    LLVMFuzzerNoMain<br>
> +    )<br>
> +  set(TestBinaries ${TestBinaries} LLVMFuzzer-${Test})<br>
> +endforeach()<br>
> +<br>
> +<br>
>  configure_lit_site_cfg(<br>
>    ${CMAKE_CURRENT_SOURCE_DIR}/<a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__lit.site.cfg.in&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=WrMwQnsyI6NtR2YafSV7q4j9CzG7YGqDW3FXDfWkKWk&e=" target="_blank">lit.site.cfg.in</a><br>
>    ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg<br>
> @@ -49,7 +64,7 @@ include_directories(${LLVM_MAIN_SRC_DIR}<br>
><br>
>  add_executable(LLVMFuzzer-Unittest<br>
>    FuzzerUnittest.cpp<br>
> -  $<TARGET_OBJECTS:LLVMFuzzerNoMain><br>
> +  $<TARGET_OBJECTS:LLVMFuzzerNoMainObjects><br>
>    )<br>
><br>
>  target_link_libraries(LLVMFuzzer-Unittest<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_test_FuzzerUnittest.cpp-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=l9hi4H41qm2MmAtjwblx_lsFaZSQbKJ2j-mcbZOMMCw&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp (original)<br>
> +++ llvm/trunk/lib/Fuzzer/test/FuzzerUnittest.cpp Fri May 22 17:35:31 2015<br>
> @@ -51,7 +51,10 @@ TEST(Fuzzer, CrossOver) {<br>
>    for (size_t Len = 1; Len < 8; Len++) {<br>
>      std::set<Unit> FoundUnits, ExpectedUnitsWitThisLength;<br>
>      for (int Iter = 0; Iter < 3000; Iter++) {<br>
> -      CrossOver(A, B, &C, Len);<br>
> +      C.resize(Len);<br>
> +      size_t NewSize = CrossOver(A.data(), A.size(), B.data(), B.size(),<br>
> +                                 C.data(), C.size());<br>
> +      C.resize(NewSize);<br>
>        FoundUnits.insert(C);<br>
>      }<br>
>      for (const Unit &U : Expected)<br>
><br>
> Added: llvm/trunk/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_test_UserSuppliedFuzzerTest.cpp-3Frev-3D238059-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=xKbtHFsYOeLi5z2llS0IvGOlyXt3UeokPz5riTLMOF8&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp?rev=238059&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp (added)<br>
> +++ llvm/trunk/lib/Fuzzer/test/UserSuppliedFuzzerTest.cpp Fri May 22 17:35:31 2015<br>
> @@ -0,0 +1,47 @@<br>
> +// Simple test for a fuzzer.<br>
> +// The fuzzer must find the string "Hi!" preceded by a magic value.<br>
> +// Uses UserSuppliedFuzzer which ensures that the magic is present.<br>
> +#include <cstdint><br>
> +#include <cassert><br>
> +#include <cstdlib><br>
> +#include <cstddef><br>
> +#include <cstring><br>
> +#include <iostream><br>
> +<br>
> +#include "FuzzerInterface.h"<br>
> +<br>
> +static const uint64_t kMagic = 8860221463604ULL;<br>
> +<br>
> +class MyFuzzer : public fuzzer::UserSuppliedFuzzer {<br>
> + public:<br>
> +  void TargetFunction(const uint8_t *Data, size_t Size) {<br>
> +    if (Size <= 10) return;<br>
> +    if (memcmp(Data, &kMagic, sizeof(kMagic))) return;<br>
> +    // It's hard to get here w/o advanced fuzzing techniques (e.g. cmp tracing).<br>
> +    // So, we simply 'fix' the data in the custom mutator.<br>
> +    if (Data[8] == 'H') {<br>
> +      if (Data[9] == 'i') {<br>
> +        if (Data[10] == '!') {<br>
> +          std::cout << "BINGO; Found the target, exiting\n";<br>
> +          exit(1);<br>
> +        }<br>
> +      }<br>
> +    }<br>
> +  }<br>
> +  // Custom mutator.<br>
> +  virtual size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {<br>
> +    assert(MaxSize > sizeof(kMagic));<br>
> +    if (Size < sizeof(kMagic))<br>
> +      Size = sizeof(kMagic);<br>
> +    // "Fix" the data, then mutate.<br>
> +    memcpy(Data, &kMagic, std::min(MaxSize, sizeof(kMagic)));<br>
> +    return BasicMutate(Data + sizeof(kMagic), Size - sizeof(kMagic),<br>
> +                       MaxSize - sizeof(kMagic));<br>
> +  }<br>
> +  // No need to redefine CrossOver() here.<br>
> +};<br>
> +<br>
> +int main(int argc, char **argv) {<br>
> +  MyFuzzer F;<br>
> +  fuzzer::FuzzerDriver(argc, argv, F);<br>
> +}<br>
><br>
> Modified: llvm/trunk/lib/Fuzzer/test/fuzzer.test<br>
> URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Fuzzer_test_fuzzer.test-3Frev-3D238059-26r1-3D238058-26r2-3D238059-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=mBmasc0SVIJGbHE0w8bjlKeFqKr2t2nTR7Av3DQ9SBE&s=EDnEKgTj42wCSLwQOiVCxrKOLCzBG8uBIGTJMxACc-0&e=" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/fuzzer.test?rev=238059&r1=238058&r2=238059&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Fuzzer/test/fuzzer.test (original)<br>
> +++ llvm/trunk/lib/Fuzzer/test/fuzzer.test Fri May 22 17:35:31 2015<br>
> @@ -26,3 +26,5 @@ RUN: not ./LLVMFuzzer-DFSanMemcmpTest-DF<br>
><br>
>  RUN: not ./LLVMFuzzer-CxxTokensTest -seed=1 -timeout=15 -tokens=%S/../cxx_fuzzer_tokens.txt 2>&1 | FileCheck %s<br>
><br>
> +RUN: not ./LLVMFuzzer-UserSuppliedFuzzerTest -seed=1 -timeout=15 2>&1 | FileCheck %s<br>
> +<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br></div>