diff options
Diffstat (limited to 'chromium/third_party/libFuzzer/src')
56 files changed, 0 insertions, 9523 deletions
diff --git a/chromium/third_party/libFuzzer/src/CMakeLists.txt b/chromium/third_party/libFuzzer/src/CMakeLists.txt deleted file mode 100644 index caea9734fe5..00000000000 --- a/chromium/third_party/libFuzzer/src/CMakeLists.txt +++ /dev/null @@ -1,147 +0,0 @@ -set(LIBFUZZER_SOURCES - FuzzerCrossOver.cpp - FuzzerDataFlowTrace.cpp - FuzzerDriver.cpp - FuzzerExtFunctionsDlsym.cpp - FuzzerExtFunctionsWeak.cpp - FuzzerExtFunctionsWindows.cpp - FuzzerExtraCounters.cpp - FuzzerIO.cpp - FuzzerIOPosix.cpp - FuzzerIOWindows.cpp - FuzzerLoop.cpp - FuzzerMerge.cpp - FuzzerMutate.cpp - FuzzerSHA1.cpp - FuzzerShmemFuchsia.cpp - FuzzerShmemPosix.cpp - FuzzerShmemWindows.cpp - FuzzerTracePC.cpp - FuzzerUtil.cpp - FuzzerUtilDarwin.cpp - FuzzerUtilFuchsia.cpp - FuzzerUtilLinux.cpp - FuzzerUtilPosix.cpp - FuzzerUtilWindows.cpp) - -set(LIBFUZZER_HEADERS - FuzzerBuiltins.h - FuzzerBuiltinsMsvc.h - FuzzerCommand.h - FuzzerCorpus.h - FuzzerDataFlowTrace.h - FuzzerDefs.h - FuzzerDictionary.h - FuzzerExtFunctions.def - FuzzerExtFunctions.h - FuzzerFlags.def - FuzzerIO.h - FuzzerInterface.h - FuzzerInternal.h - FuzzerMerge.h - FuzzerMutate.h - FuzzerOptions.h - FuzzerRandom.h - FuzzerSHA1.h - FuzzerShmem.h - FuzzerTracePC.h - FuzzerUtil.h - FuzzerValueBitMap.h) - -CHECK_CXX_SOURCE_COMPILES(" - static thread_local int blah; - int main() { - return 0; - } - " HAS_THREAD_LOCAL) - -set(LIBFUZZER_CFLAGS ${SANITIZER_COMMON_CFLAGS}) - -if(OS_NAME MATCHES "Linux|Fuchsia" AND COMPILER_RT_LIBCXX_PATH) - list(APPEND LIBFUZZER_CFLAGS -nostdinc++ -D_LIBCPP_ABI_VERSION=Fuzzer) - # Remove -stdlib= which is unused when passing -nostdinc++. - string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) -elseif(TARGET cxx-headers OR HAVE_LIBCXX) - set(LIBFUZZER_DEPS cxx-headers) -endif() - -append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer LIBFUZZER_CFLAGS) - -if (CMAKE_CXX_FLAGS MATCHES "fsanitize-coverage") - list(APPEND LIBFUZZER_CFLAGS -fno-sanitize-coverage=trace-pc-guard,edge,trace-cmp,indirect-calls,8bit-counters) -endif() - -if(NOT HAS_THREAD_LOCAL) - list(APPEND LIBFUZZER_CFLAGS -Dthread_local=__thread) -endif() - -set(FUZZER_SUPPORTED_OS ${SANITIZER_COMMON_SUPPORTED_OS}) - -add_compiler_rt_object_libraries(RTfuzzer - OS ${FUZZER_SUPPORTED_OS} - ARCHS ${FUZZER_SUPPORTED_ARCH} - SOURCES ${LIBFUZZER_SOURCES} - ADDITIONAL_HEADERS ${LIBFUZZER_HEADERS} - CFLAGS ${LIBFUZZER_CFLAGS} - DEPS ${LIBFUZZER_DEPS}) - -add_compiler_rt_object_libraries(RTfuzzer_main - OS ${FUZZER_SUPPORTED_OS} - ARCHS ${FUZZER_SUPPORTED_ARCH} - SOURCES FuzzerMain.cpp - CFLAGS ${LIBFUZZER_CFLAGS} - DEPS ${LIBFUZZER_DEPS}) - -add_compiler_rt_runtime(clang_rt.fuzzer - STATIC - OS ${FUZZER_SUPPORTED_OS} - ARCHS ${FUZZER_SUPPORTED_ARCH} - OBJECT_LIBS RTfuzzer RTfuzzer_main - CFLAGS ${LIBFUZZER_CFLAGS} - PARENT_TARGET fuzzer) - -add_compiler_rt_runtime(clang_rt.fuzzer_no_main - STATIC - OS ${FUZZER_SUPPORTED_OS} - ARCHS ${FUZZER_SUPPORTED_ARCH} - OBJECT_LIBS RTfuzzer - CFLAGS ${LIBFUZZER_CFLAGS} - PARENT_TARGET fuzzer) - -if(OS_NAME MATCHES "Linux|Fuchsia" AND COMPILER_RT_LIBCXX_PATH) - macro(partially_link_libcxx name dir arch) - set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") - file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) - add_custom_command(TARGET clang_rt.${name}-${arch} POST_BUILD - COMMAND ${CMAKE_LINKER} --whole-archive "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" --no-whole-archive ${dir}/lib/libc++.a -r -o ${name}.o - COMMAND ${CMAKE_OBJCOPY} --localize-hidden ${name}.o - COMMAND ${CMAKE_COMMAND} -E remove "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" - COMMAND ${CMAKE_AR} qcs "$<TARGET_LINKER_FILE:clang_rt.${name}-${arch}>" ${name}.o - WORKING_DIRECTORY ${cxx_${arch}_merge_dir} - ) - endmacro() - - foreach(arch ${FUZZER_SUPPORTED_ARCH}) - get_target_flags_for_arch(${arch} TARGET_CFLAGS) - set(LIBCXX_${arch}_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch}) - add_custom_libcxx(libcxx_fuzzer_${arch} ${LIBCXX_${arch}_PREFIX} - CFLAGS ${TARGET_CFLAGS} - -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS=1 - -fvisibility=hidden - CMAKE_ARGS -DCMAKE_CXX_COMPILER_WORKS=ON - -DLIBCXX_ENABLE_EXCEPTIONS=OFF - -DLIBCXX_ENABLE_SHARED=OFF - -DLIBCXX_ABI_NAMESPACE=Fuzzer - -DLIBCXX_CXX_ABI=none) - target_compile_options(RTfuzzer.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) - add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}-build) - target_compile_options(RTfuzzer_main.${arch} PRIVATE -isystem ${LIBCXX_${arch}_PREFIX}/include/c++/v1) - add_dependencies(RTfuzzer_main.${arch} libcxx_fuzzer_${arch}-build) - partially_link_libcxx(fuzzer_no_main ${LIBCXX_${arch}_PREFIX} ${arch}) - partially_link_libcxx(fuzzer ${LIBCXX_${arch}_PREFIX} ${arch}) - endforeach() -endif() - -if(COMPILER_RT_INCLUDE_TESTS) - add_subdirectory(tests) -endif() diff --git a/chromium/third_party/libFuzzer/src/FuzzerBuiltins.h b/chromium/third_party/libFuzzer/src/FuzzerBuiltins.h deleted file mode 100644 index a80938d9a54..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerBuiltins.h +++ /dev/null @@ -1,36 +0,0 @@ -//===- FuzzerBuiltins.h - Internal header for builtins ----------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Wrapper functions and marcos around builtin functions. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_BUILTINS_H -#define LLVM_FUZZER_BUILTINS_H - -#include "FuzzerDefs.h" - -#if !LIBFUZZER_MSVC -#include <cstdint> - -#define GET_CALLER_PC() __builtin_return_address(0) - -namespace fuzzer { - -inline uint8_t Bswap(uint8_t x) { return x; } -inline uint16_t Bswap(uint16_t x) { return __builtin_bswap16(x); } -inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); } -inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); } - -inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); } -inline uint32_t Clz(unsigned long long X) { return __builtin_clz(X); } -inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); } - -} // namespace fuzzer - -#endif // !LIBFUZZER_MSVC -#endif // LLVM_FUZZER_BUILTINS_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerBuiltinsMsvc.h b/chromium/third_party/libFuzzer/src/FuzzerBuiltinsMsvc.h deleted file mode 100644 index 67dd57ff9a9..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerBuiltinsMsvc.h +++ /dev/null @@ -1,59 +0,0 @@ -//===- FuzzerBuiltinsMSVC.h - Internal header for builtins ------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Wrapper functions and marcos that use intrinsics instead of builtin functions -// which cannot be compiled by MSVC. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_BUILTINS_MSVC_H -#define LLVM_FUZZER_BUILTINS_MSVC_H - -#include "FuzzerDefs.h" - -#if LIBFUZZER_MSVC -#if !defined(_M_ARM) && !defined(_M_X64) -#error "_BitScanReverse64 unavailable on this platform so MSVC is unsupported." -#endif -#include <intrin.h> -#include <cstdint> -#include <cstdlib> - -// __builtin_return_address() cannot be compiled with MSVC. Use the equivalent -// from <intrin.h> -#define GET_CALLER_PC() reinterpret_cast<uintptr_t>(_ReturnAddress()) - -namespace fuzzer { - -inline uint8_t Bswap(uint8_t x) { return x; } -// Use alternatives to __builtin functions from <stdlib.h> and <intrin.h> on -// Windows since the builtins are not supported by MSVC. -inline uint16_t Bswap(uint16_t x) { return _byteswap_ushort(x); } -inline uint32_t Bswap(uint32_t x) { return _byteswap_ulong(x); } -inline uint64_t Bswap(uint64_t x) { return _byteswap_uint64(x); } - -// The functions below were mostly copied from -// compiler-rt/lib/builtins/int_lib.h which defines the __builtin functions used -// outside of Windows. -inline uint32_t Clzll(uint64_t X) { - unsigned long LeadZeroIdx = 0; - if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx; - return 64; -} - -inline uint32_t Clz(uint32_t X) { - unsigned long LeadZeroIdx = 0; - if (_BitScanReverse(&LeadZeroIdx, X)) return 31 - LeadZeroIdx; - return 32; -} - -inline int Popcountll(unsigned long long X) { return __popcnt64(X); } - -} // namespace fuzzer - -#endif // LIBFUZER_MSVC -#endif // LLVM_FUZZER_BUILTINS_MSVC_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerCommand.h b/chromium/third_party/libFuzzer/src/FuzzerCommand.h deleted file mode 100644 index 9d258a228f8..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerCommand.h +++ /dev/null @@ -1,179 +0,0 @@ -//===- FuzzerCommand.h - Interface representing a process -------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// FuzzerCommand represents a command to run in a subprocess. It allows callers -// to manage command line arguments and output and error streams. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_COMMAND_H -#define LLVM_FUZZER_COMMAND_H - -#include "FuzzerDefs.h" -#include "FuzzerIO.h" - -#include <algorithm> -#include <sstream> -#include <string> -#include <vector> - -namespace fuzzer { - -class Command final { -public: - // This command line flag is used to indicate that the remaining command line - // is immutable, meaning this flag effectively marks the end of the mutable - // argument list. - static inline const char *ignoreRemainingArgs() { - return "-ignore_remaining_args=1"; - } - - Command() : CombinedOutAndErr(false) {} - - explicit Command(const Vector<std::string> &ArgsToAdd) - : Args(ArgsToAdd), CombinedOutAndErr(false) {} - - explicit Command(const Command &Other) - : Args(Other.Args), CombinedOutAndErr(Other.CombinedOutAndErr), - OutputFile(Other.OutputFile) {} - - Command &operator=(const Command &Other) { - Args = Other.Args; - CombinedOutAndErr = Other.CombinedOutAndErr; - OutputFile = Other.OutputFile; - return *this; - } - - ~Command() {} - - // Returns true if the given Arg is present in Args. Only checks up to - // "-ignore_remaining_args=1". - bool hasArgument(const std::string &Arg) const { - auto i = endMutableArgs(); - return std::find(Args.begin(), i, Arg) != i; - } - - // Gets all of the current command line arguments, **including** those after - // "-ignore-remaining-args=1". - const Vector<std::string> &getArguments() const { return Args; } - - // Adds the given argument before "-ignore_remaining_args=1", or at the end - // if that flag isn't present. - void addArgument(const std::string &Arg) { - Args.insert(endMutableArgs(), Arg); - } - - // Adds all given arguments before "-ignore_remaining_args=1", or at the end - // if that flag isn't present. - void addArguments(const Vector<std::string> &ArgsToAdd) { - Args.insert(endMutableArgs(), ArgsToAdd.begin(), ArgsToAdd.end()); - } - - // Removes the given argument from the command argument list. Ignores any - // occurrences after "-ignore_remaining_args=1", if present. - void removeArgument(const std::string &Arg) { - auto i = endMutableArgs(); - Args.erase(std::remove(Args.begin(), i, Arg), i); - } - - // Like hasArgument, but checks for "-[Flag]=...". - bool hasFlag(const std::string &Flag) const { - std::string Arg("-" + Flag + "="); - auto IsMatch = [&](const std::string &Other) { - return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; - }; - return std::any_of(Args.begin(), endMutableArgs(), IsMatch); - } - - // Returns the value of the first instance of a given flag, or an empty string - // if the flag isn't present. Ignores any occurrences after - // "-ignore_remaining_args=1", if present. - std::string getFlagValue(const std::string &Flag) const { - std::string Arg("-" + Flag + "="); - auto IsMatch = [&](const std::string &Other) { - return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; - }; - auto i = endMutableArgs(); - auto j = std::find_if(Args.begin(), i, IsMatch); - std::string result; - if (j != i) { - result = j->substr(Arg.length()); - } - return result; - } - - // Like AddArgument, but adds "-[Flag]=[Value]". - void addFlag(const std::string &Flag, const std::string &Value) { - addArgument("-" + Flag + "=" + Value); - } - - // Like RemoveArgument, but removes "-[Flag]=...". - void removeFlag(const std::string &Flag) { - std::string Arg("-" + Flag + "="); - auto IsMatch = [&](const std::string &Other) { - return Arg.compare(0, std::string::npos, Other, 0, Arg.length()) == 0; - }; - auto i = endMutableArgs(); - Args.erase(std::remove_if(Args.begin(), i, IsMatch), i); - } - - // Returns whether the command's stdout is being written to an output file. - bool hasOutputFile() const { return !OutputFile.empty(); } - - // Returns the currently set output file. - const std::string &getOutputFile() const { return OutputFile; } - - // Configures the command to redirect its output to the name file. - void setOutputFile(const std::string &FileName) { OutputFile = FileName; } - - // Returns whether the command's stderr is redirected to stdout. - bool isOutAndErrCombined() const { return CombinedOutAndErr; } - - // Sets whether to redirect the command's stderr to its stdout. - void combineOutAndErr(bool combine = true) { CombinedOutAndErr = combine; } - - // Returns a string representation of the command. On many systems this will - // be the equivalent command line. - std::string toString() const { - std::stringstream SS; - for (auto arg : getArguments()) - SS << arg << " "; - if (hasOutputFile()) - SS << ">" << getOutputFile() << " "; - if (isOutAndErrCombined()) - SS << "2>&1 "; - std::string result = SS.str(); - if (!result.empty()) - result = result.substr(0, result.length() - 1); - return result; - } - -private: - Command(Command &&Other) = delete; - Command &operator=(Command &&Other) = delete; - - Vector<std::string>::iterator endMutableArgs() { - return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); - } - - Vector<std::string>::const_iterator endMutableArgs() const { - return std::find(Args.begin(), Args.end(), ignoreRemainingArgs()); - } - - // The command arguments. Args[0] is the command name. - Vector<std::string> Args; - - // True indicates stderr is redirected to stdout. - bool CombinedOutAndErr; - - // If not empty, stdout is redirected to the named file. - std::string OutputFile; -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_COMMAND_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerCorpus.h b/chromium/third_party/libFuzzer/src/FuzzerCorpus.h deleted file mode 100644 index 8ad14656cff..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerCorpus.h +++ /dev/null @@ -1,315 +0,0 @@ -//===- FuzzerCorpus.h - Internal header for the Fuzzer ----------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// fuzzer::InputCorpus -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_CORPUS -#define LLVM_FUZZER_CORPUS - -#include "FuzzerDataFlowTrace.h" -#include "FuzzerDefs.h" -#include "FuzzerIO.h" -#include "FuzzerRandom.h" -#include "FuzzerSHA1.h" -#include "FuzzerTracePC.h" -#include <algorithm> -#include <numeric> -#include <random> -#include <unordered_set> - -namespace fuzzer { - -struct InputInfo { - Unit U; // The actual input data. - uint8_t Sha1[kSHA1NumBytes]; // Checksum. - // Number of features that this input has and no smaller input has. - size_t NumFeatures = 0; - size_t Tmp = 0; // Used by ValidateFeatureSet. - // Stats. - size_t NumExecutedMutations = 0; - size_t NumSuccessfullMutations = 0; - bool MayDeleteFile = false; - bool Reduced = false; - bool HasFocusFunction = false; - Vector<uint32_t> UniqFeatureSet; - Vector<uint8_t> DataFlowTraceForFocusFunction; -}; - -class InputCorpus { - static const size_t kFeatureSetSize = 1 << 21; - public: - InputCorpus(const std::string &OutputCorpus) : OutputCorpus(OutputCorpus) { - memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature)); - memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature)); - } - ~InputCorpus() { - for (auto II : Inputs) - delete II; - } - size_t size() const { return Inputs.size(); } - size_t SizeInBytes() const { - size_t Res = 0; - for (auto II : Inputs) - Res += II->U.size(); - return Res; - } - size_t NumActiveUnits() const { - size_t Res = 0; - for (auto II : Inputs) - Res += !II->U.empty(); - return Res; - } - size_t MaxInputSize() const { - size_t Res = 0; - for (auto II : Inputs) - Res = std::max(Res, II->U.size()); - return Res; - } - - size_t NumInputsThatTouchFocusFunction() { - return std::count_if(Inputs.begin(), Inputs.end(), [](const InputInfo *II) { - return II->HasFocusFunction; - }); - } - - size_t NumInputsWithDataFlowTrace() { - return std::count_if(Inputs.begin(), Inputs.end(), [](const InputInfo *II) { - return !II->DataFlowTraceForFocusFunction.empty(); - }); - } - - bool empty() const { return Inputs.empty(); } - const Unit &operator[] (size_t Idx) const { return Inputs[Idx]->U; } - void AddToCorpus(const Unit &U, size_t NumFeatures, bool MayDeleteFile, - bool HasFocusFunction, const Vector<uint32_t> &FeatureSet, - const DataFlowTrace &DFT, const InputInfo *BaseII) { - assert(!U.empty()); - if (FeatureDebug) - Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures); - Inputs.push_back(new InputInfo()); - InputInfo &II = *Inputs.back(); - II.U = U; - II.NumFeatures = NumFeatures; - II.MayDeleteFile = MayDeleteFile; - II.UniqFeatureSet = FeatureSet; - II.HasFocusFunction = HasFocusFunction; - std::sort(II.UniqFeatureSet.begin(), II.UniqFeatureSet.end()); - ComputeSHA1(U.data(), U.size(), II.Sha1); - auto Sha1Str = Sha1ToString(II.Sha1); - Hashes.insert(Sha1Str); - if (HasFocusFunction) - if (auto V = DFT.Get(Sha1Str)) - II.DataFlowTraceForFocusFunction = *V; - // This is a gross heuristic. - // Ideally, when we add an element to a corpus we need to know its DFT. - // But if we don't, we'll use the DFT of its base input. - if (II.DataFlowTraceForFocusFunction.empty() && BaseII) - II.DataFlowTraceForFocusFunction = BaseII->DataFlowTraceForFocusFunction; - UpdateCorpusDistribution(); - PrintCorpus(); - // ValidateFeatureSet(); - } - - // Debug-only - void PrintUnit(const Unit &U) { - if (!FeatureDebug) return; - for (uint8_t C : U) { - if (C != 'F' && C != 'U' && C != 'Z') - C = '.'; - Printf("%c", C); - } - } - - // Debug-only - void PrintFeatureSet(const Vector<uint32_t> &FeatureSet) { - if (!FeatureDebug) return; - Printf("{"); - for (uint32_t Feature: FeatureSet) - Printf("%u,", Feature); - Printf("}"); - } - - // Debug-only - void PrintCorpus() { - if (!FeatureDebug) return; - Printf("======= CORPUS:\n"); - int i = 0; - for (auto II : Inputs) { - if (std::find(II->U.begin(), II->U.end(), 'F') != II->U.end()) { - Printf("[%2d] ", i); - Printf("%s sz=%zd ", Sha1ToString(II->Sha1).c_str(), II->U.size()); - PrintUnit(II->U); - Printf(" "); - PrintFeatureSet(II->UniqFeatureSet); - Printf("\n"); - } - i++; - } - } - - void Replace(InputInfo *II, const Unit &U) { - assert(II->U.size() > U.size()); - Hashes.erase(Sha1ToString(II->Sha1)); - DeleteFile(*II); - ComputeSHA1(U.data(), U.size(), II->Sha1); - Hashes.insert(Sha1ToString(II->Sha1)); - II->U = U; - II->Reduced = true; - UpdateCorpusDistribution(); - } - - bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); } - bool HasUnit(const std::string &H) { return Hashes.count(H); } - InputInfo &ChooseUnitToMutate(Random &Rand) { - InputInfo &II = *Inputs[ChooseUnitIdxToMutate(Rand)]; - assert(!II.U.empty()); - return II; - }; - - // Returns an index of random unit from the corpus to mutate. - size_t ChooseUnitIdxToMutate(Random &Rand) { - size_t Idx = static_cast<size_t>(CorpusDistribution(Rand)); - assert(Idx < Inputs.size()); - return Idx; - } - - void PrintStats() { - for (size_t i = 0; i < Inputs.size(); i++) { - const auto &II = *Inputs[i]; - Printf(" [% 3zd %s] sz: % 5zd runs: % 5zd succ: % 5zd focus: %d\n", i, - Sha1ToString(II.Sha1).c_str(), II.U.size(), - II.NumExecutedMutations, II.NumSuccessfullMutations, II.HasFocusFunction); - } - } - - void PrintFeatureSet() { - for (size_t i = 0; i < kFeatureSetSize; i++) { - if(size_t Sz = GetFeature(i)) - Printf("[%zd: id %zd sz%zd] ", i, SmallestElementPerFeature[i], Sz); - } - Printf("\n\t"); - for (size_t i = 0; i < Inputs.size(); i++) - if (size_t N = Inputs[i]->NumFeatures) - Printf(" %zd=>%zd ", i, N); - Printf("\n"); - } - - void DeleteFile(const InputInfo &II) { - if (!OutputCorpus.empty() && II.MayDeleteFile) - RemoveFile(DirPlusFile(OutputCorpus, Sha1ToString(II.Sha1))); - } - - void DeleteInput(size_t Idx) { - InputInfo &II = *Inputs[Idx]; - DeleteFile(II); - Unit().swap(II.U); - if (FeatureDebug) - Printf("EVICTED %zd\n", Idx); - } - - bool AddFeature(size_t Idx, uint32_t NewSize, bool Shrink) { - assert(NewSize); - Idx = Idx % kFeatureSetSize; - uint32_t OldSize = GetFeature(Idx); - if (OldSize == 0 || (Shrink && OldSize > NewSize)) { - if (OldSize > 0) { - size_t OldIdx = SmallestElementPerFeature[Idx]; - InputInfo &II = *Inputs[OldIdx]; - assert(II.NumFeatures > 0); - II.NumFeatures--; - if (II.NumFeatures == 0) - DeleteInput(OldIdx); - } else { - NumAddedFeatures++; - } - NumUpdatedFeatures++; - if (FeatureDebug) - Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize); - SmallestElementPerFeature[Idx] = Inputs.size(); - InputSizesPerFeature[Idx] = NewSize; - return true; - } - return false; - } - - bool IsFeatureNew(size_t Idx, uint32_t NewSize, bool Shrink) { - assert(NewSize); - uint32_t OldSize = GetFeature(Idx % kFeatureSetSize); - return OldSize == 0 || (Shrink && OldSize > NewSize); - } - - size_t NumFeatures() const { return NumAddedFeatures; } - size_t NumFeatureUpdates() const { return NumUpdatedFeatures; } - -private: - - static const bool FeatureDebug = false; - - size_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; } - - void ValidateFeatureSet() { - if (FeatureDebug) - PrintFeatureSet(); - for (size_t Idx = 0; Idx < kFeatureSetSize; Idx++) - if (GetFeature(Idx)) - Inputs[SmallestElementPerFeature[Idx]]->Tmp++; - for (auto II: Inputs) { - if (II->Tmp != II->NumFeatures) - Printf("ZZZ %zd %zd\n", II->Tmp, II->NumFeatures); - assert(II->Tmp == II->NumFeatures); - II->Tmp = 0; - } - } - - // Updates the probability distribution for the units in the corpus. - // Must be called whenever the corpus or unit weights are changed. - // - // Hypothesis: units added to the corpus last are more interesting. - // - // Hypothesis: inputs with infrequent features are more interesting. - void UpdateCorpusDistribution() { - size_t N = Inputs.size(); - assert(N); - Intervals.resize(N + 1); - Weights.resize(N); - std::iota(Intervals.begin(), Intervals.end(), 0); - for (size_t i = 0; i < N; i++) - Weights[i] = Inputs[i]->NumFeatures - ? (i + 1) * (Inputs[i]->HasFocusFunction ? 1000 : 1) - : 0.; - if (FeatureDebug) { - for (size_t i = 0; i < N; i++) - Printf("%zd ", Inputs[i]->NumFeatures); - Printf("SCORE\n"); - for (size_t i = 0; i < N; i++) - Printf("%f ", Weights[i]); - Printf("Weights\n"); - } - CorpusDistribution = std::piecewise_constant_distribution<double>( - Intervals.begin(), Intervals.end(), Weights.begin()); - } - std::piecewise_constant_distribution<double> CorpusDistribution; - - Vector<double> Intervals; - Vector<double> Weights; - - std::unordered_set<std::string> Hashes; - Vector<InputInfo*> Inputs; - - size_t NumAddedFeatures = 0; - size_t NumUpdatedFeatures = 0; - uint32_t InputSizesPerFeature[kFeatureSetSize]; - uint32_t SmallestElementPerFeature[kFeatureSetSize]; - - std::string OutputCorpus; -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_CORPUS diff --git a/chromium/third_party/libFuzzer/src/FuzzerCrossOver.cpp b/chromium/third_party/libFuzzer/src/FuzzerCrossOver.cpp deleted file mode 100644 index 8b0fd7d529a..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerCrossOver.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Cross over test inputs. -//===----------------------------------------------------------------------===// - -#include "FuzzerDefs.h" -#include "FuzzerMutate.h" -#include "FuzzerRandom.h" -#include <cstring> - -namespace fuzzer { - -// Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out. -size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1, - const uint8_t *Data2, size_t Size2, - uint8_t *Out, size_t MaxOutSize) { - assert(Size1 || Size2); - MaxOutSize = Rand(MaxOutSize) + 1; - size_t OutPos = 0; - size_t Pos1 = 0; - size_t Pos2 = 0; - size_t *InPos = &Pos1; - size_t InSize = Size1; - const uint8_t *Data = Data1; - bool CurrentlyUsingFirstData = true; - while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) { - // Merge a part of Data into Out. - size_t OutSizeLeft = MaxOutSize - OutPos; - if (*InPos < InSize) { - size_t InSizeLeft = InSize - *InPos; - size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft); - size_t ExtraSize = Rand(MaxExtraSize) + 1; - memcpy(Out + OutPos, Data + *InPos, ExtraSize); - OutPos += ExtraSize; - (*InPos) += ExtraSize; - } - // Use the other input data on the next iteration. - InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1; - InSize = CurrentlyUsingFirstData ? Size2 : Size1; - Data = CurrentlyUsingFirstData ? Data2 : Data1; - CurrentlyUsingFirstData = !CurrentlyUsingFirstData; - } - return OutPos; -} - -} // namespace fuzzer diff --git a/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.cpp b/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.cpp deleted file mode 100644 index 764f3e49fd2..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.cpp +++ /dev/null @@ -1,91 +0,0 @@ -//===- FuzzerDataFlowTrace.cpp - DataFlowTrace ---*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// fuzzer::DataFlowTrace -//===----------------------------------------------------------------------===// - -#include "FuzzerDataFlowTrace.h" -#include "FuzzerIO.h" - -#include <cstdlib> -#include <fstream> -#include <string> -#include <vector> - -namespace fuzzer { - -void DataFlowTrace::Init(const std::string &DirPath, - const std::string &FocusFunction) { - if (DirPath.empty()) return; - const char *kFunctionsTxt = "functions.txt"; - Printf("INFO: DataFlowTrace: reading from '%s'\n", DirPath.c_str()); - Vector<SizedFile> Files; - GetSizedFilesFromDir(DirPath, &Files); - std::string L; - - // Read functions.txt - std::ifstream IF(DirPlusFile(DirPath, kFunctionsTxt)); - size_t FocusFuncIdx = SIZE_MAX; - size_t NumFunctions = 0; - while (std::getline(IF, L, '\n')) { - NumFunctions++; - if (FocusFunction == L) - FocusFuncIdx = NumFunctions - 1; - } - if (!NumFunctions || FocusFuncIdx == SIZE_MAX || Files.size() <= 1) - return; - // Read traces. - size_t NumTraceFiles = 0; - size_t NumTracesWithFocusFunction = 0; - for (auto &SF : Files) { - auto Name = Basename(SF.File); - if (Name == kFunctionsTxt) continue; - auto ParseError = [&](const char *Err) { - Printf("DataFlowTrace: parse error: %s\n File: %s\n Line: %s\n", Err, - Name.c_str(), L.c_str()); - }; - NumTraceFiles++; - // Printf("=== %s\n", Name.c_str()); - std::ifstream IF(SF.File); - while (std::getline(IF, L, '\n')) { - size_t SpacePos = L.find(' '); - if (SpacePos == std::string::npos) - return ParseError("no space in the trace line"); - if (L.empty() || L[0] != 'F') - return ParseError("the trace line doesn't start with 'F'"); - size_t N = std::atol(L.c_str() + 1); - if (N >= NumFunctions) - return ParseError("N is greater than the number of functions"); - if (N == FocusFuncIdx) { - NumTracesWithFocusFunction++; - const char *Beg = L.c_str() + SpacePos + 1; - const char *End = L.c_str() + L.size(); - assert(Beg < End); - size_t Len = End - Beg; - Vector<uint8_t> V(Len); - for (size_t I = 0; I < Len; I++) { - if (Beg[I] != '0' && Beg[I] != '1') - ParseError("the trace should contain only 0 or 1"); - V[I] = Beg[I] == '1'; - } - Traces[Name] = V; - // Print just a few small traces. - if (NumTracesWithFocusFunction <= 3 && Len <= 16) - Printf("%s => |%s|\n", Name.c_str(), L.c_str() + SpacePos + 1); - break; // No need to parse the following lines. - } - } - } - assert(NumTraceFiles == Files.size() - 1); - Printf("INFO: DataFlowTrace: %zd trace files, %zd functions, " - "%zd traces with focus function\n", - NumTraceFiles, NumFunctions, NumTracesWithFocusFunction); -} - -} // namespace fuzzer - diff --git a/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.h b/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.h deleted file mode 100644 index ad4faeab7b2..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerDataFlowTrace.h +++ /dev/null @@ -1,56 +0,0 @@ -//===- FuzzerDataFlowTrace.h - Internal header for the Fuzzer ---*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// fuzzer::DataFlowTrace; reads and handles a data-flow trace. -// -// A data flow trace is generated by e.g. dataflow/DataFlow.cpp -// and is stored on disk in a separate directory. -// -// The trace dir contains a file 'functions.txt' which lists function names, -// oner per line, e.g. -// ==> functions.txt <== -// Func2 -// LLVMFuzzerTestOneInput -// Func1 -// -// All other files in the dir are the traces, see dataflow/DataFlow.cpp. -// The name of the file is sha1 of the input used to generate the trace. -// -// Current status: -// the data is parsed and the summary is printed, but the data is not yet -// used in any other way. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_DATA_FLOW_TRACE -#define LLVM_FUZZER_DATA_FLOW_TRACE - -#include "FuzzerDefs.h" - -#include <unordered_map> -#include <vector> -#include <string> - -namespace fuzzer { -class DataFlowTrace { - public: - void Init(const std::string &DirPath, const std::string &FocusFunction); - void Clear() { Traces.clear(); } - const Vector<uint8_t> *Get(const std::string &InputSha1) const { - auto It = Traces.find(InputSha1); - if (It != Traces.end()) - return &It->second; - return nullptr; - } - - private: - // Input's sha1 => DFT for the FocusFunction. - std::unordered_map<std::string, Vector<uint8_t> > Traces; -}; -} // namespace fuzzer - -#endif // LLVM_FUZZER_DATA_FLOW_TRACE diff --git a/chromium/third_party/libFuzzer/src/FuzzerDefs.h b/chromium/third_party/libFuzzer/src/FuzzerDefs.h deleted file mode 100644 index c3dccbcd86f..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerDefs.h +++ /dev/null @@ -1,201 +0,0 @@ -//===- FuzzerDefs.h - Internal header for the Fuzzer ------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Basic definitions. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_DEFS_H -#define LLVM_FUZZER_DEFS_H - -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <string> -#include <vector> -#include <set> -#include <memory> - -// Platform detection. -#ifdef __linux__ -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_FUCHSIA 0 -#define LIBFUZZER_LINUX 1 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#define LIBFUZZER_WINDOWS 0 -#elif __APPLE__ -#define LIBFUZZER_APPLE 1 -#define LIBFUZZER_FUCHSIA 0 -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#define LIBFUZZER_WINDOWS 0 -#elif __NetBSD__ -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_FUCHSIA 0 -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_NETBSD 1 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#define LIBFUZZER_WINDOWS 0 -#elif __FreeBSD__ -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_FUCHSIA 0 -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 1 -#define LIBFUZZER_OPENBSD 0 -#define LIBFUZZER_WINDOWS 0 -#elif __OpenBSD__ -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_FUCHSIA 0 -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 1 -#define LIBFUZZER_WINDOWS 0 -#elif _WIN32 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_FUCHSIA 0 -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#define LIBFUZZER_WINDOWS 1 -#elif __Fuchsia__ -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_FUCHSIA 1 -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#define LIBFUZZER_WINDOWS 0 -#else -#error "Support for your platform has not been implemented" -#endif - -#if defined(_MSC_VER) && !defined(__clang__) -// MSVC compiler is being used. -#define LIBFUZZER_MSVC 1 -#else -#define LIBFUZZER_MSVC 0 -#endif - -#ifndef __has_attribute -# define __has_attribute(x) 0 -#endif - -#define LIBFUZZER_POSIX \ - (LIBFUZZER_APPLE || LIBFUZZER_LINUX || LIBFUZZER_NETBSD || \ - LIBFUZZER_FREEBSD || LIBFUZZER_OPENBSD) - -#ifdef __x86_64 -# if __has_attribute(target) -# define ATTRIBUTE_TARGET_POPCNT __attribute__((target("popcnt"))) -# else -# define ATTRIBUTE_TARGET_POPCNT -# endif -#else -# define ATTRIBUTE_TARGET_POPCNT -#endif - - -#ifdef __clang__ // avoid gcc warning. -# if __has_attribute(no_sanitize) -# define ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) -# else -# define ATTRIBUTE_NO_SANITIZE_MEMORY -# endif -# define ALWAYS_INLINE __attribute__((always_inline)) -#else -# define ATTRIBUTE_NO_SANITIZE_MEMORY -# define ALWAYS_INLINE -#endif // __clang__ - -#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) - -#if defined(__has_feature) -# if __has_feature(address_sanitizer) -# define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_ADDRESS -# elif __has_feature(memory_sanitizer) -# define ATTRIBUTE_NO_SANITIZE_ALL ATTRIBUTE_NO_SANITIZE_MEMORY -# else -# define ATTRIBUTE_NO_SANITIZE_ALL -# endif -#else -# define ATTRIBUTE_NO_SANITIZE_ALL -#endif - -#if LIBFUZZER_WINDOWS -#define ATTRIBUTE_INTERFACE __declspec(dllexport) -// This is used for __sancov_lowest_stack which is needed for -// -fsanitize-coverage=stack-depth. That feature is not yet available on -// Windows, so make the symbol static to avoid linking errors. -#define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \ - __attribute__((tls_model("initial-exec"))) thread_local static -#else -#define ATTRIBUTE_INTERFACE __attribute__((visibility("default"))) -#define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \ - ATTRIBUTE_INTERFACE __attribute__((tls_model("initial-exec"))) thread_local -#endif - -namespace fuzzer { - -template <class T> T Min(T a, T b) { return a < b ? a : b; } -template <class T> T Max(T a, T b) { return a > b ? a : b; } - -class Random; -class Dictionary; -class DictionaryEntry; -class MutationDispatcher; -struct FuzzingOptions; -class InputCorpus; -struct InputInfo; -struct ExternalFunctions; - -// Global interface to functions that may or may not be available. -extern ExternalFunctions *EF; - -// We are using a custom allocator to give a different symbol name to STL -// containers in order to avoid ODR violations. -template<typename T> - class fuzzer_allocator: public std::allocator<T> { - public: - fuzzer_allocator() = default; - - template<class U> - fuzzer_allocator(const fuzzer_allocator<U>&) {} - - template<class Other> - struct rebind { typedef fuzzer_allocator<Other> other; }; - }; - -template<typename T> -using Vector = std::vector<T, fuzzer_allocator<T>>; - -template<typename T> -using Set = std::set<T, std::less<T>, fuzzer_allocator<T>>; - -typedef Vector<uint8_t> Unit; -typedef Vector<Unit> UnitVector; -typedef int (*UserCallback)(const uint8_t *Data, size_t Size); - -int FuzzerDriver(int *argc, char ***argv, UserCallback Callback); - -uint8_t *ExtraCountersBegin(); -uint8_t *ExtraCountersEnd(); -void ClearExtraCounters(); - -extern bool RunningUserCallback; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_DEFS_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerDictionary.h b/chromium/third_party/libFuzzer/src/FuzzerDictionary.h deleted file mode 100644 index 0d9d91bcd2f..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerDictionary.h +++ /dev/null @@ -1,119 +0,0 @@ -//===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// fuzzer::Dictionary -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_DICTIONARY_H -#define LLVM_FUZZER_DICTIONARY_H - -#include "FuzzerDefs.h" -#include "FuzzerIO.h" -#include "FuzzerUtil.h" -#include <algorithm> -#include <limits> - -namespace fuzzer { -// A simple POD sized array of bytes. -template <size_t kMaxSizeT> class FixedWord { -public: - static const size_t kMaxSize = kMaxSizeT; - FixedWord() {} - FixedWord(const uint8_t *B, uint8_t S) { Set(B, S); } - - void Set(const uint8_t *B, uint8_t S) { - assert(S <= kMaxSize); - memcpy(Data, B, S); - Size = S; - } - - bool operator==(const FixedWord<kMaxSize> &w) const { - return Size == w.Size && 0 == memcmp(Data, w.Data, Size); - } - - static size_t GetMaxSize() { return kMaxSize; } - const uint8_t *data() const { return Data; } - uint8_t size() const { return Size; } - -private: - uint8_t Size = 0; - uint8_t Data[kMaxSize]; -}; - -typedef FixedWord<64> Word; - -class DictionaryEntry { - public: - DictionaryEntry() {} - DictionaryEntry(Word W) : W(W) {} - DictionaryEntry(Word W, size_t PositionHint) : W(W), PositionHint(PositionHint) {} - const Word &GetW() const { return W; } - - bool HasPositionHint() const { return PositionHint != std::numeric_limits<size_t>::max(); } - size_t GetPositionHint() const { - assert(HasPositionHint()); - return PositionHint; - } - void IncUseCount() { UseCount++; } - void IncSuccessCount() { SuccessCount++; } - size_t GetUseCount() const { return UseCount; } - size_t GetSuccessCount() const {return SuccessCount; } - - void Print(const char *PrintAfter = "\n") { - PrintASCII(W.data(), W.size()); - if (HasPositionHint()) - Printf("@%zd", GetPositionHint()); - Printf("%s", PrintAfter); - } - -private: - Word W; - size_t PositionHint = std::numeric_limits<size_t>::max(); - size_t UseCount = 0; - size_t SuccessCount = 0; -}; - -class Dictionary { - public: - static const size_t kMaxDictSize = 1 << 14; - - bool ContainsWord(const Word &W) const { - return std::any_of(begin(), end(), [&](const DictionaryEntry &DE) { - return DE.GetW() == W; - }); - } - const DictionaryEntry *begin() const { return &DE[0]; } - const DictionaryEntry *end() const { return begin() + Size; } - DictionaryEntry & operator[] (size_t Idx) { - assert(Idx < Size); - return DE[Idx]; - } - void push_back(DictionaryEntry DE) { - if (Size < kMaxDictSize) - this->DE[Size++] = DE; - } - void clear() { Size = 0; } - bool empty() const { return Size == 0; } - size_t size() const { return Size; } - -private: - DictionaryEntry DE[kMaxDictSize]; - size_t Size = 0; -}; - -// Parses one dictionary entry. -// If successful, write the enty to Unit and returns true, -// otherwise returns false. -bool ParseOneDictionaryEntry(const std::string &Str, Unit *U); -// Parses the dictionary file, fills Units, returns true iff all lines -// were parsed successfully. -bool ParseDictionaryFile(const std::string &Text, Vector<Unit> *Units); - -} // namespace fuzzer - -#endif // LLVM_FUZZER_DICTIONARY_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerDriver.cpp b/chromium/third_party/libFuzzer/src/FuzzerDriver.cpp deleted file mode 100644 index 918a972fff3..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerDriver.cpp +++ /dev/null @@ -1,777 +0,0 @@ -//===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// FuzzerDriver and flag parsing. -//===----------------------------------------------------------------------===// - -#include "FuzzerCommand.h" -#include "FuzzerCorpus.h" -#include "FuzzerIO.h" -#include "FuzzerInterface.h" -#include "FuzzerInternal.h" -#include "FuzzerMutate.h" -#include "FuzzerRandom.h" -#include "FuzzerShmem.h" -#include "FuzzerTracePC.h" -#include <algorithm> -#include <atomic> -#include <chrono> -#include <cstdlib> -#include <cstring> -#include <mutex> -#include <string> -#include <thread> - -// This function should be present in the libFuzzer so that the client -// binary can test for its existence. -extern "C" __attribute__((used)) void __libfuzzer_is_present() {} - -namespace fuzzer { - -// Program arguments. -struct FlagDescription { - const char *Name; - const char *Description; - int Default; - int *IntFlag; - const char **StrFlag; - unsigned int *UIntFlag; -}; - -struct { -#define FUZZER_DEPRECATED_FLAG(Name) -#define FUZZER_FLAG_INT(Name, Default, Description) int Name; -#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name; -#define FUZZER_FLAG_STRING(Name, Description) const char *Name; -#include "FuzzerFlags.def" -#undef FUZZER_DEPRECATED_FLAG -#undef FUZZER_FLAG_INT -#undef FUZZER_FLAG_UNSIGNED -#undef FUZZER_FLAG_STRING -} Flags; - -static const FlagDescription FlagDescriptions [] { -#define FUZZER_DEPRECATED_FLAG(Name) \ - {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr}, -#define FUZZER_FLAG_INT(Name, Default, Description) \ - {#Name, Description, Default, &Flags.Name, nullptr, nullptr}, -#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) \ - {#Name, Description, static_cast<int>(Default), \ - nullptr, nullptr, &Flags.Name}, -#define FUZZER_FLAG_STRING(Name, Description) \ - {#Name, Description, 0, nullptr, &Flags.Name, nullptr}, -#include "FuzzerFlags.def" -#undef FUZZER_DEPRECATED_FLAG -#undef FUZZER_FLAG_INT -#undef FUZZER_FLAG_UNSIGNED -#undef FUZZER_FLAG_STRING -}; - -static const size_t kNumFlags = - sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]); - -static Vector<std::string> *Inputs; -static std::string *ProgName; - -static void PrintHelp() { - Printf("Usage:\n"); - auto Prog = ProgName->c_str(); - Printf("\nTo run fuzzing pass 0 or more directories.\n"); - Printf("%s [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]\n", Prog); - - Printf("\nTo run individual tests without fuzzing pass 1 or more files:\n"); - Printf("%s [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]\n", Prog); - - Printf("\nFlags: (strictly in form -flag=value)\n"); - size_t MaxFlagLen = 0; - for (size_t F = 0; F < kNumFlags; F++) - MaxFlagLen = std::max(strlen(FlagDescriptions[F].Name), MaxFlagLen); - - for (size_t F = 0; F < kNumFlags; F++) { - const auto &D = FlagDescriptions[F]; - if (strstr(D.Description, "internal flag") == D.Description) continue; - Printf(" %s", D.Name); - for (size_t i = 0, n = MaxFlagLen - strlen(D.Name); i < n; i++) - Printf(" "); - Printf("\t"); - Printf("%d\t%s\n", D.Default, D.Description); - } - Printf("\nFlags starting with '--' will be ignored and " - "will be passed verbatim to subprocesses.\n"); -} - -static const char *FlagValue(const char *Param, const char *Name) { - size_t Len = strlen(Name); - if (Param[0] == '-' && strstr(Param + 1, Name) == Param + 1 && - Param[Len + 1] == '=') - return &Param[Len + 2]; - return nullptr; -} - -// Avoid calling stol as it triggers a bug in clang/glibc build. -static long MyStol(const char *Str) { - long Res = 0; - long Sign = 1; - if (*Str == '-') { - Str++; - Sign = -1; - } - for (size_t i = 0; Str[i]; i++) { - char Ch = Str[i]; - if (Ch < '0' || Ch > '9') - return Res; - Res = Res * 10 + (Ch - '0'); - } - return Res * Sign; -} - -static bool ParseOneFlag(const char *Param) { - if (Param[0] != '-') return false; - if (Param[1] == '-') { - static bool PrintedWarning = false; - if (!PrintedWarning) { - PrintedWarning = true; - Printf("INFO: libFuzzer ignores flags that start with '--'\n"); - } - for (size_t F = 0; F < kNumFlags; F++) - if (FlagValue(Param + 1, FlagDescriptions[F].Name)) - Printf("WARNING: did you mean '%s' (single dash)?\n", Param + 1); - return true; - } - for (size_t F = 0; F < kNumFlags; F++) { - const char *Name = FlagDescriptions[F].Name; - const char *Str = FlagValue(Param, Name); - if (Str) { - if (FlagDescriptions[F].IntFlag) { - int Val = MyStol(Str); - *FlagDescriptions[F].IntFlag = Val; - if (Flags.verbosity >= 2) - Printf("Flag: %s %d\n", Name, Val); - return true; - } else if (FlagDescriptions[F].UIntFlag) { - unsigned int Val = std::stoul(Str); - *FlagDescriptions[F].UIntFlag = Val; - if (Flags.verbosity >= 2) - Printf("Flag: %s %u\n", Name, Val); - return true; - } else if (FlagDescriptions[F].StrFlag) { - *FlagDescriptions[F].StrFlag = Str; - if (Flags.verbosity >= 2) - Printf("Flag: %s %s\n", Name, Str); - return true; - } else { // Deprecated flag. - Printf("Flag: %s: deprecated, don't use\n", Name); - return true; - } - } - } - Printf("\n\nWARNING: unrecognized flag '%s'; " - "use -help=1 to list all flags\n\n", Param); - return true; -} - -// We don't use any library to minimize dependencies. -static void ParseFlags(const Vector<std::string> &Args) { - for (size_t F = 0; F < kNumFlags; F++) { - if (FlagDescriptions[F].IntFlag) - *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default; - if (FlagDescriptions[F].UIntFlag) - *FlagDescriptions[F].UIntFlag = - static_cast<unsigned int>(FlagDescriptions[F].Default); - if (FlagDescriptions[F].StrFlag) - *FlagDescriptions[F].StrFlag = nullptr; - } - Inputs = new Vector<std::string>; - for (size_t A = 1; A < Args.size(); A++) { - if (ParseOneFlag(Args[A].c_str())) { - if (Flags.ignore_remaining_args) - break; - continue; - } - Inputs->push_back(Args[A]); - } -} - -static std::mutex Mu; - -static void PulseThread() { - while (true) { - SleepSeconds(600); - std::lock_guard<std::mutex> Lock(Mu); - Printf("pulse...\n"); - } -} - -static void WorkerThread(const Command &BaseCmd, std::atomic<unsigned> *Counter, - unsigned NumJobs, std::atomic<bool> *HasErrors) { - while (true) { - unsigned C = (*Counter)++; - if (C >= NumJobs) break; - std::string Log = "fuzz-" + std::to_string(C) + ".log"; - Command Cmd(BaseCmd); - Cmd.setOutputFile(Log); - Cmd.combineOutAndErr(); - if (Flags.verbosity) { - std::string CommandLine = Cmd.toString(); - Printf("%s\n", CommandLine.c_str()); - } - int ExitCode = ExecuteCommand(Cmd); - if (ExitCode != 0) - *HasErrors = true; - std::lock_guard<std::mutex> Lock(Mu); - Printf("================== Job %u exited with exit code %d ============\n", - C, ExitCode); - fuzzer::CopyFileToErr(Log); - } -} - -std::string CloneArgsWithoutX(const Vector<std::string> &Args, - const char *X1, const char *X2) { - std::string Cmd; - for (auto &S : Args) { - if (FlagValue(S.c_str(), X1) || FlagValue(S.c_str(), X2)) - continue; - Cmd += S + " "; - } - return Cmd; -} - -static int RunInMultipleProcesses(const Vector<std::string> &Args, - unsigned NumWorkers, unsigned NumJobs) { - std::atomic<unsigned> Counter(0); - std::atomic<bool> HasErrors(false); - Command Cmd(Args); - Cmd.removeFlag("jobs"); - Cmd.removeFlag("workers"); - Vector<std::thread> V; - std::thread Pulse(PulseThread); - Pulse.detach(); - for (unsigned i = 0; i < NumWorkers; i++) - V.push_back(std::thread(WorkerThread, std::ref(Cmd), &Counter, NumJobs, &HasErrors)); - for (auto &T : V) - T.join(); - return HasErrors ? 1 : 0; -} - -static void RssThread(Fuzzer *F, size_t RssLimitMb) { - while (true) { - SleepSeconds(1); - size_t Peak = GetPeakRSSMb(); - if (Peak > RssLimitMb) - F->RssLimitCallback(); - } -} - -static void StartRssThread(Fuzzer *F, size_t RssLimitMb) { - if (!RssLimitMb) return; - std::thread T(RssThread, F, RssLimitMb); - T.detach(); -} - -int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) { - Unit U = FileToVector(InputFilePath); - if (MaxLen && MaxLen < U.size()) - U.resize(MaxLen); - F->ExecuteCallback(U.data(), U.size()); - F->TryDetectingAMemoryLeak(U.data(), U.size(), true); - return 0; -} - -static bool AllInputsAreFiles() { - if (Inputs->empty()) return false; - for (auto &Path : *Inputs) - if (!IsFile(Path)) - return false; - return true; -} - -static std::string GetDedupTokenFromFile(const std::string &Path) { - auto S = FileToString(Path); - auto Beg = S.find("DEDUP_TOKEN:"); - if (Beg == std::string::npos) - return ""; - auto End = S.find('\n', Beg); - if (End == std::string::npos) - return ""; - return S.substr(Beg, End - Beg); -} - -int CleanseCrashInput(const Vector<std::string> &Args, - const FuzzingOptions &Options) { - if (Inputs->size() != 1 || !Flags.exact_artifact_path) { - Printf("ERROR: -cleanse_crash should be given one input file and" - " -exact_artifact_path\n"); - exit(1); - } - std::string InputFilePath = Inputs->at(0); - std::string OutputFilePath = Flags.exact_artifact_path; - Command Cmd(Args); - Cmd.removeFlag("cleanse_crash"); - - assert(Cmd.hasArgument(InputFilePath)); - Cmd.removeArgument(InputFilePath); - - auto LogFilePath = DirPlusFile( - TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt"); - auto TmpFilePath = DirPlusFile( - TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".repro"); - Cmd.addArgument(TmpFilePath); - Cmd.setOutputFile(LogFilePath); - Cmd.combineOutAndErr(); - - std::string CurrentFilePath = InputFilePath; - auto U = FileToVector(CurrentFilePath); - size_t Size = U.size(); - - const Vector<uint8_t> ReplacementBytes = {' ', 0xff}; - for (int NumAttempts = 0; NumAttempts < 5; NumAttempts++) { - bool Changed = false; - for (size_t Idx = 0; Idx < Size; Idx++) { - Printf("CLEANSE[%d]: Trying to replace byte %zd of %zd\n", NumAttempts, - Idx, Size); - uint8_t OriginalByte = U[Idx]; - if (ReplacementBytes.end() != std::find(ReplacementBytes.begin(), - ReplacementBytes.end(), - OriginalByte)) - continue; - for (auto NewByte : ReplacementBytes) { - U[Idx] = NewByte; - WriteToFile(U, TmpFilePath); - auto ExitCode = ExecuteCommand(Cmd); - RemoveFile(TmpFilePath); - if (!ExitCode) { - U[Idx] = OriginalByte; - } else { - Changed = true; - Printf("CLEANSE: Replaced byte %zd with 0x%x\n", Idx, NewByte); - WriteToFile(U, OutputFilePath); - break; - } - } - } - if (!Changed) break; - } - RemoveFile(LogFilePath); - return 0; -} - -int MinimizeCrashInput(const Vector<std::string> &Args, - const FuzzingOptions &Options) { - if (Inputs->size() != 1) { - Printf("ERROR: -minimize_crash should be given one input file\n"); - exit(1); - } - std::string InputFilePath = Inputs->at(0); - Command BaseCmd(Args); - BaseCmd.removeFlag("minimize_crash"); - BaseCmd.removeFlag("exact_artifact_path"); - assert(BaseCmd.hasArgument(InputFilePath)); - BaseCmd.removeArgument(InputFilePath); - if (Flags.runs <= 0 && Flags.max_total_time == 0) { - Printf("INFO: you need to specify -runs=N or " - "-max_total_time=N with -minimize_crash=1\n" - "INFO: defaulting to -max_total_time=600\n"); - BaseCmd.addFlag("max_total_time", "600"); - } - - auto LogFilePath = DirPlusFile( - TmpDir(), "libFuzzerTemp." + std::to_string(GetPid()) + ".txt"); - BaseCmd.setOutputFile(LogFilePath); - BaseCmd.combineOutAndErr(); - - std::string CurrentFilePath = InputFilePath; - while (true) { - Unit U = FileToVector(CurrentFilePath); - Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n", - CurrentFilePath.c_str(), U.size()); - - Command Cmd(BaseCmd); - Cmd.addArgument(CurrentFilePath); - - std::string CommandLine = Cmd.toString(); - Printf("CRASH_MIN: executing: %s\n", CommandLine.c_str()); - int ExitCode = ExecuteCommand(Cmd); - if (ExitCode == 0) { - Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str()); - exit(1); - } - Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize " - "it further\n", - CurrentFilePath.c_str(), U.size()); - auto DedupToken1 = GetDedupTokenFromFile(LogFilePath); - if (!DedupToken1.empty()) - Printf("CRASH_MIN: DedupToken1: %s\n", DedupToken1.c_str()); - - std::string ArtifactPath = - Flags.exact_artifact_path - ? Flags.exact_artifact_path - : Options.ArtifactPrefix + "minimized-from-" + Hash(U); - Cmd.addFlag("minimize_crash_internal_step", "1"); - Cmd.addFlag("exact_artifact_path", ArtifactPath); - CommandLine = Cmd.toString(); - Printf("CRASH_MIN: executing: %s\n", CommandLine.c_str()); - ExitCode = ExecuteCommand(Cmd); - CopyFileToErr(LogFilePath); - if (ExitCode == 0) { - if (Flags.exact_artifact_path) { - CurrentFilePath = Flags.exact_artifact_path; - WriteToFile(U, CurrentFilePath); - } - Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n", - CurrentFilePath.c_str(), U.size()); - break; - } - auto DedupToken2 = GetDedupTokenFromFile(LogFilePath); - if (!DedupToken2.empty()) - Printf("CRASH_MIN: DedupToken2: %s\n", DedupToken2.c_str()); - - if (DedupToken1 != DedupToken2) { - if (Flags.exact_artifact_path) { - CurrentFilePath = Flags.exact_artifact_path; - WriteToFile(U, CurrentFilePath); - } - Printf("CRASH_MIN: mismatch in dedup tokens" - " (looks like a different bug). Won't minimize further\n"); - break; - } - - CurrentFilePath = ArtifactPath; - Printf("*********************************\n"); - } - RemoveFile(LogFilePath); - return 0; -} - -int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) { - assert(Inputs->size() == 1); - std::string InputFilePath = Inputs->at(0); - Unit U = FileToVector(InputFilePath); - Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size()); - if (U.size() < 2) { - Printf("INFO: The input is small enough, exiting\n"); - exit(0); - } - F->SetMaxInputLen(U.size()); - F->SetMaxMutationLen(U.size() - 1); - F->MinimizeCrashLoop(U); - Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n"); - exit(0); - return 0; -} - -int AnalyzeDictionary(Fuzzer *F, const Vector<Unit>& Dict, - UnitVector& Corpus) { - Printf("Started dictionary minimization (up to %d tests)\n", - Dict.size() * Corpus.size() * 2); - - // Scores and usage count for each dictionary unit. - Vector<int> Scores(Dict.size()); - Vector<int> Usages(Dict.size()); - - Vector<size_t> InitialFeatures; - Vector<size_t> ModifiedFeatures; - for (auto &C : Corpus) { - // Get coverage for the testcase without modifications. - F->ExecuteCallback(C.data(), C.size()); - InitialFeatures.clear(); - TPC.CollectFeatures([&](size_t Feature) { - InitialFeatures.push_back(Feature); - }); - - for (size_t i = 0; i < Dict.size(); ++i) { - Vector<uint8_t> Data = C; - auto StartPos = std::search(Data.begin(), Data.end(), - Dict[i].begin(), Dict[i].end()); - // Skip dictionary unit, if the testcase does not contain it. - if (StartPos == Data.end()) - continue; - - ++Usages[i]; - while (StartPos != Data.end()) { - // Replace all occurrences of dictionary unit in the testcase. - auto EndPos = StartPos + Dict[i].size(); - for (auto It = StartPos; It != EndPos; ++It) - *It ^= 0xFF; - - StartPos = std::search(EndPos, Data.end(), - Dict[i].begin(), Dict[i].end()); - } - - // Get coverage for testcase with masked occurrences of dictionary unit. - F->ExecuteCallback(Data.data(), Data.size()); - ModifiedFeatures.clear(); - TPC.CollectFeatures([&](size_t Feature) { - ModifiedFeatures.push_back(Feature); - }); - - if (InitialFeatures == ModifiedFeatures) - --Scores[i]; - else - Scores[i] += 2; - } - } - - Printf("###### Useless dictionary elements. ######\n"); - for (size_t i = 0; i < Dict.size(); ++i) { - // Dictionary units with positive score are treated as useful ones. - if (Scores[i] > 0) - continue; - - Printf("\""); - PrintASCII(Dict[i].data(), Dict[i].size(), "\""); - Printf(" # Score: %d, Used: %d\n", Scores[i], Usages[i]); - } - Printf("###### End of useless dictionary elements. ######\n"); - return 0; -} - -int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) { - using namespace fuzzer; - assert(argc && argv && "Argument pointers cannot be nullptr"); - std::string Argv0((*argv)[0]); - EF = new ExternalFunctions(); - if (EF->LLVMFuzzerInitialize) - EF->LLVMFuzzerInitialize(argc, argv); - if (EF->__msan_scoped_disable_interceptor_checks) - EF->__msan_scoped_disable_interceptor_checks(); - const Vector<std::string> Args(*argv, *argv + *argc); - assert(!Args.empty()); - ProgName = new std::string(Args[0]); - if (Argv0 != *ProgName) { - Printf("ERROR: argv[0] has been modified in LLVMFuzzerInitialize\n"); - exit(1); - } - ParseFlags(Args); - if (Flags.help) { - PrintHelp(); - return 0; - } - - if (Flags.close_fd_mask & 2) - DupAndCloseStderr(); - if (Flags.close_fd_mask & 1) - CloseStdout(); - - if (Flags.jobs > 0 && Flags.workers == 0) { - Flags.workers = std::min(NumberOfCpuCores() / 2, Flags.jobs); - if (Flags.workers > 1) - Printf("Running %u workers\n", Flags.workers); - } - - if (Flags.workers > 0 && Flags.jobs > 0) - return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs); - - FuzzingOptions Options; - Options.Verbosity = Flags.verbosity; - Options.MaxLen = Flags.max_len; - Options.LenControl = Flags.len_control; - Options.UnitTimeoutSec = Flags.timeout; - Options.ErrorExitCode = Flags.error_exitcode; - Options.TimeoutExitCode = Flags.timeout_exitcode; - Options.MaxTotalTimeSec = Flags.max_total_time; - Options.DoCrossOver = Flags.cross_over; - Options.MutateDepth = Flags.mutate_depth; - Options.ReduceDepth = Flags.reduce_depth; - Options.UseCounters = Flags.use_counters; - Options.UseMemmem = Flags.use_memmem; - Options.UseCmp = Flags.use_cmp; - Options.UseValueProfile = Flags.use_value_profile; - Options.Shrink = Flags.shrink; - Options.ReduceInputs = Flags.reduce_inputs; - Options.ShuffleAtStartUp = Flags.shuffle; - Options.PreferSmall = Flags.prefer_small; - Options.ReloadIntervalSec = Flags.reload; - Options.OnlyASCII = Flags.only_ascii; - Options.DetectLeaks = Flags.detect_leaks; - Options.PurgeAllocatorIntervalSec = Flags.purge_allocator_interval; - Options.TraceMalloc = Flags.trace_malloc; - Options.RssLimitMb = Flags.rss_limit_mb; - Options.MallocLimitMb = Flags.malloc_limit_mb; - if (!Options.MallocLimitMb) - Options.MallocLimitMb = Options.RssLimitMb; - if (Flags.runs >= 0) - Options.MaxNumberOfRuns = Flags.runs; - if (!Inputs->empty() && !Flags.minimize_crash_internal_step) - Options.OutputCorpus = (*Inputs)[0]; - Options.ReportSlowUnits = Flags.report_slow_units; - if (Flags.artifact_prefix) - Options.ArtifactPrefix = Flags.artifact_prefix; - if (Flags.exact_artifact_path) - Options.ExactArtifactPath = Flags.exact_artifact_path; - Vector<Unit> Dictionary; - if (Flags.dict) - if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary)) - return 1; - if (Flags.verbosity > 0 && !Dictionary.empty()) - Printf("Dictionary: %zd entries\n", Dictionary.size()); - bool DoPlainRun = AllInputsAreFiles(); - Options.SaveArtifacts = - !DoPlainRun || Flags.minimize_crash_internal_step; - Options.PrintNewCovPcs = Flags.print_pcs; - Options.PrintNewCovFuncs = Flags.print_funcs; - Options.PrintFinalStats = Flags.print_final_stats; - Options.PrintCorpusStats = Flags.print_corpus_stats; - Options.PrintCoverage = Flags.print_coverage; - Options.PrintUnstableStats = Flags.print_unstable_stats; - if (Flags.handle_unstable == TracePC::MinUnstable || - Flags.handle_unstable == TracePC::ZeroUnstable) - Options.HandleUnstable = Flags.handle_unstable; - Options.DumpCoverage = Flags.dump_coverage; - if (Flags.exit_on_src_pos) - Options.ExitOnSrcPos = Flags.exit_on_src_pos; - if (Flags.exit_on_item) - Options.ExitOnItem = Flags.exit_on_item; - if (Flags.focus_function) - Options.FocusFunction = Flags.focus_function; - if (Flags.data_flow_trace) - Options.DataFlowTrace = Flags.data_flow_trace; - - unsigned Seed = Flags.seed; - // Initialize Seed. - if (Seed == 0) - Seed = - std::chrono::system_clock::now().time_since_epoch().count() + GetPid(); - if (Flags.verbosity) - Printf("INFO: Seed: %u\n", Seed); - - Random Rand(Seed); - auto *MD = new MutationDispatcher(Rand, Options); - auto *Corpus = new InputCorpus(Options.OutputCorpus); - auto *F = new Fuzzer(Callback, *Corpus, *MD, Options); - - for (auto &U: Dictionary) - if (U.size() <= Word::GetMaxSize()) - MD->AddWordToManualDictionary(Word(U.data(), U.size())); - - StartRssThread(F, Flags.rss_limit_mb); - - Options.HandleAbrt = Flags.handle_abrt; - Options.HandleBus = Flags.handle_bus; - Options.HandleFpe = Flags.handle_fpe; - Options.HandleIll = Flags.handle_ill; - Options.HandleInt = Flags.handle_int; - Options.HandleSegv = Flags.handle_segv; - Options.HandleTerm = Flags.handle_term; - Options.HandleXfsz = Flags.handle_xfsz; - Options.HandleUsr1 = Flags.handle_usr1; - Options.HandleUsr2 = Flags.handle_usr2; - SetSignalHandler(Options); - - std::atexit(Fuzzer::StaticExitCallback); - - if (Flags.minimize_crash) - return MinimizeCrashInput(Args, Options); - - if (Flags.minimize_crash_internal_step) - return MinimizeCrashInputInternalStep(F, Corpus); - - if (Flags.cleanse_crash) - return CleanseCrashInput(Args, Options); - -#if 0 // deprecated, to be removed. - if (auto Name = Flags.run_equivalence_server) { - SMR.Destroy(Name); - if (!SMR.Create(Name)) { - Printf("ERROR: can't create shared memory region\n"); - return 1; - } - Printf("INFO: EQUIVALENCE SERVER UP\n"); - while (true) { - SMR.WaitClient(); - size_t Size = SMR.ReadByteArraySize(); - SMR.WriteByteArray(nullptr, 0); - const Unit tmp(SMR.GetByteArray(), SMR.GetByteArray() + Size); - F->ExecuteCallback(tmp.data(), tmp.size()); - SMR.PostServer(); - } - return 0; - } - - if (auto Name = Flags.use_equivalence_server) { - if (!SMR.Open(Name)) { - Printf("ERROR: can't open shared memory region\n"); - return 1; - } - Printf("INFO: EQUIVALENCE CLIENT UP\n"); - } -#endif - - if (DoPlainRun) { - Options.SaveArtifacts = false; - int Runs = std::max(1, Flags.runs); - Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(), - Inputs->size(), Runs); - for (auto &Path : *Inputs) { - auto StartTime = system_clock::now(); - Printf("Running: %s\n", Path.c_str()); - for (int Iter = 0; Iter < Runs; Iter++) - RunOneTest(F, Path.c_str(), Options.MaxLen); - auto StopTime = system_clock::now(); - auto MS = duration_cast<milliseconds>(StopTime - StartTime).count(); - Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS); - } - Printf("***\n" - "*** NOTE: fuzzing was not performed, you have only\n" - "*** executed the target code on a fixed set of inputs.\n" - "***\n"); - F->PrintFinalStats(); - exit(0); - } - - if (Flags.merge) { - F->CrashResistantMerge(Args, *Inputs, - Flags.load_coverage_summary, - Flags.save_coverage_summary, - Flags.merge_control_file); - exit(0); - } - - if (Flags.merge_inner) { - const size_t kDefaultMaxMergeLen = 1 << 20; - if (Options.MaxLen == 0) - F->SetMaxInputLen(kDefaultMaxMergeLen); - assert(Flags.merge_control_file); - F->CrashResistantMergeInternalStep(Flags.merge_control_file); - exit(0); - } - - if (Flags.analyze_dict) { - size_t MaxLen = INT_MAX; // Large max length. - UnitVector InitialCorpus; - for (auto &Inp : *Inputs) { - Printf("Loading corpus dir: %s\n", Inp.c_str()); - ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr, - MaxLen, /*ExitOnError=*/false); - } - - if (Dictionary.empty() || Inputs->empty()) { - Printf("ERROR: can't analyze dict without dict and corpus provided\n"); - return 1; - } - if (AnalyzeDictionary(F, Dictionary, InitialCorpus)) { - Printf("Dictionary analysis failed\n"); - exit(1); - } - Printf("Dictionary analysis succeeded\n"); - exit(0); - } - - F->Loop(*Inputs); - - if (Flags.verbosity) - Printf("Done %zd runs in %zd second(s)\n", F->getTotalNumberOfRuns(), - F->secondsSinceProcessStartUp()); - F->PrintFinalStats(); - - exit(0); // Don't let F destroy itself. -} - -// Storage for global ExternalFunctions object. -ExternalFunctions *EF = nullptr; - -} // namespace fuzzer diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.def b/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.def deleted file mode 100644 index 8bfffdde56d..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.def +++ /dev/null @@ -1,51 +0,0 @@ -//===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// This defines the external function pointers that -// ``fuzzer::ExternalFunctions`` should contain and try to initialize. The -// EXT_FUNC macro must be defined at the point of inclusion. The signature of -// the macro is: -// -// EXT_FUNC(<name>, <return_type>, <function_signature>, <warn_if_missing>) -//===----------------------------------------------------------------------===// - -// Optional user functions -EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false); -EXT_FUNC(LLVMFuzzerCustomMutator, size_t, - (uint8_t * Data, size_t Size, size_t MaxSize, unsigned int Seed), - false); -EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t, - (const uint8_t * Data1, size_t Size1, - const uint8_t * Data2, size_t Size2, - uint8_t * Out, size_t MaxOutSize, unsigned int Seed), - false); - -// Sanitizer functions -EXT_FUNC(__lsan_enable, void, (), false); -EXT_FUNC(__lsan_disable, void, (), false); -EXT_FUNC(__lsan_do_recoverable_leak_check, int, (), false); -EXT_FUNC(__sanitizer_acquire_crash_state, bool, (), true); -EXT_FUNC(__sanitizer_install_malloc_and_free_hooks, int, - (void (*malloc_hook)(const volatile void *, size_t), - void (*free_hook)(const volatile void *)), - false); -EXT_FUNC(__sanitizer_purge_allocator, void, (), false); -EXT_FUNC(__sanitizer_print_memory_profile, int, (size_t, size_t), false); -EXT_FUNC(__sanitizer_print_stack_trace, void, (), true); -EXT_FUNC(__sanitizer_symbolize_pc, void, - (void *, const char *fmt, char *out_buf, size_t out_buf_size), false); -EXT_FUNC(__sanitizer_get_module_and_offset_for_pc, int, - (void *pc, char *module_path, - size_t module_path_len,void **pc_offset), false); -EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true); -EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false); -EXT_FUNC(__sanitizer_dump_coverage, void, (const uintptr_t *, uintptr_t), - false); -EXT_FUNC(__msan_scoped_disable_interceptor_checks, void, (), false); -EXT_FUNC(__msan_scoped_enable_interceptor_checks, void, (), false); -EXT_FUNC(__msan_unpoison, void, (const volatile void *, size_t size), false); diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.h b/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.h deleted file mode 100644 index 2672a385478..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctions.h +++ /dev/null @@ -1,35 +0,0 @@ -//===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Defines an interface to (possibly optional) functions. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_EXT_FUNCTIONS_H -#define LLVM_FUZZER_EXT_FUNCTIONS_H - -#include <stddef.h> -#include <stdint.h> - -namespace fuzzer { - -struct ExternalFunctions { - // Initialize function pointers. Functions that are not available will be set - // to nullptr. Do not call this constructor before ``main()`` has been - // entered. - ExternalFunctions(); - -#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - RETURN_TYPE(*NAME) FUNC_SIG = nullptr - -#include "FuzzerExtFunctions.def" - -#undef EXT_FUNC -}; -} // namespace fuzzer - -#endif diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsDlsym.cpp b/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsDlsym.cpp deleted file mode 100644 index 06bddd5de38..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsDlsym.cpp +++ /dev/null @@ -1,52 +0,0 @@ -//===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Implementation for operating systems that support dlsym(). We only use it on -// Apple platforms for now. We don't use this approach on Linux because it -// requires that clients of LibFuzzer pass ``--export-dynamic`` to the linker. -// That is a complication we don't wish to expose to clients right now. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_APPLE - -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" -#include <dlfcn.h> - -using namespace fuzzer; - -template <typename T> -static T GetFnPtr(const char *FnName, bool WarnIfMissing) { - dlerror(); // Clear any previous errors. - void *Fn = dlsym(RTLD_DEFAULT, FnName); - if (Fn == nullptr) { - if (WarnIfMissing) { - const char *ErrorMsg = dlerror(); - Printf("WARNING: Failed to find function \"%s\".", FnName); - if (ErrorMsg) - Printf(" Reason %s.", ErrorMsg); - Printf("\n"); - } - } - return reinterpret_cast<T>(Fn); -} - -namespace fuzzer { - -ExternalFunctions::ExternalFunctions() { -#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - this->NAME = GetFnPtr<decltype(ExternalFunctions::NAME)>(#NAME, WARN) - -#include "FuzzerExtFunctions.def" - -#undef EXT_FUNC -} - -} // namespace fuzzer - -#endif // LIBFUZZER_APPLE diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWeak.cpp b/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWeak.cpp deleted file mode 100644 index 6a6ef4932f4..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWeak.cpp +++ /dev/null @@ -1,55 +0,0 @@ -//===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Implementation for Linux. This relies on the linker's support for weak -// symbols. We don't use this approach on Apple platforms because it requires -// clients of LibFuzzer to pass ``-U _<symbol_name>`` to the linker to allow -// weak symbols to be undefined. That is a complication we don't want to expose -// to clients right now. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FUCHSIA || \ - LIBFUZZER_FREEBSD || LIBFUZZER_OPENBSD - -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" - -extern "C" { -// Declare these symbols as weak to allow them to be optionally defined. -#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - __attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG - -#include "FuzzerExtFunctions.def" - -#undef EXT_FUNC -} - -using namespace fuzzer; - -static void CheckFnPtr(void *FnPtr, const char *FnName, bool WarnIfMissing) { - if (FnPtr == nullptr && WarnIfMissing) { - Printf("WARNING: Failed to find function \"%s\".\n", FnName); - } -} - -namespace fuzzer { - -ExternalFunctions::ExternalFunctions() { -#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - this->NAME = ::NAME; \ - CheckFnPtr(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(::NAME)), \ - #NAME, WARN); - -#include "FuzzerExtFunctions.def" - -#undef EXT_FUNC -} - -} // namespace fuzzer - -#endif diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWindows.cpp b/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWindows.cpp deleted file mode 100644 index b01871439ca..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerExtFunctionsWindows.cpp +++ /dev/null @@ -1,83 +0,0 @@ -//=== FuzzerExtWindows.cpp - Interface to external functions --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Implementation of FuzzerExtFunctions for Windows. Uses alternatename when -// compiled with MSVC. Uses weak aliases when compiled with clang. Unfortunately -// the method each compiler supports is not supported by the other. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_WINDOWS - -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" - -using namespace fuzzer; - -// Intermediate macro to ensure the parameter is expanded before stringified. -#define STRINGIFY_(A) #A -#define STRINGIFY(A) STRINGIFY_(A) - -#if LIBFUZZER_MSVC -// Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h -#if defined(_M_IX86) || defined(__i386__) -#define WIN_SYM_PREFIX "_" -#else -#define WIN_SYM_PREFIX -#endif - -// Declare external functions as having alternativenames, so that we can -// determine if they are not defined. -#define EXTERNAL_FUNC(Name, Default) \ - __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \ - Name) "=" WIN_SYM_PREFIX STRINGIFY(Default))) -#else -// Declare external functions as weak to allow them to default to a specified -// function if not defined explicitly. We must use weak symbols because clang's -// support for alternatename is not 100%, see -// https://bugs.llvm.org/show_bug.cgi?id=40218 for more details. -#define EXTERNAL_FUNC(Name, Default) \ - __attribute__((weak, alias(STRINGIFY(Default)))) -#endif // LIBFUZZER_MSVC - -extern "C" { -#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - RETURN_TYPE NAME##Def FUNC_SIG { \ - Printf("ERROR: Function \"%s\" not defined.\n", #NAME); \ - exit(1); \ - } \ - EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG; - -#include "FuzzerExtFunctions.def" - -#undef EXT_FUNC -} - -template <typename T> -static T *GetFnPtr(T *Fun, T *FunDef, const char *FnName, bool WarnIfMissing) { - if (Fun == FunDef) { - if (WarnIfMissing) - Printf("WARNING: Failed to find function \"%s\".\n", FnName); - return nullptr; - } - return Fun; -} - -namespace fuzzer { - -ExternalFunctions::ExternalFunctions() { -#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \ - this->NAME = GetFnPtr<decltype(::NAME)>(::NAME, ::NAME##Def, #NAME, WARN); - -#include "FuzzerExtFunctions.def" - -#undef EXT_FUNC -} - -} // namespace fuzzer - -#endif // LIBFUZZER_WINDOWS diff --git a/chromium/third_party/libFuzzer/src/FuzzerExtraCounters.cpp b/chromium/third_party/libFuzzer/src/FuzzerExtraCounters.cpp deleted file mode 100644 index c99cd89be29..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerExtraCounters.cpp +++ /dev/null @@ -1,42 +0,0 @@ -//===- FuzzerExtraCounters.cpp - Extra coverage counters ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Extra coverage counters defined by user code. -//===----------------------------------------------------------------------===// - -#include "FuzzerDefs.h" - -#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ - LIBFUZZER_OPENBSD -__attribute__((weak)) extern uint8_t __start___libfuzzer_extra_counters; -__attribute__((weak)) extern uint8_t __stop___libfuzzer_extra_counters; - -namespace fuzzer { -uint8_t *ExtraCountersBegin() { return &__start___libfuzzer_extra_counters; } -uint8_t *ExtraCountersEnd() { return &__stop___libfuzzer_extra_counters; } -ATTRIBUTE_NO_SANITIZE_ALL -void ClearExtraCounters() { // hand-written memset, don't asan-ify. - uintptr_t *Beg = reinterpret_cast<uintptr_t*>(ExtraCountersBegin()); - uintptr_t *End = reinterpret_cast<uintptr_t*>(ExtraCountersEnd()); - for (; Beg < End; Beg++) { - *Beg = 0; - __asm__ __volatile__("" : : : "memory"); - } -} - -} // namespace fuzzer - -#else -// TODO: implement for other platforms. -namespace fuzzer { -uint8_t *ExtraCountersBegin() { return nullptr; } -uint8_t *ExtraCountersEnd() { return nullptr; } -void ClearExtraCounters() {} -} // namespace fuzzer - -#endif diff --git a/chromium/third_party/libFuzzer/src/FuzzerFlags.def b/chromium/third_party/libFuzzer/src/FuzzerFlags.def deleted file mode 100644 index 9e212ef656d..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerFlags.def +++ /dev/null @@ -1,164 +0,0 @@ -//===- FuzzerFlags.def - Run-time flags -------------------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Flags. FUZZER_FLAG_INT/FUZZER_FLAG_STRING macros should be defined at the -// point of inclusion. We are not using any flag parsing library for better -// portability and independence. -//===----------------------------------------------------------------------===// -FUZZER_FLAG_INT(verbosity, 1, "Verbosity level.") -FUZZER_FLAG_UNSIGNED(seed, 0, "Random seed. If 0, seed is generated.") -FUZZER_FLAG_INT(runs, -1, - "Number of individual test runs (-1 for infinite runs).") -FUZZER_FLAG_INT(max_len, 0, "Maximum length of the test input. " - "If 0, libFuzzer tries to guess a good value based on the corpus " - "and reports it. ") -FUZZER_FLAG_INT(len_control, 100, "Try generating small inputs first, " - "then try larger inputs over time. Specifies the rate at which the length " - "limit is increased (smaller == faster). If 0, immediately try inputs with " - "size up to max_len.") -FUZZER_FLAG_INT(cross_over, 1, "If 1, cross over inputs.") -FUZZER_FLAG_INT(mutate_depth, 5, - "Apply this number of consecutive mutations to each input.") -FUZZER_FLAG_INT(reduce_depth, 0, "Experimental/internal. " - "Reduce depth if mutations lose unique features") -FUZZER_FLAG_INT(shuffle, 1, "Shuffle inputs at startup") -FUZZER_FLAG_INT(prefer_small, 1, - "If 1, always prefer smaller inputs during the corpus shuffle.") -FUZZER_FLAG_INT( - timeout, 1200, - "Timeout in seconds (if positive). " - "If one unit runs more than this number of seconds the process will abort.") -FUZZER_FLAG_INT(error_exitcode, 77, "When libFuzzer itself reports a bug " - "this exit code will be used.") -FUZZER_FLAG_INT(timeout_exitcode, 77, "When libFuzzer reports a timeout " - "this exit code will be used.") -FUZZER_FLAG_INT(max_total_time, 0, "If positive, indicates the maximal total " - "time in seconds to run the fuzzer.") -FUZZER_FLAG_INT(help, 0, "Print help.") -FUZZER_FLAG_INT(merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be " - "merged into the 1-st corpus. Only interesting units will be taken. " - "This flag can be used to minimize a corpus.") -FUZZER_FLAG_STRING(merge_inner, "internal flag") -FUZZER_FLAG_STRING(merge_control_file, - "Specify a control file used for the merge process. " - "If a merge process gets killed it tries to leave this file " - "in a state suitable for resuming the merge. " - "By default a temporary file will be used.") -FUZZER_FLAG_STRING(save_coverage_summary, "Experimental:" - " save coverage summary to a given file." - " Used with -merge=1") -FUZZER_FLAG_STRING(load_coverage_summary, "Experimental:" - " load coverage summary from a given file." - " Treat this coverage as belonging to the first corpus. " - " Used with -merge=1") -FUZZER_FLAG_INT(minimize_crash, 0, "If 1, minimizes the provided" - " crash input. Use with -runs=N or -max_total_time=N to limit " - "the number attempts." - " Use with -exact_artifact_path to specify the output." - " Combine with ASAN_OPTIONS=dedup_token_length=3 (or similar) to ensure that" - " the minimized input triggers the same crash." - ) -FUZZER_FLAG_INT(cleanse_crash, 0, "If 1, tries to cleanse the provided" - " crash input to make it contain fewer original bytes." - " Use with -exact_artifact_path to specify the output." - ) -FUZZER_FLAG_INT(minimize_crash_internal_step, 0, "internal flag") -FUZZER_FLAG_INT(use_counters, 1, "Use coverage counters") -FUZZER_FLAG_INT(use_memmem, 1, - "Use hints from intercepting memmem, strstr, etc") -FUZZER_FLAG_INT(use_value_profile, 0, - "Experimental. Use value profile to guide fuzzing.") -FUZZER_FLAG_INT(use_cmp, 1, "Use CMP traces to guide mutations") -FUZZER_FLAG_INT(shrink, 0, "Experimental. Try to shrink corpus inputs.") -FUZZER_FLAG_INT(reduce_inputs, 1, - "Try to reduce the size of inputs while preserving their full feature sets") -FUZZER_FLAG_UNSIGNED(jobs, 0, "Number of jobs to run. If jobs >= 1 we spawn" - " this number of jobs in separate worker processes" - " with stdout/stderr redirected to fuzz-JOB.log.") -FUZZER_FLAG_UNSIGNED(workers, 0, - "Number of simultaneous worker processes to run the jobs." - " If zero, \"min(jobs,NumberOfCpuCores()/2)\" is used.") -FUZZER_FLAG_INT(reload, 1, - "Reload the main corpus every <N> seconds to get new units" - " discovered by other processes. If 0, disabled") -FUZZER_FLAG_INT(report_slow_units, 10, - "Report slowest units if they run for more than this number of seconds.") -FUZZER_FLAG_INT(only_ascii, 0, - "If 1, generate only ASCII (isprint+isspace) inputs.") -FUZZER_FLAG_STRING(dict, "Experimental. Use the dictionary file.") -FUZZER_FLAG_STRING(artifact_prefix, "Write fuzzing artifacts (crash, " - "timeout, or slow inputs) as " - "$(artifact_prefix)file") -FUZZER_FLAG_STRING(exact_artifact_path, - "Write the single artifact on failure (crash, timeout) " - "as $(exact_artifact_path). This overrides -artifact_prefix " - "and will not use checksum in the file name. Do not " - "use the same path for several parallel processes.") -FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.") -FUZZER_FLAG_INT(print_funcs, 2, "If >=1, print out at most this number of " - "newly covered functions.") -FUZZER_FLAG_INT(print_final_stats, 0, "If 1, print statistics at exit.") -FUZZER_FLAG_INT(print_corpus_stats, 0, - "If 1, print statistics on corpus elements at exit.") -FUZZER_FLAG_INT(print_coverage, 0, "If 1, print coverage information as text" - " at exit.") -FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated." - " If 1, dump coverage information as a" - " .sancov file at exit.") -FUZZER_FLAG_INT(handle_unstable, 0, "Experimental." - " Executes every input 3 times in total if a unique feature" - " is found during the first execution." - " If 1, we only use the minimum hit count from the 3 runs" - " to determine whether an input is interesting." - " If 2, we disregard edges that are found unstable for" - " feature collection.") -FUZZER_FLAG_INT(print_unstable_stats, 0, "Experimental." - " If 1, print unstable statistics at exit.") -FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.") -FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGBUS.") -FUZZER_FLAG_INT(handle_abrt, 1, "If 1, try to intercept SIGABRT.") -FUZZER_FLAG_INT(handle_ill, 1, "If 1, try to intercept SIGILL.") -FUZZER_FLAG_INT(handle_fpe, 1, "If 1, try to intercept SIGFPE.") -FUZZER_FLAG_INT(handle_int, 1, "If 1, try to intercept SIGINT.") -FUZZER_FLAG_INT(handle_term, 1, "If 1, try to intercept SIGTERM.") -FUZZER_FLAG_INT(handle_xfsz, 1, "If 1, try to intercept SIGXFSZ.") -FUZZER_FLAG_INT(handle_usr1, 1, "If 1, try to intercept SIGUSR1.") -FUZZER_FLAG_INT(handle_usr2, 1, "If 1, try to intercept SIGUSR2.") -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. stderr of asan.") -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_FLAG_INT(purge_allocator_interval, 1, "Purge allocator caches and " - "quarantines every <N> seconds. When rss_limit_mb is specified (>0), " - "purging starts when RSS exceeds 50% of rss_limit_mb. Pass " - "purge_allocator_interval=-1 to disable this functionality.") -FUZZER_FLAG_INT(trace_malloc, 0, "If >= 1 will print all mallocs/frees. " - "If >= 2 will also print stack traces.") -FUZZER_FLAG_INT(rss_limit_mb, 2048, "If non-zero, the fuzzer will exit upon" - "reaching this limit of RSS memory usage.") -FUZZER_FLAG_INT(malloc_limit_mb, 0, "If non-zero, the fuzzer will exit " - "if the target tries to allocate this number of Mb with one malloc call. " - "If zero (default) same limit as rss_limit_mb is applied.") -FUZZER_FLAG_STRING(exit_on_src_pos, "Exit if a newly found PC originates" - " from the given source location. Example: -exit_on_src_pos=foo.cc:123. " - "Used primarily for testing libFuzzer itself.") -FUZZER_FLAG_STRING(exit_on_item, "Exit if an item with a given sha1 sum" - " was added to the corpus. " - "Used primarily for testing libFuzzer itself.") -FUZZER_FLAG_INT(ignore_remaining_args, 0, "If 1, ignore all arguments passed " - "after this one. Useful for fuzzers that need to do their own " - "argument parsing.") -FUZZER_FLAG_STRING(focus_function, "Experimental. " - "Fuzzing will focus on inputs that trigger calls to this function") - -FUZZER_DEPRECATED_FLAG(run_equivalence_server) -FUZZER_DEPRECATED_FLAG(use_equivalence_server) -FUZZER_FLAG_INT(analyze_dict, 0, "Experimental") -FUZZER_DEPRECATED_FLAG(use_clang_coverage) -FUZZER_FLAG_STRING(data_flow_trace, "Experimental: use the data flow trace") diff --git a/chromium/third_party/libFuzzer/src/FuzzerIO.cpp b/chromium/third_party/libFuzzer/src/FuzzerIO.cpp deleted file mode 100644 index c4c31e82471..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerIO.cpp +++ /dev/null @@ -1,129 +0,0 @@ -//===- FuzzerIO.cpp - IO utils. -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// IO functions. -//===----------------------------------------------------------------------===// - -#include "FuzzerIO.h" -#include "FuzzerDefs.h" -#include "FuzzerExtFunctions.h" -#include <algorithm> -#include <cstdarg> -#include <fstream> -#include <iterator> -#include <sys/stat.h> -#include <sys/types.h> - -namespace fuzzer { - -static FILE *OutputFile = stderr; - -long GetEpoch(const std::string &Path) { - struct stat St; - if (stat(Path.c_str(), &St)) - return 0; // Can't stat, be conservative. - return St.st_mtime; -} - -Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) { - std::ifstream T(Path, std::ios::binary); - if (ExitOnError && !T) { - Printf("No such directory: %s; exiting\n", Path.c_str()); - exit(1); - } - - T.seekg(0, T.end); - auto EndPos = T.tellg(); - if (EndPos < 0) return {}; - size_t FileLen = EndPos; - if (MaxSize) - FileLen = std::min(FileLen, MaxSize); - - T.seekg(0, T.beg); - Unit Res(FileLen); - T.read(reinterpret_cast<char *>(Res.data()), FileLen); - return Res; -} - -std::string FileToString(const std::string &Path) { - std::ifstream T(Path, std::ios::binary); - return std::string((std::istreambuf_iterator<char>(T)), - std::istreambuf_iterator<char>()); -} - -void CopyFileToErr(const std::string &Path) { - Printf("%s", FileToString(Path).c_str()); -} - -void WriteToFile(const Unit &U, const std::string &Path) { - // Use raw C interface because this function may be called from a sig handler. - FILE *Out = fopen(Path.c_str(), "w"); - if (!Out) return; - fwrite(U.data(), sizeof(U[0]), U.size(), Out); - fclose(Out); -} - -void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V, - long *Epoch, size_t MaxSize, bool ExitOnError) { - long E = Epoch ? *Epoch : 0; - Vector<std::string> Files; - ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true); - size_t NumLoaded = 0; - for (size_t i = 0; i < Files.size(); i++) { - auto &X = Files[i]; - if (Epoch && GetEpoch(X) < E) continue; - NumLoaded++; - if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024) - Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path); - auto S = FileToVector(X, MaxSize, ExitOnError); - if (!S.empty()) - V->push_back(S); - } -} - - -void GetSizedFilesFromDir(const std::string &Dir, Vector<SizedFile> *V) { - Vector<std::string> Files; - ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true); - for (auto &File : Files) - if (size_t Size = FileSize(File)) - V->push_back({File, Size}); -} - -std::string DirPlusFile(const std::string &DirPath, - const std::string &FileName) { - return DirPath + GetSeparator() + FileName; -} - -void DupAndCloseStderr() { - int OutputFd = DuplicateFile(2); - if (OutputFd > 0) { - FILE *NewOutputFile = OpenFile(OutputFd, "w"); - if (NewOutputFile) { - OutputFile = NewOutputFile; - if (EF->__sanitizer_set_report_fd) - EF->__sanitizer_set_report_fd( - reinterpret_cast<void *>(GetHandleFromFd(OutputFd))); - DiscardOutput(2); - } - } -} - -void CloseStdout() { - DiscardOutput(1); -} - -void Printf(const char *Fmt, ...) { - va_list ap; - va_start(ap, Fmt); - vfprintf(OutputFile, Fmt, ap); - va_end(ap); - fflush(OutputFile); -} - -} // namespace fuzzer diff --git a/chromium/third_party/libFuzzer/src/FuzzerIO.h b/chromium/third_party/libFuzzer/src/FuzzerIO.h deleted file mode 100644 index b4a68190e78..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerIO.h +++ /dev/null @@ -1,87 +0,0 @@ -//===- FuzzerIO.h - Internal header for IO utils ----------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// IO interface. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_IO_H -#define LLVM_FUZZER_IO_H - -#include "FuzzerDefs.h" - -namespace fuzzer { - -long GetEpoch(const std::string &Path); - -Unit FileToVector(const std::string &Path, size_t MaxSize = 0, - bool ExitOnError = true); - -std::string FileToString(const std::string &Path); - -void CopyFileToErr(const std::string &Path); - -void WriteToFile(const Unit &U, const std::string &Path); - -void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V, - long *Epoch, size_t MaxSize, bool ExitOnError); - -// Returns "Dir/FileName" or equivalent for the current OS. -std::string DirPlusFile(const std::string &DirPath, - const std::string &FileName); - -// Returns the name of the dir, similar to the 'dirname' utility. -std::string DirName(const std::string &FileName); - -// Returns path to a TmpDir. -std::string TmpDir(); - -bool IsInterestingCoverageFile(const std::string &FileName); - -void DupAndCloseStderr(); - -void CloseStdout(); - -void Printf(const char *Fmt, ...); - -// Print using raw syscalls, useful when printing at early init stages. -void RawPrint(const char *Str); - -// Platform specific functions: -bool IsFile(const std::string &Path); -size_t FileSize(const std::string &Path); - -void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, - Vector<std::string> *V, bool TopDir); - -struct SizedFile { - std::string File; - size_t Size; - bool operator<(const SizedFile &B) const { return Size < B.Size; } -}; - -void GetSizedFilesFromDir(const std::string &Dir, Vector<SizedFile> *V); - -char GetSeparator(); -// Similar to the basename utility: returns the file name w/o the dir prefix. -std::string Basename(const std::string &Path); - -FILE* OpenFile(int Fd, const char *Mode); - -int CloseFile(int Fd); - -int DuplicateFile(int Fd); - -void RemoveFile(const std::string &Path); - -void DiscardOutput(int Fd); - -intptr_t GetHandleFromFd(int fd); - -} // namespace fuzzer - -#endif // LLVM_FUZZER_IO_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerIOPosix.cpp b/chromium/third_party/libFuzzer/src/FuzzerIOPosix.cpp deleted file mode 100644 index 401b4cbbf74..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerIOPosix.cpp +++ /dev/null @@ -1,147 +0,0 @@ -//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// IO functions implementation using Posix API. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_POSIX || LIBFUZZER_FUCHSIA - -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" -#include <cstdarg> -#include <cstdio> -#include <dirent.h> -#include <fstream> -#include <iterator> -#include <libgen.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -namespace fuzzer { - -bool IsFile(const std::string &Path) { - struct stat St; - if (stat(Path.c_str(), &St)) - return false; - return S_ISREG(St.st_mode); -} - -static bool IsDirectory(const std::string &Path) { - struct stat St; - if (stat(Path.c_str(), &St)) - return false; - return S_ISDIR(St.st_mode); -} - -size_t FileSize(const std::string &Path) { - struct stat St; - if (stat(Path.c_str(), &St)) - return 0; - return St.st_size; -} - -std::string Basename(const std::string &Path) { - size_t Pos = Path.rfind(GetSeparator()); - if (Pos == std::string::npos) return Path; - assert(Pos < Path.size()); - return Path.substr(Pos + 1); -} - -void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, - Vector<std::string> *V, bool TopDir) { - auto E = GetEpoch(Dir); - if (Epoch) - if (E && *Epoch >= E) return; - - DIR *D = opendir(Dir.c_str()); - if (!D) { - Printf("%s: %s; exiting\n", strerror(errno), Dir.c_str()); - exit(1); - } - while (auto E = readdir(D)) { - std::string Path = DirPlusFile(Dir, E->d_name); - if (E->d_type == DT_REG || E->d_type == DT_LNK || - (E->d_type == DT_UNKNOWN && IsFile(Path))) - V->push_back(Path); - else if ((E->d_type == DT_DIR || - (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && - *E->d_name != '.') - ListFilesInDirRecursive(Path, Epoch, V, false); - } - closedir(D); - if (Epoch && TopDir) - *Epoch = E; -} - -char GetSeparator() { - return '/'; -} - -FILE* OpenFile(int Fd, const char* Mode) { - return fdopen(Fd, Mode); -} - -int CloseFile(int fd) { - return close(fd); -} - -int DuplicateFile(int Fd) { - return dup(Fd); -} - -void RemoveFile(const std::string &Path) { - unlink(Path.c_str()); -} - -void DiscardOutput(int Fd) { - FILE* Temp = fopen("/dev/null", "w"); - if (!Temp) - return; - dup2(fileno(Temp), Fd); - fclose(Temp); -} - -intptr_t GetHandleFromFd(int fd) { - return static_cast<intptr_t>(fd); -} - -std::string DirName(const std::string &FileName) { - char *Tmp = new char[FileName.size() + 1]; - memcpy(Tmp, FileName.c_str(), FileName.size() + 1); - std::string Res = dirname(Tmp); - delete [] Tmp; - return Res; -} - -std::string TmpDir() { - if (auto Env = getenv("TMPDIR")) - return Env; - return "/tmp"; -} - -bool IsInterestingCoverageFile(const std::string &FileName) { - if (FileName.find("compiler-rt/lib/") != std::string::npos) - return false; // sanitizer internal. - if (FileName.find("/usr/lib/") != std::string::npos) - return false; - if (FileName.find("/usr/include/") != std::string::npos) - return false; - if (FileName == "<null>") - return false; - return true; -} - - -void RawPrint(const char *Str) { - write(2, Str, strlen(Str)); -} - -} // namespace fuzzer - -#endif // LIBFUZZER_POSIX diff --git a/chromium/third_party/libFuzzer/src/FuzzerIOWindows.cpp b/chromium/third_party/libFuzzer/src/FuzzerIOWindows.cpp deleted file mode 100644 index 75dcaf72a94..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerIOWindows.cpp +++ /dev/null @@ -1,343 +0,0 @@ -//===- FuzzerIOWindows.cpp - IO utils for Windows. ------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// IO functions implementation for Windows. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_WINDOWS - -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" -#include <cstdarg> -#include <cstdio> -#include <fstream> -#include <io.h> -#include <iterator> -#include <sys/stat.h> -#include <sys/types.h> -#include <windows.h> - -namespace fuzzer { - -static bool IsFile(const std::string &Path, const DWORD &FileAttributes) { - - if (FileAttributes & FILE_ATTRIBUTE_NORMAL) - return true; - - if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) - return false; - - HANDLE FileHandle( - CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, 0)); - - if (FileHandle == INVALID_HANDLE_VALUE) { - Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(), - GetLastError()); - return false; - } - - DWORD FileType = GetFileType(FileHandle); - - if (FileType == FILE_TYPE_UNKNOWN) { - Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(), - GetLastError()); - CloseHandle(FileHandle); - return false; - } - - if (FileType != FILE_TYPE_DISK) { - CloseHandle(FileHandle); - return false; - } - - CloseHandle(FileHandle); - return true; -} - -bool IsFile(const std::string &Path) { - DWORD Att = GetFileAttributesA(Path.c_str()); - - if (Att == INVALID_FILE_ATTRIBUTES) { - Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n", - Path.c_str(), GetLastError()); - return false; - } - - return IsFile(Path, Att); -} - -std::string Basename(const std::string &Path) { - size_t Pos = Path.find_last_of("/\\"); - if (Pos == std::string::npos) return Path; - assert(Pos < Path.size()); - return Path.substr(Pos + 1); -} - -size_t FileSize(const std::string &Path) { - WIN32_FILE_ATTRIBUTE_DATA attr; - if (!GetFileAttributesExA(Path.c_str(), GetFileExInfoStandard, &attr)) { - Printf("GetFileAttributesExA() failed for \"%s\" (Error code: %lu).\n", - Path.c_str(), GetLastError()); - return 0; - } - ULARGE_INTEGER size; - size.HighPart = attr.nFileSizeHigh; - size.LowPart = attr.nFileSizeLow; - return size.QuadPart; -} - -void ListFilesInDirRecursive(const std::string &Dir, long *Epoch, - Vector<std::string> *V, bool TopDir) { - auto E = GetEpoch(Dir); - if (Epoch) - if (E && *Epoch >= E) return; - - std::string Path(Dir); - assert(!Path.empty()); - if (Path.back() != '\\') - Path.push_back('\\'); - Path.push_back('*'); - - // Get the first directory entry. - WIN32_FIND_DATAA FindInfo; - HANDLE FindHandle(FindFirstFileA(Path.c_str(), &FindInfo)); - if (FindHandle == INVALID_HANDLE_VALUE) - { - if (GetLastError() == ERROR_FILE_NOT_FOUND) - return; - Printf("No such file or directory: %s; exiting\n", Dir.c_str()); - exit(1); - } - - do { - std::string FileName = DirPlusFile(Dir, FindInfo.cFileName); - - if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - size_t FilenameLen = strlen(FindInfo.cFileName); - if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') || - (FilenameLen == 2 && FindInfo.cFileName[0] == '.' && - FindInfo.cFileName[1] == '.')) - continue; - - ListFilesInDirRecursive(FileName, Epoch, V, false); - } - else if (IsFile(FileName, FindInfo.dwFileAttributes)) - V->push_back(FileName); - } while (FindNextFileA(FindHandle, &FindInfo)); - - DWORD LastError = GetLastError(); - if (LastError != ERROR_NO_MORE_FILES) - Printf("FindNextFileA failed (Error code: %lu).\n", LastError); - - FindClose(FindHandle); - - if (Epoch && TopDir) - *Epoch = E; -} - -char GetSeparator() { - return '\\'; -} - -FILE* OpenFile(int Fd, const char* Mode) { - return _fdopen(Fd, Mode); -} - -int CloseFile(int Fd) { - return _close(Fd); -} - -int DuplicateFile(int Fd) { - return _dup(Fd); -} - -void RemoveFile(const std::string &Path) { - _unlink(Path.c_str()); -} - -void DiscardOutput(int Fd) { - FILE* Temp = fopen("nul", "w"); - if (!Temp) - return; - _dup2(_fileno(Temp), Fd); - fclose(Temp); -} - -intptr_t GetHandleFromFd(int fd) { - return _get_osfhandle(fd); -} - -static bool IsSeparator(char C) { - return C == '\\' || C == '/'; -} - -// Parse disk designators, like "C:\". If Relative == true, also accepts: "C:". -// Returns number of characters considered if successful. -static size_t ParseDrive(const std::string &FileName, const size_t Offset, - bool Relative = true) { - if (Offset + 1 >= FileName.size() || FileName[Offset + 1] != ':') - return 0; - if (Offset + 2 >= FileName.size() || !IsSeparator(FileName[Offset + 2])) { - if (!Relative) // Accept relative path? - return 0; - else - return 2; - } - return 3; -} - -// Parse a file name, like: SomeFile.txt -// Returns number of characters considered if successful. -static size_t ParseFileName(const std::string &FileName, const size_t Offset) { - size_t Pos = Offset; - const size_t End = FileName.size(); - for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos) - ; - return Pos - Offset; -} - -// Parse a directory ending in separator, like: `SomeDir\` -// Returns number of characters considered if successful. -static size_t ParseDir(const std::string &FileName, const size_t Offset) { - size_t Pos = Offset; - const size_t End = FileName.size(); - if (Pos >= End || IsSeparator(FileName[Pos])) - return 0; - for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos) - ; - if (Pos >= End) - return 0; - ++Pos; // Include separator. - return Pos - Offset; -} - -// Parse a servername and share, like: `SomeServer\SomeShare\` -// Returns number of characters considered if successful. -static size_t ParseServerAndShare(const std::string &FileName, - const size_t Offset) { - size_t Pos = Offset, Res; - if (!(Res = ParseDir(FileName, Pos))) - return 0; - Pos += Res; - if (!(Res = ParseDir(FileName, Pos))) - return 0; - Pos += Res; - return Pos - Offset; -} - -// Parse the given Ref string from the position Offset, to exactly match the given -// string Patt. -// Returns number of characters considered if successful. -static size_t ParseCustomString(const std::string &Ref, size_t Offset, - const char *Patt) { - size_t Len = strlen(Patt); - if (Offset + Len > Ref.size()) - return 0; - return Ref.compare(Offset, Len, Patt) == 0 ? Len : 0; -} - -// Parse a location, like: -// \\?\UNC\Server\Share\ \\?\C:\ \\Server\Share\ \ C:\ C: -// Returns number of characters considered if successful. -static size_t ParseLocation(const std::string &FileName) { - size_t Pos = 0, Res; - - if ((Res = ParseCustomString(FileName, Pos, R"(\\?\)"))) { - Pos += Res; - if ((Res = ParseCustomString(FileName, Pos, R"(UNC\)"))) { - Pos += Res; - if ((Res = ParseServerAndShare(FileName, Pos))) - return Pos + Res; - return 0; - } - if ((Res = ParseDrive(FileName, Pos, false))) - return Pos + Res; - return 0; - } - - if (Pos < FileName.size() && IsSeparator(FileName[Pos])) { - ++Pos; - if (Pos < FileName.size() && IsSeparator(FileName[Pos])) { - ++Pos; - if ((Res = ParseServerAndShare(FileName, Pos))) - return Pos + Res; - return 0; - } - return Pos; - } - - if ((Res = ParseDrive(FileName, Pos))) - return Pos + Res; - - return Pos; -} - -std::string DirName(const std::string &FileName) { - size_t LocationLen = ParseLocation(FileName); - size_t DirLen = 0, Res; - while ((Res = ParseDir(FileName, LocationLen + DirLen))) - DirLen += Res; - size_t FileLen = ParseFileName(FileName, LocationLen + DirLen); - - if (LocationLen + DirLen + FileLen != FileName.size()) { - Printf("DirName() failed for \"%s\", invalid path.\n", FileName.c_str()); - exit(1); - } - - if (DirLen) { - --DirLen; // Remove trailing separator. - if (!FileLen) { // Path ended in separator. - assert(DirLen); - // Remove file name from Dir. - while (DirLen && !IsSeparator(FileName[LocationLen + DirLen - 1])) - --DirLen; - if (DirLen) // Remove trailing separator. - --DirLen; - } - } - - if (!LocationLen) { // Relative path. - if (!DirLen) - return "."; - return std::string(".\\").append(FileName, 0, DirLen); - } - - return FileName.substr(0, LocationLen + DirLen); -} - -std::string TmpDir() { - std::string Tmp; - Tmp.resize(MAX_PATH + 1); - DWORD Size = GetTempPathA(Tmp.size(), &Tmp[0]); - if (Size == 0) { - Printf("Couldn't get Tmp path.\n"); - exit(1); - } - Tmp.resize(Size); - return Tmp; -} - -bool IsInterestingCoverageFile(const std::string &FileName) { - if (FileName.find("Program Files") != std::string::npos) - return false; - if (FileName.find("compiler-rt\\lib\\") != std::string::npos) - return false; // sanitizer internal. - if (FileName == "<null>") - return false; - return true; -} - -void RawPrint(const char *Str) { - // Not tested, may or may not work. Fix if needed. - Printf("%s", Str); -} - -} // namespace fuzzer - -#endif // LIBFUZZER_WINDOWS diff --git a/chromium/third_party/libFuzzer/src/FuzzerInterface.h b/chromium/third_party/libFuzzer/src/FuzzerInterface.h deleted file mode 100644 index 0f7effb2ab6..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerInterface.h +++ /dev/null @@ -1,71 +0,0 @@ -//===- FuzzerInterface.h - Interface header for the Fuzzer ------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Define the interface between libFuzzer and the library being tested. -//===----------------------------------------------------------------------===// - -// NOTE: the libFuzzer interface is thin and in the majority of cases -// you should not include this file into your target. In 95% of cases -// all you need is to define the following function in your file: -// extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); - -// WARNING: keep the interface in C. - -#ifndef LLVM_FUZZER_INTERFACE_H -#define LLVM_FUZZER_INTERFACE_H - -#include <stddef.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -// Mandatory user-provided target function. -// Executes the code under test with [Data, Data+Size) as the input. -// libFuzzer will invoke this function *many* times with different inputs. -// Must return 0. -__attribute__((visibility("default"))) int -LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); - -// Optional user-provided initialization function. -// If provided, this function will be called by libFuzzer once at startup. -// It may read and modify argc/argv. -// Must return 0. -__attribute__((visibility("default"))) int LLVMFuzzerInitialize(int *argc, - char ***argv); - -// Optional user-provided custom mutator. -// Mutates raw data in [Data, Data+Size) inplace. -// Returns the new size, which is not greater than MaxSize. -// Given the same Seed produces the same mutation. -__attribute__((visibility("default"))) size_t -LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, - unsigned int Seed); - -// Optional user-provided custom cross-over function. -// Combines pieces of Data1 & Data2 together into Out. -// Returns the new size, which is not greater than MaxOutSize. -// Should produce the same mutation given the same Seed. -__attribute__((visibility("default"))) size_t -LLVMFuzzerCustomCrossOver(const uint8_t *Data1, size_t Size1, - const uint8_t *Data2, size_t Size2, uint8_t *Out, - size_t MaxOutSize, unsigned int Seed); - -// Experimental, may go away in future. -// libFuzzer-provided function to be used inside LLVMFuzzerCustomMutator. -// Mutates raw data in [Data, Data+Size) inplace. -// Returns the new size, which is not greater than MaxSize. -__attribute__((visibility("default"))) size_t -LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize); - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // LLVM_FUZZER_INTERFACE_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerInternal.h b/chromium/third_party/libFuzzer/src/FuzzerInternal.h deleted file mode 100644 index bfc898248ad..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerInternal.h +++ /dev/null @@ -1,179 +0,0 @@ -//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Define the main class fuzzer::Fuzzer and most functions. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_INTERNAL_H -#define LLVM_FUZZER_INTERNAL_H - -#include "FuzzerDataFlowTrace.h" -#include "FuzzerDefs.h" -#include "FuzzerExtFunctions.h" -#include "FuzzerInterface.h" -#include "FuzzerOptions.h" -#include "FuzzerSHA1.h" -#include "FuzzerValueBitMap.h" -#include <algorithm> -#include <atomic> -#include <chrono> -#include <climits> -#include <cstdlib> -#include <string.h> - -namespace fuzzer { - -using namespace std::chrono; - -class Fuzzer { -public: - - Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, - FuzzingOptions Options); - ~Fuzzer(); - void Loop(const Vector<std::string> &CorpusDirs); - void ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs); - void MinimizeCrashLoop(const Unit &U); - void RereadOutputCorpus(size_t MaxSize); - - size_t secondsSinceProcessStartUp() { - return duration_cast<seconds>(system_clock::now() - ProcessStartTime) - .count(); - } - - bool TimedOut() { - return Options.MaxTotalTimeSec > 0 && - secondsSinceProcessStartUp() > - static_cast<size_t>(Options.MaxTotalTimeSec); - } - - size_t execPerSec() { - size_t Seconds = secondsSinceProcessStartUp(); - return Seconds ? TotalNumberOfRuns / Seconds : 0; - } - - size_t getTotalNumberOfRuns() { return TotalNumberOfRuns; } - - static void StaticAlarmCallback(); - static void StaticCrashSignalCallback(); - static void StaticExitCallback(); - static void StaticInterruptCallback(); - static void StaticFileSizeExceedCallback(); - static void StaticGracefulExitCallback(); - - void ExecuteCallback(const uint8_t *Data, size_t Size); - void CheckForUnstableCounters(const uint8_t *Data, size_t Size); - bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false, - InputInfo *II = nullptr, bool *FoundUniqFeatures = nullptr); - - // Merge Corpora[1:] into Corpora[0]. - void Merge(const Vector<std::string> &Corpora); - void CrashResistantMerge(const Vector<std::string> &Args, - const Vector<std::string> &Corpora, - const char *CoverageSummaryInputPathOrNull, - const char *CoverageSummaryOutputPathOrNull, - const char *MergeControlFilePathOrNull); - void CrashResistantMergeInternalStep(const std::string &ControlFilePath); - MutationDispatcher &GetMD() { return MD; } - void PrintFinalStats(); - void SetMaxInputLen(size_t MaxInputLen); - void SetMaxMutationLen(size_t MaxMutationLen); - void RssLimitCallback(); - - bool InFuzzingThread() const { return IsMyThread; } - size_t GetCurrentUnitInFuzzingThead(const uint8_t **Data) const; - void TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, - bool DuringInitialCorpusExecution); - - void HandleMalloc(size_t Size); - void AnnounceOutput(const uint8_t *Data, size_t Size); - -private: - void AlarmCallback(); - void CrashCallback(); - void ExitCallback(); - void MaybeExitGracefully(); - void CrashOnOverwrittenData(); - void InterruptCallback(); - void MutateAndTestOne(); - void PurgeAllocator(); - void ReportNewCoverage(InputInfo *II, const Unit &U); - void PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size); - void WriteToOutputCorpus(const Unit &U); - void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); - void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0); - void PrintStatusForNewUnit(const Unit &U, const char *Text); - void CheckExitOnSrcPosOrItem(); - - static void StaticDeathCallback(); - void DumpCurrentUnit(const char *Prefix); - void DeathCallback(); - - void AllocateCurrentUnitData(); - uint8_t *CurrentUnitData = nullptr; - std::atomic<size_t> CurrentUnitSize; - uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit. - - bool GracefulExitRequested = false; - - size_t TotalNumberOfRuns = 0; - size_t NumberOfNewUnitsAdded = 0; - - size_t LastCorpusUpdateRun = 0; - - bool HasMoreMallocsThanFrees = false; - size_t NumberOfLeakDetectionAttempts = 0; - - system_clock::time_point LastAllocatorPurgeAttemptTime = system_clock::now(); - - UserCallback CB; - InputCorpus &Corpus; - MutationDispatcher &MD; - FuzzingOptions Options; - DataFlowTrace DFT; - - system_clock::time_point ProcessStartTime = system_clock::now(); - system_clock::time_point UnitStartTime, UnitStopTime; - long TimeOfLongestUnitInSeconds = 0; - long EpochOfLastReadOfOutputCorpus = 0; - - size_t MaxInputLen = 0; - size_t MaxMutationLen = 0; - size_t TmpMaxMutationLen = 0; - - Vector<uint32_t> UniqFeatureSetTmp; - - // Need to know our own thread. - static thread_local bool IsMyThread; -}; - -struct ScopedEnableMsanInterceptorChecks { - ScopedEnableMsanInterceptorChecks() { - if (EF->__msan_scoped_enable_interceptor_checks) - EF->__msan_scoped_enable_interceptor_checks(); - } - ~ScopedEnableMsanInterceptorChecks() { - if (EF->__msan_scoped_disable_interceptor_checks) - EF->__msan_scoped_disable_interceptor_checks(); - } -}; - -struct ScopedDisableMsanInterceptorChecks { - ScopedDisableMsanInterceptorChecks() { - if (EF->__msan_scoped_disable_interceptor_checks) - EF->__msan_scoped_disable_interceptor_checks(); - } - ~ScopedDisableMsanInterceptorChecks() { - if (EF->__msan_scoped_enable_interceptor_checks) - EF->__msan_scoped_enable_interceptor_checks(); - } -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_INTERNAL_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerLoop.cpp b/chromium/third_party/libFuzzer/src/FuzzerLoop.cpp deleted file mode 100644 index 09c57c3f6b7..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerLoop.cpp +++ /dev/null @@ -1,905 +0,0 @@ -//===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Fuzzer's main loop. -//===----------------------------------------------------------------------===// - -#include "FuzzerCorpus.h" -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include "FuzzerMutate.h" -#include "FuzzerRandom.h" -#include "FuzzerShmem.h" -#include "FuzzerTracePC.h" -#include <algorithm> -#include <cstring> -#include <memory> -#include <mutex> -#include <set> - -#if defined(__has_include) -#if __has_include(<sanitizer / lsan_interface.h>) -#include <sanitizer/lsan_interface.h> -#endif -#endif - -#define NO_SANITIZE_MEMORY -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) -#undef NO_SANITIZE_MEMORY -#define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) -#endif -#endif - -namespace fuzzer { -static const size_t kMaxUnitSizeToPrint = 256; - -thread_local bool Fuzzer::IsMyThread; - -SharedMemoryRegion SMR; - -bool RunningUserCallback = false; - -// Only one Fuzzer per process. -static Fuzzer *F; - -// Leak detection is expensive, so we first check if there were more mallocs -// than frees (using the sanitizer malloc hooks) and only then try to call lsan. -struct MallocFreeTracer { - void Start(int TraceLevel) { - this->TraceLevel = TraceLevel; - if (TraceLevel) - Printf("MallocFreeTracer: START\n"); - Mallocs = 0; - Frees = 0; - } - // Returns true if there were more mallocs than frees. - bool Stop() { - if (TraceLevel) - Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(), - Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT"); - bool Result = Mallocs > Frees; - Mallocs = 0; - Frees = 0; - TraceLevel = 0; - return Result; - } - std::atomic<size_t> Mallocs; - std::atomic<size_t> Frees; - int TraceLevel = 0; - - std::recursive_mutex TraceMutex; - bool TraceDisabled = false; -}; - -static MallocFreeTracer AllocTracer; - -// Locks printing and avoids nested hooks triggered from mallocs/frees in -// sanitizer. -class TraceLock { -public: - TraceLock() : Lock(AllocTracer.TraceMutex) { - AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; - } - ~TraceLock() { AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; } - - bool IsDisabled() const { - // This is already inverted value. - return !AllocTracer.TraceDisabled; - } - -private: - std::lock_guard<std::recursive_mutex> Lock; -}; - -ATTRIBUTE_NO_SANITIZE_MEMORY -void MallocHook(const volatile void *ptr, size_t size) { - size_t N = AllocTracer.Mallocs++; - F->HandleMalloc(size); - if (int TraceLevel = AllocTracer.TraceLevel) { - TraceLock Lock; - if (Lock.IsDisabled()) - return; - Printf("MALLOC[%zd] %p %zd\n", N, ptr, size); - if (TraceLevel >= 2 && EF) - PrintStackTrace(); - } -} - -ATTRIBUTE_NO_SANITIZE_MEMORY -void FreeHook(const volatile void *ptr) { - size_t N = AllocTracer.Frees++; - if (int TraceLevel = AllocTracer.TraceLevel) { - TraceLock Lock; - if (Lock.IsDisabled()) - return; - Printf("FREE[%zd] %p\n", N, ptr); - if (TraceLevel >= 2 && EF) - PrintStackTrace(); - } -} - -// Crash on a single malloc that exceeds the rss limit. -void Fuzzer::HandleMalloc(size_t Size) { - if (!Options.MallocLimitMb || (Size >> 20) < (size_t)Options.MallocLimitMb) - return; - Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(), - Size); - Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); - PrintStackTrace(); - DumpCurrentUnit("oom-"); - Printf("SUMMARY: libFuzzer: out-of-memory\n"); - PrintFinalStats(); - _Exit(Options.ErrorExitCode); // Stop right now. -} - -Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, - FuzzingOptions Options) - : CB(CB), Corpus(Corpus), MD(MD), Options(Options) { - if (EF->__sanitizer_set_death_callback) - EF->__sanitizer_set_death_callback(StaticDeathCallback); - assert(!F); - F = this; - TPC.ResetMaps(); - IsMyThread = true; - if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks) - EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook); - TPC.SetUseCounters(Options.UseCounters); - TPC.SetUseValueProfileMask(Options.UseValueProfile); - - if (Options.Verbosity) - TPC.PrintModuleInfo(); - if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec) - EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus); - MaxInputLen = MaxMutationLen = Options.MaxLen; - TmpMaxMutationLen = Max(size_t(4), Corpus.MaxInputSize()); - AllocateCurrentUnitData(); - CurrentUnitSize = 0; - memset(BaseSha1, 0, sizeof(BaseSha1)); - TPC.SetFocusFunction(Options.FocusFunction); - DFT.Init(Options.DataFlowTrace, Options.FocusFunction); -} - -Fuzzer::~Fuzzer() {} - -void Fuzzer::AllocateCurrentUnitData() { - if (CurrentUnitData || MaxInputLen == 0) - return; - CurrentUnitData = new uint8_t[MaxInputLen]; -} - -void Fuzzer::StaticDeathCallback() { - assert(F); - F->DeathCallback(); -} - -void Fuzzer::DumpCurrentUnit(const char *Prefix) { - if (!CurrentUnitData) - return; // Happens when running individual inputs. - ScopedDisableMsanInterceptorChecks S; - MD.PrintMutationSequence(); - Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str()); - size_t UnitSize = CurrentUnitSize; - if (UnitSize <= kMaxUnitSizeToPrint) { - PrintHexArray(CurrentUnitData, UnitSize, "\n"); - PrintASCII(CurrentUnitData, UnitSize, "\n"); - } - WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize}, - Prefix); -} - -NO_SANITIZE_MEMORY -void Fuzzer::DeathCallback() { - DumpCurrentUnit("crash-"); - PrintFinalStats(); -} - -void Fuzzer::StaticAlarmCallback() { - assert(F); - F->AlarmCallback(); -} - -void Fuzzer::StaticCrashSignalCallback() { - assert(F); - F->CrashCallback(); -} - -void Fuzzer::StaticExitCallback() { - assert(F); - F->ExitCallback(); -} - -void Fuzzer::StaticInterruptCallback() { - assert(F); - F->InterruptCallback(); -} - -void Fuzzer::StaticGracefulExitCallback() { - assert(F); - F->GracefulExitRequested = true; - Printf("INFO: signal received, trying to exit gracefully\n"); -} - -void Fuzzer::StaticFileSizeExceedCallback() { - Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid()); - exit(1); -} - -void Fuzzer::CrashCallback() { - if (EF->__sanitizer_acquire_crash_state) - EF->__sanitizer_acquire_crash_state(); - Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid()); - PrintStackTrace(); - Printf("NOTE: libFuzzer has rudimentary signal handlers.\n" - " Combine libFuzzer with AddressSanitizer or similar for better " - "crash reports.\n"); - Printf("SUMMARY: libFuzzer: deadly signal\n"); - DumpCurrentUnit("crash-"); - PrintFinalStats(); - _Exit(Options.ErrorExitCode); // Stop right now. -} - -void Fuzzer::ExitCallback() { - if (!RunningUserCallback) - return; // This exit did not come from the user callback - if (EF->__sanitizer_acquire_crash_state && - !EF->__sanitizer_acquire_crash_state()) - return; - Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid()); - PrintStackTrace(); - Printf("SUMMARY: libFuzzer: fuzz target exited\n"); - DumpCurrentUnit("crash-"); - PrintFinalStats(); - _Exit(Options.ErrorExitCode); -} - -void Fuzzer::MaybeExitGracefully() { - if (!GracefulExitRequested) return; - Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid()); - PrintFinalStats(); - _Exit(0); -} - -void Fuzzer::InterruptCallback() { - Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); - PrintFinalStats(); - _Exit(0); // Stop right now, don't perform any at-exit actions. -} - -NO_SANITIZE_MEMORY -void Fuzzer::AlarmCallback() { - assert(Options.UnitTimeoutSec > 0); - // In Windows Alarm callback is executed by a different thread. - // NetBSD's current behavior needs this change too. -#if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD - if (!InFuzzingThread()) - return; -#endif - if (!RunningUserCallback) - return; // We have not started running units yet. - size_t Seconds = - duration_cast<seconds>(system_clock::now() - UnitStartTime).count(); - if (Seconds == 0) - return; - if (Options.Verbosity >= 2) - Printf("AlarmCallback %zd\n", Seconds); - if (Seconds >= (size_t)Options.UnitTimeoutSec) { - if (EF->__sanitizer_acquire_crash_state && - !EF->__sanitizer_acquire_crash_state()) - return; - Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds); - Printf(" and the timeout value is %d (use -timeout=N to change)\n", - Options.UnitTimeoutSec); - DumpCurrentUnit("timeout-"); - Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(), - Seconds); - PrintStackTrace(); - Printf("SUMMARY: libFuzzer: timeout\n"); - PrintFinalStats(); - _Exit(Options.TimeoutExitCode); // Stop right now. - } -} - -void Fuzzer::RssLimitCallback() { - if (EF->__sanitizer_acquire_crash_state && - !EF->__sanitizer_acquire_crash_state()) - return; - Printf( - "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n", - GetPid(), GetPeakRSSMb(), Options.RssLimitMb); - Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); - PrintMemoryProfile(); - DumpCurrentUnit("oom-"); - Printf("SUMMARY: libFuzzer: out-of-memory\n"); - PrintFinalStats(); - _Exit(Options.ErrorExitCode); // Stop right now. -} - -void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) { - size_t ExecPerSec = execPerSec(); - if (!Options.Verbosity) - return; - Printf("#%zd\t%s", TotalNumberOfRuns, Where); - if (size_t N = TPC.GetTotalPCCoverage()) - Printf(" cov: %zd", N); - if (size_t N = Corpus.NumFeatures()) - Printf(" ft: %zd", N); - if (!Corpus.empty()) { - Printf(" corp: %zd", Corpus.NumActiveUnits()); - if (size_t N = Corpus.SizeInBytes()) { - if (N < (1 << 14)) - Printf("/%zdb", N); - else if (N < (1 << 24)) - Printf("/%zdKb", N >> 10); - else - Printf("/%zdMb", N >> 20); - } - if (size_t FF = Corpus.NumInputsThatTouchFocusFunction()) - Printf(" focus: %zd", FF); - } - if (TmpMaxMutationLen) - Printf(" lim: %zd", TmpMaxMutationLen); - if (Units) - Printf(" units: %zd", Units); - - Printf(" exec/s: %zd", ExecPerSec); - Printf(" rss: %zdMb", GetPeakRSSMb()); - Printf("%s", End); -} - -void Fuzzer::PrintFinalStats() { - if (Options.PrintCoverage) - TPC.PrintCoverage(); - if (Options.PrintUnstableStats) - TPC.PrintUnstableStats(); - if (Options.DumpCoverage) - TPC.DumpCoverage(); - if (Options.PrintCorpusStats) - Corpus.PrintStats(); - if (!Options.PrintFinalStats) - return; - size_t ExecPerSec = execPerSec(); - Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns); - Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec); - Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded); - Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds); - Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); -} - -void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { - assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0. - assert(MaxInputLen); - this->MaxInputLen = MaxInputLen; - this->MaxMutationLen = MaxInputLen; - AllocateCurrentUnitData(); - Printf("INFO: -max_len is not provided; " - "libFuzzer will not generate inputs larger than %zd bytes\n", - MaxInputLen); -} - -void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { - assert(MaxMutationLen && MaxMutationLen <= MaxInputLen); - this->MaxMutationLen = MaxMutationLen; -} - -void Fuzzer::CheckExitOnSrcPosOrItem() { - if (!Options.ExitOnSrcPos.empty()) { - static auto *PCsSet = new Set<uintptr_t>; - auto HandlePC = [&](uintptr_t PC) { - if (!PCsSet->insert(PC).second) - return; - std::string Descr = DescribePC("%F %L", PC + 1); - if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) { - Printf("INFO: found line matching '%s', exiting.\n", - Options.ExitOnSrcPos.c_str()); - _Exit(0); - } - }; - TPC.ForEachObservedPC(HandlePC); - } - if (!Options.ExitOnItem.empty()) { - if (Corpus.HasUnit(Options.ExitOnItem)) { - Printf("INFO: found item with checksum '%s', exiting.\n", - Options.ExitOnItem.c_str()); - _Exit(0); - } - } -} - -void Fuzzer::RereadOutputCorpus(size_t MaxSize) { - if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec) - return; - Vector<Unit> AdditionalCorpus; - ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus, - &EpochOfLastReadOfOutputCorpus, MaxSize, - /*ExitOnError*/ false); - if (Options.Verbosity >= 2) - Printf("Reload: read %zd new units.\n", AdditionalCorpus.size()); - bool Reloaded = false; - for (auto &U : AdditionalCorpus) { - if (U.size() > MaxSize) - U.resize(MaxSize); - if (!Corpus.HasUnit(U)) { - if (RunOne(U.data(), U.size())) { - CheckExitOnSrcPosOrItem(); - Reloaded = true; - } - } - } - if (Reloaded) - PrintStats("RELOAD"); -} - -void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) { - auto TimeOfUnit = - duration_cast<seconds>(UnitStopTime - UnitStartTime).count(); - if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && - secondsSinceProcessStartUp() >= 2) - PrintStats("pulse "); - if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 && - TimeOfUnit >= Options.ReportSlowUnits) { - TimeOfLongestUnitInSeconds = TimeOfUnit; - Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds); - WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-"); - } -} - -void Fuzzer::CheckForUnstableCounters(const uint8_t *Data, size_t Size) { - auto CBSetupAndRun = [&]() { - ScopedEnableMsanInterceptorChecks S; - UnitStartTime = system_clock::now(); - TPC.ResetMaps(); - RunningUserCallback = true; - CB(Data, Size); - RunningUserCallback = false; - UnitStopTime = system_clock::now(); - }; - - // Copy original run counters into our unstable counters - TPC.InitializeUnstableCounters(); - - // First Rerun - CBSetupAndRun(); - if (TPC.UpdateUnstableCounters(Options.HandleUnstable)) { - // Second Rerun - CBSetupAndRun(); - TPC.UpdateAndApplyUnstableCounters(Options.HandleUnstable); - } -} - -bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, - InputInfo *II, bool *FoundUniqFeatures) { - if (!Size) - return false; - - ExecuteCallback(Data, Size); - - UniqFeatureSetTmp.clear(); - size_t FoundUniqFeaturesOfII = 0; - size_t NumUpdatesBefore = Corpus.NumFeatureUpdates(); - bool NewFeaturesUnstable = false; - - if (Options.HandleUnstable || Options.PrintUnstableStats) { - TPC.CollectFeatures([&](size_t Feature) { - if (Corpus.IsFeatureNew(Feature, Size, Options.Shrink)) - NewFeaturesUnstable = true; - }); - if (NewFeaturesUnstable) - CheckForUnstableCounters(Data, Size); - } - - TPC.CollectFeatures([&](size_t Feature) { - if (Corpus.AddFeature(Feature, Size, Options.Shrink)) - UniqFeatureSetTmp.push_back(Feature); - if (Options.ReduceInputs && II) - if (std::binary_search(II->UniqFeatureSet.begin(), - II->UniqFeatureSet.end(), Feature)) - FoundUniqFeaturesOfII++; - }); - - if (FoundUniqFeatures) - *FoundUniqFeatures = FoundUniqFeaturesOfII; - PrintPulseAndReportSlowInput(Data, Size); - size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore; - - if (NumNewFeatures) { - TPC.UpdateObservedPCs(); - Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile, - TPC.ObservedFocusFunction(), UniqFeatureSetTmp, DFT, II); - return true; - } - if (II && FoundUniqFeaturesOfII && - II->DataFlowTraceForFocusFunction.empty() && - FoundUniqFeaturesOfII == II->UniqFeatureSet.size() && - II->U.size() > Size) { - Corpus.Replace(II, {Data, Data + Size}); - return true; - } - return false; -} - -size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const { - assert(InFuzzingThread()); - *Data = CurrentUnitData; - return CurrentUnitSize; -} - -void Fuzzer::CrashOnOverwrittenData() { - Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n", - GetPid()); - DumpCurrentUnit("crash-"); - Printf("SUMMARY: libFuzzer: out-of-memory\n"); - _Exit(Options.ErrorExitCode); // Stop right now. -} - -// Compare two arrays, but not all bytes if the arrays are large. -static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) { - const size_t Limit = 64; - if (Size <= 64) - return !memcmp(A, B, Size); - // Compare first and last Limit/2 bytes. - return !memcmp(A, B, Limit / 2) && - !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2); -} - -void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) { - TPC.RecordInitialStack(); - TotalNumberOfRuns++; - assert(InFuzzingThread()); - if (SMR.IsClient()) - SMR.WriteByteArray(Data, Size); - // We copy the contents of Unit into a separate heap buffer - // so that we reliably find buffer overflows in it. - uint8_t *DataCopy = new uint8_t[Size]; - memcpy(DataCopy, Data, Size); - if (EF->__msan_unpoison) - EF->__msan_unpoison(DataCopy, Size); - if (CurrentUnitData && CurrentUnitData != Data) - memcpy(CurrentUnitData, Data, Size); - CurrentUnitSize = Size; - { - ScopedEnableMsanInterceptorChecks S; - AllocTracer.Start(Options.TraceMalloc); - UnitStartTime = system_clock::now(); - TPC.ResetMaps(); - RunningUserCallback = true; - int Res = CB(DataCopy, Size); - RunningUserCallback = false; - UnitStopTime = system_clock::now(); - (void)Res; - assert(Res == 0); - HasMoreMallocsThanFrees = AllocTracer.Stop(); - } - if (!LooseMemeq(DataCopy, Data, Size)) - CrashOnOverwrittenData(); - CurrentUnitSize = 0; - delete[] DataCopy; -} - -void Fuzzer::WriteToOutputCorpus(const Unit &U) { - if (Options.OnlyASCII) - assert(IsASCII(U)); - if (Options.OutputCorpus.empty()) - return; - std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U)); - WriteToFile(U, Path); - if (Options.Verbosity >= 2) - Printf("Written %zd bytes to %s\n", U.size(), Path.c_str()); -} - -void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { - if (!Options.SaveArtifacts) - return; - std::string Path = Options.ArtifactPrefix + Prefix + Hash(U); - if (!Options.ExactArtifactPath.empty()) - Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix. - WriteToFile(U, Path); - Printf("artifact_prefix='%s'; Test unit written to %s\n", - Options.ArtifactPrefix.c_str(), Path.c_str()); - if (U.size() <= kMaxUnitSizeToPrint) - Printf("Base64: %s\n", Base64(U).c_str()); -} - -void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) { - if (!Options.PrintNEW) - return; - PrintStats(Text, ""); - if (Options.Verbosity) { - Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize()); - MD.PrintMutationSequence(); - Printf("\n"); - } -} - -void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) { - II->NumSuccessfullMutations++; - MD.RecordSuccessfulMutationSequence(); - PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW "); - WriteToOutputCorpus(U); - NumberOfNewUnitsAdded++; - CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus. - LastCorpusUpdateRun = TotalNumberOfRuns; -} - -// Tries detecting a memory leak on the particular input that we have just -// executed before calling this function. -void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, - bool DuringInitialCorpusExecution) { - if (!HasMoreMallocsThanFrees) - return; // mallocs==frees, a leak is unlikely. - if (!Options.DetectLeaks) - return; - if (!DuringInitialCorpusExecution && - TotalNumberOfRuns >= Options.MaxNumberOfRuns) - return; - if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) || - !(EF->__lsan_do_recoverable_leak_check)) - return; // No lsan. - // Run the target once again, but with lsan disabled so that if there is - // a real leak we do not report it twice. - EF->__lsan_disable(); - ExecuteCallback(Data, Size); - EF->__lsan_enable(); - if (!HasMoreMallocsThanFrees) - return; // a leak is unlikely. - if (NumberOfLeakDetectionAttempts++ > 1000) { - Options.DetectLeaks = false; - Printf("INFO: libFuzzer disabled leak detection after every mutation.\n" - " Most likely the target function accumulates allocated\n" - " memory in a global state w/o actually leaking it.\n" - " You may try running this binary with -trace_malloc=[12]" - " to get a trace of mallocs and frees.\n" - " If LeakSanitizer is enabled in this process it will still\n" - " run on the process shutdown.\n"); - return; - } - // Now perform the actual lsan pass. This is expensive and we must ensure - // we don't call it too often. - if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it. - if (DuringInitialCorpusExecution) - Printf("\nINFO: a leak has been found in the initial corpus.\n\n"); - Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n"); - CurrentUnitSize = Size; - DumpCurrentUnit("leak-"); - PrintFinalStats(); - _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on. - } -} - -void Fuzzer::MutateAndTestOne() { - MD.StartMutationSequence(); - - auto &II = Corpus.ChooseUnitToMutate(MD.GetRand()); - const auto &U = II.U; - memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1)); - assert(CurrentUnitData); - size_t Size = U.size(); - assert(Size <= MaxInputLen && "Oversized Unit"); - memcpy(CurrentUnitData, U.data(), Size); - - assert(MaxMutationLen > 0); - - size_t CurrentMaxMutationLen = - Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen)); - assert(CurrentMaxMutationLen > 0); - - for (int i = 0; i < Options.MutateDepth; i++) { - if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) - break; - MaybeExitGracefully(); - size_t NewSize = 0; - if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() && - Size <= CurrentMaxMutationLen) - NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size, - II.DataFlowTraceForFocusFunction); - else - NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen); - assert(NewSize > 0 && "Mutator returned empty unit"); - assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit"); - Size = NewSize; - II.NumExecutedMutations++; - - bool FoundUniqFeatures = false; - bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II, - &FoundUniqFeatures); - TryDetectingAMemoryLeak(CurrentUnitData, Size, - /*DuringInitialCorpusExecution*/ false); - if (NewCov) { - ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size}); - break; // We will mutate this input more in the next rounds. - } - if (Options.ReduceDepth && !FoundUniqFeatures) - break; - } -} - -void Fuzzer::PurgeAllocator() { - if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator) - return; - if (duration_cast<seconds>(system_clock::now() - - LastAllocatorPurgeAttemptTime) - .count() < Options.PurgeAllocatorIntervalSec) - return; - - if (Options.RssLimitMb <= 0 || - GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2) - EF->__sanitizer_purge_allocator(); - - LastAllocatorPurgeAttemptTime = system_clock::now(); -} - -void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) { - const size_t kMaxSaneLen = 1 << 20; - const size_t kMinDefaultLen = 4096; - Vector<SizedFile> SizedFiles; - size_t MaxSize = 0; - size_t MinSize = -1; - size_t TotalSize = 0; - size_t LastNumFiles = 0; - for (auto &Dir : CorpusDirs) { - GetSizedFilesFromDir(Dir, &SizedFiles); - Printf("INFO: % 8zd files found in %s\n", SizedFiles.size() - LastNumFiles, - Dir.c_str()); - LastNumFiles = SizedFiles.size(); - } - for (auto &File : SizedFiles) { - MaxSize = Max(File.Size, MaxSize); - MinSize = Min(File.Size, MinSize); - TotalSize += File.Size; - } - if (Options.MaxLen == 0) - SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen)); - assert(MaxInputLen > 0); - - // Test the callback with empty input and never try it again. - uint8_t dummy = 0; - ExecuteCallback(&dummy, 0); - - if (SizedFiles.empty()) { - Printf("INFO: A corpus is not provided, starting from an empty corpus\n"); - Unit U({'\n'}); // Valid ASCII input. - RunOne(U.data(), U.size()); - } else { - Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb" - " rss: %zdMb\n", - SizedFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb()); - if (Options.ShuffleAtStartUp) - std::shuffle(SizedFiles.begin(), SizedFiles.end(), MD.GetRand()); - - if (Options.PreferSmall) { - std::stable_sort(SizedFiles.begin(), SizedFiles.end()); - assert(SizedFiles.front().Size <= SizedFiles.back().Size); - } - - // Load and execute inputs one by one. - for (auto &SF : SizedFiles) { - auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false); - assert(U.size() <= MaxInputLen); - RunOne(U.data(), U.size()); - CheckExitOnSrcPosOrItem(); - TryDetectingAMemoryLeak(U.data(), U.size(), - /*DuringInitialCorpusExecution*/ true); - } - } - - PrintStats("INITED"); - if (!Options.FocusFunction.empty()) - Printf("INFO: %zd/%zd inputs touch the focus function\n", - Corpus.NumInputsThatTouchFocusFunction(), Corpus.size()); - if (!Options.DataFlowTrace.empty()) - Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n", - Corpus.NumInputsWithDataFlowTrace(), Corpus.size()); - - if (Corpus.empty() && Options.MaxNumberOfRuns) { - Printf("ERROR: no interesting inputs were found. " - "Is the code instrumented for coverage? Exiting.\n"); - exit(1); - } -} - -void Fuzzer::Loop(const Vector<std::string> &CorpusDirs) { - ReadAndExecuteSeedCorpora(CorpusDirs); - DFT.Clear(); // No need for DFT any more. - TPC.SetPrintNewPCs(Options.PrintNewCovPcs); - TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs); - system_clock::time_point LastCorpusReload = system_clock::now(); - if (Options.DoCrossOver) - MD.SetCorpus(&Corpus); - while (true) { - auto Now = system_clock::now(); - if (duration_cast<seconds>(Now - LastCorpusReload).count() >= - Options.ReloadIntervalSec) { - RereadOutputCorpus(MaxInputLen); - LastCorpusReload = system_clock::now(); - } - if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) - break; - if (TimedOut()) - break; - - // Update TmpMaxMutationLen - if (Options.LenControl) { - if (TmpMaxMutationLen < MaxMutationLen && - TotalNumberOfRuns - LastCorpusUpdateRun > - Options.LenControl * Log(TmpMaxMutationLen)) { - TmpMaxMutationLen = - Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen)); - LastCorpusUpdateRun = TotalNumberOfRuns; - } - } else { - TmpMaxMutationLen = MaxMutationLen; - } - - // Perform several mutations and runs. - MutateAndTestOne(); - - PurgeAllocator(); - } - - PrintStats("DONE ", "\n"); - MD.PrintRecommendedDictionary(); -} - -void Fuzzer::MinimizeCrashLoop(const Unit &U) { - if (U.size() <= 1) - return; - while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) { - MD.StartMutationSequence(); - memcpy(CurrentUnitData, U.data(), U.size()); - for (int i = 0; i < Options.MutateDepth; i++) { - size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen); - assert(NewSize > 0 && NewSize <= MaxMutationLen); - ExecuteCallback(CurrentUnitData, NewSize); - PrintPulseAndReportSlowInput(CurrentUnitData, NewSize); - TryDetectingAMemoryLeak(CurrentUnitData, NewSize, - /*DuringInitialCorpusExecution*/ false); - } - } -} - -void Fuzzer::AnnounceOutput(const uint8_t *Data, size_t Size) { - if (SMR.IsServer()) { - SMR.WriteByteArray(Data, Size); - } else if (SMR.IsClient()) { - SMR.PostClient(); - SMR.WaitServer(); - size_t OtherSize = SMR.ReadByteArraySize(); - uint8_t *OtherData = SMR.GetByteArray(); - if (Size != OtherSize || memcmp(Data, OtherData, Size) != 0) { - size_t i = 0; - for (i = 0; i < Min(Size, OtherSize); i++) - if (Data[i] != OtherData[i]) - break; - Printf("==%lu== ERROR: libFuzzer: equivalence-mismatch. Sizes: %zd %zd; " - "offset %zd\n", - GetPid(), Size, OtherSize, i); - DumpCurrentUnit("mismatch-"); - Printf("SUMMARY: libFuzzer: equivalence-mismatch\n"); - PrintFinalStats(); - _Exit(Options.ErrorExitCode); - } - } -} - -} // namespace fuzzer - -extern "C" { - -__attribute__((visibility("default"))) size_t -LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { - assert(fuzzer::F); - return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize); -} - -// Experimental -__attribute__((visibility("default"))) void -LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) { - assert(fuzzer::F); - fuzzer::F->AnnounceOutput(Data, Size); -} -} // extern "C" diff --git a/chromium/third_party/libFuzzer/src/FuzzerMain.cpp b/chromium/third_party/libFuzzer/src/FuzzerMain.cpp deleted file mode 100644 index f2c8e9c7bb1..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerMain.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===- FuzzerMain.cpp - main() function and flags -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// main() and flags. -//===----------------------------------------------------------------------===// - -#include "FuzzerDefs.h" - -extern "C" { -// This function should be defined by the user. -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); -} // extern "C" - -__attribute__((visibility("default"))) int main(int argc, char **argv) { - return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput); -} diff --git a/chromium/third_party/libFuzzer/src/FuzzerMerge.cpp b/chromium/third_party/libFuzzer/src/FuzzerMerge.cpp deleted file mode 100644 index 5f3052a39c1..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerMerge.cpp +++ /dev/null @@ -1,390 +0,0 @@ -//===- FuzzerMerge.cpp - merging corpora ----------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Merging corpora. -//===----------------------------------------------------------------------===// - -#include "FuzzerCommand.h" -#include "FuzzerMerge.h" -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include "FuzzerTracePC.h" -#include "FuzzerUtil.h" - -#include <fstream> -#include <iterator> -#include <set> -#include <sstream> - -namespace fuzzer { - -bool Merger::Parse(const std::string &Str, bool ParseCoverage) { - std::istringstream SS(Str); - return Parse(SS, ParseCoverage); -} - -void Merger::ParseOrExit(std::istream &IS, bool ParseCoverage) { - if (!Parse(IS, ParseCoverage)) { - Printf("MERGE: failed to parse the control file (unexpected error)\n"); - exit(1); - } -} - -// The control file example: -// -// 3 # The number of inputs -// 1 # The number of inputs in the first corpus, <= the previous number -// file0 -// file1 -// file2 # One file name per line. -// STARTED 0 123 # FileID, file size -// DONE 0 1 4 6 8 # FileID COV1 COV2 ... -// STARTED 1 456 # If DONE is missing, the input crashed while processing. -// STARTED 2 567 -// DONE 2 8 9 -bool Merger::Parse(std::istream &IS, bool ParseCoverage) { - LastFailure.clear(); - std::string Line; - - // Parse NumFiles. - if (!std::getline(IS, Line, '\n')) return false; - std::istringstream L1(Line); - size_t NumFiles = 0; - L1 >> NumFiles; - if (NumFiles == 0 || NumFiles > 10000000) return false; - - // Parse NumFilesInFirstCorpus. - if (!std::getline(IS, Line, '\n')) return false; - std::istringstream L2(Line); - NumFilesInFirstCorpus = NumFiles + 1; - L2 >> NumFilesInFirstCorpus; - if (NumFilesInFirstCorpus > NumFiles) return false; - - // Parse file names. - Files.resize(NumFiles); - for (size_t i = 0; i < NumFiles; i++) - if (!std::getline(IS, Files[i].Name, '\n')) - return false; - - // Parse STARTED and DONE lines. - size_t ExpectedStartMarker = 0; - const size_t kInvalidStartMarker = -1; - size_t LastSeenStartMarker = kInvalidStartMarker; - Vector<uint32_t> TmpFeatures; - while (std::getline(IS, Line, '\n')) { - std::istringstream ISS1(Line); - std::string Marker; - size_t N; - ISS1 >> Marker; - ISS1 >> N; - if (Marker == "STARTED") { - // STARTED FILE_ID FILE_SIZE - if (ExpectedStartMarker != N) - return false; - ISS1 >> Files[ExpectedStartMarker].Size; - LastSeenStartMarker = ExpectedStartMarker; - assert(ExpectedStartMarker < Files.size()); - ExpectedStartMarker++; - } else if (Marker == "DONE") { - // DONE FILE_ID COV1 COV2 COV3 ... - size_t CurrentFileIdx = N; - if (CurrentFileIdx != LastSeenStartMarker) - return false; - LastSeenStartMarker = kInvalidStartMarker; - if (ParseCoverage) { - TmpFeatures.clear(); // use a vector from outer scope to avoid resizes. - while (ISS1 >> std::hex >> N) - TmpFeatures.push_back(N); - std::sort(TmpFeatures.begin(), TmpFeatures.end()); - Files[CurrentFileIdx].Features = TmpFeatures; - } - } else { - return false; - } - } - if (LastSeenStartMarker != kInvalidStartMarker) - LastFailure = Files[LastSeenStartMarker].Name; - - FirstNotProcessedFile = ExpectedStartMarker; - return true; -} - -size_t Merger::ApproximateMemoryConsumption() const { - size_t Res = 0; - for (const auto &F: Files) - Res += sizeof(F) + F.Features.size() * sizeof(F.Features[0]); - return Res; -} - -// Decides which files need to be merged (add thost to NewFiles). -// Returns the number of new features added. -size_t Merger::Merge(const Set<uint32_t> &InitialFeatures, - Vector<std::string> *NewFiles) { - NewFiles->clear(); - assert(NumFilesInFirstCorpus <= Files.size()); - Set<uint32_t> AllFeatures(InitialFeatures); - - // What features are in the initial corpus? - for (size_t i = 0; i < NumFilesInFirstCorpus; i++) { - auto &Cur = Files[i].Features; - AllFeatures.insert(Cur.begin(), Cur.end()); - } - size_t InitialNumFeatures = AllFeatures.size(); - - // Remove all features that we already know from all other inputs. - for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) { - auto &Cur = Files[i].Features; - Vector<uint32_t> Tmp; - std::set_difference(Cur.begin(), Cur.end(), AllFeatures.begin(), - AllFeatures.end(), std::inserter(Tmp, Tmp.begin())); - Cur.swap(Tmp); - } - - // Sort. Give preference to - // * smaller files - // * files with more features. - std::sort(Files.begin() + NumFilesInFirstCorpus, Files.end(), - [&](const MergeFileInfo &a, const MergeFileInfo &b) -> bool { - if (a.Size != b.Size) - return a.Size < b.Size; - return a.Features.size() > b.Features.size(); - }); - - // One greedy pass: add the file's features to AllFeatures. - // If new features were added, add this file to NewFiles. - for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) { - auto &Cur = Files[i].Features; - // Printf("%s -> sz %zd ft %zd\n", Files[i].Name.c_str(), - // Files[i].Size, Cur.size()); - size_t OldSize = AllFeatures.size(); - AllFeatures.insert(Cur.begin(), Cur.end()); - if (AllFeatures.size() > OldSize) - NewFiles->push_back(Files[i].Name); - } - return AllFeatures.size() - InitialNumFeatures; -} - -void Merger::PrintSummary(std::ostream &OS) { - for (auto &File : Files) { - OS << std::hex; - OS << File.Name << " size: " << File.Size << " features: "; - for (auto Feature : File.Features) - OS << " " << Feature; - OS << "\n"; - } -} - -Set<uint32_t> Merger::AllFeatures() const { - Set<uint32_t> S; - for (auto &File : Files) - S.insert(File.Features.begin(), File.Features.end()); - return S; -} - -Set<uint32_t> Merger::ParseSummary(std::istream &IS) { - std::string Line, Tmp; - Set<uint32_t> Res; - while (std::getline(IS, Line, '\n')) { - size_t N; - std::istringstream ISS1(Line); - ISS1 >> Tmp; // Name - ISS1 >> Tmp; // size: - assert(Tmp == "size:" && "Corrupt summary file"); - ISS1 >> std::hex; - ISS1 >> N; // File Size - ISS1 >> Tmp; // features: - assert(Tmp == "features:" && "Corrupt summary file"); - while (ISS1 >> std::hex >> N) - Res.insert(N); - } - return Res; -} - -// Inner process. May crash if the target crashes. -void Fuzzer::CrashResistantMergeInternalStep(const std::string &CFPath) { - Printf("MERGE-INNER: using the control file '%s'\n", CFPath.c_str()); - Merger M; - std::ifstream IF(CFPath); - M.ParseOrExit(IF, false); - IF.close(); - if (!M.LastFailure.empty()) - Printf("MERGE-INNER: '%s' caused a failure at the previous merge step\n", - M.LastFailure.c_str()); - - Printf("MERGE-INNER: %zd total files;" - " %zd processed earlier; will process %zd files now\n", - M.Files.size(), M.FirstNotProcessedFile, - M.Files.size() - M.FirstNotProcessedFile); - - std::ofstream OF(CFPath, std::ofstream::out | std::ofstream::app); - Set<size_t> AllFeatures; - for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) { - MaybeExitGracefully(); - auto U = FileToVector(M.Files[i].Name); - if (U.size() > MaxInputLen) { - U.resize(MaxInputLen); - U.shrink_to_fit(); - } - std::ostringstream StartedLine; - // Write the pre-run marker. - OF << "STARTED " << std::dec << i << " " << U.size() << "\n"; - OF.flush(); // Flush is important since Command::Execute may crash. - // Run. - TPC.ResetMaps(); - ExecuteCallback(U.data(), U.size()); - // Collect coverage. We are iterating over the files in this order: - // * First, files in the initial corpus ordered by size, smallest first. - // * Then, all other files, smallest first. - // So it makes no sense to record all features for all files, instead we - // only record features that were not seen before. - Set<size_t> UniqFeatures; - TPC.CollectFeatures([&](size_t Feature) { - if (AllFeatures.insert(Feature).second) - UniqFeatures.insert(Feature); - }); - // Show stats. - if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1))) - PrintStats("pulse "); - // Write the post-run marker and the coverage. - OF << "DONE " << i; - for (size_t F : UniqFeatures) - OF << " " << std::hex << F; - OF << "\n"; - OF.flush(); - } -} - -static void WriteNewControlFile(const std::string &CFPath, - const Vector<SizedFile> &AllFiles, - size_t NumFilesInFirstCorpus) { - RemoveFile(CFPath); - std::ofstream ControlFile(CFPath); - ControlFile << AllFiles.size() << "\n"; - ControlFile << NumFilesInFirstCorpus << "\n"; - for (auto &SF: AllFiles) - ControlFile << SF.File << "\n"; - if (!ControlFile) { - Printf("MERGE-OUTER: failed to write to the control file: %s\n", - CFPath.c_str()); - exit(1); - } -} - -// Outer process. Does not call the target code and thus sohuld not fail. -void Fuzzer::CrashResistantMerge(const Vector<std::string> &Args, - const Vector<std::string> &Corpora, - const char *CoverageSummaryInputPathOrNull, - const char *CoverageSummaryOutputPathOrNull, - const char *MergeControlFilePathOrNull) { - if (Corpora.size() <= 1) { - Printf("Merge requires two or more corpus dirs\n"); - return; - } - auto CFPath = - MergeControlFilePathOrNull - ? MergeControlFilePathOrNull - : DirPlusFile(TmpDir(), - "libFuzzerTemp." + std::to_string(GetPid()) + ".txt"); - - size_t NumAttempts = 0; - if (MergeControlFilePathOrNull && FileSize(MergeControlFilePathOrNull)) { - Printf("MERGE-OUTER: non-empty control file provided: '%s'\n", - MergeControlFilePathOrNull); - Merger M; - std::ifstream IF(MergeControlFilePathOrNull); - if (M.Parse(IF, /*ParseCoverage=*/false)) { - Printf("MERGE-OUTER: control file ok, %zd files total," - " first not processed file %zd\n", - M.Files.size(), M.FirstNotProcessedFile); - if (!M.LastFailure.empty()) - Printf("MERGE-OUTER: '%s' will be skipped as unlucky " - "(merge has stumbled on it the last time)\n", - M.LastFailure.c_str()); - if (M.FirstNotProcessedFile >= M.Files.size()) { - Printf("MERGE-OUTER: nothing to do, merge has been completed before\n"); - exit(0); - } - - NumAttempts = M.Files.size() - M.FirstNotProcessedFile; - } else { - Printf("MERGE-OUTER: bad control file, will overwrite it\n"); - } - } - - if (!NumAttempts) { - // The supplied control file is empty or bad, create a fresh one. - Vector<SizedFile> AllFiles; - GetSizedFilesFromDir(Corpora[0], &AllFiles); - size_t NumFilesInFirstCorpus = AllFiles.size(); - std::sort(AllFiles.begin(), AllFiles.end()); - for (size_t i = 1; i < Corpora.size(); i++) - GetSizedFilesFromDir(Corpora[i], &AllFiles); - std::sort(AllFiles.begin() + NumFilesInFirstCorpus, AllFiles.end()); - Printf("MERGE-OUTER: %zd files, %zd in the initial corpus\n", - AllFiles.size(), NumFilesInFirstCorpus); - WriteNewControlFile(CFPath, AllFiles, NumFilesInFirstCorpus); - NumAttempts = AllFiles.size(); - } - - // Execute the inner process until it passes. - // Every inner process should execute at least one input. - Command BaseCmd(Args); - BaseCmd.removeFlag("merge"); - bool Success = false; - for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) { - MaybeExitGracefully(); - Printf("MERGE-OUTER: attempt %zd\n", Attempt); - Command Cmd(BaseCmd); - Cmd.addFlag("merge_control_file", CFPath); - Cmd.addFlag("merge_inner", "1"); - auto ExitCode = ExecuteCommand(Cmd); - if (!ExitCode) { - Printf("MERGE-OUTER: succesfull in %zd attempt(s)\n", Attempt); - Success = true; - break; - } - } - if (!Success) { - Printf("MERGE-OUTER: zero succesfull attempts, exiting\n"); - exit(1); - } - // Read the control file and do the merge. - Merger M; - std::ifstream IF(CFPath); - IF.seekg(0, IF.end); - Printf("MERGE-OUTER: the control file has %zd bytes\n", (size_t)IF.tellg()); - IF.seekg(0, IF.beg); - M.ParseOrExit(IF, true); - IF.close(); - Printf("MERGE-OUTER: consumed %zdMb (%zdMb rss) to parse the control file\n", - M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb()); - if (CoverageSummaryOutputPathOrNull) { - Printf("MERGE-OUTER: writing coverage summary for %zd files to %s\n", - M.Files.size(), CoverageSummaryOutputPathOrNull); - std::ofstream SummaryOut(CoverageSummaryOutputPathOrNull); - M.PrintSummary(SummaryOut); - } - Vector<std::string> NewFiles; - Set<uint32_t> InitialFeatures; - if (CoverageSummaryInputPathOrNull) { - std::ifstream SummaryIn(CoverageSummaryInputPathOrNull); - InitialFeatures = M.ParseSummary(SummaryIn); - Printf("MERGE-OUTER: coverage summary loaded from %s, %zd features found\n", - CoverageSummaryInputPathOrNull, InitialFeatures.size()); - } - size_t NumNewFeatures = M.Merge(InitialFeatures, &NewFiles); - Printf("MERGE-OUTER: %zd new files with %zd new features added\n", - NewFiles.size(), NumNewFeatures); - for (auto &F: NewFiles) - WriteToOutputCorpus(FileToVector(F, MaxInputLen)); - // We are done, delete the control file if it was a temporary one. - if (!MergeControlFilePathOrNull) - RemoveFile(CFPath); -} - -} // namespace fuzzer diff --git a/chromium/third_party/libFuzzer/src/FuzzerMerge.h b/chromium/third_party/libFuzzer/src/FuzzerMerge.h deleted file mode 100644 index e54885a1eba..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerMerge.h +++ /dev/null @@ -1,80 +0,0 @@ -//===- FuzzerMerge.h - merging corpa ----------------------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Merging Corpora. -// -// The task: -// Take the existing corpus (possibly empty) and merge new inputs into -// it so that only inputs with new coverage ('features') are added. -// The process should tolerate the crashes, OOMs, leaks, etc. -// -// Algorithm: -// The outter process collects the set of files and writes their names -// into a temporary "control" file, then repeatedly launches the inner -// process until all inputs are processed. -// The outer process does not actually execute the target code. -// -// The inner process reads the control file and sees a) list of all the inputs -// and b) the last processed input. Then it starts processing the inputs one -// by one. Before processing every input it writes one line to control file: -// STARTED INPUT_ID INPUT_SIZE -// After processing an input it write another line: -// DONE INPUT_ID Feature1 Feature2 Feature3 ... -// If a crash happens while processing an input the last line in the control -// file will be "STARTED INPUT_ID" and so the next process will know -// where to resume. -// -// Once all inputs are processed by the innner process(es) the outer process -// reads the control files and does the merge based entirely on the contents -// of control file. -// It uses a single pass greedy algorithm choosing first the smallest inputs -// within the same size the inputs that have more new features. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_MERGE_H -#define LLVM_FUZZER_MERGE_H - -#include "FuzzerDefs.h" - -#include <istream> -#include <ostream> -#include <set> -#include <vector> - -namespace fuzzer { - -struct MergeFileInfo { - std::string Name; - size_t Size = 0; - Vector<uint32_t> Features; -}; - -struct Merger { - Vector<MergeFileInfo> Files; - size_t NumFilesInFirstCorpus = 0; - size_t FirstNotProcessedFile = 0; - std::string LastFailure; - - bool Parse(std::istream &IS, bool ParseCoverage); - bool Parse(const std::string &Str, bool ParseCoverage); - void ParseOrExit(std::istream &IS, bool ParseCoverage); - void PrintSummary(std::ostream &OS); - Set<uint32_t> ParseSummary(std::istream &IS); - size_t Merge(const Set<uint32_t> &InitialFeatures, - Vector<std::string> *NewFiles); - size_t Merge(Vector<std::string> *NewFiles) { - return Merge(Set<uint32_t>{}, NewFiles); - } - size_t ApproximateMemoryConsumption() const; - Set<uint32_t> AllFeatures() const; -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_MERGE_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerMutate.cpp b/chromium/third_party/libFuzzer/src/FuzzerMutate.cpp deleted file mode 100644 index 142b2b0b001..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerMutate.cpp +++ /dev/null @@ -1,562 +0,0 @@ -//===- FuzzerMutate.cpp - Mutate a test input -----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Mutate a test input. -//===----------------------------------------------------------------------===// - -#include "FuzzerMutate.h" -#include "FuzzerCorpus.h" -#include "FuzzerDefs.h" -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" -#include "FuzzerOptions.h" - -namespace fuzzer { - -const size_t Dictionary::kMaxDictSize; - -static void PrintASCII(const Word &W, const char *PrintAfter) { - PrintASCII(W.data(), W.size(), PrintAfter); -} - -MutationDispatcher::MutationDispatcher(Random &Rand, - const FuzzingOptions &Options) - : Rand(Rand), Options(Options) { - DefaultMutators.insert( - DefaultMutators.begin(), - { - {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"}, - {&MutationDispatcher::Mutate_InsertByte, "InsertByte"}, - {&MutationDispatcher::Mutate_InsertRepeatedBytes, - "InsertRepeatedBytes"}, - {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"}, - {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"}, - {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"}, - {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"}, - {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"}, - {&MutationDispatcher::Mutate_CopyPart, "CopyPart"}, - {&MutationDispatcher::Mutate_CrossOver, "CrossOver"}, - {&MutationDispatcher::Mutate_AddWordFromManualDictionary, - "ManualDict"}, - {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary, - "PersAutoDict"}, - }); - if(Options.UseCmp) - DefaultMutators.push_back( - {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"}); - - if (EF->LLVMFuzzerCustomMutator) - Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"}); - else - Mutators = DefaultMutators; - - if (EF->LLVMFuzzerCustomCrossOver) - Mutators.push_back( - {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"}); -} - -static char RandCh(Random &Rand) { - if (Rand.RandBool()) return Rand(256); - const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00"; - return Special[Rand(sizeof(Special) - 1)]; -} - -size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size, - size_t MaxSize) { - return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand()); -} - -size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size, - size_t MaxSize) { - if (!Corpus || Corpus->size() < 2 || Size == 0) - return 0; - size_t Idx = Rand(Corpus->size()); - const Unit &Other = (*Corpus)[Idx]; - if (Other.empty()) - return 0; - CustomCrossOverInPlaceHere.resize(MaxSize); - auto &U = CustomCrossOverInPlaceHere; - size_t NewSize = EF->LLVMFuzzerCustomCrossOver( - Data, Size, Other.data(), Other.size(), U.data(), U.size(), Rand.Rand()); - if (!NewSize) - return 0; - assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit"); - memcpy(Data, U.data(), NewSize); - return NewSize; -} - -size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size, - size_t MaxSize) { - if (Size > MaxSize || Size == 0) return 0; - size_t ShuffleAmount = - Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size. - size_t ShuffleStart = Rand(Size - ShuffleAmount); - assert(ShuffleStart + ShuffleAmount <= Size); - std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand); - return Size; -} - -size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size, - size_t MaxSize) { - if (Size <= 1) return 0; - size_t N = Rand(Size / 2) + 1; - assert(N < Size); - size_t Idx = Rand(Size - N + 1); - // Erase Data[Idx:Idx+N]. - memmove(Data + Idx, Data + Idx + N, Size - Idx - N); - // Printf("Erase: %zd %zd => %zd; Idx %zd\n", N, Size, Size - N, Idx); - return Size - N; -} - -size_t MutationDispatcher::Mutate_InsertByte(uint8_t *Data, size_t Size, - size_t MaxSize) { - if (Size >= MaxSize) return 0; - size_t Idx = Rand(Size + 1); - // Insert new value at Data[Idx]. - memmove(Data + Idx + 1, Data + Idx, Size - Idx); - Data[Idx] = RandCh(Rand); - return Size + 1; -} - -size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data, - size_t Size, - size_t MaxSize) { - const size_t kMinBytesToInsert = 3; - if (Size + kMinBytesToInsert >= MaxSize) return 0; - size_t MaxBytesToInsert = std::min(MaxSize - Size, (size_t)128); - size_t N = Rand(MaxBytesToInsert - kMinBytesToInsert + 1) + kMinBytesToInsert; - assert(Size + N <= MaxSize && N); - size_t Idx = Rand(Size + 1); - // Insert new values at Data[Idx]. - memmove(Data + Idx + N, Data + Idx, Size - Idx); - // Give preference to 0x00 and 0xff. - uint8_t Byte = Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255); - for (size_t i = 0; i < N; i++) - Data[Idx + i] = Byte; - return Size + N; -} - -size_t MutationDispatcher::Mutate_ChangeByte(uint8_t *Data, size_t Size, - size_t MaxSize) { - if (Size > MaxSize) return 0; - size_t Idx = Rand(Size); - Data[Idx] = RandCh(Rand); - return Size; -} - -size_t MutationDispatcher::Mutate_ChangeBit(uint8_t *Data, size_t Size, - size_t MaxSize) { - if (Size > MaxSize) return 0; - size_t Idx = Rand(Size); - Data[Idx] ^= 1 << Rand(8); - return Size; -} - -size_t MutationDispatcher::Mutate_AddWordFromManualDictionary(uint8_t *Data, - size_t Size, - size_t MaxSize) { - return AddWordFromDictionary(ManualDictionary, Data, Size, MaxSize); -} - -size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size, - size_t MaxSize, - DictionaryEntry &DE) { - const Word &W = DE.GetW(); - bool UsePositionHint = DE.HasPositionHint() && - DE.GetPositionHint() + W.size() < Size && - Rand.RandBool(); - if (Rand.RandBool()) { // Insert W. - if (Size + W.size() > MaxSize) return 0; - size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1); - memmove(Data + Idx + W.size(), Data + Idx, Size - Idx); - memcpy(Data + Idx, W.data(), W.size()); - Size += W.size(); - } else { // Overwrite some bytes with W. - if (W.size() > Size) return 0; - size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size - W.size()); - memcpy(Data + Idx, W.data(), W.size()); - } - return Size; -} - -// Somewhere in the past we have observed a comparison instructions -// with arguments Arg1 Arg2. This function tries to guess a dictionary -// entry that will satisfy that comparison. -// It first tries to find one of the arguments (possibly swapped) in the -// input and if it succeeds it creates a DE with a position hint. -// Otherwise it creates a DE with one of the arguments w/o a position hint. -DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( - const void *Arg1, const void *Arg2, - const void *Arg1Mutation, const void *Arg2Mutation, - size_t ArgSize, const uint8_t *Data, - size_t Size) { - bool HandleFirst = Rand.RandBool(); - const void *ExistingBytes, *DesiredBytes; - Word W; - const uint8_t *End = Data + Size; - for (int Arg = 0; Arg < 2; Arg++) { - ExistingBytes = HandleFirst ? Arg1 : Arg2; - DesiredBytes = HandleFirst ? Arg2Mutation : Arg1Mutation; - HandleFirst = !HandleFirst; - W.Set(reinterpret_cast<const uint8_t*>(DesiredBytes), ArgSize); - const size_t kMaxNumPositions = 8; - size_t Positions[kMaxNumPositions]; - size_t NumPositions = 0; - for (const uint8_t *Cur = Data; - Cur < End && NumPositions < kMaxNumPositions; Cur++) { - Cur = - (const uint8_t *)SearchMemory(Cur, End - Cur, ExistingBytes, ArgSize); - if (!Cur) break; - Positions[NumPositions++] = Cur - Data; - } - if (!NumPositions) continue; - return DictionaryEntry(W, Positions[Rand(NumPositions)]); - } - DictionaryEntry DE(W); - return DE; -} - - -template <class T> -DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( - T Arg1, T Arg2, const uint8_t *Data, size_t Size) { - if (Rand.RandBool()) Arg1 = Bswap(Arg1); - if (Rand.RandBool()) Arg2 = Bswap(Arg2); - T Arg1Mutation = Arg1 + Rand(-1, 1); - T Arg2Mutation = Arg2 + Rand(-1, 1); - return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation, - sizeof(Arg1), Data, Size); -} - -DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP( - const Word &Arg1, const Word &Arg2, const uint8_t *Data, size_t Size) { - return MakeDictionaryEntryFromCMP(Arg1.data(), Arg2.data(), Arg1.data(), - Arg2.data(), Arg1.size(), Data, Size); -} - -size_t MutationDispatcher::Mutate_AddWordFromTORC( - uint8_t *Data, size_t Size, size_t MaxSize) { - Word W; - DictionaryEntry DE; - switch (Rand(4)) { - case 0: { - auto X = TPC.TORC8.Get(Rand.Rand()); - DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); - } break; - case 1: { - auto X = TPC.TORC4.Get(Rand.Rand()); - if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool()) - DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size); - else - DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); - } break; - case 2: { - auto X = TPC.TORCW.Get(Rand.Rand()); - DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size); - } break; - case 3: if (Options.UseMemmem) { - auto X = TPC.MMT.Get(Rand.Rand()); - DE = DictionaryEntry(X); - } break; - default: - assert(0); - } - if (!DE.GetW().size()) return 0; - Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE); - if (!Size) return 0; - DictionaryEntry &DERef = - CmpDictionaryEntriesDeque[CmpDictionaryEntriesDequeIdx++ % - kCmpDictionaryEntriesDequeSize]; - DERef = DE; - CurrentDictionaryEntrySequence.push_back(&DERef); - return Size; -} - -size_t MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary( - uint8_t *Data, size_t Size, size_t MaxSize) { - return AddWordFromDictionary(PersistentAutoDictionary, Data, Size, MaxSize); -} - -size_t MutationDispatcher::AddWordFromDictionary(Dictionary &D, uint8_t *Data, - size_t Size, size_t MaxSize) { - if (Size > MaxSize) return 0; - if (D.empty()) return 0; - DictionaryEntry &DE = D[Rand(D.size())]; - Size = ApplyDictionaryEntry(Data, Size, MaxSize, DE); - if (!Size) return 0; - DE.IncUseCount(); - CurrentDictionaryEntrySequence.push_back(&DE); - return Size; -} - -// Overwrites part of To[0,ToSize) with a part of From[0,FromSize). -// Returns ToSize. -size_t MutationDispatcher::CopyPartOf(const uint8_t *From, size_t FromSize, - uint8_t *To, size_t ToSize) { - // Copy From[FromBeg, FromBeg + CopySize) into To[ToBeg, ToBeg + CopySize). - size_t ToBeg = Rand(ToSize); - size_t CopySize = Rand(ToSize - ToBeg) + 1; - assert(ToBeg + CopySize <= ToSize); - CopySize = std::min(CopySize, FromSize); - size_t FromBeg = Rand(FromSize - CopySize + 1); - assert(FromBeg + CopySize <= FromSize); - memmove(To + ToBeg, From + FromBeg, CopySize); - return ToSize; -} - -// Inserts part of From[0,ToSize) into To. -// Returns new size of To on success or 0 on failure. -size_t MutationDispatcher::InsertPartOf(const uint8_t *From, size_t FromSize, - uint8_t *To, size_t ToSize, - size_t MaxToSize) { - if (ToSize >= MaxToSize) return 0; - size_t AvailableSpace = MaxToSize - ToSize; - size_t MaxCopySize = std::min(AvailableSpace, FromSize); - size_t CopySize = Rand(MaxCopySize) + 1; - size_t FromBeg = Rand(FromSize - CopySize + 1); - assert(FromBeg + CopySize <= FromSize); - size_t ToInsertPos = Rand(ToSize + 1); - assert(ToInsertPos + CopySize <= MaxToSize); - size_t TailSize = ToSize - ToInsertPos; - if (To == From) { - MutateInPlaceHere.resize(MaxToSize); - memcpy(MutateInPlaceHere.data(), From + FromBeg, CopySize); - memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize); - memmove(To + ToInsertPos, MutateInPlaceHere.data(), CopySize); - } else { - memmove(To + ToInsertPos + CopySize, To + ToInsertPos, TailSize); - memmove(To + ToInsertPos, From + FromBeg, CopySize); - } - return ToSize + CopySize; -} - -size_t MutationDispatcher::Mutate_CopyPart(uint8_t *Data, size_t Size, - size_t MaxSize) { - if (Size > MaxSize || Size == 0) return 0; - // If Size == MaxSize, `InsertPartOf(...)` will - // fail so there's no point using it in this case. - if (Size == MaxSize || Rand.RandBool()) - return CopyPartOf(Data, Size, Data, Size); - else - return InsertPartOf(Data, Size, Data, Size, MaxSize); -} - -size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, - size_t MaxSize) { - if (Size > MaxSize) return 0; - size_t B = Rand(Size); - while (B < Size && !isdigit(Data[B])) B++; - if (B == Size) return 0; - size_t E = B; - while (E < Size && isdigit(Data[E])) E++; - assert(B < E); - // now we have digits in [B, E). - // strtol and friends don't accept non-zero-teminated data, parse it manually. - uint64_t Val = Data[B] - '0'; - for (size_t i = B + 1; i < E; i++) - Val = Val * 10 + Data[i] - '0'; - - // Mutate the integer value. - switch(Rand(5)) { - case 0: Val++; break; - case 1: Val--; break; - case 2: Val /= 2; break; - case 3: Val *= 2; break; - case 4: Val = Rand(Val * Val); break; - default: assert(0); - } - // Just replace the bytes with the new ones, don't bother moving bytes. - for (size_t i = B; i < E; i++) { - size_t Idx = E + B - i - 1; - assert(Idx >= B && Idx < E); - Data[Idx] = (Val % 10) + '0'; - Val /= 10; - } - return Size; -} - -template<class T> -size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) { - if (Size < sizeof(T)) return 0; - size_t Off = Rand(Size - sizeof(T) + 1); - assert(Off + sizeof(T) <= Size); - T Val; - if (Off < 64 && !Rand(4)) { - Val = Size; - if (Rand.RandBool()) - Val = Bswap(Val); - } else { - memcpy(&Val, Data + Off, sizeof(Val)); - T Add = Rand(21); - Add -= 10; - if (Rand.RandBool()) - Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes. - else - Val = Val + Add; // Add assuming current endiannes. - if (Add == 0 || Rand.RandBool()) // Maybe negate. - Val = -Val; - } - memcpy(Data + Off, &Val, sizeof(Val)); - return Size; -} - -size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data, - size_t Size, - size_t MaxSize) { - if (Size > MaxSize) return 0; - switch (Rand(4)) { - case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand); - case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand); - case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand); - case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand); - default: assert(0); - } - return 0; -} - -size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size, - size_t MaxSize) { - if (Size > MaxSize) return 0; - if (!Corpus || Corpus->size() < 2 || Size == 0) return 0; - size_t Idx = Rand(Corpus->size()); - const Unit &O = (*Corpus)[Idx]; - if (O.empty()) return 0; - MutateInPlaceHere.resize(MaxSize); - auto &U = MutateInPlaceHere; - size_t NewSize = 0; - switch(Rand(3)) { - case 0: - NewSize = CrossOver(Data, Size, O.data(), O.size(), U.data(), U.size()); - break; - case 1: - NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize); - if (!NewSize) - NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size()); - break; - case 2: - NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size()); - break; - default: assert(0); - } - assert(NewSize > 0 && "CrossOver returned empty unit"); - assert(NewSize <= MaxSize && "CrossOver returned overisized unit"); - memcpy(Data, U.data(), NewSize); - return NewSize; -} - -void MutationDispatcher::StartMutationSequence() { - CurrentMutatorSequence.clear(); - CurrentDictionaryEntrySequence.clear(); -} - -// Copy successful dictionary entries to PersistentAutoDictionary. -void MutationDispatcher::RecordSuccessfulMutationSequence() { - for (auto DE : CurrentDictionaryEntrySequence) { - // PersistentAutoDictionary.AddWithSuccessCountOne(DE); - DE->IncSuccessCount(); - assert(DE->GetW().size()); - // Linear search is fine here as this happens seldom. - if (!PersistentAutoDictionary.ContainsWord(DE->GetW())) - PersistentAutoDictionary.push_back({DE->GetW(), 1}); - } -} - -void MutationDispatcher::PrintRecommendedDictionary() { - Vector<DictionaryEntry> V; - for (auto &DE : PersistentAutoDictionary) - if (!ManualDictionary.ContainsWord(DE.GetW())) - V.push_back(DE); - if (V.empty()) return; - Printf("###### Recommended dictionary. ######\n"); - for (auto &DE: V) { - assert(DE.GetW().size()); - Printf("\""); - PrintASCII(DE.GetW(), "\""); - Printf(" # Uses: %zd\n", DE.GetUseCount()); - } - Printf("###### End of recommended dictionary. ######\n"); -} - -void MutationDispatcher::PrintMutationSequence() { - Printf("MS: %zd ", CurrentMutatorSequence.size()); - for (auto M : CurrentMutatorSequence) - Printf("%s-", M.Name); - if (!CurrentDictionaryEntrySequence.empty()) { - Printf(" DE: "); - for (auto DE : CurrentDictionaryEntrySequence) { - Printf("\""); - PrintASCII(DE->GetW(), "\"-"); - } - } -} - -size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) { - return MutateImpl(Data, Size, MaxSize, Mutators); -} - -size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size, - size_t MaxSize) { - return MutateImpl(Data, Size, MaxSize, DefaultMutators); -} - -// Mutates Data in place, returns new size. -size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size, - size_t MaxSize, - Vector<Mutator> &Mutators) { - assert(MaxSize > 0); - // Some mutations may fail (e.g. can't insert more bytes if Size == MaxSize), - // in which case they will return 0. - // Try several times before returning un-mutated data. - for (int Iter = 0; Iter < 100; Iter++) { - auto M = Mutators[Rand(Mutators.size())]; - size_t NewSize = (this->*(M.Fn))(Data, Size, MaxSize); - if (NewSize && NewSize <= MaxSize) { - if (Options.OnlyASCII) - ToASCII(Data, NewSize); - CurrentMutatorSequence.push_back(M); - return NewSize; - } - } - *Data = ' '; - return 1; // Fallback, should not happen frequently. -} - -// Mask represents the set of Data bytes that are worth mutating. -size_t MutationDispatcher::MutateWithMask(uint8_t *Data, size_t Size, - size_t MaxSize, - const Vector<uint8_t> &Mask) { - assert(Size <= Mask.size()); - // * Copy the worthy bytes into a temporary array T - // * Mutate T - // * Copy T back. - // This is totally unoptimized. - auto &T = MutateWithMaskTemp; - if (T.size() < Size) - T.resize(Size); - size_t OneBits = 0; - for (size_t I = 0; I < Size; I++) - if (Mask[I]) - T[OneBits++] = Data[I]; - - assert(!T.empty()); - size_t NewSize = Mutate(T.data(), OneBits, OneBits); - assert(NewSize <= OneBits); - (void)NewSize; - // Even if NewSize < OneBits we still use all OneBits bytes. - for (size_t I = 0, J = 0; I < Size; I++) - if (Mask[I]) - Data[I] = T[J++]; - return Size; -} - -void MutationDispatcher::AddWordToManualDictionary(const Word &W) { - ManualDictionary.push_back( - {W, std::numeric_limits<size_t>::max()}); -} - -} // namespace fuzzer diff --git a/chromium/third_party/libFuzzer/src/FuzzerMutate.h b/chromium/third_party/libFuzzer/src/FuzzerMutate.h deleted file mode 100644 index a51c7fb44d4..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerMutate.h +++ /dev/null @@ -1,157 +0,0 @@ -//===- FuzzerMutate.h - Internal header for the Fuzzer ----------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// fuzzer::MutationDispatcher -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_MUTATE_H -#define LLVM_FUZZER_MUTATE_H - -#include "FuzzerDefs.h" -#include "FuzzerDictionary.h" -#include "FuzzerOptions.h" -#include "FuzzerRandom.h" - -namespace fuzzer { - -class MutationDispatcher { -public: - MutationDispatcher(Random &Rand, const FuzzingOptions &Options); - ~MutationDispatcher() {} - /// Indicate that we are about to start a new sequence of mutations. - void StartMutationSequence(); - /// Print the current sequence of mutations. - void PrintMutationSequence(); - /// Indicate that the current sequence of mutations was successful. - void RecordSuccessfulMutationSequence(); - /// Mutates data by invoking user-provided mutator. - size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize); - /// Mutates data by invoking user-provided crossover. - size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize); - /// Mutates data by shuffling bytes. - size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize); - /// Mutates data by erasing bytes. - size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize); - /// Mutates data by inserting a byte. - size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize); - /// Mutates data by inserting several repeated bytes. - size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize); - /// Mutates data by chanding one byte. - size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize); - /// Mutates data by chanding one bit. - size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize); - /// Mutates data by copying/inserting a part of data into a different place. - size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize); - - /// Mutates data by adding a word from the manual dictionary. - size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size, - size_t MaxSize); - - /// Mutates data by adding a word from the TORC. - size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize); - - /// Mutates data by adding a word from the persistent automatic dictionary. - size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size, - size_t MaxSize); - - /// Tries to find an ASCII integer in Data, changes it to another ASCII int. - size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize); - /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways. - size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize); - - /// CrossOver Data with some other element of the corpus. - size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize); - - /// Applies one of the configured mutations. - /// Returns the new size of data which could be up to MaxSize. - size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize); - - /// Applies one of the configured mutations to the bytes of Data - /// that have '1' in Mask. - /// Mask.size() should be >= Size. - size_t MutateWithMask(uint8_t *Data, size_t Size, size_t MaxSize, - const Vector<uint8_t> &Mask); - - /// Applies one of the default mutations. Provided as a service - /// to mutation authors. - size_t DefaultMutate(uint8_t *Data, size_t Size, size_t MaxSize); - - /// Creates a cross-over of two pieces of Data, returns its size. - size_t CrossOver(const uint8_t *Data1, size_t Size1, const uint8_t *Data2, - size_t Size2, uint8_t *Out, size_t MaxOutSize); - - void AddWordToManualDictionary(const Word &W); - - void PrintRecommendedDictionary(); - - void SetCorpus(const InputCorpus *Corpus) { this->Corpus = Corpus; } - - Random &GetRand() { return Rand; } - - private: - struct Mutator { - size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max); - const char *Name; - }; - - size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size, - size_t MaxSize); - size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize, - Vector<Mutator> &Mutators); - - size_t InsertPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, - size_t ToSize, size_t MaxToSize); - size_t CopyPartOf(const uint8_t *From, size_t FromSize, uint8_t *To, - size_t ToSize); - size_t ApplyDictionaryEntry(uint8_t *Data, size_t Size, size_t MaxSize, - DictionaryEntry &DE); - - template <class T> - DictionaryEntry MakeDictionaryEntryFromCMP(T Arg1, T Arg2, - const uint8_t *Data, size_t Size); - DictionaryEntry MakeDictionaryEntryFromCMP(const Word &Arg1, const Word &Arg2, - const uint8_t *Data, size_t Size); - DictionaryEntry MakeDictionaryEntryFromCMP(const void *Arg1, const void *Arg2, - const void *Arg1Mutation, - const void *Arg2Mutation, - size_t ArgSize, - const uint8_t *Data, size_t Size); - - Random &Rand; - const FuzzingOptions Options; - - // Dictionary provided by the user via -dict=DICT_FILE. - Dictionary ManualDictionary; - // Temporary dictionary modified by the fuzzer itself, - // recreated periodically. - Dictionary TempAutoDictionary; - // Persistent dictionary modified by the fuzzer, consists of - // entries that led to successful discoveries in the past mutations. - Dictionary PersistentAutoDictionary; - - Vector<DictionaryEntry *> CurrentDictionaryEntrySequence; - - static const size_t kCmpDictionaryEntriesDequeSize = 16; - DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize]; - size_t CmpDictionaryEntriesDequeIdx = 0; - - const InputCorpus *Corpus = nullptr; - Vector<uint8_t> MutateInPlaceHere; - Vector<uint8_t> MutateWithMaskTemp; - // CustomCrossOver needs its own buffer as a custom implementation may call - // LLVMFuzzerMutate, which in turn may resize MutateInPlaceHere. - Vector<uint8_t> CustomCrossOverInPlaceHere; - - Vector<Mutator> Mutators; - Vector<Mutator> DefaultMutators; - Vector<Mutator> CurrentMutatorSequence; -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_MUTATE_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerOptions.h b/chromium/third_party/libFuzzer/src/FuzzerOptions.h deleted file mode 100644 index bb642f1e236..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerOptions.h +++ /dev/null @@ -1,77 +0,0 @@ -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// fuzzer::FuzzingOptions -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_OPTIONS_H -#define LLVM_FUZZER_OPTIONS_H - -#include "FuzzerDefs.h" - -namespace fuzzer { - -struct FuzzingOptions { - int Verbosity = 1; - size_t MaxLen = 0; - size_t LenControl = 1000; - int UnitTimeoutSec = 300; - int TimeoutExitCode = 77; - int ErrorExitCode = 77; - int MaxTotalTimeSec = 0; - int RssLimitMb = 0; - int MallocLimitMb = 0; - bool DoCrossOver = true; - int MutateDepth = 5; - bool ReduceDepth = false; - bool UseCounters = false; - bool UseMemmem = true; - bool UseCmp = false; - int UseValueProfile = false; - bool Shrink = false; - bool ReduceInputs = false; - int ReloadIntervalSec = 1; - bool ShuffleAtStartUp = true; - bool PreferSmall = true; - size_t MaxNumberOfRuns = -1L; - int ReportSlowUnits = 10; - bool OnlyASCII = false; - std::string OutputCorpus; - std::string ArtifactPrefix = "./"; - std::string ExactArtifactPath; - std::string ExitOnSrcPos; - std::string ExitOnItem; - std::string FocusFunction; - std::string DataFlowTrace; - bool SaveArtifacts = true; - bool PrintNEW = true; // Print a status line when new units are found; - bool PrintNewCovPcs = false; - int PrintNewCovFuncs = 0; - bool PrintFinalStats = false; - bool PrintCorpusStats = false; - bool PrintCoverage = false; - bool PrintUnstableStats = false; - int HandleUnstable = 0; - bool DumpCoverage = false; - bool DetectLeaks = true; - int PurgeAllocatorIntervalSec = 1; - int TraceMalloc = 0; - bool HandleAbrt = false; - bool HandleBus = false; - bool HandleFpe = false; - bool HandleIll = false; - bool HandleInt = false; - bool HandleSegv = false; - bool HandleTerm = false; - bool HandleXfsz = false; - bool HandleUsr1 = false; - bool HandleUsr2 = false; -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_OPTIONS_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerRandom.h b/chromium/third_party/libFuzzer/src/FuzzerRandom.h deleted file mode 100644 index 8a1aa3ef5fd..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerRandom.h +++ /dev/null @@ -1,34 +0,0 @@ -//===- FuzzerRandom.h - Internal header for the Fuzzer ----------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// fuzzer::Random -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_RANDOM_H -#define LLVM_FUZZER_RANDOM_H - -#include <random> - -namespace fuzzer { -class Random : public std::mt19937 { - public: - Random(unsigned int seed) : std::mt19937(seed) {} - result_type operator()() { return this->std::mt19937::operator()(); } - size_t Rand() { return this->operator()(); } - size_t RandBool() { return Rand() % 2; } - size_t operator()(size_t n) { return n ? Rand() % n : 0; } - intptr_t operator()(intptr_t From, intptr_t To) { - assert(From < To); - intptr_t RangeSize = To - From + 1; - return operator()(RangeSize) + From; - } -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_RANDOM_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerSHA1.cpp b/chromium/third_party/libFuzzer/src/FuzzerSHA1.cpp deleted file mode 100644 index d2f8e811bbf..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerSHA1.cpp +++ /dev/null @@ -1,222 +0,0 @@ -//===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// This code is taken from public domain -// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c) -// and modified by adding anonymous namespace, adding an interface -// function fuzzer::ComputeSHA1() and removing unnecessary code. -// -// lib/Fuzzer can not use SHA1 implementation from openssl because -// openssl may not be available and because we may be fuzzing openssl itself. -// For the same reason we do not want to depend on SHA1 from LLVM tree. -//===----------------------------------------------------------------------===// - -#include "FuzzerSHA1.h" -#include "FuzzerDefs.h" - -/* This code is public-domain - it is based on libcrypt - * placed in the public domain by Wei Dai and other contributors. - */ - -#include <iomanip> -#include <sstream> -#include <stdint.h> -#include <string.h> - -namespace { // Added for LibFuzzer - -#ifdef __BIG_ENDIAN__ -# define SHA_BIG_ENDIAN -#elif defined __LITTLE_ENDIAN__ -/* override */ -#elif defined __BYTE_ORDER -# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define SHA_BIG_ENDIAN -# endif -#else // ! defined __LITTLE_ENDIAN__ -# include <endian.h> // machine/endian.h -# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -# define SHA_BIG_ENDIAN -# endif -#endif - - -/* header */ - -#define HASH_LENGTH 20 -#define BLOCK_LENGTH 64 - -typedef struct sha1nfo { - uint32_t buffer[BLOCK_LENGTH/4]; - uint32_t state[HASH_LENGTH/4]; - uint32_t byteCount; - uint8_t bufferOffset; - uint8_t keyBuffer[BLOCK_LENGTH]; - uint8_t innerHash[HASH_LENGTH]; -} sha1nfo; - -/* public API - prototypes - TODO: doxygen*/ - -/** - */ -void sha1_init(sha1nfo *s); -/** - */ -void sha1_writebyte(sha1nfo *s, uint8_t data); -/** - */ -void sha1_write(sha1nfo *s, const char *data, size_t len); -/** - */ -uint8_t* sha1_result(sha1nfo *s); - - -/* code */ -#define SHA1_K0 0x5a827999 -#define SHA1_K20 0x6ed9eba1 -#define SHA1_K40 0x8f1bbcdc -#define SHA1_K60 0xca62c1d6 - -void sha1_init(sha1nfo *s) { - s->state[0] = 0x67452301; - s->state[1] = 0xefcdab89; - s->state[2] = 0x98badcfe; - s->state[3] = 0x10325476; - s->state[4] = 0xc3d2e1f0; - s->byteCount = 0; - s->bufferOffset = 0; -} - -uint32_t sha1_rol32(uint32_t number, uint8_t bits) { - return ((number << bits) | (number >> (32-bits))); -} - -void sha1_hashBlock(sha1nfo *s) { - uint8_t i; - uint32_t a,b,c,d,e,t; - - a=s->state[0]; - b=s->state[1]; - c=s->state[2]; - d=s->state[3]; - e=s->state[4]; - for (i=0; i<80; i++) { - if (i>=16) { - t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; - s->buffer[i&15] = sha1_rol32(t,1); - } - if (i<20) { - t = (d ^ (b & (c ^ d))) + SHA1_K0; - } else if (i<40) { - t = (b ^ c ^ d) + SHA1_K20; - } else if (i<60) { - t = ((b & c) | (d & (b | c))) + SHA1_K40; - } else { - t = (b ^ c ^ d) + SHA1_K60; - } - t+=sha1_rol32(a,5) + e + s->buffer[i&15]; - e=d; - d=c; - c=sha1_rol32(b,30); - b=a; - a=t; - } - s->state[0] += a; - s->state[1] += b; - s->state[2] += c; - s->state[3] += d; - s->state[4] += e; -} - -void sha1_addUncounted(sha1nfo *s, uint8_t data) { - uint8_t * const b = (uint8_t*) s->buffer; -#ifdef SHA_BIG_ENDIAN - b[s->bufferOffset] = data; -#else - b[s->bufferOffset ^ 3] = data; -#endif - s->bufferOffset++; - if (s->bufferOffset == BLOCK_LENGTH) { - sha1_hashBlock(s); - s->bufferOffset = 0; - } -} - -void sha1_writebyte(sha1nfo *s, uint8_t data) { - ++s->byteCount; - sha1_addUncounted(s, data); -} - -void sha1_write(sha1nfo *s, const char *data, size_t len) { - for (;len--;) sha1_writebyte(s, (uint8_t) *data++); -} - -void sha1_pad(sha1nfo *s) { - // Implement SHA-1 padding (fips180-2 §5.1.1) - - // Pad with 0x80 followed by 0x00 until the end of the block - sha1_addUncounted(s, 0x80); - while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); - - // Append length in the last 8 bytes - sha1_addUncounted(s, 0); // We're only using 32 bit lengths - sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths - sha1_addUncounted(s, 0); // So zero pad the top bits - sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 - sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as - sha1_addUncounted(s, s->byteCount >> 13); // byte. - sha1_addUncounted(s, s->byteCount >> 5); - sha1_addUncounted(s, s->byteCount << 3); -} - -uint8_t* sha1_result(sha1nfo *s) { - // Pad to complete the last block - sha1_pad(s); - -#ifndef SHA_BIG_ENDIAN - // Swap byte order back - int i; - for (i=0; i<5; i++) { - s->state[i]= - (((s->state[i])<<24)& 0xff000000) - | (((s->state[i])<<8) & 0x00ff0000) - | (((s->state[i])>>8) & 0x0000ff00) - | (((s->state[i])>>24)& 0x000000ff); - } -#endif - - // Return pointer to hash (20 characters) - return (uint8_t*) s->state; -} - -} // namespace; Added for LibFuzzer - -namespace fuzzer { - -// The rest is added for LibFuzzer -void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) { - sha1nfo s; - sha1_init(&s); - sha1_write(&s, (const char*)Data, Len); - memcpy(Out, sha1_result(&s), HASH_LENGTH); -} - -std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) { - std::stringstream SS; - for (int i = 0; i < kSHA1NumBytes; i++) - SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i]; - return SS.str(); -} - -std::string Hash(const Unit &U) { - uint8_t Hash[kSHA1NumBytes]; - ComputeSHA1(U.data(), U.size(), Hash); - return Sha1ToString(Hash); -} - -} diff --git a/chromium/third_party/libFuzzer/src/FuzzerSHA1.h b/chromium/third_party/libFuzzer/src/FuzzerSHA1.h deleted file mode 100644 index 3b5e6e807f4..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerSHA1.h +++ /dev/null @@ -1,33 +0,0 @@ -//===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// SHA1 utils. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_SHA1_H -#define LLVM_FUZZER_SHA1_H - -#include "FuzzerDefs.h" -#include <cstddef> -#include <stdint.h> - -namespace fuzzer { - -// Private copy of SHA1 implementation. -static const int kSHA1NumBytes = 20; - -// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'. -void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out); - -std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]); - -std::string Hash(const Unit &U); - -} // namespace fuzzer - -#endif // LLVM_FUZZER_SHA1_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerShmem.h b/chromium/third_party/libFuzzer/src/FuzzerShmem.h deleted file mode 100644 index 53568e0acb6..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerShmem.h +++ /dev/null @@ -1,69 +0,0 @@ -//===- FuzzerShmem.h - shared memory interface ------------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// SharedMemoryRegion -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_SHMEM_H -#define LLVM_FUZZER_SHMEM_H - -#include <algorithm> -#include <cstring> -#include <string> - -#include "FuzzerDefs.h" - -namespace fuzzer { - -class SharedMemoryRegion { - public: - bool Create(const char *Name); - bool Open(const char *Name); - bool Destroy(const char *Name); - uint8_t *GetData() { return Data; } - void PostServer() {Post(0);} - void WaitServer() {Wait(0);} - void PostClient() {Post(1);} - void WaitClient() {Wait(1);} - - size_t WriteByteArray(const uint8_t *Bytes, size_t N) { - assert(N <= kShmemSize - sizeof(N)); - memcpy(GetData(), &N, sizeof(N)); - memcpy(GetData() + sizeof(N), Bytes, N); - assert(N == ReadByteArraySize()); - return N; - } - size_t ReadByteArraySize() { - size_t Res; - memcpy(&Res, GetData(), sizeof(Res)); - return Res; - } - uint8_t *GetByteArray() { return GetData() + sizeof(size_t); } - - bool IsServer() const { return Data && IAmServer; } - bool IsClient() const { return Data && !IAmServer; } - -private: - - static const size_t kShmemSize = 1 << 22; - bool IAmServer; - std::string Path(const char *Name); - std::string SemName(const char *Name, int Idx); - void Post(int Idx); - void Wait(int Idx); - - bool Map(int fd); - uint8_t *Data = nullptr; - void *Semaphore[2]; -}; - -extern SharedMemoryRegion SMR; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_SHMEM_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerShmemFuchsia.cpp b/chromium/third_party/libFuzzer/src/FuzzerShmemFuchsia.cpp deleted file mode 100644 index e9ce50c2ac8..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerShmemFuchsia.cpp +++ /dev/null @@ -1,38 +0,0 @@ -//===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// SharedMemoryRegion. For Fuchsia, this is just stubs as equivalence servers -// are not currently supported. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" - -#if LIBFUZZER_FUCHSIA - -#include "FuzzerShmem.h" - -namespace fuzzer { - -bool SharedMemoryRegion::Create(const char *Name) { - return false; -} - -bool SharedMemoryRegion::Open(const char *Name) { - return false; -} - -bool SharedMemoryRegion::Destroy(const char *Name) { - return false; -} - -void SharedMemoryRegion::Post(int Idx) {} - -void SharedMemoryRegion::Wait(int Idx) {} - -} // namespace fuzzer - -#endif // LIBFUZZER_FUCHSIA diff --git a/chromium/third_party/libFuzzer/src/FuzzerShmemPosix.cpp b/chromium/third_party/libFuzzer/src/FuzzerShmemPosix.cpp deleted file mode 100644 index 41a93f61004..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerShmemPosix.cpp +++ /dev/null @@ -1,108 +0,0 @@ -//===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// SharedMemoryRegion -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_POSIX - -#include "FuzzerIO.h" -#include "FuzzerShmem.h" - -#include <errno.h> -#include <fcntl.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -namespace fuzzer { - -std::string SharedMemoryRegion::Path(const char *Name) { - return DirPlusFile(TmpDir(), Name); -} - -std::string SharedMemoryRegion::SemName(const char *Name, int Idx) { - std::string Res(Name); - // When passing a name without a leading <slash> character to - // sem_open, the behaviour is unspecified in POSIX. Add a leading - // <slash> character for the name if there is no such one. - if (!Res.empty() && Res[0] != '/') - Res.insert(Res.begin(), '/'); - return Res + (char)('0' + Idx); -} - -bool SharedMemoryRegion::Map(int fd) { - Data = - (uint8_t *)mmap(0, kShmemSize, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); - if (Data == (uint8_t*)-1) - return false; - return true; -} - -bool SharedMemoryRegion::Create(const char *Name) { - int fd = open(Path(Name).c_str(), O_CREAT | O_RDWR, 0777); - if (fd < 0) return false; - if (ftruncate(fd, kShmemSize) < 0) return false; - if (!Map(fd)) - return false; - for (int i = 0; i < 2; i++) { - sem_unlink(SemName(Name, i).c_str()); - Semaphore[i] = sem_open(SemName(Name, i).c_str(), O_CREAT, 0644, 0); - if (Semaphore[i] == SEM_FAILED) - return false; - } - IAmServer = true; - return true; -} - -bool SharedMemoryRegion::Open(const char *Name) { - int fd = open(Path(Name).c_str(), O_RDWR); - if (fd < 0) return false; - struct stat stat_res; - if (0 != fstat(fd, &stat_res)) - return false; - assert(stat_res.st_size == kShmemSize); - if (!Map(fd)) - return false; - for (int i = 0; i < 2; i++) { - Semaphore[i] = sem_open(SemName(Name, i).c_str(), 0); - if (Semaphore[i] == SEM_FAILED) - return false; - } - IAmServer = false; - return true; -} - -bool SharedMemoryRegion::Destroy(const char *Name) { - return 0 == unlink(Path(Name).c_str()); -} - -void SharedMemoryRegion::Post(int Idx) { - assert(Idx == 0 || Idx == 1); - sem_post((sem_t*)Semaphore[Idx]); -} - -void SharedMemoryRegion::Wait(int Idx) { - assert(Idx == 0 || Idx == 1); - for (int i = 0; i < 10 && sem_wait((sem_t*)Semaphore[Idx]); i++) { - // sem_wait may fail if interrupted by a signal. - sleep(i); - if (i) - Printf("%s: sem_wait[%d] failed %s\n", i < 9 ? "WARNING" : "ERROR", i, - strerror(errno)); - if (i == 9) abort(); - } -} - -} // namespace fuzzer - -#endif // LIBFUZZER_POSIX diff --git a/chromium/third_party/libFuzzer/src/FuzzerShmemWindows.cpp b/chromium/third_party/libFuzzer/src/FuzzerShmemWindows.cpp deleted file mode 100644 index d330ebf4fd0..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerShmemWindows.cpp +++ /dev/null @@ -1,64 +0,0 @@ -//===- FuzzerShmemWindows.cpp - Posix shared memory -------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// SharedMemoryRegion -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_WINDOWS - -#include "FuzzerIO.h" -#include "FuzzerShmem.h" - -#include <fcntl.h> -#include <stdio.h> -#include <sys/stat.h> -#include <sys/types.h> - -namespace fuzzer { - -std::string SharedMemoryRegion::Path(const char *Name) { - return DirPlusFile(TmpDir(), Name); -} - -std::string SharedMemoryRegion::SemName(const char *Name, int Idx) { - std::string Res(Name); - return Res + (char)('0' + Idx); -} - -bool SharedMemoryRegion::Map(int fd) { - assert(0 && "UNIMPLEMENTED"); - return false; -} - -bool SharedMemoryRegion::Create(const char *Name) { - assert(0 && "UNIMPLEMENTED"); - return false; -} - -bool SharedMemoryRegion::Open(const char *Name) { - assert(0 && "UNIMPLEMENTED"); - return false; -} - -bool SharedMemoryRegion::Destroy(const char *Name) { - assert(0 && "UNIMPLEMENTED"); - return false; -} - -void SharedMemoryRegion::Post(int Idx) { - assert(0 && "UNIMPLEMENTED"); -} - -void SharedMemoryRegion::Wait(int Idx) { - Semaphore[1] = nullptr; - assert(0 && "UNIMPLEMENTED"); -} - -} // namespace fuzzer - -#endif // LIBFUZZER_WINDOWS diff --git a/chromium/third_party/libFuzzer/src/FuzzerTracePC.cpp b/chromium/third_party/libFuzzer/src/FuzzerTracePC.cpp deleted file mode 100644 index 252660b0e11..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerTracePC.cpp +++ /dev/null @@ -1,719 +0,0 @@ -//===- FuzzerTracePC.cpp - PC tracing--------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Trace PCs. -// This module implements __sanitizer_cov_trace_pc_guard[_init], -// the callback required for -fsanitize-coverage=trace-pc-guard instrumentation. -// -//===----------------------------------------------------------------------===// - -#include "FuzzerTracePC.h" -#include "FuzzerBuiltins.h" -#include "FuzzerBuiltinsMsvc.h" -#include "FuzzerCorpus.h" -#include "FuzzerDefs.h" -#include "FuzzerDictionary.h" -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" -#include "FuzzerUtil.h" -#include "FuzzerValueBitMap.h" -#include <set> - -// The coverage counters and PCs. -// These are declared as global variables named "__sancov_*" to simplify -// experiments with inlined instrumentation. -alignas(64) ATTRIBUTE_INTERFACE -uint8_t __sancov_trace_pc_guard_8bit_counters[fuzzer::TracePC::kNumPCs]; - -ATTRIBUTE_INTERFACE -uintptr_t __sancov_trace_pc_pcs[fuzzer::TracePC::kNumPCs]; - -// Used by -fsanitize-coverage=stack-depth to track stack depth -ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC uintptr_t __sancov_lowest_stack; - -namespace fuzzer { - -TracePC TPC; - -uint8_t *TracePC::Counters() const { - return __sancov_trace_pc_guard_8bit_counters; -} - -uintptr_t *TracePC::PCs() const { - return __sancov_trace_pc_pcs; -} - -size_t TracePC::GetTotalPCCoverage() { - if (ObservedPCs.size()) - return ObservedPCs.size(); - size_t Res = 0; - for (size_t i = 1, N = GetNumPCs(); i < N; i++) - if (PCs()[i]) - Res++; - return Res; -} - -template<class CallBack> -void TracePC::IterateInline8bitCounters(CallBack CB) const { - if (NumInline8bitCounters && NumInline8bitCounters == NumPCsInPCTables) { - size_t CounterIdx = 0; - for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) { - uint8_t *Beg = ModuleCounters[i].Start; - size_t Size = ModuleCounters[i].Stop - Beg; - assert(Size == (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start)); - for (size_t j = 0; j < Size; j++, CounterIdx++) - CB(i, j, CounterIdx); - } - } -} - -// Initializes unstable counters by copying Inline8bitCounters to unstable -// counters. -void TracePC::InitializeUnstableCounters() { - IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { - UnstableCounters[UnstableIdx].Counter = ModuleCounters[i].Start[j]; - }); -} - -// Compares the current counters with counters from previous runs -// and records differences as unstable edges. -bool TracePC::UpdateUnstableCounters(int UnstableMode) { - bool Updated = false; - IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { - if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) { - Updated = true; - UnstableCounters[UnstableIdx].IsUnstable = true; - if (UnstableMode == ZeroUnstable) - UnstableCounters[UnstableIdx].Counter = 0; - else if (UnstableMode == MinUnstable) - UnstableCounters[UnstableIdx].Counter = std::min( - ModuleCounters[i].Start[j], UnstableCounters[UnstableIdx].Counter); - } - }); - return Updated; -} - -// Updates and applies unstable counters to ModuleCounters in single iteration -void TracePC::UpdateAndApplyUnstableCounters(int UnstableMode) { - IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { - if (ModuleCounters[i].Start[j] != UnstableCounters[UnstableIdx].Counter) { - UnstableCounters[UnstableIdx].IsUnstable = true; - if (UnstableMode == ZeroUnstable) - ModuleCounters[i].Start[j] = 0; - else if (UnstableMode == MinUnstable) - ModuleCounters[i].Start[j] = std::min( - ModuleCounters[i].Start[j], UnstableCounters[UnstableIdx].Counter); - } - }); -} - -void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) { - if (Start == Stop) return; - if (NumModulesWithInline8bitCounters && - ModuleCounters[NumModulesWithInline8bitCounters-1].Start == Start) return; - assert(NumModulesWithInline8bitCounters < - sizeof(ModuleCounters) / sizeof(ModuleCounters[0])); - ModuleCounters[NumModulesWithInline8bitCounters++] = {Start, Stop}; - NumInline8bitCounters += Stop - Start; -} - -void TracePC::HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop) { - const PCTableEntry *B = reinterpret_cast<const PCTableEntry *>(Start); - const PCTableEntry *E = reinterpret_cast<const PCTableEntry *>(Stop); - if (NumPCTables && ModulePCTable[NumPCTables - 1].Start == B) return; - assert(NumPCTables < sizeof(ModulePCTable) / sizeof(ModulePCTable[0])); - ModulePCTable[NumPCTables++] = {B, E}; - NumPCsInPCTables += E - B; -} - -void TracePC::HandleInit(uint32_t *Start, uint32_t *Stop) { - if (Start == Stop || *Start) return; - assert(NumModules < sizeof(Modules) / sizeof(Modules[0])); - for (uint32_t *P = Start; P < Stop; P++) { - NumGuards++; - if (NumGuards == kNumPCs) { - RawPrint( - "WARNING: The binary has too many instrumented PCs.\n" - " You may want to reduce the size of the binary\n" - " for more efficient fuzzing and precise coverage data\n"); - } - *P = NumGuards % kNumPCs; - } - Modules[NumModules].Start = Start; - Modules[NumModules].Stop = Stop; - NumModules++; -} - -void TracePC::PrintModuleInfo() { - if (NumGuards) { - Printf("INFO: Loaded %zd modules (%zd guards): ", NumModules, NumGuards); - for (size_t i = 0; i < NumModules; i++) - Printf("%zd [%p, %p), ", Modules[i].Stop - Modules[i].Start, - Modules[i].Start, Modules[i].Stop); - Printf("\n"); - } - if (NumModulesWithInline8bitCounters) { - Printf("INFO: Loaded %zd modules (%zd inline 8-bit counters): ", - NumModulesWithInline8bitCounters, NumInline8bitCounters); - for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) - Printf("%zd [%p, %p), ", ModuleCounters[i].Stop - ModuleCounters[i].Start, - ModuleCounters[i].Start, ModuleCounters[i].Stop); - Printf("\n"); - } - if (NumPCTables) { - Printf("INFO: Loaded %zd PC tables (%zd PCs): ", NumPCTables, - NumPCsInPCTables); - for (size_t i = 0; i < NumPCTables; i++) { - Printf("%zd [%p,%p), ", ModulePCTable[i].Stop - ModulePCTable[i].Start, - ModulePCTable[i].Start, ModulePCTable[i].Stop); - } - Printf("\n"); - - if ((NumGuards && NumGuards != NumPCsInPCTables) || - (NumInline8bitCounters && NumInline8bitCounters != NumPCsInPCTables)) { - Printf("ERROR: The size of coverage PC tables does not match the\n" - "number of instrumented PCs. This might be a compiler bug,\n" - "please contact the libFuzzer developers.\n" - "Also check https://bugs.llvm.org/show_bug.cgi?id=34636\n" - "for possible workarounds (tl;dr: don't use the old GNU ld)\n"); - _Exit(1); - } - } - if (size_t NumExtraCounters = ExtraCountersEnd() - ExtraCountersBegin()) - Printf("INFO: %zd Extra Counters\n", NumExtraCounters); -} - -ATTRIBUTE_NO_SANITIZE_ALL -void TracePC::HandleCallerCallee(uintptr_t Caller, uintptr_t Callee) { - const uintptr_t kBits = 12; - const uintptr_t kMask = (1 << kBits) - 1; - uintptr_t Idx = (Caller & kMask) | ((Callee & kMask) << kBits); - ValueProfileMap.AddValueModPrime(Idx); -} - -/// \return the address of the previous instruction. -/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.h` -inline ALWAYS_INLINE uintptr_t GetPreviousInstructionPc(uintptr_t PC) { -#if defined(__arm__) - // T32 (Thumb) branch instructions might be 16 or 32 bit long, - // so we return (pc-2) in that case in order to be safe. - // For A32 mode we return (pc-4) because all instructions are 32 bit long. - return (PC - 3) & (~1); -#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__aarch64__) - // PCs are always 4 byte aligned. - return PC - 4; -#elif defined(__sparc__) || defined(__mips__) - return PC - 8; -#else - return PC - 1; -#endif -} - -/// \return the address of the next instruction. -/// Note: the logic is copied from `sanitizer_common/sanitizer_stacktrace.cc` -inline ALWAYS_INLINE uintptr_t GetNextInstructionPc(uintptr_t PC) { -#if defined(__mips__) - return PC + 8; -#elif defined(__powerpc__) || defined(__sparc__) || defined(__arm__) || \ - defined(__aarch64__) - return PC + 4; -#else - return PC + 1; -#endif -} - -void TracePC::UpdateObservedPCs() { - Vector<uintptr_t> CoveredFuncs; - auto ObservePC = [&](uintptr_t PC) { - if (ObservedPCs.insert(PC).second && DoPrintNewPCs) { - PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", GetNextInstructionPc(PC)); - Printf("\n"); - } - }; - - auto Observe = [&](const PCTableEntry &TE) { - if (TE.PCFlags & 1) - if (++ObservedFuncs[TE.PC] == 1 && NumPrintNewFuncs) - CoveredFuncs.push_back(TE.PC); - ObservePC(TE.PC); - }; - - if (NumPCsInPCTables) { - if (NumInline8bitCounters == NumPCsInPCTables) { - IterateInline8bitCounters([&](int i, int j, int CounterIdx) { - if (ModuleCounters[i].Start[j]) - Observe(ModulePCTable[i].Start[j]); - }); - } else if (NumGuards == NumPCsInPCTables) { - size_t GuardIdx = 1; - for (size_t i = 0; i < NumModules; i++) { - uint32_t *Beg = Modules[i].Start; - size_t Size = Modules[i].Stop - Beg; - assert(Size == - (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start)); - for (size_t j = 0; j < Size; j++, GuardIdx++) - if (Counters()[GuardIdx]) - Observe(ModulePCTable[i].Start[j]); - } - } - } - - for (size_t i = 0, N = Min(CoveredFuncs.size(), NumPrintNewFuncs); i < N; - i++) { - Printf("\tNEW_FUNC[%zd/%zd]: ", i + 1, CoveredFuncs.size()); - PrintPC("%p %F %L", "%p", GetNextInstructionPc(CoveredFuncs[i])); - Printf("\n"); - } -} - - -static std::string GetModuleName(uintptr_t PC) { - char ModulePathRaw[4096] = ""; // What's PATH_MAX in portable C++? - void *OffsetRaw = nullptr; - if (!EF->__sanitizer_get_module_and_offset_for_pc( - reinterpret_cast<void *>(PC), ModulePathRaw, - sizeof(ModulePathRaw), &OffsetRaw)) - return ""; - return ModulePathRaw; -} - -template<class CallBack> -void TracePC::IterateCoveredFunctions(CallBack CB) { - for (size_t i = 0; i < NumPCTables; i++) { - auto &M = ModulePCTable[i]; - assert(M.Start < M.Stop); - auto ModuleName = GetModuleName(M.Start->PC); - for (auto NextFE = M.Start; NextFE < M.Stop; ) { - auto FE = NextFE; - assert((FE->PCFlags & 1) && "Not a function entry point"); - do { - NextFE++; - } while (NextFE < M.Stop && !(NextFE->PCFlags & 1)); - if (ObservedFuncs.count(FE->PC)) - CB(FE, NextFE, ObservedFuncs[FE->PC]); - } - } -} - -void TracePC::SetFocusFunction(const std::string &FuncName) { - // This function should be called once. - assert(FocusFunction.first > NumModulesWithInline8bitCounters); - if (FuncName.empty()) - return; - for (size_t M = 0; M < NumModulesWithInline8bitCounters; M++) { - auto &PCTE = ModulePCTable[M]; - size_t N = PCTE.Stop - PCTE.Start; - for (size_t I = 0; I < N; I++) { - if (!(PCTE.Start[I].PCFlags & 1)) continue; // not a function entry. - auto Name = DescribePC("%F", GetNextInstructionPc(PCTE.Start[I].PC)); - if (Name[0] == 'i' && Name[1] == 'n' && Name[2] == ' ') - Name = Name.substr(3, std::string::npos); - if (FuncName != Name) continue; - Printf("INFO: Focus function is set to '%s'\n", Name.c_str()); - FocusFunction = {M, I}; - return; - } - } -} - -bool TracePC::ObservedFocusFunction() { - size_t I = FocusFunction.first; - size_t J = FocusFunction.second; - if (I >= NumModulesWithInline8bitCounters) - return false; - auto &MC = ModuleCounters[I]; - size_t Size = MC.Stop - MC.Start; - if (J >= Size) - return false; - return MC.Start[J] != 0; -} - -void TracePC::PrintCoverage() { - if (!EF->__sanitizer_symbolize_pc || - !EF->__sanitizer_get_module_and_offset_for_pc) { - Printf("INFO: __sanitizer_symbolize_pc or " - "__sanitizer_get_module_and_offset_for_pc is not available," - " not printing coverage\n"); - return; - } - Printf("COVERAGE:\n"); - auto CoveredFunctionCallback = [&](const PCTableEntry *First, - const PCTableEntry *Last, - uintptr_t Counter) { - assert(First < Last); - auto VisualizePC = GetNextInstructionPc(First->PC); - std::string FileStr = DescribePC("%s", VisualizePC); - if (!IsInterestingCoverageFile(FileStr)) - return; - std::string FunctionStr = DescribePC("%F", VisualizePC); - if (FunctionStr.find("in ") == 0) - FunctionStr = FunctionStr.substr(3); - std::string LineStr = DescribePC("%l", VisualizePC); - size_t Line = std::stoul(LineStr); - size_t NumEdges = Last - First; - Vector<uintptr_t> UncoveredPCs; - for (auto TE = First; TE < Last; TE++) - if (!ObservedPCs.count(TE->PC)) - UncoveredPCs.push_back(TE->PC); - Printf("COVERED_FUNC: hits: %zd", Counter); - Printf(" edges: %zd/%zd", NumEdges - UncoveredPCs.size(), NumEdges); - Printf(" %s %s:%zd\n", FunctionStr.c_str(), FileStr.c_str(), Line); - for (auto PC: UncoveredPCs) - Printf(" UNCOVERED_PC: %s\n", - DescribePC("%s:%l", GetNextInstructionPc(PC)).c_str()); - }; - - IterateCoveredFunctions(CoveredFunctionCallback); -} - -void TracePC::DumpCoverage() { - if (EF->__sanitizer_dump_coverage) { - Vector<uintptr_t> PCsCopy(GetNumPCs()); - for (size_t i = 0; i < GetNumPCs(); i++) - PCsCopy[i] = PCs()[i] ? GetPreviousInstructionPc(PCs()[i]) : 0; - EF->__sanitizer_dump_coverage(PCsCopy.data(), PCsCopy.size()); - } -} - -void TracePC::PrintUnstableStats() { - size_t count = 0; - Printf("UNSTABLE_FUNCTIONS:\n"); - IterateInline8bitCounters([&](int i, int j, int UnstableIdx) { - const PCTableEntry &TE = ModulePCTable[i].Start[j]; - if (UnstableCounters[UnstableIdx].IsUnstable) { - count++; - if (ObservedFuncs.count(TE.PC)) { - auto VisualizePC = GetNextInstructionPc(TE.PC); - std::string FunctionStr = DescribePC("%F", VisualizePC); - if (FunctionStr.find("in ") == 0) - FunctionStr = FunctionStr.substr(3); - Printf("%s\n", FunctionStr.c_str()); - } - } - }); - - Printf("stat::stability_rate: %.2f\n", - 100 - static_cast<float>(count * 100) / NumInline8bitCounters); -} - -// Value profile. -// We keep track of various values that affect control flow. -// These values are inserted into a bit-set-based hash map. -// Every new bit in the map is treated as a new coverage. -// -// For memcmp/strcmp/etc the interesting value is the length of the common -// prefix of the parameters. -// For cmp instructions the interesting value is a XOR of the parameters. -// The interesting value is mixed up with the PC and is then added to the map. - -ATTRIBUTE_NO_SANITIZE_ALL -void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, - size_t n, bool StopAtZero) { - if (!n) return; - size_t Len = std::min(n, Word::GetMaxSize()); - const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1); - const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2); - uint8_t B1[Word::kMaxSize]; - uint8_t B2[Word::kMaxSize]; - // Copy the data into locals in this non-msan-instrumented function - // to avoid msan complaining further. - size_t Hash = 0; // Compute some simple hash of both strings. - for (size_t i = 0; i < Len; i++) { - B1[i] = A1[i]; - B2[i] = A2[i]; - size_t T = B1[i]; - Hash ^= (T << 8) | B2[i]; - } - size_t I = 0; - for (; I < Len; I++) - if (B1[I] != B2[I] || (StopAtZero && B1[I] == 0)) - break; - size_t PC = reinterpret_cast<size_t>(caller_pc); - size_t Idx = (PC & 4095) | (I << 12); - ValueProfileMap.AddValue(Idx); - TORCW.Insert(Idx ^ Hash, Word(B1, Len), Word(B2, Len)); -} - -template <class T> -ATTRIBUTE_TARGET_POPCNT ALWAYS_INLINE -ATTRIBUTE_NO_SANITIZE_ALL -void TracePC::HandleCmp(uintptr_t PC, T Arg1, T Arg2) { - uint64_t ArgXor = Arg1 ^ Arg2; - if (sizeof(T) == 4) - TORC4.Insert(ArgXor, Arg1, Arg2); - else if (sizeof(T) == 8) - TORC8.Insert(ArgXor, Arg1, Arg2); - uint64_t HammingDistance = Popcountll(ArgXor); // [0,64] - uint64_t AbsoluteDistance = (Arg1 == Arg2 ? 0 : Clzll(Arg1 - Arg2) + 1); - ValueProfileMap.AddValue(PC * 128 + HammingDistance); - ValueProfileMap.AddValue(PC * 128 + 64 + AbsoluteDistance); -} - -static size_t InternalStrnlen(const char *S, size_t MaxLen) { - size_t Len = 0; - for (; Len < MaxLen && S[Len]; Len++) {} - return Len; -} - -// Finds min of (strlen(S1), strlen(S2)). -// Needed bacause one of these strings may actually be non-zero terminated. -static size_t InternalStrnlen2(const char *S1, const char *S2) { - size_t Len = 0; - for (; S1[Len] && S2[Len]; Len++) {} - return Len; -} - -void TracePC::ClearInlineCounters() { - for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) { - uint8_t *Beg = ModuleCounters[i].Start; - size_t Size = ModuleCounters[i].Stop - Beg; - memset(Beg, 0, Size); - } -} - -ATTRIBUTE_NO_SANITIZE_ALL -void TracePC::RecordInitialStack() { - int stack; - __sancov_lowest_stack = InitialStack = reinterpret_cast<uintptr_t>(&stack); -} - -uintptr_t TracePC::GetMaxStackOffset() const { - return InitialStack - __sancov_lowest_stack; // Stack grows down -} - -} // namespace fuzzer - -extern "C" { -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - uint32_t Idx = *Guard; - __sancov_trace_pc_pcs[Idx] = PC; - __sancov_trace_pc_guard_8bit_counters[Idx]++; -} - -// Best-effort support for -fsanitize-coverage=trace-pc, which is available -// in both Clang and GCC. -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -void __sanitizer_cov_trace_pc() { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - uintptr_t Idx = PC & (((uintptr_t)1 << fuzzer::TracePC::kTracePcBits) - 1); - __sancov_trace_pc_pcs[Idx] = PC; - __sancov_trace_pc_guard_8bit_counters[Idx]++; -} - -ATTRIBUTE_INTERFACE -void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) { - fuzzer::TPC.HandleInit(Start, Stop); -} - -ATTRIBUTE_INTERFACE -void __sanitizer_cov_8bit_counters_init(uint8_t *Start, uint8_t *Stop) { - fuzzer::TPC.HandleInline8bitCountersInit(Start, Stop); -} - -ATTRIBUTE_INTERFACE -void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, - const uintptr_t *pcs_end) { - fuzzer::TPC.HandlePCsInit(pcs_beg, pcs_end); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCallerCallee(PC, Callee); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -// Now the __sanitizer_cov_trace_const_cmp[1248] callbacks just mimic -// the behaviour of __sanitizer_cov_trace_cmp[1248] ones. This, however, -// should be changed later to make full use of instrumentation. -void __sanitizer_cov_trace_const_cmp8(uint64_t Arg1, uint64_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_const_cmp4(uint32_t Arg1, uint32_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_const_cmp2(uint16_t Arg1, uint16_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_const_cmp1(uint8_t Arg1, uint8_t Arg2) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Arg1, Arg2); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) { - uint64_t N = Cases[0]; - uint64_t ValSizeInBits = Cases[1]; - uint64_t *Vals = Cases + 2; - // Skip the most common and the most boring case. - if (Vals[N - 1] < 256 && Val < 256) - return; - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - size_t i; - uint64_t Token = 0; - for (i = 0; i < N; i++) { - Token = Val ^ Vals[i]; - if (Val < Vals[i]) - break; - } - - if (ValSizeInBits == 16) - fuzzer::TPC.HandleCmp(PC + i, static_cast<uint16_t>(Token), (uint16_t)(0)); - else if (ValSizeInBits == 32) - fuzzer::TPC.HandleCmp(PC + i, static_cast<uint32_t>(Token), (uint32_t)(0)); - else - fuzzer::TPC.HandleCmp(PC + i, Token, (uint64_t)(0)); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_div4(uint32_t Val) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Val, (uint32_t)0); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_div8(uint64_t Val) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Val, (uint64_t)0); -} - -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -ATTRIBUTE_TARGET_POPCNT -void __sanitizer_cov_trace_gep(uintptr_t Idx) { - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - fuzzer::TPC.HandleCmp(PC, Idx, (uintptr_t)0); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1, - const void *s2, size_t n, int result) { - if (!fuzzer::RunningUserCallback) return; - if (result == 0) return; // No reason to mutate. - if (n <= 1) return; // Not interesting. - fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/false); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1, - const char *s2, size_t n, int result) { - if (!fuzzer::RunningUserCallback) return; - if (result == 0) return; // No reason to mutate. - size_t Len1 = fuzzer::InternalStrnlen(s1, n); - size_t Len2 = fuzzer::InternalStrnlen(s2, n); - n = std::min(n, Len1); - n = std::min(n, Len2); - if (n <= 1) return; // Not interesting. - fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/true); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1, - const char *s2, int result) { - if (!fuzzer::RunningUserCallback) return; - if (result == 0) return; // No reason to mutate. - size_t N = fuzzer::InternalStrnlen2(s1, s2); - if (N <= 1) return; // Not interesting. - fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, N, /*StopAtZero*/true); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, - const char *s2, size_t n, int result) { - if (!fuzzer::RunningUserCallback) return; - return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, - const char *s2, int result) { - if (!fuzzer::RunningUserCallback) return; - return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, - const char *s2, char *result) { - if (!fuzzer::RunningUserCallback) return; - fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, - const char *s2, char *result) { - if (!fuzzer::RunningUserCallback) return; - fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); -} - -ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY -void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, - const void *s2, size_t len2, void *result) { - if (!fuzzer::RunningUserCallback) return; - fuzzer::TPC.MMT.Add(reinterpret_cast<const uint8_t *>(s2), len2); -} -} // extern "C" diff --git a/chromium/third_party/libFuzzer/src/FuzzerTracePC.h b/chromium/third_party/libFuzzer/src/FuzzerTracePC.h deleted file mode 100644 index 39f97acdb07..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerTracePC.h +++ /dev/null @@ -1,310 +0,0 @@ -//===- FuzzerTracePC.h - Internal header for the Fuzzer ---------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// fuzzer::TracePC -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_TRACE_PC -#define LLVM_FUZZER_TRACE_PC - -#include "FuzzerDefs.h" -#include "FuzzerDictionary.h" -#include "FuzzerValueBitMap.h" - -#include <set> -#include <unordered_map> - -namespace fuzzer { - -// TableOfRecentCompares (TORC) remembers the most recently performed -// comparisons of type T. -// We record the arguments of CMP instructions in this table unconditionally -// because it seems cheaper this way than to compute some expensive -// conditions inside __sanitizer_cov_trace_cmp*. -// After the unit has been executed we may decide to use the contents of -// this table to populate a Dictionary. -template<class T, size_t kSizeT> -struct TableOfRecentCompares { - static const size_t kSize = kSizeT; - struct Pair { - T A, B; - }; - ATTRIBUTE_NO_SANITIZE_ALL - void Insert(size_t Idx, const T &Arg1, const T &Arg2) { - Idx = Idx % kSize; - Table[Idx].A = Arg1; - Table[Idx].B = Arg2; - } - - Pair Get(size_t I) { return Table[I % kSize]; } - - Pair Table[kSize]; -}; - -template <size_t kSizeT> -struct MemMemTable { - static const size_t kSize = kSizeT; - Word MemMemWords[kSize]; - Word EmptyWord; - - void Add(const uint8_t *Data, size_t Size) { - if (Size <= 2) return; - Size = std::min(Size, Word::GetMaxSize()); - size_t Idx = SimpleFastHash(Data, Size) % kSize; - MemMemWords[Idx].Set(Data, Size); - } - const Word &Get(size_t Idx) { - for (size_t i = 0; i < kSize; i++) { - const Word &W = MemMemWords[(Idx + i) % kSize]; - if (W.size()) return W; - } - EmptyWord.Set(nullptr, 0); - return EmptyWord; - } -}; - -class TracePC { - public: - static const size_t kNumPCs = 1 << 21; - // How many bits of PC are used from __sanitizer_cov_trace_pc. - static const size_t kTracePcBits = 18; - - enum HandleUnstableOptions { - MinUnstable = 1, - ZeroUnstable = 2, - }; - - void HandleInit(uint32_t *Start, uint32_t *Stop); - void HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop); - void HandlePCsInit(const uintptr_t *Start, const uintptr_t *Stop); - void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee); - template <class T> void HandleCmp(uintptr_t PC, T Arg1, T Arg2); - size_t GetTotalPCCoverage(); - void SetUseCounters(bool UC) { UseCounters = UC; } - void SetUseValueProfileMask(uint32_t VPMask) { UseValueProfileMask = VPMask; } - void SetPrintNewPCs(bool P) { DoPrintNewPCs = P; } - void SetPrintNewFuncs(size_t P) { NumPrintNewFuncs = P; } - void UpdateObservedPCs(); - template <class Callback> void CollectFeatures(Callback CB) const; - - void ResetMaps() { - ValueProfileMap.Reset(); - if (NumModules) - memset(Counters(), 0, GetNumPCs()); - ClearExtraCounters(); - ClearInlineCounters(); - } - - void ClearInlineCounters(); - - void UpdateFeatureSet(size_t CurrentElementIdx, size_t CurrentElementSize); - void PrintFeatureSet(); - - void PrintModuleInfo(); - - void PrintCoverage(); - void DumpCoverage(); - void PrintUnstableStats(); - - template<class CallBack> - void IterateCoveredFunctions(CallBack CB); - - void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2, - size_t n, bool StopAtZero); - - TableOfRecentCompares<uint32_t, 32> TORC4; - TableOfRecentCompares<uint64_t, 32> TORC8; - TableOfRecentCompares<Word, 32> TORCW; - MemMemTable<1024> MMT; - - size_t GetNumPCs() const { - return NumGuards == 0 ? (1 << kTracePcBits) : Min(kNumPCs, NumGuards + 1); - } - uintptr_t GetPC(size_t Idx) { - assert(Idx < GetNumPCs()); - return PCs()[Idx]; - } - - void RecordInitialStack(); - uintptr_t GetMaxStackOffset() const; - - template<class CallBack> - void ForEachObservedPC(CallBack CB) { - for (auto PC : ObservedPCs) - CB(PC); - } - - void SetFocusFunction(const std::string &FuncName); - bool ObservedFocusFunction(); - - void InitializeUnstableCounters(); - bool UpdateUnstableCounters(int UnstableMode); - void UpdateAndApplyUnstableCounters(int UnstableMode); - -private: - struct UnstableEdge { - uint8_t Counter; - bool IsUnstable; - }; - - UnstableEdge UnstableCounters[kNumPCs]; - - bool UseCounters = false; - uint32_t UseValueProfileMask = false; - bool DoPrintNewPCs = false; - size_t NumPrintNewFuncs = 0; - - struct Module { - uint32_t *Start, *Stop; - }; - - Module Modules[4096]; - size_t NumModules; // linker-initialized. - size_t NumGuards; // linker-initialized. - - struct { uint8_t *Start, *Stop; } ModuleCounters[4096]; - size_t NumModulesWithInline8bitCounters; // linker-initialized. - size_t NumInline8bitCounters; - - struct PCTableEntry { - uintptr_t PC, PCFlags; - }; - - struct { const PCTableEntry *Start, *Stop; } ModulePCTable[4096]; - size_t NumPCTables; - size_t NumPCsInPCTables; - - uint8_t *Counters() const; - uintptr_t *PCs() const; - - Set<uintptr_t> ObservedPCs; - std::unordered_map<uintptr_t, uintptr_t> ObservedFuncs; // PC => Counter. - - template <class Callback> - void IterateInline8bitCounters(Callback CB) const; - - std::pair<size_t, size_t> FocusFunction = {-1, -1}; // Module and PC IDs. - - ValueBitMap ValueProfileMap; - uintptr_t InitialStack; -}; - -template <class Callback> -// void Callback(size_t FirstFeature, size_t Idx, uint8_t Value); -ATTRIBUTE_NO_SANITIZE_ALL -void ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End, - size_t FirstFeature, Callback Handle8bitCounter) { - typedef uintptr_t LargeType; - const size_t Step = sizeof(LargeType) / sizeof(uint8_t); - const size_t StepMask = Step - 1; - auto P = Begin; - // Iterate by 1 byte until either the alignment boundary or the end. - for (; reinterpret_cast<uintptr_t>(P) & StepMask && P < End; P++) - if (uint8_t V = *P) - Handle8bitCounter(FirstFeature, P - Begin, V); - - // Iterate by Step bytes at a time. - for (; P < End; P += Step) - if (LargeType Bundle = *reinterpret_cast<const LargeType *>(P)) - for (size_t I = 0; I < Step; I++, Bundle >>= 8) - if (uint8_t V = Bundle & 0xff) - Handle8bitCounter(FirstFeature, P - Begin + I, V); - - // Iterate by 1 byte until the end. - for (; P < End; P++) - if (uint8_t V = *P) - Handle8bitCounter(FirstFeature, P - Begin, V); -} - -// Given a non-zero Counter returns a number in the range [0,7]. -template<class T> -unsigned CounterToFeature(T Counter) { - // Returns a feature number by placing Counters into buckets as illustrated - // below. - // - // Counter bucket: [1] [2] [3] [4-7] [8-15] [16-31] [32-127] [128+] - // Feature number: 0 1 2 3 4 5 6 7 - // - // This is a heuristic taken from AFL (see - // http://lcamtuf.coredump.cx/afl/technical_details.txt). - // - // This implementation may change in the future so clients should - // not rely on it. - assert(Counter); - unsigned Bit = 0; - /**/ if (Counter >= 128) Bit = 7; - else if (Counter >= 32) Bit = 6; - else if (Counter >= 16) Bit = 5; - else if (Counter >= 8) Bit = 4; - else if (Counter >= 4) Bit = 3; - else if (Counter >= 3) Bit = 2; - else if (Counter >= 2) Bit = 1; - return Bit; -} - -template <class Callback> // void Callback(size_t Feature) -ATTRIBUTE_NO_SANITIZE_ADDRESS -__attribute__((noinline)) -void TracePC::CollectFeatures(Callback HandleFeature) const { - uint8_t *Counters = this->Counters(); - size_t N = GetNumPCs(); - auto Handle8bitCounter = [&](size_t FirstFeature, - size_t Idx, uint8_t Counter) { - if (UseCounters) - HandleFeature(FirstFeature + Idx * 8 + CounterToFeature(Counter)); - else - HandleFeature(FirstFeature + Idx); - }; - - size_t FirstFeature = 0; - - if (!NumInline8bitCounters) { - ForEachNonZeroByte(Counters, Counters + N, FirstFeature, Handle8bitCounter); - FirstFeature += N * 8; - } - - if (NumInline8bitCounters) { - for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) { - ForEachNonZeroByte(ModuleCounters[i].Start, ModuleCounters[i].Stop, - FirstFeature, Handle8bitCounter); - FirstFeature += 8 * (ModuleCounters[i].Stop - ModuleCounters[i].Start); - } - } - - ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), FirstFeature, - Handle8bitCounter); - FirstFeature += (ExtraCountersEnd() - ExtraCountersBegin()) * 8; - - if (UseValueProfileMask) { - ValueProfileMap.ForEach([&](size_t Idx) { - HandleFeature(FirstFeature + Idx); - }); - FirstFeature += ValueProfileMap.SizeInBits(); - } - - // Step function, grows similar to 8 * Log_2(A). - auto StackDepthStepFunction = [](uint32_t A) -> uint32_t { - if (!A) return A; - uint32_t Log2 = Log(A); - if (Log2 < 3) return A; - Log2 -= 3; - return (Log2 + 1) * 8 + ((A >> Log2) & 7); - }; - assert(StackDepthStepFunction(1024) == 64); - assert(StackDepthStepFunction(1024 * 4) == 80); - assert(StackDepthStepFunction(1024 * 1024) == 144); - - if (auto MaxStackOffset = GetMaxStackOffset()) - HandleFeature(FirstFeature + StackDepthStepFunction(MaxStackOffset / 8)); -} - -extern TracePC TPC; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_TRACE_PC diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtil.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtil.cpp deleted file mode 100644 index 6286f9a718a..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerUtil.cpp +++ /dev/null @@ -1,232 +0,0 @@ -//===- FuzzerUtil.cpp - Misc utils ----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Misc utils. -//===----------------------------------------------------------------------===// - -#include "FuzzerUtil.h" -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include <cassert> -#include <chrono> -#include <cstring> -#include <errno.h> -#include <mutex> -#include <signal.h> -#include <sstream> -#include <stdio.h> -#include <sys/types.h> -#include <thread> - -namespace fuzzer { - -void PrintHexArray(const uint8_t *Data, size_t Size, - const char *PrintAfter) { - for (size_t i = 0; i < Size; i++) - Printf("0x%x,", (unsigned)Data[i]); - Printf("%s", PrintAfter); -} - -void Print(const Unit &v, const char *PrintAfter) { - PrintHexArray(v.data(), v.size(), PrintAfter); -} - -void PrintASCIIByte(uint8_t Byte) { - if (Byte == '\\') - Printf("\\\\"); - else if (Byte == '"') - Printf("\\\""); - else if (Byte >= 32 && Byte < 127) - Printf("%c", Byte); - else - Printf("\\x%02x", Byte); -} - -void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter) { - for (size_t i = 0; i < Size; i++) - PrintASCIIByte(Data[i]); - Printf("%s", PrintAfter); -} - -void PrintASCII(const Unit &U, const char *PrintAfter) { - PrintASCII(U.data(), U.size(), PrintAfter); -} - -bool ToASCII(uint8_t *Data, size_t Size) { - bool Changed = false; - for (size_t i = 0; i < Size; i++) { - uint8_t &X = Data[i]; - auto NewX = X; - NewX &= 127; - if (!isspace(NewX) && !isprint(NewX)) - NewX = ' '; - Changed |= NewX != X; - X = NewX; - } - return Changed; -} - -bool IsASCII(const Unit &U) { return IsASCII(U.data(), U.size()); } - -bool IsASCII(const uint8_t *Data, size_t Size) { - for (size_t i = 0; i < Size; i++) - if (!(isprint(Data[i]) || isspace(Data[i]))) return false; - return true; -} - -bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) { - U->clear(); - if (Str.empty()) return false; - size_t L = 0, R = Str.size() - 1; // We are parsing the range [L,R]. - // Skip spaces from both sides. - while (L < R && isspace(Str[L])) L++; - while (R > L && isspace(Str[R])) R--; - if (R - L < 2) return false; - // Check the closing " - if (Str[R] != '"') return false; - R--; - // Find the opening " - while (L < R && Str[L] != '"') L++; - if (L >= R) return false; - assert(Str[L] == '\"'); - L++; - assert(L <= R); - for (size_t Pos = L; Pos <= R; Pos++) { - uint8_t V = (uint8_t)Str[Pos]; - if (!isprint(V) && !isspace(V)) return false; - if (V =='\\') { - // Handle '\\' - if (Pos + 1 <= R && (Str[Pos + 1] == '\\' || Str[Pos + 1] == '"')) { - U->push_back(Str[Pos + 1]); - Pos++; - continue; - } - // Handle '\xAB' - if (Pos + 3 <= R && Str[Pos + 1] == 'x' - && isxdigit(Str[Pos + 2]) && isxdigit(Str[Pos + 3])) { - char Hex[] = "0xAA"; - Hex[2] = Str[Pos + 2]; - Hex[3] = Str[Pos + 3]; - U->push_back(strtol(Hex, nullptr, 16)); - Pos += 3; - continue; - } - return false; // Invalid escape. - } else { - // Any other character. - U->push_back(V); - } - } - return true; -} - -bool ParseDictionaryFile(const std::string &Text, Vector<Unit> *Units) { - if (Text.empty()) { - Printf("ParseDictionaryFile: file does not exist or is empty\n"); - return false; - } - std::istringstream ISS(Text); - Units->clear(); - Unit U; - int LineNo = 0; - std::string S; - while (std::getline(ISS, S, '\n')) { - LineNo++; - size_t Pos = 0; - while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces. - if (Pos == S.size()) continue; // Empty line. - if (S[Pos] == '#') continue; // Comment line. - if (ParseOneDictionaryEntry(S, &U)) { - Units->push_back(U); - } else { - Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo, - S.c_str()); - return false; - } - } - return true; -} - -std::string Base64(const Unit &U) { - static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - std::string Res; - size_t i; - for (i = 0; i + 2 < U.size(); i += 3) { - uint32_t x = (U[i] << 16) + (U[i + 1] << 8) + U[i + 2]; - Res += Table[(x >> 18) & 63]; - Res += Table[(x >> 12) & 63]; - Res += Table[(x >> 6) & 63]; - Res += Table[x & 63]; - } - if (i + 1 == U.size()) { - uint32_t x = (U[i] << 16); - Res += Table[(x >> 18) & 63]; - Res += Table[(x >> 12) & 63]; - Res += "=="; - } else if (i + 2 == U.size()) { - uint32_t x = (U[i] << 16) + (U[i + 1] << 8); - Res += Table[(x >> 18) & 63]; - Res += Table[(x >> 12) & 63]; - Res += Table[(x >> 6) & 63]; - Res += "="; - } - return Res; -} - -static std::mutex SymbolizeMutex; - -std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) { - std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock); - if (!EF->__sanitizer_symbolize_pc || !l.owns_lock()) - return "<can not symbolize>"; - char PcDescr[1024] = {}; - EF->__sanitizer_symbolize_pc(reinterpret_cast<void*>(PC), - SymbolizedFMT, PcDescr, sizeof(PcDescr)); - PcDescr[sizeof(PcDescr) - 1] = 0; // Just in case. - return PcDescr; -} - -void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC) { - if (EF->__sanitizer_symbolize_pc) - Printf("%s", DescribePC(SymbolizedFMT, PC).c_str()); - else - Printf(FallbackFMT, PC); -} - -void PrintStackTrace() { - std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock); - if (EF->__sanitizer_print_stack_trace && l.owns_lock()) - EF->__sanitizer_print_stack_trace(); -} - -void PrintMemoryProfile() { - std::unique_lock<std::mutex> l(SymbolizeMutex, std::try_to_lock); - if (EF->__sanitizer_print_memory_profile && l.owns_lock()) - EF->__sanitizer_print_memory_profile(95, 8); -} - -unsigned NumberOfCpuCores() { - unsigned N = std::thread::hardware_concurrency(); - if (!N) { - Printf("WARNING: std::thread::hardware_concurrency not well defined for " - "your platform. Assuming CPU count of 1.\n"); - N = 1; - } - return N; -} - -size_t SimpleFastHash(const uint8_t *Data, size_t Size) { - size_t Res = 0; - for (size_t i = 0; i < Size; i++) - Res = Res * 11 + Data[i]; - return Res; -} - -} // namespace fuzzer diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtil.h b/chromium/third_party/libFuzzer/src/FuzzerUtil.h deleted file mode 100644 index d2f1d5de426..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerUtil.h +++ /dev/null @@ -1,93 +0,0 @@ -//===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Util functions. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_UTIL_H -#define LLVM_FUZZER_UTIL_H - -#include "FuzzerBuiltins.h" -#include "FuzzerBuiltinsMsvc.h" -#include "FuzzerCommand.h" -#include "FuzzerDefs.h" - -namespace fuzzer { - -void PrintHexArray(const Unit &U, const char *PrintAfter = ""); - -void PrintHexArray(const uint8_t *Data, size_t Size, - const char *PrintAfter = ""); - -void PrintASCII(const uint8_t *Data, size_t Size, const char *PrintAfter = ""); - -void PrintASCII(const Unit &U, const char *PrintAfter = ""); - -// Changes U to contain only ASCII (isprint+isspace) characters. -// Returns true iff U has been changed. -bool ToASCII(uint8_t *Data, size_t Size); - -bool IsASCII(const Unit &U); - -bool IsASCII(const uint8_t *Data, size_t Size); - -std::string Base64(const Unit &U); - -void PrintPC(const char *SymbolizedFMT, const char *FallbackFMT, uintptr_t PC); - -std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC); - -void PrintStackTrace(); - -void PrintMemoryProfile(); - -unsigned NumberOfCpuCores(); - -// Platform specific functions. -void SetSignalHandler(const FuzzingOptions& Options); - -void SleepSeconds(int Seconds); - -unsigned long GetPid(); - -size_t GetPeakRSSMb(); - -int ExecuteCommand(const Command &Cmd); - -FILE *OpenProcessPipe(const char *Command, const char *Mode); - -const void *SearchMemory(const void *haystack, size_t haystacklen, - const void *needle, size_t needlelen); - -std::string CloneArgsWithoutX(const Vector<std::string> &Args, - const char *X1, const char *X2); - -inline std::string CloneArgsWithoutX(const Vector<std::string> &Args, - const char *X) { - return CloneArgsWithoutX(Args, X, X); -} - -inline std::pair<std::string, std::string> SplitBefore(std::string X, - std::string S) { - auto Pos = S.find(X); - if (Pos == std::string::npos) - return std::make_pair(S, ""); - return std::make_pair(S.substr(0, Pos), S.substr(Pos)); -} - -std::string DisassembleCmd(const std::string &FileName); - -std::string SearchRegexCmd(const std::string &Regex); - -size_t SimpleFastHash(const uint8_t *Data, size_t Size); - -inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; } - -} // namespace fuzzer - -#endif // LLVM_FUZZER_UTIL_H diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilDarwin.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilDarwin.cpp deleted file mode 100644 index 4bfbc11a50c..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerUtilDarwin.cpp +++ /dev/null @@ -1,162 +0,0 @@ -//===- FuzzerUtilDarwin.cpp - Misc utils ----------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Misc utils for Darwin. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_APPLE -#include "FuzzerCommand.h" -#include "FuzzerIO.h" -#include <mutex> -#include <signal.h> -#include <spawn.h> -#include <stdlib.h> -#include <string.h> -#include <sys/wait.h> - -// There is no header for this on macOS so declare here -extern "C" char **environ; - -namespace fuzzer { - -static std::mutex SignalMutex; -// Global variables used to keep track of how signal handling should be -// restored. They should **not** be accessed without holding `SignalMutex`. -static int ActiveThreadCount = 0; -static struct sigaction OldSigIntAction; -static struct sigaction OldSigQuitAction; -static sigset_t OldBlockedSignalsSet; - -// This is a reimplementation of Libc's `system()`. On Darwin the Libc -// implementation contains a mutex which prevents it from being used -// concurrently. This implementation **can** be used concurrently. It sets the -// signal handlers when the first thread enters and restores them when the last -// thread finishes execution of the function and ensures this is not racey by -// using a mutex. -int ExecuteCommand(const Command &Cmd) { - std::string CmdLine = Cmd.toString(); - posix_spawnattr_t SpawnAttributes; - if (posix_spawnattr_init(&SpawnAttributes)) - return -1; - // Block and ignore signals of the current process when the first thread - // enters. - { - std::lock_guard<std::mutex> Lock(SignalMutex); - if (ActiveThreadCount == 0) { - static struct sigaction IgnoreSignalAction; - sigset_t BlockedSignalsSet; - memset(&IgnoreSignalAction, 0, sizeof(IgnoreSignalAction)); - IgnoreSignalAction.sa_handler = SIG_IGN; - - if (sigaction(SIGINT, &IgnoreSignalAction, &OldSigIntAction) == -1) { - Printf("Failed to ignore SIGINT\n"); - (void)posix_spawnattr_destroy(&SpawnAttributes); - return -1; - } - if (sigaction(SIGQUIT, &IgnoreSignalAction, &OldSigQuitAction) == -1) { - Printf("Failed to ignore SIGQUIT\n"); - // Try our best to restore the signal handlers. - (void)sigaction(SIGINT, &OldSigIntAction, NULL); - (void)posix_spawnattr_destroy(&SpawnAttributes); - return -1; - } - - (void)sigemptyset(&BlockedSignalsSet); - (void)sigaddset(&BlockedSignalsSet, SIGCHLD); - if (sigprocmask(SIG_BLOCK, &BlockedSignalsSet, &OldBlockedSignalsSet) == - -1) { - Printf("Failed to block SIGCHLD\n"); - // Try our best to restore the signal handlers. - (void)sigaction(SIGQUIT, &OldSigQuitAction, NULL); - (void)sigaction(SIGINT, &OldSigIntAction, NULL); - (void)posix_spawnattr_destroy(&SpawnAttributes); - return -1; - } - } - ++ActiveThreadCount; - } - - // NOTE: Do not introduce any new `return` statements past this - // point. It is important that `ActiveThreadCount` always be decremented - // when leaving this function. - - // Make sure the child process uses the default handlers for the - // following signals rather than inheriting what the parent has. - sigset_t DefaultSigSet; - (void)sigemptyset(&DefaultSigSet); - (void)sigaddset(&DefaultSigSet, SIGQUIT); - (void)sigaddset(&DefaultSigSet, SIGINT); - (void)posix_spawnattr_setsigdefault(&SpawnAttributes, &DefaultSigSet); - // Make sure the child process doesn't block SIGCHLD - (void)posix_spawnattr_setsigmask(&SpawnAttributes, &OldBlockedSignalsSet); - short SpawnFlags = POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; - (void)posix_spawnattr_setflags(&SpawnAttributes, SpawnFlags); - - pid_t Pid; - char **Environ = environ; // Read from global - const char *CommandCStr = CmdLine.c_str(); - char *const Argv[] = { - strdup("sh"), - strdup("-c"), - strdup(CommandCStr), - NULL - }; - int ErrorCode = 0, ProcessStatus = 0; - // FIXME: We probably shouldn't hardcode the shell path. - ErrorCode = posix_spawn(&Pid, "/bin/sh", NULL, &SpawnAttributes, - Argv, Environ); - (void)posix_spawnattr_destroy(&SpawnAttributes); - if (!ErrorCode) { - pid_t SavedPid = Pid; - do { - // Repeat until call completes uninterrupted. - Pid = waitpid(SavedPid, &ProcessStatus, /*options=*/0); - } while (Pid == -1 && errno == EINTR); - if (Pid == -1) { - // Fail for some other reason. - ProcessStatus = -1; - } - } else if (ErrorCode == ENOMEM || ErrorCode == EAGAIN) { - // Fork failure. - ProcessStatus = -1; - } else { - // Shell execution failure. - ProcessStatus = W_EXITCODE(127, 0); - } - for (unsigned i = 0, n = sizeof(Argv) / sizeof(Argv[0]); i < n; ++i) - free(Argv[i]); - - // Restore the signal handlers of the current process when the last thread - // using this function finishes. - { - std::lock_guard<std::mutex> Lock(SignalMutex); - --ActiveThreadCount; - if (ActiveThreadCount == 0) { - bool FailedRestore = false; - if (sigaction(SIGINT, &OldSigIntAction, NULL) == -1) { - Printf("Failed to restore SIGINT handling\n"); - FailedRestore = true; - } - if (sigaction(SIGQUIT, &OldSigQuitAction, NULL) == -1) { - Printf("Failed to restore SIGQUIT handling\n"); - FailedRestore = true; - } - if (sigprocmask(SIG_BLOCK, &OldBlockedSignalsSet, NULL) == -1) { - Printf("Failed to unblock SIGCHLD\n"); - FailedRestore = true; - } - if (FailedRestore) - ProcessStatus = -1; - } - } - return ProcessStatus; -} - -} // namespace fuzzer - -#endif // LIBFUZZER_APPLE diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilFuchsia.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilFuchsia.cpp deleted file mode 100644 index cd48fefef35..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerUtilFuchsia.cpp +++ /dev/null @@ -1,473 +0,0 @@ -//===- FuzzerUtilFuchsia.cpp - Misc utils for Fuchsia. --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Misc utils implementation using Fuchsia/Zircon APIs. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" - -#if LIBFUZZER_FUCHSIA - -#include "FuzzerInternal.h" -#include "FuzzerUtil.h" -#include <cerrno> -#include <cinttypes> -#include <cstdint> -#include <fcntl.h> -#include <lib/fdio/spawn.h> -#include <string> -#include <sys/select.h> -#include <thread> -#include <unistd.h> -#include <zircon/errors.h> -#include <zircon/process.h> -#include <zircon/sanitizer.h> -#include <zircon/status.h> -#include <zircon/syscalls.h> -#include <zircon/syscalls/debug.h> -#include <zircon/syscalls/exception.h> -#include <zircon/syscalls/port.h> -#include <zircon/types.h> - -namespace fuzzer { - -// Given that Fuchsia doesn't have the POSIX signals that libFuzzer was written -// around, the general approach is to spin up dedicated threads to watch for -// each requested condition (alarm, interrupt, crash). Of these, the crash -// handler is the most involved, as it requires resuming the crashed thread in -// order to invoke the sanitizers to get the needed state. - -// Forward declaration of assembly trampoline needed to resume crashed threads. -// This appears to have external linkage to C++, which is why it's not in the -// anonymous namespace. The assembly definition inside MakeTrampoline() -// actually defines the symbol with internal linkage only. -void CrashTrampolineAsm() __asm__("CrashTrampolineAsm"); - -namespace { - -// A magic value for the Zircon exception port, chosen to spell 'FUZZING' -// when interpreted as a byte sequence on little-endian platforms. -const uint64_t kFuzzingCrash = 0x474e495a5a5546; - -// Helper function to handle Zircon syscall failures. -void ExitOnErr(zx_status_t Status, const char *Syscall) { - if (Status != ZX_OK) { - Printf("libFuzzer: %s failed: %s\n", Syscall, - _zx_status_get_string(Status)); - exit(1); - } -} - -void AlarmHandler(int Seconds) { - while (true) { - SleepSeconds(Seconds); - Fuzzer::StaticAlarmCallback(); - } -} - -void InterruptHandler() { - fd_set readfds; - // Ctrl-C sends ETX in Zircon. - do { - FD_ZERO(&readfds); - FD_SET(STDIN_FILENO, &readfds); - select(STDIN_FILENO + 1, &readfds, nullptr, nullptr, nullptr); - } while(!FD_ISSET(STDIN_FILENO, &readfds) || getchar() != 0x03); - Fuzzer::StaticInterruptCallback(); -} - -// For the crash handler, we need to call Fuzzer::StaticCrashSignalCallback -// without POSIX signal handlers. To achieve this, we use an assembly function -// to add the necessary CFI unwinding information and a C function to bridge -// from that back into C++. - -// FIXME: This works as a short-term solution, but this code really shouldn't be -// architecture dependent. A better long term solution is to implement remote -// unwinding and expose the necessary APIs through sanitizer_common and/or ASAN -// to allow the exception handling thread to gather the crash state directly. -// -// Alternatively, Fuchsia may in future actually implement basic signal -// handling for the machine trap signals. -#if defined(__x86_64__) -#define FOREACH_REGISTER(OP_REG, OP_NUM) \ - OP_REG(rax) \ - OP_REG(rbx) \ - OP_REG(rcx) \ - OP_REG(rdx) \ - OP_REG(rsi) \ - OP_REG(rdi) \ - OP_REG(rbp) \ - OP_REG(rsp) \ - OP_REG(r8) \ - OP_REG(r9) \ - OP_REG(r10) \ - OP_REG(r11) \ - OP_REG(r12) \ - OP_REG(r13) \ - OP_REG(r14) \ - OP_REG(r15) \ - OP_REG(rip) - -#elif defined(__aarch64__) -#define FOREACH_REGISTER(OP_REG, OP_NUM) \ - OP_NUM(0) \ - OP_NUM(1) \ - OP_NUM(2) \ - OP_NUM(3) \ - OP_NUM(4) \ - OP_NUM(5) \ - OP_NUM(6) \ - OP_NUM(7) \ - OP_NUM(8) \ - OP_NUM(9) \ - OP_NUM(10) \ - OP_NUM(11) \ - OP_NUM(12) \ - OP_NUM(13) \ - OP_NUM(14) \ - OP_NUM(15) \ - OP_NUM(16) \ - OP_NUM(17) \ - OP_NUM(18) \ - OP_NUM(19) \ - OP_NUM(20) \ - OP_NUM(21) \ - OP_NUM(22) \ - OP_NUM(23) \ - OP_NUM(24) \ - OP_NUM(25) \ - OP_NUM(26) \ - OP_NUM(27) \ - OP_NUM(28) \ - OP_NUM(29) \ - OP_NUM(30) \ - OP_REG(sp) - -#else -#error "Unsupported architecture for fuzzing on Fuchsia" -#endif - -// Produces a CFI directive for the named or numbered register. -#define CFI_OFFSET_REG(reg) ".cfi_offset " #reg ", %c[" #reg "]\n" -#define CFI_OFFSET_NUM(num) CFI_OFFSET_REG(r##num) - -// Produces an assembler input operand for the named or numbered register. -#define ASM_OPERAND_REG(reg) \ - [reg] "i"(offsetof(zx_thread_state_general_regs_t, reg)), -#define ASM_OPERAND_NUM(num) \ - [r##num] "i"(offsetof(zx_thread_state_general_regs_t, r[num])), - -// Trampoline to bridge from the assembly below to the static C++ crash -// callback. -__attribute__((noreturn)) -static void StaticCrashHandler() { - Fuzzer::StaticCrashSignalCallback(); - for (;;) { - _Exit(1); - } -} - -// Creates the trampoline with the necessary CFI information to unwind through -// to the crashing call stack. The attribute is necessary because the function -// is never called; it's just a container around the assembly to allow it to -// use operands for compile-time computed constants. -__attribute__((used)) -void MakeTrampoline() { - __asm__(".cfi_endproc\n" - ".pushsection .text.CrashTrampolineAsm\n" - ".type CrashTrampolineAsm,STT_FUNC\n" -"CrashTrampolineAsm:\n" - ".cfi_startproc simple\n" - ".cfi_signal_frame\n" -#if defined(__x86_64__) - ".cfi_return_column rip\n" - ".cfi_def_cfa rsp, 0\n" - FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM) - "call %c[StaticCrashHandler]\n" - "ud2\n" -#elif defined(__aarch64__) - ".cfi_return_column 33\n" - ".cfi_def_cfa sp, 0\n" - ".cfi_offset 33, %c[pc]\n" - FOREACH_REGISTER(CFI_OFFSET_REG, CFI_OFFSET_NUM) - "bl %[StaticCrashHandler]\n" -#else -#error "Unsupported architecture for fuzzing on Fuchsia" -#endif - ".cfi_endproc\n" - ".size CrashTrampolineAsm, . - CrashTrampolineAsm\n" - ".popsection\n" - ".cfi_startproc\n" - : // No outputs - : FOREACH_REGISTER(ASM_OPERAND_REG, ASM_OPERAND_NUM) -#if defined(__aarch64__) - ASM_OPERAND_REG(pc) -#endif - [StaticCrashHandler] "i" (StaticCrashHandler)); -} - -void CrashHandler(zx_handle_t *Event) { - // This structure is used to ensure we close handles to objects we create in - // this handler. - struct ScopedHandle { - ~ScopedHandle() { _zx_handle_close(Handle); } - zx_handle_t Handle = ZX_HANDLE_INVALID; - }; - - // Create and bind the exception port. We need to claim to be a "debugger" so - // the kernel will allow us to modify and resume dying threads (see below). - // Once the port is set, we can signal the main thread to continue and wait - // for the exception to arrive. - ScopedHandle Port; - ExitOnErr(_zx_port_create(0, &Port.Handle), "_zx_port_create"); - zx_handle_t Self = _zx_process_self(); - - ExitOnErr(_zx_task_bind_exception_port(Self, Port.Handle, kFuzzingCrash, - ZX_EXCEPTION_PORT_DEBUGGER), - "_zx_task_bind_exception_port"); - - ExitOnErr(_zx_object_signal(*Event, 0, ZX_USER_SIGNAL_0), - "_zx_object_signal"); - - zx_port_packet_t Packet; - ExitOnErr(_zx_port_wait(Port.Handle, ZX_TIME_INFINITE, &Packet), - "_zx_port_wait"); - - // At this point, we want to get the state of the crashing thread, but - // libFuzzer and the sanitizers assume this will happen from that same thread - // via a POSIX signal handler. "Resurrecting" the thread in the middle of the - // appropriate callback is as simple as forcibly setting the instruction - // pointer/program counter, provided we NEVER EVER return from that function - // (since otherwise our stack will not be valid). - ScopedHandle Thread; - ExitOnErr(_zx_object_get_child(Self, Packet.exception.tid, - ZX_RIGHT_SAME_RIGHTS, &Thread.Handle), - "_zx_object_get_child"); - - zx_thread_state_general_regs_t GeneralRegisters; - ExitOnErr(_zx_thread_read_state(Thread.Handle, ZX_THREAD_STATE_GENERAL_REGS, - &GeneralRegisters, sizeof(GeneralRegisters)), - "_zx_thread_read_state"); - - // To unwind properly, we need to push the crashing thread's register state - // onto the stack and jump into a trampoline with CFI instructions on how - // to restore it. -#if defined(__x86_64__) - uintptr_t StackPtr = - (GeneralRegisters.rsp - (128 + sizeof(GeneralRegisters))) & - -(uintptr_t)16; - __unsanitized_memcpy(reinterpret_cast<void *>(StackPtr), &GeneralRegisters, - sizeof(GeneralRegisters)); - GeneralRegisters.rsp = StackPtr; - GeneralRegisters.rip = reinterpret_cast<zx_vaddr_t>(CrashTrampolineAsm); - -#elif defined(__aarch64__) - uintptr_t StackPtr = - (GeneralRegisters.sp - sizeof(GeneralRegisters)) & -(uintptr_t)16; - __unsanitized_memcpy(reinterpret_cast<void *>(StackPtr), &GeneralRegisters, - sizeof(GeneralRegisters)); - GeneralRegisters.sp = StackPtr; - GeneralRegisters.pc = reinterpret_cast<zx_vaddr_t>(CrashTrampolineAsm); - -#else -#error "Unsupported architecture for fuzzing on Fuchsia" -#endif - - // Now force the crashing thread's state. - ExitOnErr(_zx_thread_write_state(Thread.Handle, ZX_THREAD_STATE_GENERAL_REGS, - &GeneralRegisters, sizeof(GeneralRegisters)), - "_zx_thread_write_state"); - - ExitOnErr(_zx_task_resume_from_exception(Thread.Handle, Port.Handle, 0), - "_zx_task_resume_from_exception"); -} - -} // namespace - -// Platform specific functions. -void SetSignalHandler(const FuzzingOptions &Options) { - // Set up alarm handler if needed. - if (Options.UnitTimeoutSec > 0) { - std::thread T(AlarmHandler, Options.UnitTimeoutSec / 2 + 1); - T.detach(); - } - - // Set up interrupt handler if needed. - if (Options.HandleInt || Options.HandleTerm) { - std::thread T(InterruptHandler); - T.detach(); - } - - // Early exit if no crash handler needed. - if (!Options.HandleSegv && !Options.HandleBus && !Options.HandleIll && - !Options.HandleFpe && !Options.HandleAbrt) - return; - - // Set up the crash handler and wait until it is ready before proceeding. - zx_handle_t Event; - ExitOnErr(_zx_event_create(0, &Event), "_zx_event_create"); - - std::thread T(CrashHandler, &Event); - zx_status_t Status = - _zx_object_wait_one(Event, ZX_USER_SIGNAL_0, ZX_TIME_INFINITE, nullptr); - _zx_handle_close(Event); - ExitOnErr(Status, "_zx_object_wait_one"); - - T.detach(); -} - -void SleepSeconds(int Seconds) { - _zx_nanosleep(_zx_deadline_after(ZX_SEC(Seconds))); -} - -unsigned long GetPid() { - zx_status_t rc; - zx_info_handle_basic_t Info; - if ((rc = _zx_object_get_info(_zx_process_self(), ZX_INFO_HANDLE_BASIC, &Info, - sizeof(Info), NULL, NULL)) != ZX_OK) { - Printf("libFuzzer: unable to get info about self: %s\n", - _zx_status_get_string(rc)); - exit(1); - } - return Info.koid; -} - -size_t GetPeakRSSMb() { - zx_status_t rc; - zx_info_task_stats_t Info; - if ((rc = _zx_object_get_info(_zx_process_self(), ZX_INFO_TASK_STATS, &Info, - sizeof(Info), NULL, NULL)) != ZX_OK) { - Printf("libFuzzer: unable to get info about self: %s\n", - _zx_status_get_string(rc)); - exit(1); - } - return (Info.mem_private_bytes + Info.mem_shared_bytes) >> 20; -} - -template <typename Fn> -class RunOnDestruction { - public: - explicit RunOnDestruction(Fn fn) : fn_(fn) {} - ~RunOnDestruction() { fn_(); } - - private: - Fn fn_; -}; - -template <typename Fn> -RunOnDestruction<Fn> at_scope_exit(Fn fn) { - return RunOnDestruction<Fn>(fn); -} - -int ExecuteCommand(const Command &Cmd) { - zx_status_t rc; - - // Convert arguments to C array - auto Args = Cmd.getArguments(); - size_t Argc = Args.size(); - assert(Argc != 0); - std::unique_ptr<const char *[]> Argv(new const char *[Argc + 1]); - for (size_t i = 0; i < Argc; ++i) - Argv[i] = Args[i].c_str(); - Argv[Argc] = nullptr; - - // Determine output. On Fuchsia, the fuzzer is typically run as a component - // that lacks a mutable working directory. Fortunately, when this is the case - // a mutable output directory must be specified using "-artifact_prefix=...", - // so write the log file(s) there. - int FdOut = STDOUT_FILENO; - if (Cmd.hasOutputFile()) { - std::string Path; - if (Cmd.hasFlag("artifact_prefix")) - Path = Cmd.getFlagValue("artifact_prefix") + "/" + Cmd.getOutputFile(); - else - Path = Cmd.getOutputFile(); - FdOut = open(Path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0); - if (FdOut == -1) { - Printf("libFuzzer: failed to open %s: %s\n", Path.c_str(), - strerror(errno)); - return ZX_ERR_IO; - } - } - auto CloseFdOut = at_scope_exit([FdOut]() { - if (FdOut != STDOUT_FILENO) - close(FdOut); - }); - - // Determine stderr - int FdErr = STDERR_FILENO; - if (Cmd.isOutAndErrCombined()) - FdErr = FdOut; - - // Clone the file descriptors into the new process - fdio_spawn_action_t SpawnAction[] = { - { - .action = FDIO_SPAWN_ACTION_CLONE_FD, - .fd = - { - .local_fd = STDIN_FILENO, - .target_fd = STDIN_FILENO, - }, - }, - { - .action = FDIO_SPAWN_ACTION_CLONE_FD, - .fd = - { - .local_fd = FdOut, - .target_fd = STDOUT_FILENO, - }, - }, - { - .action = FDIO_SPAWN_ACTION_CLONE_FD, - .fd = - { - .local_fd = FdErr, - .target_fd = STDERR_FILENO, - }, - }, - }; - - // Start the process. - char ErrorMsg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH]; - zx_handle_t ProcessHandle = ZX_HANDLE_INVALID; - rc = fdio_spawn_etc( - ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL & (~FDIO_SPAWN_CLONE_STDIO), - Argv[0], Argv.get(), nullptr, 3, SpawnAction, &ProcessHandle, ErrorMsg); - if (rc != ZX_OK) { - Printf("libFuzzer: failed to launch '%s': %s, %s\n", Argv[0], ErrorMsg, - _zx_status_get_string(rc)); - return rc; - } - auto CloseHandle = at_scope_exit([&]() { _zx_handle_close(ProcessHandle); }); - - // Now join the process and return the exit status. - if ((rc = _zx_object_wait_one(ProcessHandle, ZX_PROCESS_TERMINATED, - ZX_TIME_INFINITE, nullptr)) != ZX_OK) { - Printf("libFuzzer: failed to join '%s': %s\n", Argv[0], - _zx_status_get_string(rc)); - return rc; - } - - zx_info_process_t Info; - if ((rc = _zx_object_get_info(ProcessHandle, ZX_INFO_PROCESS, &Info, - sizeof(Info), nullptr, nullptr)) != ZX_OK) { - Printf("libFuzzer: unable to get return code from '%s': %s\n", Argv[0], - _zx_status_get_string(rc)); - return rc; - } - - return Info.return_code; -} - -const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, - size_t PattLen) { - return memmem(Data, DataLen, Patt, PattLen); -} - -} // namespace fuzzer - -#endif // LIBFUZZER_FUCHSIA diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilLinux.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilLinux.cpp deleted file mode 100644 index c103fd230b0..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerUtilLinux.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//===- FuzzerUtilLinux.cpp - Misc utils for Linux. ------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Misc utils for Linux. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ - LIBFUZZER_OPENBSD -#include "FuzzerCommand.h" - -#include <stdlib.h> - -namespace fuzzer { - -int ExecuteCommand(const Command &Cmd) { - std::string CmdLine = Cmd.toString(); - return system(CmdLine.c_str()); -} - -} // namespace fuzzer - -#endif diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilPosix.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilPosix.cpp deleted file mode 100644 index bc64d329370..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerUtilPosix.cpp +++ /dev/null @@ -1,152 +0,0 @@ -//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Misc utils implementation using Posix API. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_POSIX -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include <cassert> -#include <chrono> -#include <cstring> -#include <errno.h> -#include <iomanip> -#include <signal.h> -#include <stdio.h> -#include <sys/resource.h> -#include <sys/syscall.h> -#include <sys/time.h> -#include <sys/types.h> -#include <thread> -#include <unistd.h> - -namespace fuzzer { - -static void AlarmHandler(int, siginfo_t *, void *) { - Fuzzer::StaticAlarmCallback(); -} - -static void CrashHandler(int, siginfo_t *, void *) { - Fuzzer::StaticCrashSignalCallback(); -} - -static void InterruptHandler(int, siginfo_t *, void *) { - Fuzzer::StaticInterruptCallback(); -} - -static void GracefulExitHandler(int, siginfo_t *, void *) { - Fuzzer::StaticGracefulExitCallback(); -} - -static void FileSizeExceedHandler(int, siginfo_t *, void *) { - Fuzzer::StaticFileSizeExceedCallback(); -} - -static void SetSigaction(int signum, - void (*callback)(int, siginfo_t *, void *)) { - struct sigaction sigact = {}; - if (sigaction(signum, nullptr, &sigact)) { - Printf("libFuzzer: sigaction failed with %d\n", errno); - exit(1); - } - if (sigact.sa_flags & SA_SIGINFO) { - if (sigact.sa_sigaction) - return; - } else { - if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && - sigact.sa_handler != SIG_ERR) - return; - } - - sigact = {}; - sigact.sa_sigaction = callback; - if (sigaction(signum, &sigact, 0)) { - Printf("libFuzzer: sigaction failed with %d\n", errno); - exit(1); - } -} - -void SetTimer(int Seconds) { - struct itimerval T { - {Seconds, 0}, { Seconds, 0 } - }; - if (setitimer(ITIMER_REAL, &T, nullptr)) { - Printf("libFuzzer: setitimer failed with %d\n", errno); - exit(1); - } - SetSigaction(SIGALRM, AlarmHandler); -} - -void SetSignalHandler(const FuzzingOptions& Options) { - if (Options.UnitTimeoutSec > 0) - SetTimer(Options.UnitTimeoutSec / 2 + 1); - if (Options.HandleInt) - SetSigaction(SIGINT, InterruptHandler); - if (Options.HandleTerm) - SetSigaction(SIGTERM, InterruptHandler); - if (Options.HandleSegv) - SetSigaction(SIGSEGV, CrashHandler); - if (Options.HandleBus) - SetSigaction(SIGBUS, CrashHandler); - if (Options.HandleAbrt) - SetSigaction(SIGABRT, CrashHandler); - if (Options.HandleIll) - SetSigaction(SIGILL, CrashHandler); - if (Options.HandleFpe) - SetSigaction(SIGFPE, CrashHandler); - if (Options.HandleXfsz) - SetSigaction(SIGXFSZ, FileSizeExceedHandler); - if (Options.HandleUsr1) - SetSigaction(SIGUSR1, GracefulExitHandler); - if (Options.HandleUsr2) - SetSigaction(SIGUSR2, GracefulExitHandler); -} - -void SleepSeconds(int Seconds) { - sleep(Seconds); // Use C API to avoid coverage from instrumented libc++. -} - -unsigned long GetPid() { return (unsigned long)getpid(); } - -size_t GetPeakRSSMb() { - struct rusage usage; - if (getrusage(RUSAGE_SELF, &usage)) - return 0; - if (LIBFUZZER_LINUX || LIBFUZZER_FREEBSD || LIBFUZZER_NETBSD || - LIBFUZZER_OPENBSD) { - // ru_maxrss is in KiB - return usage.ru_maxrss >> 10; - } else if (LIBFUZZER_APPLE) { - // ru_maxrss is in bytes - return usage.ru_maxrss >> 20; - } - assert(0 && "GetPeakRSSMb() is not implemented for your platform"); - return 0; -} - -FILE *OpenProcessPipe(const char *Command, const char *Mode) { - return popen(Command, Mode); -} - -const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, - size_t PattLen) { - return memmem(Data, DataLen, Patt, PattLen); -} - -std::string DisassembleCmd(const std::string &FileName) { - return "objdump -d " + FileName; -} - -std::string SearchRegexCmd(const std::string &Regex) { - return "grep '" + Regex + "'"; -} - -} // namespace fuzzer - -#endif // LIBFUZZER_POSIX diff --git a/chromium/third_party/libFuzzer/src/FuzzerUtilWindows.cpp b/chromium/third_party/libFuzzer/src/FuzzerUtilWindows.cpp deleted file mode 100644 index 393b4768be7..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerUtilWindows.cpp +++ /dev/null @@ -1,196 +0,0 @@ -//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// Misc utils implementation for Windows. -//===----------------------------------------------------------------------===// -#include "FuzzerDefs.h" -#if LIBFUZZER_WINDOWS -#include "FuzzerCommand.h" -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include <cassert> -#include <chrono> -#include <cstring> -#include <errno.h> -#include <iomanip> -#include <signal.h> -#include <stdio.h> -#include <sys/types.h> -#include <windows.h> - -// This must be included after windows.h. -#include <psapi.h> - -namespace fuzzer { - -static const FuzzingOptions* HandlerOpt = nullptr; - -static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) { - switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { - case EXCEPTION_ACCESS_VIOLATION: - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - case EXCEPTION_STACK_OVERFLOW: - if (HandlerOpt->HandleSegv) - Fuzzer::StaticCrashSignalCallback(); - break; - case EXCEPTION_DATATYPE_MISALIGNMENT: - case EXCEPTION_IN_PAGE_ERROR: - if (HandlerOpt->HandleBus) - Fuzzer::StaticCrashSignalCallback(); - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - case EXCEPTION_PRIV_INSTRUCTION: - if (HandlerOpt->HandleIll) - Fuzzer::StaticCrashSignalCallback(); - break; - case EXCEPTION_FLT_DENORMAL_OPERAND: - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - case EXCEPTION_FLT_INEXACT_RESULT: - case EXCEPTION_FLT_INVALID_OPERATION: - case EXCEPTION_FLT_OVERFLOW: - case EXCEPTION_FLT_STACK_CHECK: - case EXCEPTION_FLT_UNDERFLOW: - case EXCEPTION_INT_DIVIDE_BY_ZERO: - case EXCEPTION_INT_OVERFLOW: - if (HandlerOpt->HandleFpe) - Fuzzer::StaticCrashSignalCallback(); - break; - // TODO: handle (Options.HandleXfsz) - } - return EXCEPTION_CONTINUE_SEARCH; -} - -BOOL WINAPI CtrlHandler(DWORD dwCtrlType) { - switch (dwCtrlType) { - case CTRL_C_EVENT: - if (HandlerOpt->HandleInt) - Fuzzer::StaticInterruptCallback(); - return TRUE; - case CTRL_BREAK_EVENT: - if (HandlerOpt->HandleTerm) - Fuzzer::StaticInterruptCallback(); - return TRUE; - } - return FALSE; -} - -void CALLBACK AlarmHandler(PVOID, BOOLEAN) { - Fuzzer::StaticAlarmCallback(); -} - -class TimerQ { - HANDLE TimerQueue; - public: - TimerQ() : TimerQueue(NULL) {}; - ~TimerQ() { - if (TimerQueue) - DeleteTimerQueueEx(TimerQueue, NULL); - }; - void SetTimer(int Seconds) { - if (!TimerQueue) { - TimerQueue = CreateTimerQueue(); - if (!TimerQueue) { - Printf("libFuzzer: CreateTimerQueue failed.\n"); - exit(1); - } - } - HANDLE Timer; - if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL, - Seconds*1000, Seconds*1000, 0)) { - Printf("libFuzzer: CreateTimerQueueTimer failed.\n"); - exit(1); - } - }; -}; - -static TimerQ Timer; - -static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); } - -void SetSignalHandler(const FuzzingOptions& Options) { - HandlerOpt = &Options; - - if (Options.UnitTimeoutSec > 0) - Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1); - - if (Options.HandleInt || Options.HandleTerm) - if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) { - DWORD LastError = GetLastError(); - Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n", - LastError); - exit(1); - } - - if (Options.HandleSegv || Options.HandleBus || Options.HandleIll || - Options.HandleFpe) - SetUnhandledExceptionFilter(ExceptionHandler); - - if (Options.HandleAbrt) - if (SIG_ERR == signal(SIGABRT, CrashHandler)) { - Printf("libFuzzer: signal failed with %d\n", errno); - exit(1); - } -} - -void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); } - -unsigned long GetPid() { return GetCurrentProcessId(); } - -size_t GetPeakRSSMb() { - PROCESS_MEMORY_COUNTERS info; - if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info))) - return 0; - return info.PeakWorkingSetSize >> 20; -} - -FILE *OpenProcessPipe(const char *Command, const char *Mode) { - return _popen(Command, Mode); -} - -int ExecuteCommand(const Command &Cmd) { - std::string CmdLine = Cmd.toString(); - return system(CmdLine.c_str()); -} - -const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, - size_t PattLen) { - // TODO: make this implementation more efficient. - const char *Cdata = (const char *)Data; - const char *Cpatt = (const char *)Patt; - - if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen) - return NULL; - - if (PattLen == 1) - return memchr(Data, *Cpatt, DataLen); - - const char *End = Cdata + DataLen - PattLen + 1; - - for (const char *It = Cdata; It < End; ++It) - if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0) - return It; - - return NULL; -} - -std::string DisassembleCmd(const std::string &FileName) { - Vector<std::string> command_vector; - command_vector.push_back("dumpbin /summary > nul"); - if (ExecuteCommand(Command(command_vector)) == 0) - return "dumpbin /disasm " + FileName; - Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n"); - exit(1); -} - -std::string SearchRegexCmd(const std::string &Regex) { - return "findstr /r \"" + Regex + "\""; -} - -} // namespace fuzzer - -#endif // LIBFUZZER_WINDOWS diff --git a/chromium/third_party/libFuzzer/src/FuzzerValueBitMap.h b/chromium/third_party/libFuzzer/src/FuzzerValueBitMap.h deleted file mode 100644 index 13d7cbd95dd..00000000000 --- a/chromium/third_party/libFuzzer/src/FuzzerValueBitMap.h +++ /dev/null @@ -1,73 +0,0 @@ -//===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// ValueBitMap. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_VALUE_BIT_MAP_H -#define LLVM_FUZZER_VALUE_BIT_MAP_H - -#include "FuzzerDefs.h" - -namespace fuzzer { - -// A bit map containing kMapSizeInWords bits. -struct ValueBitMap { - static const size_t kMapSizeInBits = 1 << 16; - static const size_t kMapPrimeMod = 65371; // Largest Prime < kMapSizeInBits; - static const size_t kBitsInWord = (sizeof(uintptr_t) * 8); - static const size_t kMapSizeInWords = kMapSizeInBits / kBitsInWord; - public: - - // Clears all bits. - void Reset() { memset(Map, 0, sizeof(Map)); } - - // Computes a hash function of Value and sets the corresponding bit. - // Returns true if the bit was changed from 0 to 1. - ATTRIBUTE_NO_SANITIZE_ALL - inline bool AddValue(uintptr_t Value) { - uintptr_t Idx = Value % kMapSizeInBits; - uintptr_t WordIdx = Idx / kBitsInWord; - uintptr_t BitIdx = Idx % kBitsInWord; - uintptr_t Old = Map[WordIdx]; - uintptr_t New = Old | (1UL << BitIdx); - Map[WordIdx] = New; - return New != Old; - } - - ATTRIBUTE_NO_SANITIZE_ALL - inline bool AddValueModPrime(uintptr_t Value) { - return AddValue(Value % kMapPrimeMod); - } - - inline bool Get(uintptr_t Idx) { - assert(Idx < kMapSizeInBits); - uintptr_t WordIdx = Idx / kBitsInWord; - uintptr_t BitIdx = Idx % kBitsInWord; - return Map[WordIdx] & (1UL << BitIdx); - } - - size_t SizeInBits() const { return kMapSizeInBits; } - - template <class Callback> - ATTRIBUTE_NO_SANITIZE_ALL - void ForEach(Callback CB) const { - for (size_t i = 0; i < kMapSizeInWords; i++) - if (uintptr_t M = Map[i]) - for (size_t j = 0; j < sizeof(M) * 8; j++) - if (M & ((uintptr_t)1 << j)) - CB(i * sizeof(M) * 8 + j); - } - - private: - uintptr_t Map[kMapSizeInWords] __attribute__((aligned(512))); -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_VALUE_BIT_MAP_H diff --git a/chromium/third_party/libFuzzer/src/README.txt b/chromium/third_party/libFuzzer/src/README.txt deleted file mode 100644 index 3eee01c7767..00000000000 --- a/chromium/third_party/libFuzzer/src/README.txt +++ /dev/null @@ -1 +0,0 @@ -See http://llvm.org/docs/LibFuzzer.html diff --git a/chromium/third_party/libFuzzer/src/afl/afl_driver.cpp b/chromium/third_party/libFuzzer/src/afl/afl_driver.cpp deleted file mode 100644 index 5a10c0d27f3..00000000000 --- a/chromium/third_party/libFuzzer/src/afl/afl_driver.cpp +++ /dev/null @@ -1,378 +0,0 @@ -//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===// - -/* This file allows to fuzz libFuzzer-style target functions - (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode. - -Usage: -################################################################################ -cat << EOF > test_fuzzer.cc -#include <stddef.h> -#include <stdint.h> -extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - if (size > 0 && data[0] == 'H') - if (size > 1 && data[1] == 'I') - if (size > 2 && data[2] == '!') - __builtin_trap(); - return 0; -} -EOF -# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. -clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c -# Build afl-llvm-rt.o.c from the AFL distribution. -clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c -# Build this file, link it with afl-llvm-rt.o.o and the target code. -clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o -# Run AFL: -rm -rf IN OUT; mkdir IN OUT; echo z > IN/z; -$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out -################################################################################ -Environment Variables: -There are a few environment variables that can be set to use features that -afl-fuzz doesn't have. - -AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file -specified. If the file does not exist, it is created. This is useful for getting -stack traces (when using ASAN for example) or original error messages on hard to -reproduce bugs. - -AFL_DRIVER_EXTRA_STATS_FILENAME: Setting this causes afl_driver to write extra -statistics to the file specified. Currently these are peak_rss_mb -(the peak amount of virtual memory used in MB) and slowest_unit_time_secs. If -the file does not exist it is created. If the file does exist then -afl_driver assumes it was restarted by afl-fuzz and will try to read old -statistics from the file. If that fails then the process will quit. - -*/ -#include <assert.h> -#include <errno.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/resource.h> -#include <sys/time.h> -#include <unistd.h> - -#include <fstream> -#include <iostream> -#include <vector> - -// Platform detection. Copied from FuzzerInternal.h -#ifdef __linux__ -#define LIBFUZZER_LINUX 1 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __APPLE__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 1 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __NetBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 1 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 0 -#elif __FreeBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 1 -#define LIBFUZZER_OPENBSD 0 -#elif __OpenBSD__ -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_OPENBSD 1 -#else -#error "Support for your platform has not been implemented" -#endif - -// Used to avoid repeating error checking boilerplate. If cond is false, a -// fatal error has occurred in the program. In this event print error_message -// to stderr and abort(). Otherwise do nothing. Note that setting -// AFL_DRIVER_STDERR_DUPLICATE_FILENAME may cause error_message to be appended -// to the file as well, if the error occurs after the duplication is performed. -#define CHECK_ERROR(cond, error_message) \ - if (!(cond)) { \ - fprintf(stderr, "%s\n", (error_message)); \ - abort(); \ - } - -// libFuzzer interface is thin, so we don't include any libFuzzer headers. -extern "C" { -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); -__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); -} - -// Notify AFL about persistent mode. -static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; -extern "C" int __afl_persistent_loop(unsigned int); -static volatile char suppress_warning2 = AFL_PERSISTENT[0]; - -// Notify AFL about deferred forkserver. -static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; -extern "C" void __afl_manual_init(); -static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0]; - -// Input buffer. -static const size_t kMaxAflInputSize = 1 << 20; -static uint8_t AflInputBuf[kMaxAflInputSize]; - -// Variables we need for writing to the extra stats file. -static FILE *extra_stats_file = NULL; -static uint32_t previous_peak_rss = 0; -static time_t slowest_unit_time_secs = 0; -static const int kNumExtraStats = 2; -static const char *kExtraStatsFormatString = "peak_rss_mb : %u\n" - "slowest_unit_time_sec : %u\n"; - -// Experimental feature to use afl_driver without AFL's deferred mode. -// Needs to run before __afl_auto_init. -__attribute__((constructor(0))) void __decide_deferred_forkserver(void) { - if (getenv("AFL_DRIVER_DONT_DEFER")) { - if (unsetenv("__AFL_DEFER_FORKSRV")) { - perror("Failed to unset __AFL_DEFER_FORKSRV"); - abort(); - } - } -} - -// Copied from FuzzerUtil.cpp. -size_t GetPeakRSSMb() { - struct rusage usage; - if (getrusage(RUSAGE_SELF, &usage)) - return 0; - if (LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || - LIBFUZZER_OPENBSD) { - // ru_maxrss is in KiB - return usage.ru_maxrss >> 10; - } else if (LIBFUZZER_APPLE) { - // ru_maxrss is in bytes - return usage.ru_maxrss >> 20; - } - assert(0 && "GetPeakRSSMb() is not implemented for your platform"); - return 0; -} - -// Based on SetSigaction in FuzzerUtil.cpp -static void SetSigaction(int signum, - void (*callback)(int, siginfo_t *, void *)) { - struct sigaction sigact; - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_sigaction = callback; - if (sigaction(signum, &sigact, 0)) { - fprintf(stderr, "libFuzzer: sigaction failed with %d\n", errno); - exit(1); - } -} - -// Write extra stats to the file specified by the user. If none is specified -// this function will never be called. -static void write_extra_stats() { - uint32_t peak_rss = GetPeakRSSMb(); - - if (peak_rss < previous_peak_rss) - peak_rss = previous_peak_rss; - - int chars_printed = fprintf(extra_stats_file, kExtraStatsFormatString, - peak_rss, slowest_unit_time_secs); - - CHECK_ERROR(chars_printed != 0, "Failed to write extra_stats_file"); - - CHECK_ERROR(fclose(extra_stats_file) == 0, - "Failed to close extra_stats_file"); -} - -// Call write_extra_stats before we exit. -static void crash_handler(int, siginfo_t *, void *) { - // Make sure we don't try calling write_extra_stats again if we crashed while - // trying to call it. - static bool first_crash = true; - CHECK_ERROR(first_crash, - "Crashed in crash signal handler. This is a bug in the fuzzer."); - - first_crash = false; - write_extra_stats(); -} - -// If the user has specified an extra_stats_file through the environment -// variable AFL_DRIVER_EXTRA_STATS_FILENAME, then perform necessary set up -// to write stats to it on exit. If no file is specified, do nothing. Otherwise -// install signal and exit handlers to write to the file when the process exits. -// Then if the file doesn't exist create it and set extra stats to 0. But if it -// does exist then read the initial values of the extra stats from the file -// and check that the file is writable. -static void maybe_initialize_extra_stats() { - // If AFL_DRIVER_EXTRA_STATS_FILENAME isn't set then we have nothing to do. - char *extra_stats_filename = getenv("AFL_DRIVER_EXTRA_STATS_FILENAME"); - if (!extra_stats_filename) - return; - - // Open the file and find the previous peak_rss_mb value. - // This is necessary because the fuzzing process is restarted after N - // iterations are completed. So we may need to get this value from a previous - // process to be accurate. - extra_stats_file = fopen(extra_stats_filename, "r"); - - // If extra_stats_file already exists: read old stats from it. - if (extra_stats_file) { - int matches = fscanf(extra_stats_file, kExtraStatsFormatString, - &previous_peak_rss, &slowest_unit_time_secs); - - // Make sure we have read a real extra stats file and that we have used it - // to set slowest_unit_time_secs and previous_peak_rss. - CHECK_ERROR(matches == kNumExtraStats, "Extra stats file is corrupt"); - - CHECK_ERROR(fclose(extra_stats_file) == 0, "Failed to close file"); - - // Now open the file for writing. - extra_stats_file = fopen(extra_stats_filename, "w"); - CHECK_ERROR(extra_stats_file, - "Failed to open extra stats file for writing"); - } else { - // Looks like this is the first time in a fuzzing job this is being called. - extra_stats_file = fopen(extra_stats_filename, "w+"); - CHECK_ERROR(extra_stats_file, "failed to create extra stats file"); - } - - // Make sure that crash_handler gets called on any kind of fatal error. - int crash_signals[] = {SIGSEGV, SIGBUS, SIGABRT, SIGILL, SIGFPE, SIGINT, - SIGTERM}; - - const size_t num_signals = sizeof(crash_signals) / sizeof(crash_signals[0]); - - for (size_t idx = 0; idx < num_signals; idx++) - SetSigaction(crash_signals[idx], crash_handler); - - // Make sure it gets called on other kinds of exits. - atexit(write_extra_stats); -} - -// If the user asks us to duplicate stderr, then do it. -static void maybe_duplicate_stderr() { - char* stderr_duplicate_filename = - getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); - - if (!stderr_duplicate_filename) - return; - - FILE* stderr_duplicate_stream = - freopen(stderr_duplicate_filename, "a+", stderr); - - if (!stderr_duplicate_stream) { - fprintf( - stderr, - "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); - abort(); - } -} - -// Define LLVMFuzzerMutate to avoid link failures for targets that use it -// with libFuzzer's LLVMFuzzerCustomMutator. -extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { - assert(false && "LLVMFuzzerMutate should not be called from afl_driver"); - return 0; -} - -// Execute any files provided as parameters. -int ExecuteFilesOnyByOne(int argc, char **argv) { - for (int i = 1; i < argc; i++) { - std::ifstream in(argv[i], std::ios::binary); - in.seekg(0, in.end); - size_t length = in.tellg(); - in.seekg (0, in.beg); - std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl; - // Allocate exactly length bytes so that we reliably catch buffer overflows. - std::vector<char> bytes(length); - in.read(bytes.data(), bytes.size()); - assert(in); - LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t *>(bytes.data()), - bytes.size()); - std::cout << "Execution successful" << std::endl; - } - return 0; -} - -int main(int argc, char **argv) { - fprintf(stderr, - "======================= INFO =========================\n" - "This binary is built for AFL-fuzz.\n" - "To run the target function on individual input(s) execute this:\n" - " %s < INPUT_FILE\n" - "or\n" - " %s INPUT_FILE1 [INPUT_FILE2 ... ]\n" - "To fuzz with afl-fuzz execute this:\n" - " afl-fuzz [afl-flags] %s [-N]\n" - "afl-fuzz will run N iterations before " - "re-spawning the process (default: 1000)\n" - "======================================================\n", - argv[0], argv[0], argv[0]); - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); - // Do any other expensive one-time initialization here. - - maybe_duplicate_stderr(); - maybe_initialize_extra_stats(); - - if (!getenv("AFL_DRIVER_DONT_DEFER")) - __afl_manual_init(); - - int N = 1000; - if (argc == 2 && argv[1][0] == '-') - N = atoi(argv[1] + 1); - else if(argc == 2 && (N = atoi(argv[1])) > 0) - fprintf(stderr, "WARNING: using the deprecated call style `%s %d`\n", - argv[0], N); - else if (argc > 1) - return ExecuteFilesOnyByOne(argc, argv); - - assert(N > 0); - - // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization - // on the first execution of LLVMFuzzerTestOneInput is ignored. - uint8_t dummy_input[1] = {0}; - LLVMFuzzerTestOneInput(dummy_input, 1); - - time_t unit_time_secs; - int num_runs = 0; - while (__afl_persistent_loop(N)) { - ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize); - if (n_read > 0) { - // Copy AflInputBuf into a separate buffer to let asan find buffer - // overflows. Don't use unique_ptr/etc to avoid extra dependencies. - uint8_t *copy = new uint8_t[n_read]; - memcpy(copy, AflInputBuf, n_read); - - struct timeval unit_start_time; - CHECK_ERROR(gettimeofday(&unit_start_time, NULL) == 0, - "Calling gettimeofday failed"); - - num_runs++; - LLVMFuzzerTestOneInput(copy, n_read); - - struct timeval unit_stop_time; - CHECK_ERROR(gettimeofday(&unit_stop_time, NULL) == 0, - "Calling gettimeofday failed"); - - // Update slowest_unit_time_secs if we see a new max. - unit_time_secs = unit_stop_time.tv_sec - unit_start_time.tv_sec; - if (slowest_unit_time_secs < unit_time_secs) - slowest_unit_time_secs = unit_time_secs; - - delete[] copy; - } - } - fprintf(stderr, "%s: successfully executed %d input(s)\n", argv[0], num_runs); -} diff --git a/chromium/third_party/libFuzzer/src/build.sh b/chromium/third_party/libFuzzer/src/build.sh deleted file mode 100755 index 504e54e3a81..00000000000 --- a/chromium/third_party/libFuzzer/src/build.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -LIBFUZZER_SRC_DIR=$(dirname $0) -CXX="${CXX:-clang}" -for f in $LIBFUZZER_SRC_DIR/*.cpp; do - $CXX -g -O2 -fno-omit-frame-pointer -std=c++11 $f -c & -done -wait -rm -f libFuzzer.a -ar ru libFuzzer.a Fuzzer*.o -rm -f Fuzzer*.o - diff --git a/chromium/third_party/libFuzzer/src/dataflow/DataFlow.cpp b/chromium/third_party/libFuzzer/src/dataflow/DataFlow.cpp deleted file mode 100644 index a79c796ac45..00000000000 --- a/chromium/third_party/libFuzzer/src/dataflow/DataFlow.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/*===- DataFlow.cpp - a standalone DataFlow tracer -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// An experimental data-flow tracer for fuzz targets. -// It is based on DFSan and SanitizerCoverage. -// https://clang.llvm.org/docs/DataFlowSanitizer.html -// https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow -// -// It executes the fuzz target on the given input while monitoring the -// data flow for every instrumented comparison instruction. -// -// The output shows which functions depend on which bytes of the input. -// -// Build: -// 1. Compile this file with -fsanitize=dataflow -// 2. Build the fuzz target with -g -fsanitize=dataflow -// -fsanitize-coverage=trace-pc-guard,pc-table,func,trace-cmp -// 3. Link those together with -fsanitize=dataflow -// -// -fsanitize-coverage=trace-cmp inserts callbacks around every comparison -// instruction, DFSan modifies the calls to pass the data flow labels. -// The callbacks update the data flow label for the current function. -// See e.g. __dfsw___sanitizer_cov_trace_cmp1 below. -// -// -fsanitize-coverage=trace-pc-guard,pc-table,func instruments function -// entries so that the comparison callback knows that current function. -// -// -// Run: -// # Collect data flow for INPUT_FILE, write to OUTPUT_FILE (default: stdout) -// ./a.out INPUT_FILE [OUTPUT_FILE] -// -// # Print all instrumented functions. llvm-symbolizer must be present in PATH -// ./a.out -// -// Example output: -// =============== -// F0 11111111111111 -// F1 10000000000000 -// =============== -// "FN xxxxxxxxxx": tells what bytes of the input does the function N depend on. -// The byte string is LEN+1 bytes. The last byte is set if the function -// depends on the input length. -//===----------------------------------------------------------------------===*/ - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> - -#include <execinfo.h> // backtrace_symbols_fd - -#include <sanitizer/dfsan_interface.h> - -extern "C" { -extern int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size); -__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); -} // extern "C" - -static size_t InputLen; -static size_t NumFuncs; -static const uintptr_t *FuncsBeg; -static __thread size_t CurrentFunc; -static dfsan_label *FuncLabels; // Array of NumFuncs elements. -static char *PrintableStringForLabel; // InputLen + 2 bytes. -static bool LabelSeen[1 << 8 * sizeof(dfsan_label)]; - -// Prints all instrumented functions. -static int PrintFunctions() { - // We don't have the symbolizer integrated with dfsan yet. - // So use backtrace_symbols_fd and pipe it through llvm-symbolizer. - // TODO(kcc): this is pretty ugly and may break in lots of ways. - // We'll need to make a proper in-process symbolizer work with DFSan. - FILE *Pipe = popen("sed 's/(+/ /g; s/).*//g' " - "| llvm-symbolizer " - "| grep 'dfs\\$' " - "| sed 's/dfs\\$//g'", "w"); - for (size_t I = 0; I < NumFuncs; I++) { - uintptr_t PC = FuncsBeg[I * 2]; - void *const Buf[1] = {(void*)PC}; - backtrace_symbols_fd(Buf, 1, fileno(Pipe)); - } - pclose(Pipe); - return 0; -} - -extern "C" -void SetBytesForLabel(dfsan_label L, char *Bytes) { - if (LabelSeen[L]) - return; - LabelSeen[L] = true; - assert(L); - if (L <= InputLen + 1) { - Bytes[L - 1] = '1'; - } else { - auto *DLI = dfsan_get_label_info(L); - SetBytesForLabel(DLI->l1, Bytes); - SetBytesForLabel(DLI->l2, Bytes); - } -} - -static char *GetPrintableStringForLabel(dfsan_label L) { - memset(PrintableStringForLabel, '0', InputLen + 1); - PrintableStringForLabel[InputLen + 1] = 0; - memset(LabelSeen, 0, sizeof(LabelSeen)); - SetBytesForLabel(L, PrintableStringForLabel); - return PrintableStringForLabel; -} - -static void PrintDataFlow(FILE *Out) { - for (size_t I = 0; I < NumFuncs; I++) - if (FuncLabels[I]) - fprintf(Out, "F%zd %s\n", I, GetPrintableStringForLabel(FuncLabels[I])); -} - -int main(int argc, char **argv) { - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); - if (argc == 1) - return PrintFunctions(); - assert(argc == 4 || argc == 5); - size_t Beg = atoi(argv[1]); - size_t End = atoi(argv[2]); - assert(Beg < End); - - const char *Input = argv[3]; - fprintf(stderr, "INFO: reading '%s'\n", Input); - FILE *In = fopen(Input, "r"); - assert(In); - fseek(In, 0, SEEK_END); - InputLen = ftell(In); - fseek(In, 0, SEEK_SET); - unsigned char *Buf = (unsigned char*)malloc(InputLen); - size_t NumBytesRead = fread(Buf, 1, InputLen, In); - assert(NumBytesRead == InputLen); - PrintableStringForLabel = (char*)malloc(InputLen + 2); - fclose(In); - - fprintf(stderr, "INFO: running '%s'\n", Input); - for (size_t I = 1; I <= InputLen; I++) { - dfsan_label L = dfsan_create_label("", nullptr); - assert(L == I); - size_t Idx = I - 1; - if (Idx >= Beg && Idx < End) - dfsan_set_label(L, Buf + Idx, 1); - } - dfsan_label SizeL = dfsan_create_label("", nullptr); - assert(SizeL == InputLen + 1); - dfsan_set_label(SizeL, &InputLen, sizeof(InputLen)); - - LLVMFuzzerTestOneInput(Buf, InputLen); - free(Buf); - - bool OutIsStdout = argc == 4; - fprintf(stderr, "INFO: writing dataflow to %s\n", - OutIsStdout ? "<stdout>" : argv[4]); - FILE *Out = OutIsStdout ? stdout : fopen(argv[4], "w"); - PrintDataFlow(Out); - if (!OutIsStdout) fclose(Out); -} - -extern "C" { - -void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, - uint32_t *stop) { - assert(NumFuncs == 0 && "This tool does not support DSOs"); - assert(start < stop && "The code is not instrumented for coverage"); - if (start == stop || *start) return; // Initialize only once. - for (uint32_t *x = start; x < stop; x++) - *x = ++NumFuncs; // The first index is 1. - FuncLabels = (dfsan_label*)calloc(NumFuncs, sizeof(dfsan_label)); - fprintf(stderr, "INFO: %zd instrumented function(s) observed\n", NumFuncs); -} - -void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg, - const uintptr_t *pcs_end) { - assert(NumFuncs == (pcs_end - pcs_beg) / 2); - FuncsBeg = pcs_beg; -} - -void __sanitizer_cov_trace_pc_indir(uint64_t x){} // unused. - -void __sanitizer_cov_trace_pc_guard(uint32_t *guard){ - uint32_t FuncNum = *guard - 1; // Guards start from 1. - assert(FuncNum < NumFuncs); - CurrentFunc = FuncNum; -} - -void __dfsw___sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases, - dfsan_label L1, dfsan_label UnusedL) { - assert(CurrentFunc < NumFuncs); - FuncLabels[CurrentFunc] = dfsan_union(FuncLabels[CurrentFunc], L1); -} - -#define HOOK(Name, Type) \ - void Name(Type Arg1, Type Arg2, dfsan_label L1, dfsan_label L2) { \ - assert(CurrentFunc < NumFuncs); \ - FuncLabels[CurrentFunc] = \ - dfsan_union(FuncLabels[CurrentFunc], dfsan_union(L1, L2)); \ - } - -HOOK(__dfsw___sanitizer_cov_trace_const_cmp1, uint8_t) -HOOK(__dfsw___sanitizer_cov_trace_const_cmp2, uint16_t) -HOOK(__dfsw___sanitizer_cov_trace_const_cmp4, uint32_t) -HOOK(__dfsw___sanitizer_cov_trace_const_cmp8, uint64_t) -HOOK(__dfsw___sanitizer_cov_trace_cmp1, uint8_t) -HOOK(__dfsw___sanitizer_cov_trace_cmp2, uint16_t) -HOOK(__dfsw___sanitizer_cov_trace_cmp4, uint32_t) -HOOK(__dfsw___sanitizer_cov_trace_cmp8, uint64_t) - -} // extern "C" diff --git a/chromium/third_party/libFuzzer/src/scripts/collect_data_flow.py b/chromium/third_party/libFuzzer/src/scripts/collect_data_flow.py deleted file mode 100755 index 3edff66bb9d..00000000000 --- a/chromium/third_party/libFuzzer/src/scripts/collect_data_flow.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -#===- lib/fuzzer/scripts/collect_data_flow.py ------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# Runs the data-flow tracer several times on the same input in order to collect -# the complete trace for all input bytes (running it on all bytes at once -# may fail if DFSan runs out of labels). -# Usage: -# -# # Collect dataflow for one input, store it in OUTPUT (default is stdout) -# collect_data_flow.py BINARY INPUT [OUTPUT] -# -# # Collect dataflow for all inputs in CORPUS_DIR, store them in OUTPUT_DIR -# collect_data_flow.py BINARY CORPUS_DIR OUTPUT_DIR -#===------------------------------------------------------------------------===# -import atexit -import hashlib -import sys -import os -import subprocess -import tempfile -import shutil - -tmpdir = "" - -def cleanup(d): - print("removing: %s" % d) - shutil.rmtree(d) - -def collect_dataflow_for_corpus(self, exe, corpus_dir, output_dir): - print("Collecting dataflow for corpus: %s output_dir: %s" % (corpus_dir, - output_dir)) - assert not os.path.exists(output_dir) - os.mkdir(output_dir) - for root, dirs, files in os.walk(corpus_dir): - for f in files: - path = os.path.join(root, f) - sha1 = hashlib.sha1(open(path).read()).hexdigest() - output = os.path.join(output_dir, sha1) - subprocess.call([self, exe, path, output]) - functions_txt = open(os.path.join(output_dir, "functions.txt"), "w") - subprocess.call([exe], stdout=functions_txt) - - -def main(argv): - exe = argv[1] - inp = argv[2] - if os.path.isdir(inp): - return collect_dataflow_for_corpus(argv[0], exe, inp, argv[3]) - size = os.path.getsize(inp) - q = [[0, size]] - tmpdir = tempfile.mkdtemp(prefix="libfuzzer-tmp-") - atexit.register(cleanup, tmpdir) - print "tmpdir: ", tmpdir - outputs = [] - while len(q): - r = q.pop() - print "******* Trying: ", r - tmpfile = os.path.join(tmpdir, str(r[0]) + "-" + str(r[1])) - ret = subprocess.call([exe, str(r[0]), str(r[1]), inp, tmpfile]) - if ret and r[1] - r[0] >= 2: - q.append([r[0], (r[1] + r[0]) / 2]) - q.append([(r[1] + r[0]) / 2, r[1]]) - else: - outputs.append(tmpfile) - print "******* Success: ", r - f = sys.stdout - if len(argv) >= 4: - f = open(argv[3], "w") - merge = os.path.join(os.path.dirname(argv[0]), "merge_data_flow.py") - subprocess.call([merge] + outputs, stdout=f) - -if __name__ == '__main__': - main(sys.argv) diff --git a/chromium/third_party/libFuzzer/src/scripts/merge_data_flow.py b/chromium/third_party/libFuzzer/src/scripts/merge_data_flow.py deleted file mode 100755 index d2f5081e7b8..00000000000 --- a/chromium/third_party/libFuzzer/src/scripts/merge_data_flow.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python -#===- lib/fuzzer/scripts/merge_data_flow.py ------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# Merge several data flow traces into one. -# Usage: -# merge_data_flow.py trace1 trace2 ... > result -#===------------------------------------------------------------------------===# -import sys -import fileinput -from array import array - -def Merge(a, b): - res = array('b') - for i in range(0, len(a)): - res.append(ord('1' if a[i] == '1' or b[i] == '1' else '0')) - return res.tostring() - -def main(argv): - D = {} - for line in fileinput.input(): - [F,BV] = line.strip().split(' ') - if F in D: - D[F] = Merge(D[F], BV) - else: - D[F] = BV; - for F in D.keys(): - print("%s %s" % (F, D[F])) - -if __name__ == '__main__': - main(sys.argv) diff --git a/chromium/third_party/libFuzzer/src/scripts/unbalanced_allocs.py b/chromium/third_party/libFuzzer/src/scripts/unbalanced_allocs.py deleted file mode 100755 index 74478ad55af..00000000000 --- a/chromium/third_party/libFuzzer/src/scripts/unbalanced_allocs.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -#===- lib/fuzzer/scripts/unbalanced_allocs.py ------------------------------===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# -# Post-process -trace_malloc=2 output and printout only allocations and frees -# unbalanced inside of fuzzer runs. -# Usage: -# my_fuzzer -trace_malloc=2 -runs=10 2>&1 | unbalanced_allocs.py -skip=5 -# -#===------------------------------------------------------------------------===# - -import argparse -import sys - -_skip = 0 - -def PrintStack(line, stack): - global _skip - if _skip > 0: - return - print('Unbalanced ' + line.rstrip()); - for l in stack: - print(l.rstrip()) - -def ProcessStack(line, f): - stack = [] - while line and line.startswith(' #'): - stack += [line] - line = f.readline() - return line, stack - -def ProcessFree(line, f, allocs): - if not line.startswith('FREE['): - return f.readline() - - addr = int(line.split()[1], 16) - next_line, stack = ProcessStack(f.readline(), f) - if addr in allocs: - del allocs[addr] - else: - PrintStack(line, stack) - return next_line - -def ProcessMalloc(line, f, allocs): - if not line.startswith('MALLOC['): - return ProcessFree(line, f, allocs) - - addr = int(line.split()[1], 16) - assert not addr in allocs - - next_line, stack = ProcessStack(f.readline(), f) - allocs[addr] = (line, stack) - return next_line - -def ProcessRun(line, f): - if not line.startswith('MallocFreeTracer: START'): - return ProcessMalloc(line, f, {}) - - allocs = {} - print(line.rstrip()) - line = f.readline() - while line: - if line.startswith('MallocFreeTracer: STOP'): - global _skip - _skip = _skip - 1 - for _, (l, s) in allocs.items(): - PrintStack(l, s) - print(line.rstrip()) - return f.readline() - line = ProcessMalloc(line, f, allocs) - return line - -def ProcessFile(f): - line = f.readline() - while line: - line = ProcessRun(line, f); - -def main(argv): - parser = argparse.ArgumentParser() - parser.add_argument('--skip', default=0, help='number of runs to ignore') - args = parser.parse_args() - global _skip - _skip = int(args.skip) + 1 - ProcessFile(sys.stdin) - -if __name__ == '__main__': - main(sys.argv) diff --git a/chromium/third_party/libFuzzer/src/standalone/StandaloneFuzzTargetMain.c b/chromium/third_party/libFuzzer/src/standalone/StandaloneFuzzTargetMain.c deleted file mode 100644 index 0d76ea49e79..00000000000 --- a/chromium/third_party/libFuzzer/src/standalone/StandaloneFuzzTargetMain.c +++ /dev/null @@ -1,41 +0,0 @@ -/*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// This main() function can be linked to a fuzz target (i.e. a library -// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize()) -// instead of libFuzzer. This main() function will not perform any fuzzing -// but will simply feed all input files one by one to the fuzz target. -// -// Use this file to provide reproducers for bugs when linking against libFuzzer -// or other fuzzing engine is undesirable. -//===----------------------------------------------------------------------===*/ -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> - -extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); -__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); -int main(int argc, char **argv) { - fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); - for (int i = 1; i < argc; i++) { - fprintf(stderr, "Running: %s\n", argv[i]); - FILE *f = fopen(argv[i], "r"); - assert(f); - fseek(f, 0, SEEK_END); - size_t len = ftell(f); - fseek(f, 0, SEEK_SET); - unsigned char *buf = (unsigned char*)malloc(len); - size_t n_read = fread(buf, 1, len, f); - assert(n_read == len); - LLVMFuzzerTestOneInput(buf, len); - free(buf); - fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); - } -} |