diff options
author | thegeorg <[email protected]> | 2022-11-07 19:34:08 +0300 |
---|---|---|
committer | thegeorg <[email protected]> | 2022-11-07 19:34:08 +0300 |
commit | 50f76e264c70a223a34b24aa59e97bff97128f4c (patch) | |
tree | e604247a10f09df6158c172577b9bfa431f1e1b5 /contrib/libs/libfuzzer12 | |
parent | 278a58c5af63dbd7f7a6d8b8d92dc246651242da (diff) |
Switch fuzz tests to contrib/libs/libfuzzer
Diffstat (limited to 'contrib/libs/libfuzzer12')
49 files changed, 0 insertions, 9711 deletions
diff --git a/contrib/libs/libfuzzer12/CODE_OWNERS.TXT b/contrib/libs/libfuzzer12/CODE_OWNERS.TXT deleted file mode 100644 index 125487816bc..00000000000 --- a/contrib/libs/libfuzzer12/CODE_OWNERS.TXT +++ /dev/null @@ -1,53 +0,0 @@ -This file is a list of the people responsible for ensuring that patches for a -particular part of compiler-rt are reviewed, either by themself or by -someone else. They are also the gatekeepers for their part of compiler-rt, with -the final word on what goes in or not. - -The list is sorted by surname and formatted to allow easy grepping and -beautification by scripts. The fields are: name (N), email (E), web-address -(W), PGP key ID and fingerprint (P), description (D), and snail-mail address -(S). - -N: Peter Collingbourne -D: DataFlowSanitizer - -N: Daniel Dunbar -D: Makefile build - -N: Timur Iskhodzhanov -D: AddressSanitizer for Windows - -N: Howard Hinnant -D: builtins library - -N: Alexander Potapenko -D: MacOS/iOS port of sanitizers - -N: Alexey Samsonov -D: CMake build, test suite - -N: Kostya Serebryany -D: AddressSanitizer, sanitizer_common, porting sanitizers to another platforms, LeakSanitizer - -N: Richard Smith -D: UndefinedBehaviorSanitizer - -N: Evgeniy Stepanov -D: MemorySanitizer, Android port of sanitizers - -N: Dmitry Vyukov -D: ThreadSanitizer - -N: Bill Wendling -D: Profile runtime library diff --git a/contrib/libs/libfuzzer12/CREDITS.TXT b/contrib/libs/libfuzzer12/CREDITS.TXT deleted file mode 100644 index 6964eba020b..00000000000 --- a/contrib/libs/libfuzzer12/CREDITS.TXT +++ /dev/null @@ -1,36 +0,0 @@ -This file is a partial list of people who have contributed to the LLVM/CompilerRT -project. If you have contributed a patch or made some other contribution to -LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be -done! - -The list is sorted by surname and formatted to allow easy grepping and -beautification by scripts. The fields are: name (N), email (E), web-address -(W), PGP key ID and fingerprint (P), description (D), and snail-mail address -(S). - -N: Craig van Vliet -W: http://www.auroraux.org -D: Code style and Readability fixes. - -N: Edward O'Callaghan -W: http://www.auroraux.org -D: CMake'ify Compiler-RT build system -D: Maintain Solaris & AuroraUX ports of Compiler-RT - -N: Howard Hinnant -D: Architect and primary author of compiler-rt - -N: Guan-Hong Liu -D: IEEE Quad-precision functions - -N: Joerg Sonnenberger -D: Maintains NetBSD port. - -N: Matt Thomas -D: ARM improvements. diff --git a/contrib/libs/libfuzzer12/FuzzerBuiltins.h b/contrib/libs/libfuzzer12/FuzzerBuiltins.h deleted file mode 100644 index 4c0ada82662..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerBuiltins.h +++ /dev/null @@ -1,35 +0,0 @@ -//===- FuzzerBuiltins.h - Internal header for builtins ----------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Wrapper functions and marcos around builtin functions. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_BUILTINS_H -#define LLVM_FUZZER_BUILTINS_H - -#include "FuzzerPlatform.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/contrib/libs/libfuzzer12/FuzzerBuiltinsMsvc.h b/contrib/libs/libfuzzer12/FuzzerBuiltinsMsvc.h deleted file mode 100644 index c5bec9787d8..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerBuiltinsMsvc.h +++ /dev/null @@ -1,72 +0,0 @@ -//===- FuzzerBuiltinsMSVC.h - Internal header for builtins ------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 "FuzzerPlatform.h" - -#if LIBFUZZER_MSVC -#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() _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 !defined(_M_ARM) && !defined(_M_X64) - // Scan the high 32 bits. - if (_BitScanReverse(&LeadZeroIdx, static_cast<unsigned long>(X >> 32))) - return static_cast<int>(63 - (LeadZeroIdx + 32)); // Create a bit offset from the MSB. - // Scan the low 32 bits. - if (_BitScanReverse(&LeadZeroIdx, static_cast<unsigned long>(X))) - return static_cast<int>(63 - LeadZeroIdx); - -#else - if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx; -#endif - 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) { -#if !defined(_M_ARM) && !defined(_M_X64) - return __popcnt(X) + __popcnt(X >> 32); -#else - return __popcnt64(X); -#endif -} - -} // namespace fuzzer - -#endif // LIBFUZER_MSVC -#endif // LLVM_FUZZER_BUILTINS_MSVC_H diff --git a/contrib/libs/libfuzzer12/FuzzerCommand.h b/contrib/libs/libfuzzer12/FuzzerCommand.h deleted file mode 100644 index 87308864af5..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerCommand.h +++ /dev/null @@ -1,178 +0,0 @@ -//===- FuzzerCommand.h - Interface representing a process -------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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/contrib/libs/libfuzzer12/FuzzerCorpus.h b/contrib/libs/libfuzzer12/FuzzerCorpus.h deleted file mode 100644 index daea4f5213b..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerCorpus.h +++ /dev/null @@ -1,581 +0,0 @@ -//===- FuzzerCorpus.h - Internal header for the Fuzzer ----------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 <chrono> -#include <numeric> -#include <random> -#include <unordered_set> - -namespace fuzzer { - -struct InputInfo { - Unit U; // The actual input data. - std::chrono::microseconds TimeOfUnit; - 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 NeverReduce = false; - bool MayDeleteFile = false; - bool Reduced = false; - bool HasFocusFunction = false; - Vector<uint32_t> UniqFeatureSet; - Vector<uint8_t> DataFlowTraceForFocusFunction; - // Power schedule. - bool NeedsEnergyUpdate = false; - double Energy = 0.0; - size_t SumIncidence = 0; - Vector<std::pair<uint32_t, uint16_t>> FeatureFreqs; - - // Delete feature Idx and its frequency from FeatureFreqs. - bool DeleteFeatureFreq(uint32_t Idx) { - if (FeatureFreqs.empty()) - return false; - - // Binary search over local feature frequencies sorted by index. - auto Lower = std::lower_bound(FeatureFreqs.begin(), FeatureFreqs.end(), - std::pair<uint32_t, uint16_t>(Idx, 0)); - - if (Lower != FeatureFreqs.end() && Lower->first == Idx) { - FeatureFreqs.erase(Lower); - return true; - } - return false; - } - - // Assign more energy to a high-entropy seed, i.e., that reveals more - // information about the globally rare features in the neighborhood of the - // seed. Since we do not know the entropy of a seed that has never been - // executed we assign fresh seeds maximum entropy and let II->Energy approach - // the true entropy from above. If ScalePerExecTime is true, the computed - // entropy is scaled based on how fast this input executes compared to the - // average execution time of inputs. The faster an input executes, the more - // energy gets assigned to the input. - void UpdateEnergy(size_t GlobalNumberOfFeatures, bool ScalePerExecTime, - std::chrono::microseconds AverageUnitExecutionTime) { - Energy = 0.0; - SumIncidence = 0; - - // Apply add-one smoothing to locally discovered features. - for (auto F : FeatureFreqs) { - size_t LocalIncidence = F.second + 1; - Energy -= LocalIncidence * logl(LocalIncidence); - SumIncidence += LocalIncidence; - } - - // Apply add-one smoothing to locally undiscovered features. - // PreciseEnergy -= 0; // since logl(1.0) == 0) - SumIncidence += (GlobalNumberOfFeatures - FeatureFreqs.size()); - - // Add a single locally abundant feature apply add-one smoothing. - size_t AbdIncidence = NumExecutedMutations + 1; - Energy -= AbdIncidence * logl(AbdIncidence); - SumIncidence += AbdIncidence; - - // Normalize. - if (SumIncidence != 0) - Energy = (Energy / SumIncidence) + logl(SumIncidence); - - if (ScalePerExecTime) { - // Scaling to favor inputs with lower execution time. - uint32_t PerfScore = 100; - if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 10) - PerfScore = 10; - else if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 4) - PerfScore = 25; - else if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 2) - PerfScore = 50; - else if (TimeOfUnit.count() * 3 > AverageUnitExecutionTime.count() * 4) - PerfScore = 75; - else if (TimeOfUnit.count() * 4 < AverageUnitExecutionTime.count()) - PerfScore = 300; - else if (TimeOfUnit.count() * 3 < AverageUnitExecutionTime.count()) - PerfScore = 200; - else if (TimeOfUnit.count() * 2 < AverageUnitExecutionTime.count()) - PerfScore = 150; - - Energy *= PerfScore; - } - } - - // Increment the frequency of the feature Idx. - void UpdateFeatureFrequency(uint32_t Idx) { - NeedsEnergyUpdate = true; - - // The local feature frequencies is an ordered vector of pairs. - // If there are no local feature frequencies, push_back preserves order. - // Set the feature frequency for feature Idx32 to 1. - if (FeatureFreqs.empty()) { - FeatureFreqs.push_back(std::pair<uint32_t, uint16_t>(Idx, 1)); - return; - } - - // Binary search over local feature frequencies sorted by index. - auto Lower = std::lower_bound(FeatureFreqs.begin(), FeatureFreqs.end(), - std::pair<uint32_t, uint16_t>(Idx, 0)); - - // If feature Idx32 already exists, increment its frequency. - // Otherwise, insert a new pair right after the next lower index. - if (Lower != FeatureFreqs.end() && Lower->first == Idx) { - Lower->second++; - } else { - FeatureFreqs.insert(Lower, std::pair<uint32_t, uint16_t>(Idx, 1)); - } - } -}; - -struct EntropicOptions { - bool Enabled; - size_t NumberOfRarestFeatures; - size_t FeatureFrequencyThreshold; - bool ScalePerExecTime; -}; - -class InputCorpus { - static const uint32_t kFeatureSetSize = 1 << 21; - static const uint8_t kMaxMutationFactor = 20; - static const size_t kSparseEnergyUpdates = 100; - - size_t NumExecutedMutations = 0; - - EntropicOptions Entropic; - -public: - InputCorpus(const std::string &OutputCorpus, EntropicOptions Entropic) - : Entropic(Entropic), 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; - } - void IncrementNumExecutedMutations() { NumExecutedMutations++; } - - 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; } - InputInfo *AddToCorpus(const Unit &U, size_t NumFeatures, bool MayDeleteFile, - bool HasFocusFunction, bool NeverReduce, - std::chrono::microseconds TimeOfUnit, - 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.NeverReduce = NeverReduce; - II.TimeOfUnit = TimeOfUnit; - II.MayDeleteFile = MayDeleteFile; - II.UniqFeatureSet = FeatureSet; - II.HasFocusFunction = HasFocusFunction; - // Assign maximal energy to the new seed. - II.Energy = RareFeatures.empty() ? 1.0 : log(RareFeatures.size()); - II.SumIncidence = RareFeatures.size(); - II.NeedsEnergyUpdate = false; - 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; - DistributionNeedsUpdate = true; - PrintCorpus(); - // ValidateFeatureSet(); - return &II; - } - - // 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; - DistributionNeedsUpdate = true; - } - - 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; - } - - InputInfo &ChooseUnitToCrossOverWith(Random &Rand, bool UniformDist) { - if (!UniformDist) { - return ChooseUnitToMutate(Rand); - } - InputInfo &II = *Inputs[Rand(Inputs.size())]; - assert(!II.U.empty()); - return II; - } - - // Returns an index of random unit from the corpus to mutate. - size_t ChooseUnitIdxToMutate(Random &Rand) { - UpdateCorpusDistribution(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); - II.Energy = 0.0; - II.NeedsEnergyUpdate = false; - DistributionNeedsUpdate = true; - if (FeatureDebug) - Printf("EVICTED %zd\n", Idx); - } - - void AddRareFeature(uint32_t Idx) { - // Maintain *at least* TopXRarestFeatures many rare features - // and all features with a frequency below ConsideredRare. - // Remove all other features. - while (RareFeatures.size() > Entropic.NumberOfRarestFeatures && - FreqOfMostAbundantRareFeature > Entropic.FeatureFrequencyThreshold) { - - // Find most and second most abbundant feature. - uint32_t MostAbundantRareFeatureIndices[2] = {RareFeatures[0], - RareFeatures[0]}; - size_t Delete = 0; - for (size_t i = 0; i < RareFeatures.size(); i++) { - uint32_t Idx2 = RareFeatures[i]; - if (GlobalFeatureFreqs[Idx2] >= - GlobalFeatureFreqs[MostAbundantRareFeatureIndices[0]]) { - MostAbundantRareFeatureIndices[1] = MostAbundantRareFeatureIndices[0]; - MostAbundantRareFeatureIndices[0] = Idx2; - Delete = i; - } - } - - // Remove most abundant rare feature. - RareFeatures[Delete] = RareFeatures.back(); - RareFeatures.pop_back(); - - for (auto II : Inputs) { - if (II->DeleteFeatureFreq(MostAbundantRareFeatureIndices[0])) - II->NeedsEnergyUpdate = true; - } - - // Set 2nd most abundant as the new most abundant feature count. - FreqOfMostAbundantRareFeature = - GlobalFeatureFreqs[MostAbundantRareFeatureIndices[1]]; - } - - // Add rare feature, handle collisions, and update energy. - RareFeatures.push_back(Idx); - GlobalFeatureFreqs[Idx] = 0; - for (auto II : Inputs) { - II->DeleteFeatureFreq(Idx); - - // Apply add-one smoothing to this locally undiscovered feature. - // Zero energy seeds will never be fuzzed and remain zero energy. - if (II->Energy > 0.0) { - II->SumIncidence += 1; - II->Energy += logl(II->SumIncidence) / II->SumIncidence; - } - } - - DistributionNeedsUpdate = true; - } - - 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++; - if (Entropic.Enabled) - AddRareFeature((uint32_t)Idx); - } - NumUpdatedFeatures++; - if (FeatureDebug) - Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize); - SmallestElementPerFeature[Idx] = Inputs.size(); - InputSizesPerFeature[Idx] = NewSize; - return true; - } - return false; - } - - // Increment frequency of feature Idx globally and locally. - void UpdateFeatureFrequency(InputInfo *II, size_t Idx) { - uint32_t Idx32 = Idx % kFeatureSetSize; - - // Saturated increment. - if (GlobalFeatureFreqs[Idx32] == 0xFFFF) - return; - uint16_t Freq = GlobalFeatureFreqs[Idx32]++; - - // Skip if abundant. - if (Freq > FreqOfMostAbundantRareFeature || - std::find(RareFeatures.begin(), RareFeatures.end(), Idx32) == - RareFeatures.end()) - return; - - // Update global frequencies. - if (Freq == FreqOfMostAbundantRareFeature) - FreqOfMostAbundantRareFeature++; - - // Update local frequencies. - if (II) - II->UpdateFeatureFrequency(Idx32); - } - - 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: inputs that maximize information about globally rare features - // are interesting. - void UpdateCorpusDistribution(Random &Rand) { - // Skip update if no seeds or rare features were added/deleted. - // Sparse updates for local change of feature frequencies, - // i.e., randomly do not skip. - if (!DistributionNeedsUpdate && - (!Entropic.Enabled || Rand(kSparseEnergyUpdates))) - return; - - DistributionNeedsUpdate = false; - - size_t N = Inputs.size(); - assert(N); - Intervals.resize(N + 1); - Weights.resize(N); - std::iota(Intervals.begin(), Intervals.end(), 0); - - std::chrono::microseconds AverageUnitExecutionTime(0); - for (auto II : Inputs) { - AverageUnitExecutionTime += II->TimeOfUnit; - } - AverageUnitExecutionTime /= N; - - bool VanillaSchedule = true; - if (Entropic.Enabled) { - for (auto II : Inputs) { - if (II->NeedsEnergyUpdate && II->Energy != 0.0) { - II->NeedsEnergyUpdate = false; - II->UpdateEnergy(RareFeatures.size(), Entropic.ScalePerExecTime, - AverageUnitExecutionTime); - } - } - - for (size_t i = 0; i < N; i++) { - - if (Inputs[i]->NumFeatures == 0) { - // If the seed doesn't represent any features, assign zero energy. - Weights[i] = 0.; - } else if (Inputs[i]->NumExecutedMutations / kMaxMutationFactor > - NumExecutedMutations / Inputs.size()) { - // If the seed was fuzzed a lot more than average, assign zero energy. - Weights[i] = 0.; - } else { - // Otherwise, simply assign the computed energy. - Weights[i] = Inputs[i]->Energy; - } - - // If energy for all seeds is zero, fall back to vanilla schedule. - if (Weights[i] > 0.0) - VanillaSchedule = false; - } - } - - if (VanillaSchedule) { - 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]; - - bool DistributionNeedsUpdate = true; - uint16_t FreqOfMostAbundantRareFeature = 0; - uint16_t GlobalFeatureFreqs[kFeatureSetSize] = {}; - Vector<uint32_t> RareFeatures; - - std::string OutputCorpus; -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_CORPUS diff --git a/contrib/libs/libfuzzer12/FuzzerCrossOver.cpp b/contrib/libs/libfuzzer12/FuzzerCrossOver.cpp deleted file mode 100644 index 83d9f8d47cb..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerCrossOver.cpp +++ /dev/null @@ -1,51 +0,0 @@ -//===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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/contrib/libs/libfuzzer12/FuzzerDataFlowTrace.cpp b/contrib/libs/libfuzzer12/FuzzerDataFlowTrace.cpp deleted file mode 100644 index 0e9cdf7e66b..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerDataFlowTrace.cpp +++ /dev/null @@ -1,286 +0,0 @@ -//===- FuzzerDataFlowTrace.cpp - DataFlowTrace ---*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// fuzzer::DataFlowTrace -//===----------------------------------------------------------------------===// - -#include "FuzzerDataFlowTrace.h" - -#include "FuzzerCommand.h" -#include "FuzzerIO.h" -#include "FuzzerRandom.h" -#include "FuzzerSHA1.h" -#include "FuzzerUtil.h" - -#include <cstdlib> -#include <fstream> -#include <numeric> -#include <queue> -#include <sstream> -#include <string> -#include <unordered_map> -#include <unordered_set> -#include <vector> - -namespace fuzzer { -static const char *kFunctionsTxt = "functions.txt"; - -bool BlockCoverage::AppendCoverage(const std::string &S) { - std::stringstream SS(S); - return AppendCoverage(SS); -} - -// Coverage lines have this form: -// CN X Y Z T -// where N is the number of the function, T is the total number of instrumented -// BBs, and X,Y,Z, if present, are the indecies of covered BB. -// BB #0, which is the entry block, is not explicitly listed. -bool BlockCoverage::AppendCoverage(std::istream &IN) { - std::string L; - while (std::getline(IN, L, '\n')) { - if (L.empty()) - continue; - std::stringstream SS(L.c_str() + 1); - size_t FunctionId = 0; - SS >> FunctionId; - if (L[0] == 'F') { - FunctionsWithDFT.insert(FunctionId); - continue; - } - if (L[0] != 'C') continue; - Vector<uint32_t> CoveredBlocks; - while (true) { - uint32_t BB = 0; - SS >> BB; - if (!SS) break; - CoveredBlocks.push_back(BB); - } - if (CoveredBlocks.empty()) return false; - uint32_t NumBlocks = CoveredBlocks.back(); - CoveredBlocks.pop_back(); - for (auto BB : CoveredBlocks) - if (BB >= NumBlocks) return false; - auto It = Functions.find(FunctionId); - auto &Counters = - It == Functions.end() - ? Functions.insert({FunctionId, Vector<uint32_t>(NumBlocks)}) - .first->second - : It->second; - - if (Counters.size() != NumBlocks) return false; // wrong number of blocks. - - Counters[0]++; - for (auto BB : CoveredBlocks) - Counters[BB]++; - } - return true; -} - -// Assign weights to each function. -// General principles: -// * any uncovered function gets weight 0. -// * a function with lots of uncovered blocks gets bigger weight. -// * a function with a less frequently executed code gets bigger weight. -Vector<double> BlockCoverage::FunctionWeights(size_t NumFunctions) const { - Vector<double> Res(NumFunctions); - for (auto It : Functions) { - auto FunctionID = It.first; - auto Counters = It.second; - assert(FunctionID < NumFunctions); - auto &Weight = Res[FunctionID]; - // Give higher weight if the function has a DFT. - Weight = FunctionsWithDFT.count(FunctionID) ? 1000. : 1; - // Give higher weight to functions with less frequently seen basic blocks. - Weight /= SmallestNonZeroCounter(Counters); - // Give higher weight to functions with the most uncovered basic blocks. - Weight *= NumberOfUncoveredBlocks(Counters) + 1; - } - return Res; -} - -void DataFlowTrace::ReadCoverage(const std::string &DirPath) { - Vector<SizedFile> Files; - GetSizedFilesFromDir(DirPath, &Files); - for (auto &SF : Files) { - auto Name = Basename(SF.File); - if (Name == kFunctionsTxt) continue; - if (!CorporaHashes.count(Name)) continue; - std::ifstream IF(SF.File); - Coverage.AppendCoverage(IF); - } -} - -static void DFTStringAppendToVector(Vector<uint8_t> *DFT, - const std::string &DFTString) { - assert(DFT->size() == DFTString.size()); - for (size_t I = 0, Len = DFT->size(); I < Len; I++) - (*DFT)[I] = DFTString[I] == '1'; -} - -// converts a string of '0' and '1' into a Vector<uint8_t> -static Vector<uint8_t> DFTStringToVector(const std::string &DFTString) { - Vector<uint8_t> DFT(DFTString.size()); - DFTStringAppendToVector(&DFT, DFTString); - return DFT; -} - -static bool ParseError(const char *Err, const std::string &Line) { - Printf("DataFlowTrace: parse error: %s: Line: %s\n", Err, Line.c_str()); - return false; -} - -// TODO(metzman): replace std::string with std::string_view for -// better performance. Need to figure our how to use string_view on Windows. -static bool ParseDFTLine(const std::string &Line, size_t *FunctionNum, - std::string *DFTString) { - if (!Line.empty() && Line[0] != 'F') - return false; // Ignore coverage. - size_t SpacePos = Line.find(' '); - if (SpacePos == std::string::npos) - return ParseError("no space in the trace line", Line); - if (Line.empty() || Line[0] != 'F') - return ParseError("the trace line doesn't start with 'F'", Line); - *FunctionNum = std::atol(Line.c_str() + 1); - const char *Beg = Line.c_str() + SpacePos + 1; - const char *End = Line.c_str() + Line.size(); - assert(Beg < End); - size_t Len = End - Beg; - for (size_t I = 0; I < Len; I++) { - if (Beg[I] != '0' && Beg[I] != '1') - return ParseError("the trace should contain only 0 or 1", Line); - } - *DFTString = Beg; - return true; -} - -bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction, - Vector<SizedFile> &CorporaFiles, Random &Rand) { - if (DirPath.empty()) return false; - Printf("INFO: DataFlowTrace: reading from '%s'\n", DirPath.c_str()); - Vector<SizedFile> Files; - GetSizedFilesFromDir(DirPath, &Files); - std::string L; - size_t FocusFuncIdx = SIZE_MAX; - Vector<std::string> FunctionNames; - - // Collect the hashes of the corpus files. - for (auto &SF : CorporaFiles) - CorporaHashes.insert(Hash(FileToVector(SF.File))); - - // Read functions.txt - std::ifstream IF(DirPlusFile(DirPath, kFunctionsTxt)); - size_t NumFunctions = 0; - while (std::getline(IF, L, '\n')) { - FunctionNames.push_back(L); - NumFunctions++; - if (*FocusFunction == L) - FocusFuncIdx = NumFunctions - 1; - } - if (!NumFunctions) - return false; - - if (*FocusFunction == "auto") { - // AUTOFOCUS works like this: - // * reads the coverage data from the DFT files. - // * assigns weights to functions based on coverage. - // * chooses a random function according to the weights. - ReadCoverage(DirPath); - auto Weights = Coverage.FunctionWeights(NumFunctions); - Vector<double> Intervals(NumFunctions + 1); - std::iota(Intervals.begin(), Intervals.end(), 0); - auto Distribution = std::piecewise_constant_distribution<double>( - Intervals.begin(), Intervals.end(), Weights.begin()); - FocusFuncIdx = static_cast<size_t>(Distribution(Rand)); - *FocusFunction = FunctionNames[FocusFuncIdx]; - assert(FocusFuncIdx < NumFunctions); - Printf("INFO: AUTOFOCUS: %zd %s\n", FocusFuncIdx, - FunctionNames[FocusFuncIdx].c_str()); - for (size_t i = 0; i < NumFunctions; i++) { - if (!Weights[i]) continue; - Printf(" [%zd] W %g\tBB-tot %u\tBB-cov %u\tEntryFreq %u:\t%s\n", i, - Weights[i], Coverage.GetNumberOfBlocks(i), - Coverage.GetNumberOfCoveredBlocks(i), Coverage.GetCounter(i, 0), - FunctionNames[i].c_str()); - } - } - - if (!NumFunctions || FocusFuncIdx == SIZE_MAX || Files.size() <= 1) - return false; - - // Read traces. - size_t NumTraceFiles = 0; - size_t NumTracesWithFocusFunction = 0; - for (auto &SF : Files) { - auto Name = Basename(SF.File); - if (Name == kFunctionsTxt) continue; - if (!CorporaHashes.count(Name)) continue; // not in the corpus. - NumTraceFiles++; - // Printf("=== %s\n", Name.c_str()); - std::ifstream IF(SF.File); - while (std::getline(IF, L, '\n')) { - size_t FunctionNum = 0; - std::string DFTString; - if (ParseDFTLine(L, &FunctionNum, &DFTString) && - FunctionNum == FocusFuncIdx) { - NumTracesWithFocusFunction++; - - if (FunctionNum >= NumFunctions) - return ParseError("N is greater than the number of functions", L); - Traces[Name] = DFTStringToVector(DFTString); - // Print just a few small traces. - if (NumTracesWithFocusFunction <= 3 && DFTString.size() <= 16) - Printf("%s => |%s|\n", Name.c_str(), std::string(DFTString).c_str()); - break; // No need to parse the following lines. - } - } - } - Printf("INFO: DataFlowTrace: %zd trace files, %zd functions, " - "%zd traces with focus function\n", - NumTraceFiles, NumFunctions, NumTracesWithFocusFunction); - return NumTraceFiles > 0; -} - -int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, - const Vector<SizedFile> &CorporaFiles) { - Printf("INFO: collecting data flow: bin: %s dir: %s files: %zd\n", - DFTBinary.c_str(), DirPath.c_str(), CorporaFiles.size()); - if (CorporaFiles.empty()) { - Printf("ERROR: can't collect data flow without corpus provided."); - return 1; - } - - static char DFSanEnv[] = "DFSAN_OPTIONS=warn_unimplemented=0"; - putenv(DFSanEnv); - MkDir(DirPath); - for (auto &F : CorporaFiles) { - // For every input F we need to collect the data flow and the coverage. - // Data flow collection may fail if we request too many DFSan tags at once. - // So, we start from requesting all tags in range [0,Size) and if that fails - // we then request tags in [0,Size/2) and [Size/2, Size), and so on. - // Function number => DFT. - auto OutPath = DirPlusFile(DirPath, Hash(FileToVector(F.File))); - std::unordered_map<size_t, Vector<uint8_t>> DFTMap; - std::unordered_set<std::string> Cov; - Command Cmd; - Cmd.addArgument(DFTBinary); - Cmd.addArgument(F.File); - Cmd.addArgument(OutPath); - Printf("CMD: %s\n", Cmd.toString().c_str()); - ExecuteCommand(Cmd); - } - // Write functions.txt if it's currently empty or doesn't exist. - auto FunctionsTxtPath = DirPlusFile(DirPath, kFunctionsTxt); - if (FileToString(FunctionsTxtPath).empty()) { - Command Cmd; - Cmd.addArgument(DFTBinary); - Cmd.setOutputFile(FunctionsTxtPath); - ExecuteCommand(Cmd); - } - return 0; -} - -} // namespace fuzzer diff --git a/contrib/libs/libfuzzer12/FuzzerDataFlowTrace.h b/contrib/libs/libfuzzer12/FuzzerDataFlowTrace.h deleted file mode 100644 index d6e3de30a4e..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerDataFlowTrace.h +++ /dev/null @@ -1,135 +0,0 @@ -//===- FuzzerDataFlowTrace.h - Internal header for the Fuzzer ---*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 "FuzzerIO.h" - -#include <unordered_map> -#include <unordered_set> -#include <vector> -#include <string> - -namespace fuzzer { - -int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath, - const Vector<SizedFile> &CorporaFiles); - -class BlockCoverage { - public: - bool AppendCoverage(std::istream &IN); - bool AppendCoverage(const std::string &S); - - size_t NumCoveredFunctions() const { return Functions.size(); } - - uint32_t GetCounter(size_t FunctionId, size_t BasicBlockId) { - auto It = Functions.find(FunctionId); - if (It == Functions.end()) return 0; - const auto &Counters = It->second; - if (BasicBlockId < Counters.size()) - return Counters[BasicBlockId]; - return 0; - } - - uint32_t GetNumberOfBlocks(size_t FunctionId) { - auto It = Functions.find(FunctionId); - if (It == Functions.end()) return 0; - const auto &Counters = It->second; - return Counters.size(); - } - - uint32_t GetNumberOfCoveredBlocks(size_t FunctionId) { - auto It = Functions.find(FunctionId); - if (It == Functions.end()) return 0; - const auto &Counters = It->second; - uint32_t Result = 0; - for (auto Cnt: Counters) - if (Cnt) - Result++; - return Result; - } - - Vector<double> FunctionWeights(size_t NumFunctions) const; - void clear() { Functions.clear(); } - - private: - - typedef Vector<uint32_t> CoverageVector; - - uint32_t NumberOfCoveredBlocks(const CoverageVector &Counters) const { - uint32_t Res = 0; - for (auto Cnt : Counters) - if (Cnt) - Res++; - return Res; - } - - uint32_t NumberOfUncoveredBlocks(const CoverageVector &Counters) const { - return Counters.size() - NumberOfCoveredBlocks(Counters); - } - - uint32_t SmallestNonZeroCounter(const CoverageVector &Counters) const { - assert(!Counters.empty()); - uint32_t Res = Counters[0]; - for (auto Cnt : Counters) - if (Cnt) - Res = Min(Res, Cnt); - assert(Res); - return Res; - } - - // Function ID => vector of counters. - // Each counter represents how many input files trigger the given basic block. - std::unordered_map<size_t, CoverageVector> Functions; - // Functions that have DFT entry. - std::unordered_set<size_t> FunctionsWithDFT; -}; - -class DataFlowTrace { - public: - void ReadCoverage(const std::string &DirPath); - bool Init(const std::string &DirPath, std::string *FocusFunction, - Vector<SizedFile> &CorporaFiles, Random &Rand); - 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; - BlockCoverage Coverage; - std::unordered_set<std::string> CorporaHashes; -}; -} // namespace fuzzer - -#endif // LLVM_FUZZER_DATA_FLOW_TRACE diff --git a/contrib/libs/libfuzzer12/FuzzerDefs.h b/contrib/libs/libfuzzer12/FuzzerDefs.h deleted file mode 100644 index 1bc89c94488..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerDefs.h +++ /dev/null @@ -1,77 +0,0 @@ -//===- FuzzerDefs.h - Internal header for the Fuzzer ------------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Basic definitions. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_DEFS_H -#define LLVM_FUZZER_DEFS_H - -#include <cassert> -#include <cstddef> -#include <cstdint> -#include <cstring> -#include <memory> -#include <set> -#include <string> -#include <vector> - - -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); - -#define exit(status) FuzzerExit(status) -void FuzzerExit(int status); -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/contrib/libs/libfuzzer12/FuzzerDictionary.h b/contrib/libs/libfuzzer12/FuzzerDictionary.h deleted file mode 100644 index 301c5d9afec..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerDictionary.h +++ /dev/null @@ -1,118 +0,0 @@ -//===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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/contrib/libs/libfuzzer12/FuzzerDriver.cpp b/contrib/libs/libfuzzer12/FuzzerDriver.cpp deleted file mode 100644 index 44b8e23cfbf..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerDriver.cpp +++ /dev/null @@ -1,933 +0,0 @@ -//===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// FuzzerDriver and flag parsing. -//===----------------------------------------------------------------------===// - -#include "FuzzerCommand.h" -#include "FuzzerCorpus.h" -#include "FuzzerFork.h" -#include "FuzzerIO.h" -#include "FuzzerInterface.h" -#include "FuzzerInternal.h" -#include "FuzzerMerge.h" -#include "FuzzerMutate.h" -#include "FuzzerPlatform.h" -#include "FuzzerRandom.h" -#include "FuzzerTracePC.h" -#include <algorithm> -#include <atomic> -#include <chrono> -#include <cstdlib> -#include <cstring> -#include <mutex> -#include <string> -#include <thread> -#include <fstream> - -// This function should be present in the libFuzzer so that the client -// binary can test for its existence. -#if LIBFUZZER_MSVC -extern "C" void __libfuzzer_is_present() {} -#if defined(_M_IX86) || defined(__i386__) -#pragma comment(linker, "/include:___libfuzzer_is_present") -#else -#pragma comment(linker, "/include:__libfuzzer_is_present") -#endif -#else -extern "C" __attribute__((used)) void __libfuzzer_is_present() {} -#endif // LIBFUZZER_MSVC - -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, - const ExternalFunctions *EF) { - 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; - } - - // Disable len_control by default, if LLVMFuzzerCustomMutator is used. - if (EF->LLVMFuzzerCustomMutator) { - Flags.len_control = 0; - Printf("INFO: found LLVMFuzzerCustomMutator (%p). " - "Disabling -len_control by default.\n", EF->LLVMFuzzerCustomMutator); - } - - 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); - } -} - -static void ValidateDirectoryExists(const std::string &Path, - bool CreateDirectory) { - if (Path.empty()) { - Printf("ERROR: Provided directory path is an empty string\n"); - exit(1); - } - - if (IsDirectory(Path)) - return; - - if (CreateDirectory) { - if (!MkDirRecursive(Path)) { - Printf("ERROR: Failed to create directory \"%s\"\n", Path.c_str()); - exit(1); - } - return; - } - - Printf("ERROR: The required directory \"%s\" does not exist\n", Path.c_str()); - exit(1); -} - -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()); - if (Flags.print_full_coverage) { - // Leak detection is not needed when collecting full coverage data. - F->TPCUpdateObservedPCs(); - } else { - 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 GetDedupTokenFromCmdOutput(const std::string &S) { - 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 TmpFilePath = TempPath("CleanseCrashInput", ".repro"); - Cmd.addArgument(TmpFilePath); - Cmd.setOutputFile(getDevNull()); - 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; - } - 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"); - } - - 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); - - Printf("CRASH_MIN: executing: %s\n", Cmd.toString().c_str()); - std::string CmdOutput; - bool Success = ExecuteCommand(Cmd, &CmdOutput); - if (Success) { - 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 = GetDedupTokenFromCmdOutput(CmdOutput); - 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); - Printf("CRASH_MIN: executing: %s\n", Cmd.toString().c_str()); - CmdOutput.clear(); - Success = ExecuteCommand(Cmd, &CmdOutput); - Printf("%s", CmdOutput.c_str()); - if (Success) { - 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 = GetDedupTokenFromCmdOutput(CmdOutput); - 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"); - } - 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; -} - -void Merge(Fuzzer *F, FuzzingOptions &Options, const Vector<std::string> &Args, - const Vector<std::string> &Corpora, const char *CFPathOrNull) { - if (Corpora.size() < 2) { - Printf("INFO: Merge requires two or more corpus dirs\n"); - exit(0); - } - - Vector<SizedFile> OldCorpus, NewCorpus; - GetSizedFilesFromDir(Corpora[0], &OldCorpus); - for (size_t i = 1; i < Corpora.size(); i++) - GetSizedFilesFromDir(Corpora[i], &NewCorpus); - std::sort(OldCorpus.begin(), OldCorpus.end()); - std::sort(NewCorpus.begin(), NewCorpus.end()); - - std::string CFPath = CFPathOrNull ? CFPathOrNull : TempPath("Merge", ".txt"); - Vector<std::string> NewFiles; - Set<uint32_t> NewFeatures, NewCov; - CrashResistantMerge(Args, OldCorpus, NewCorpus, &NewFiles, {}, &NewFeatures, - {}, &NewCov, CFPath, true); - for (auto &Path : NewFiles) - F->WriteToOutputCorpus(FileToVector(Path, Options.MaxLen)); - // We are done, delete the control file if it was a temporary one. - if (!Flags.merge_control_file) - RemoveFile(CFPath); - - exit(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; -} - -Vector<std::string> ParseSeedInuts(const char *seed_inputs) { - // Parse -seed_inputs=file1,file2,... or -seed_inputs=@seed_inputs_file - Vector<std::string> Files; - if (!seed_inputs) return Files; - std::string SeedInputs; - if (Flags.seed_inputs[0] == '@') - SeedInputs = FileToString(Flags.seed_inputs + 1); // File contains list. - else - SeedInputs = Flags.seed_inputs; // seed_inputs contains the list. - if (SeedInputs.empty()) { - Printf("seed_inputs is empty or @file does not exist.\n"); - exit(1); - } - // Parse SeedInputs. - size_t comma_pos = 0; - while ((comma_pos = SeedInputs.find_last_of(',')) != std::string::npos) { - Files.push_back(SeedInputs.substr(comma_pos + 1)); - SeedInputs = SeedInputs.substr(0, comma_pos); - } - Files.push_back(SeedInputs); - return Files; -} - -static Vector<SizedFile> ReadCorpora(const Vector<std::string> &CorpusDirs, - const Vector<std::string> &ExtraSeedFiles) { - Vector<SizedFile> SizedFiles; - 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 : ExtraSeedFiles) - if (auto Size = FileSize(File)) - SizedFiles.push_back({File, Size}); - return SizedFiles; -} - -void FuzzerExit(int status) { - if (EF->LLVMFuzzerCleanup) - EF->LLVMFuzzerCleanup(); - (exit)(status); -} - -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, EF); - 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.KeepSeed = Flags.keep_seed; - Options.UnitTimeoutSec = Flags.timeout; - Options.ErrorExitCode = Flags.error_exitcode; - Options.TimeoutExitCode = Flags.timeout_exitcode; - Options.InterruptExitCode = Flags.interrupted_exitcode; - Options.DumpInterrupted = Flags.dump_interrupted; - Options.IgnoreTimeouts = Flags.ignore_timeouts; - Options.IgnoreOOMs = Flags.ignore_ooms; - Options.IgnoreCrashes = Flags.ignore_crashes; - Options.MaxTotalTimeSec = Flags.max_total_time; - Options.DoCrossOver = Flags.cross_over; - Options.CrossOverUniformDist = Flags.cross_over_uniform_dist; - 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) { - // Ensure output corpus assumed to be the first arbitrary argument input - // is not a path to an existing file. - std::string OutputCorpusDir = (*Inputs)[0]; - if (!IsFile(OutputCorpusDir)) { - Options.OutputCorpus = OutputCorpusDir; - ValidateDirectoryExists(Options.OutputCorpus, Flags.create_missing_dirs); - } - } - Options.ReportSlowUnits = Flags.report_slow_units; - if (Flags.artifact_prefix) { - Options.ArtifactPrefix = Flags.artifact_prefix; - - // Since the prefix could be a full path to a file name prefix, assume - // that if the path ends with the platform's separator that a directory - // is desired - std::string ArtifactPathDir = Options.ArtifactPrefix; - if (!IsSeparator(ArtifactPathDir[ArtifactPathDir.length() - 1])) { - ArtifactPathDir = DirName(ArtifactPathDir); - } - ValidateDirectoryExists(ArtifactPathDir, Flags.create_missing_dirs); - } - if (Flags.exact_artifact_path) { - Options.ExactArtifactPath = Flags.exact_artifact_path; - ValidateDirectoryExists(DirName(Options.ExactArtifactPath), - Flags.create_missing_dirs); - } - 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 RunIndividualFiles = AllInputsAreFiles(); - Options.SaveArtifacts = - !RunIndividualFiles || 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.PrintFullCoverage = Flags.print_full_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; - if (Flags.features_dir) { - Options.FeaturesDir = Flags.features_dir; - ValidateDirectoryExists(Options.FeaturesDir, Flags.create_missing_dirs); - } - if (Flags.mutation_graph_file) - Options.MutationGraphFile = Flags.mutation_graph_file; - if (Flags.collect_data_flow) - Options.CollectDataFlow = Flags.collect_data_flow; - if (Flags.stop_file) - Options.StopFile = Flags.stop_file; - Options.Entropic = Flags.entropic; - Options.EntropicFeatureFrequencyThreshold = - (size_t)Flags.entropic_feature_frequency_threshold; - Options.EntropicNumberOfRarestFeatures = - (size_t)Flags.entropic_number_of_rarest_features; - Options.EntropicScalePerExecTime = Flags.entropic_scale_per_exec_time; - if (!Options.FocusFunction.empty()) - Options.Entropic = false; // FocusFunction overrides entropic scheduling. - if (Options.Entropic) - Printf("INFO: Running with entropic power schedule (0x%X, %d).\n", - Options.EntropicFeatureFrequencyThreshold, - Options.EntropicNumberOfRarestFeatures); - struct EntropicOptions Entropic; - Entropic.Enabled = Options.Entropic; - Entropic.FeatureFrequencyThreshold = - Options.EntropicFeatureFrequencyThreshold; - Entropic.NumberOfRarestFeatures = Options.EntropicNumberOfRarestFeatures; - Entropic.ScalePerExecTime = Options.EntropicScalePerExecTime; - - 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); - - if (Flags.collect_data_flow && !Flags.fork && !Flags.merge) { - if (RunIndividualFiles) - return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace, - ReadCorpora({}, *Inputs)); - else - return CollectDataFlow(Flags.collect_data_flow, Flags.data_flow_trace, - ReadCorpora(*Inputs, {})); - } - - Random Rand(Seed); - auto *MD = new MutationDispatcher(Rand, Options); - auto *Corpus = new InputCorpus(Options.OutputCorpus, Entropic); - auto *F = new Fuzzer(Callback, *Corpus, *MD, Options); - - for (auto &U: Dictionary) - if (U.size() <= Word::GetMaxSize()) - MD->AddWordToManualDictionary(Word(U.data(), U.size())); - - // Threads are only supported by Chrome. Don't use them with emscripten - // for now. -#if !LIBFUZZER_EMSCRIPTEN - StartRssThread(F, Flags.rss_limit_mb); -#endif // LIBFUZZER_EMSCRIPTEN - - Options.HandleAbrt = Flags.handle_abrt; - Options.HandleAlrm = !Flags.minimize_crash; - 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; - Options.HandleWinExcept = Flags.handle_winexcept; - - 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 (RunIndividualFiles) { - 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.fork) - FuzzWithFork(F->GetMD().GetRand(), Options, Args, *Inputs, Flags.fork); - - if (Flags.merge) - Merge(F, Options, Args, *Inputs, Flags.merge_control_file); - - 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); - } - - auto CorporaFiles = ReadCorpora(*Inputs, ParseSeedInuts(Flags.seed_inputs)); - F->Loop(CorporaFiles); - - 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. -} - -extern "C" ATTRIBUTE_INTERFACE int -LLVMFuzzerRunDriver(int *argc, char ***argv, - int (*UserCb)(const uint8_t *Data, size_t Size)) { - return FuzzerDriver(argc, argv, UserCb); -} - -// Storage for global ExternalFunctions object. -ExternalFunctions *EF = nullptr; - -} // namespace fuzzer diff --git a/contrib/libs/libfuzzer12/FuzzerExtFunctions.def b/contrib/libs/libfuzzer12/FuzzerExtFunctions.def deleted file mode 100644 index 40b1e73945f..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerExtFunctions.def +++ /dev/null @@ -1,51 +0,0 @@ -//===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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(LLVMFuzzerCleanup, void, (), 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, int, (), 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_log_write, void, (const char *buf, size_t len), false); -EXT_FUNC(__sanitizer_purge_allocator, void, (), false); -EXT_FUNC(__sanitizer_print_memory_profile, void, (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(__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); -EXT_FUNC(__msan_unpoison_param, void, (size_t n), false); diff --git a/contrib/libs/libfuzzer12/FuzzerExtFunctions.h b/contrib/libs/libfuzzer12/FuzzerExtFunctions.h deleted file mode 100644 index c88aac4e67c..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerExtFunctions.h +++ /dev/null @@ -1,34 +0,0 @@ -//===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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/contrib/libs/libfuzzer12/FuzzerExtFunctionsDlsym.cpp b/contrib/libs/libfuzzer12/FuzzerExtFunctionsDlsym.cpp deleted file mode 100644 index 95233d2a10d..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerExtFunctionsDlsym.cpp +++ /dev/null @@ -1,51 +0,0 @@ -//===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 "FuzzerPlatform.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/contrib/libs/libfuzzer12/FuzzerExtFunctionsWeak.cpp b/contrib/libs/libfuzzer12/FuzzerExtFunctionsWeak.cpp deleted file mode 100644 index 3ef758daa7b..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerExtFunctionsWeak.cpp +++ /dev/null @@ -1,54 +0,0 @@ -//===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 "FuzzerPlatform.h" -#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FUCHSIA || \ - LIBFUZZER_FREEBSD || LIBFUZZER_EMSCRIPTEN - -#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/contrib/libs/libfuzzer12/FuzzerExtFunctionsWindows.cpp b/contrib/libs/libfuzzer12/FuzzerExtFunctionsWindows.cpp deleted file mode 100644 index 688bad1d51c..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerExtFunctionsWindows.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//=== FuzzerExtWindows.cpp - Interface to external functions --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 "FuzzerPlatform.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/contrib/libs/libfuzzer12/FuzzerExtraCounters.cpp b/contrib/libs/libfuzzer12/FuzzerExtraCounters.cpp deleted file mode 100644 index 04f569a1a87..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerExtraCounters.cpp +++ /dev/null @@ -1,42 +0,0 @@ -//===- FuzzerExtraCounters.cpp - Extra coverage counters ------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Extra coverage counters defined by user code. -//===----------------------------------------------------------------------===// - -#include "FuzzerPlatform.h" -#include <cstdint> - -#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ - LIBFUZZER_FUCHSIA || LIBFUZZER_EMSCRIPTEN -__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/contrib/libs/libfuzzer12/FuzzerFlags.def b/contrib/libs/libfuzzer12/FuzzerFlags.def deleted file mode 100644 index 078333e81fd..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerFlags.def +++ /dev/null @@ -1,205 +0,0 @@ -//===- FuzzerFlags.def - Run-time flags -------------------------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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. Default value is 0, if LLVMFuzzerCustomMutator is used.") -FUZZER_FLAG_STRING(seed_inputs, "A comma-separated list of input files " - "to use as an additional seed corpus. Alternatively, an \"@\" followed by " - "the name of a file containing the comma-separated list.") -FUZZER_FLAG_INT(keep_seed, 0, "If 1, keep seed inputs in the corpus even if " - "they do not produce new coverage. When used with |reduce_inputs==1|, the " - "seed inputs will never be reduced. This option can be useful when seeds are" - "not properly formed for the fuzz target but still have useful snippets.") -FUZZER_FLAG_INT(cross_over, 1, "If 1, cross over inputs.") -FUZZER_FLAG_INT(cross_over_uniform_dist, 0, "Experimental. If 1, use a " - "uniform probability distribution when choosing inputs to cross over with. " - "Some of the inputs in the corpus may never get chosen for mutation " - "depending on the input mutation scheduling policy. With this flag, all " - "inputs, regardless of the input mutation scheduling policy, can be chosen " - "as an input to cross over with. This can be particularly useful with " - "|keep_seed==1|; all the initial seed inputs, even though they do not " - "increase coverage because they are not properly formed, will still be " - "chosen as an input to cross over with.") - -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, 70, "When libFuzzer reports a timeout " - "this exit code will be used.") -FUZZER_FLAG_INT(interrupted_exitcode, 0, "[arcadia] When libFuzzer intercepts a singal " - "this exit code will be used.") -FUZZER_FLAG_INT(dump_interrupted, 0, "[arcadia] If 1, dump current unit on signal.") -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(fork, 0, "Experimental mode where fuzzing happens " - "in a subprocess") -FUZZER_FLAG_INT(ignore_timeouts, 1, "Ignore timeouts in fork mode") -FUZZER_FLAG_INT(ignore_ooms, 1, "Ignore OOMs in fork mode") -FUZZER_FLAG_INT(ignore_crashes, 0, "Ignore crashes in fork mode") -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(stop_file, "Stop fuzzing ASAP if this file exists") -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." - "The same file can be used for multistep merge process.") -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_STRING(features_dir, "internal flag. Used to dump feature sets on disk." - "Every time a new input is added to the corpus, a corresponding file in the features_dir" - " is created containing the unique features of that input." - " Features are stored in binary format.") -FUZZER_FLAG_STRING(mutation_graph_file, "Saves a graph (in DOT format) to" - " mutation_graph_file. The graph contains a vertex for each input that has" - " unique coverage; directed edges are provided between parents and children" - " where the child has unique coverage, and are recorded with the type of" - " mutation that caused the child.") -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(print_full_coverage, 0, "If 1, print full coverage information " - "(all branches) as text at exit.") -FUZZER_FLAG_INT(dump_coverage, 0, "Deprecated.") -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(handle_winexcept, 1, "If 1, try to intercept uncaught Windows " - "Visual C++ Exceptions.") -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. " - "If -focus_function=auto and -data_flow_trace is used, libFuzzer " - "will choose the focus functions automatically. Disables -entropic when " - "specified.") -FUZZER_FLAG_INT(entropic, 1, "Enables entropic power schedule.") -FUZZER_FLAG_INT(entropic_feature_frequency_threshold, 0xFF, "Experimental. If " - "entropic is enabled, all features which are observed less often than " - "the specified value are considered as rare.") -FUZZER_FLAG_INT(entropic_number_of_rarest_features, 100, "Experimental. If " - "entropic is enabled, we keep track of the frequencies only for the " - "Top-X least abundant features (union features that are considered as " - "rare).") -FUZZER_FLAG_INT(entropic_scale_per_exec_time, 0, "Experimental. If 1, " - "the Entropic power schedule gets scaled based on the input execution " - "time. Inputs with lower execution time get scheduled more (up to 30x). " - "Note that, if 1, fuzzer stops from being deterministic even if a " - "non-zero random seed is given.") - -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") -FUZZER_FLAG_STRING(collect_data_flow, - "Experimental: collect the data flow trace") - -FUZZER_FLAG_INT(create_missing_dirs, 0, "Automatically attempt to create " - "directories for arguments that would normally expect them to already " - "exist (i.e. artifact_prefix, exact_artifact_path, features_dir, corpus)") diff --git a/contrib/libs/libfuzzer12/FuzzerFork.cpp b/contrib/libs/libfuzzer12/FuzzerFork.cpp deleted file mode 100644 index 84725d22a9c..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerFork.cpp +++ /dev/null @@ -1,413 +0,0 @@ -//===- FuzzerFork.cpp - run fuzzing in separate subprocesses --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Spawn and orchestrate separate fuzzing processes. -//===----------------------------------------------------------------------===// - -#include "FuzzerCommand.h" -#include "FuzzerFork.h" -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include "FuzzerMerge.h" -#include "FuzzerSHA1.h" -#include "FuzzerTracePC.h" -#include "FuzzerUtil.h" - -#include <atomic> -#include <chrono> -#include <condition_variable> -#include <fstream> -#include <memory> -#include <mutex> -#include <queue> -#include <sstream> -#include <thread> - -namespace fuzzer { - -struct Stats { - size_t number_of_executed_units = 0; - size_t peak_rss_mb = 0; - size_t average_exec_per_sec = 0; -}; - -static Stats ParseFinalStatsFromLog(const std::string &LogPath) { - std::ifstream In(LogPath); - std::string Line; - Stats Res; - struct { - const char *Name; - size_t *Var; - } NameVarPairs[] = { - {"stat::number_of_executed_units:", &Res.number_of_executed_units}, - {"stat::peak_rss_mb:", &Res.peak_rss_mb}, - {"stat::average_exec_per_sec:", &Res.average_exec_per_sec}, - {nullptr, nullptr}, - }; - while (std::getline(In, Line, '\n')) { - if (Line.find("stat::") != 0) continue; - std::istringstream ISS(Line); - std::string Name; - size_t Val; - ISS >> Name >> Val; - for (size_t i = 0; NameVarPairs[i].Name; i++) - if (Name == NameVarPairs[i].Name) - *NameVarPairs[i].Var = Val; - } - return Res; -} - -struct FuzzJob { - // Inputs. - Command Cmd; - std::string CorpusDir; - std::string FeaturesDir; - std::string LogPath; - std::string SeedListPath; - std::string CFPath; - size_t JobId; - - int DftTimeInSeconds = 0; - - // Fuzzing Outputs. - int ExitCode; - - ~FuzzJob() { - RemoveFile(CFPath); - RemoveFile(LogPath); - RemoveFile(SeedListPath); - RmDirRecursive(CorpusDir); - RmDirRecursive(FeaturesDir); - } -}; - -struct GlobalEnv { - Vector<std::string> Args; - Vector<std::string> CorpusDirs; - std::string MainCorpusDir; - std::string TempDir; - std::string DFTDir; - std::string DataFlowBinary; - Set<uint32_t> Features, Cov; - Set<std::string> FilesWithDFT; - Vector<std::string> Files; - Random *Rand; - std::chrono::system_clock::time_point ProcessStartTime; - int Verbosity = 0; - - size_t NumTimeouts = 0; - size_t NumOOMs = 0; - size_t NumCrashes = 0; - - - size_t NumRuns = 0; - - std::string StopFile() { return DirPlusFile(TempDir, "STOP"); } - - size_t secondsSinceProcessStartUp() const { - return std::chrono::duration_cast<std::chrono::seconds>( - std::chrono::system_clock::now() - ProcessStartTime) - .count(); - } - - FuzzJob *CreateNewJob(size_t JobId) { - Command Cmd(Args); - Cmd.removeFlag("fork"); - Cmd.removeFlag("runs"); - Cmd.removeFlag("collect_data_flow"); - for (auto &C : CorpusDirs) // Remove all corpora from the args. - Cmd.removeArgument(C); - Cmd.addFlag("reload", "0"); // working in an isolated dir, no reload. - Cmd.addFlag("print_final_stats", "1"); - Cmd.addFlag("print_funcs", "0"); // no need to spend time symbolizing. - Cmd.addFlag("max_total_time", std::to_string(std::min((size_t)300, JobId))); - Cmd.addFlag("stop_file", StopFile()); - if (!DataFlowBinary.empty()) { - Cmd.addFlag("data_flow_trace", DFTDir); - if (!Cmd.hasFlag("focus_function")) - Cmd.addFlag("focus_function", "auto"); - } - auto Job = new FuzzJob; - std::string Seeds; - if (size_t CorpusSubsetSize = - std::min(Files.size(), (size_t)sqrt(Files.size() + 2))) { - auto Time1 = std::chrono::system_clock::now(); - for (size_t i = 0; i < CorpusSubsetSize; i++) { - auto &SF = Files[Rand->SkewTowardsLast(Files.size())]; - Seeds += (Seeds.empty() ? "" : ",") + SF; - CollectDFT(SF); - } - auto Time2 = std::chrono::system_clock::now(); - Job->DftTimeInSeconds = duration_cast<seconds>(Time2 - Time1).count(); - } - if (!Seeds.empty()) { - Job->SeedListPath = - DirPlusFile(TempDir, std::to_string(JobId) + ".seeds"); - WriteToFile(Seeds, Job->SeedListPath); - Cmd.addFlag("seed_inputs", "@" + Job->SeedListPath); - } - Job->LogPath = DirPlusFile(TempDir, std::to_string(JobId) + ".log"); - Job->CorpusDir = DirPlusFile(TempDir, "C" + std::to_string(JobId)); - Job->FeaturesDir = DirPlusFile(TempDir, "F" + std::to_string(JobId)); - Job->CFPath = DirPlusFile(TempDir, std::to_string(JobId) + ".merge"); - Job->JobId = JobId; - - - Cmd.addArgument(Job->CorpusDir); - Cmd.addFlag("features_dir", Job->FeaturesDir); - - for (auto &D : {Job->CorpusDir, Job->FeaturesDir}) { - RmDirRecursive(D); - MkDir(D); - } - - Cmd.setOutputFile(Job->LogPath); - Cmd.combineOutAndErr(); - - Job->Cmd = Cmd; - - if (Verbosity >= 2) - Printf("Job %zd/%p Created: %s\n", JobId, Job, - Job->Cmd.toString().c_str()); - // Start from very short runs and gradually increase them. - return Job; - } - - void RunOneMergeJob(FuzzJob *Job) { - auto Stats = ParseFinalStatsFromLog(Job->LogPath); - NumRuns += Stats.number_of_executed_units; - - Vector<SizedFile> TempFiles, MergeCandidates; - // Read all newly created inputs and their feature sets. - // Choose only those inputs that have new features. - GetSizedFilesFromDir(Job->CorpusDir, &TempFiles); - std::sort(TempFiles.begin(), TempFiles.end()); - for (auto &F : TempFiles) { - auto FeatureFile = F.File; - FeatureFile.replace(0, Job->CorpusDir.size(), Job->FeaturesDir); - auto FeatureBytes = FileToVector(FeatureFile, 0, false); - assert((FeatureBytes.size() % sizeof(uint32_t)) == 0); - Vector<uint32_t> NewFeatures(FeatureBytes.size() / sizeof(uint32_t)); - memcpy(NewFeatures.data(), FeatureBytes.data(), FeatureBytes.size()); - for (auto Ft : NewFeatures) { - if (!Features.count(Ft)) { - MergeCandidates.push_back(F); - break; - } - } - } - // if (!FilesToAdd.empty() || Job->ExitCode != 0) - Printf("#%zd: cov: %zd ft: %zd corp: %zd exec/s %zd " - "oom/timeout/crash: %zd/%zd/%zd time: %zds job: %zd dft_time: %d\n", - NumRuns, Cov.size(), Features.size(), Files.size(), - Stats.average_exec_per_sec, NumOOMs, NumTimeouts, NumCrashes, - secondsSinceProcessStartUp(), Job->JobId, Job->DftTimeInSeconds); - - if (MergeCandidates.empty()) return; - - Vector<std::string> FilesToAdd; - Set<uint32_t> NewFeatures, NewCov; - CrashResistantMerge(Args, {}, MergeCandidates, &FilesToAdd, Features, - &NewFeatures, Cov, &NewCov, Job->CFPath, false); - for (auto &Path : FilesToAdd) { - auto U = FileToVector(Path); - auto NewPath = DirPlusFile(MainCorpusDir, Hash(U)); - WriteToFile(U, NewPath); - Files.push_back(NewPath); - } - Features.insert(NewFeatures.begin(), NewFeatures.end()); - Cov.insert(NewCov.begin(), NewCov.end()); - for (auto Idx : NewCov) - if (auto *TE = TPC.PCTableEntryByIdx(Idx)) - if (TPC.PcIsFuncEntry(TE)) - PrintPC(" NEW_FUNC: %p %F %L\n", "", - TPC.GetNextInstructionPc(TE->PC)); - - } - - - void CollectDFT(const std::string &InputPath) { - if (DataFlowBinary.empty()) return; - if (!FilesWithDFT.insert(InputPath).second) return; - Command Cmd(Args); - Cmd.removeFlag("fork"); - Cmd.removeFlag("runs"); - Cmd.addFlag("data_flow_trace", DFTDir); - Cmd.addArgument(InputPath); - for (auto &C : CorpusDirs) // Remove all corpora from the args. - Cmd.removeArgument(C); - Cmd.setOutputFile(DirPlusFile(TempDir, "dft.log")); - Cmd.combineOutAndErr(); - // Printf("CollectDFT: %s\n", Cmd.toString().c_str()); - ExecuteCommand(Cmd); - } - -}; - -struct JobQueue { - std::queue<FuzzJob *> Qu; - std::mutex Mu; - std::condition_variable Cv; - - void Push(FuzzJob *Job) { - { - std::lock_guard<std::mutex> Lock(Mu); - Qu.push(Job); - } - Cv.notify_one(); - } - FuzzJob *Pop() { - std::unique_lock<std::mutex> Lk(Mu); - // std::lock_guard<std::mutex> Lock(Mu); - Cv.wait(Lk, [&]{return !Qu.empty();}); - assert(!Qu.empty()); - auto Job = Qu.front(); - Qu.pop(); - return Job; - } -}; - -void WorkerThread(JobQueue *FuzzQ, JobQueue *MergeQ) { - while (auto Job = FuzzQ->Pop()) { - // Printf("WorkerThread: job %p\n", Job); - Job->ExitCode = ExecuteCommand(Job->Cmd); - MergeQ->Push(Job); - } -} - -// This is just a skeleton of an experimental -fork=1 feature. -void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, - const Vector<std::string> &Args, - const Vector<std::string> &CorpusDirs, int NumJobs) { - Printf("INFO: -fork=%d: fuzzing in separate process(s)\n", NumJobs); - - GlobalEnv Env; - Env.Args = Args; - Env.CorpusDirs = CorpusDirs; - Env.Rand = &Rand; - Env.Verbosity = Options.Verbosity; - Env.ProcessStartTime = std::chrono::system_clock::now(); - Env.DataFlowBinary = Options.CollectDataFlow; - - Vector<SizedFile> SeedFiles; - for (auto &Dir : CorpusDirs) - GetSizedFilesFromDir(Dir, &SeedFiles); - std::sort(SeedFiles.begin(), SeedFiles.end()); - Env.TempDir = TempPath("FuzzWithFork", ".dir"); - Env.DFTDir = DirPlusFile(Env.TempDir, "DFT"); - RmDirRecursive(Env.TempDir); // in case there is a leftover from old runs. - MkDir(Env.TempDir); - MkDir(Env.DFTDir); - - - if (CorpusDirs.empty()) - MkDir(Env.MainCorpusDir = DirPlusFile(Env.TempDir, "C")); - else - Env.MainCorpusDir = CorpusDirs[0]; - - if (Options.KeepSeed) { - for (auto &File : SeedFiles) - Env.Files.push_back(File.File); - } else { - auto CFPath = DirPlusFile(Env.TempDir, "merge.txt"); - CrashResistantMerge(Env.Args, {}, SeedFiles, &Env.Files, {}, &Env.Features, - {}, &Env.Cov, CFPath, false); - RemoveFile(CFPath); - } - Printf("INFO: -fork=%d: %zd seed inputs, starting to fuzz in %s\n", NumJobs, - Env.Files.size(), Env.TempDir.c_str()); - - int ExitCode = 0; - - JobQueue FuzzQ, MergeQ; - - auto StopJobs = [&]() { - for (int i = 0; i < NumJobs; i++) - FuzzQ.Push(nullptr); - MergeQ.Push(nullptr); - WriteToFile(Unit({1}), Env.StopFile()); - }; - - size_t JobId = 1; - Vector<std::thread> Threads; - for (int t = 0; t < NumJobs; t++) { - Threads.push_back(std::thread(WorkerThread, &FuzzQ, &MergeQ)); - FuzzQ.Push(Env.CreateNewJob(JobId++)); - } - - while (true) { - std::unique_ptr<FuzzJob> Job(MergeQ.Pop()); - if (!Job) - break; - ExitCode = Job->ExitCode; - if (ExitCode == Options.InterruptExitCode) { - Printf("==%lu== libFuzzer: a child was interrupted; exiting\n", GetPid()); - StopJobs(); - break; - } - Fuzzer::MaybeExitGracefully(); - - Env.RunOneMergeJob(Job.get()); - - // Continue if our crash is one of the ignorred ones. - if (Options.IgnoreTimeouts && ExitCode == Options.TimeoutExitCode) - Env.NumTimeouts++; - else if (Options.IgnoreOOMs && ExitCode == Options.OOMExitCode) - Env.NumOOMs++; - else if (ExitCode != 0) { - Env.NumCrashes++; - if (Options.IgnoreCrashes) { - std::ifstream In(Job->LogPath); - std::string Line; - while (std::getline(In, Line, '\n')) - if (Line.find("ERROR:") != Line.npos || - Line.find("runtime error:") != Line.npos) - Printf("%s\n", Line.c_str()); - } else { - // And exit if we don't ignore this crash. - Printf("INFO: log from the inner process:\n%s", - FileToString(Job->LogPath).c_str()); - StopJobs(); - break; - } - } - - // Stop if we are over the time budget. - // This is not precise, since other threads are still running - // and we will wait while joining them. - // We also don't stop instantly: other jobs need to finish. - if (Options.MaxTotalTimeSec > 0 && - Env.secondsSinceProcessStartUp() >= (size_t)Options.MaxTotalTimeSec) { - Printf("INFO: fuzzed for %zd seconds, wrapping up soon\n", - Env.secondsSinceProcessStartUp()); - StopJobs(); - break; - } - if (Env.NumRuns >= Options.MaxNumberOfRuns) { - Printf("INFO: fuzzed for %zd iterations, wrapping up soon\n", - Env.NumRuns); - StopJobs(); - break; - } - - FuzzQ.Push(Env.CreateNewJob(JobId++)); - } - - for (auto &T : Threads) - T.join(); - - // The workers have terminated. Don't try to remove the directory before they - // terminate to avoid a race condition preventing cleanup on Windows. - RmDirRecursive(Env.TempDir); - - // Use the exit code from the last child process. - Printf("INFO: exiting: %d time: %zds\n", ExitCode, - Env.secondsSinceProcessStartUp()); - exit(ExitCode); -} - -} // namespace fuzzer diff --git a/contrib/libs/libfuzzer12/FuzzerFork.h b/contrib/libs/libfuzzer12/FuzzerFork.h deleted file mode 100644 index b29a43e13fb..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerFork.h +++ /dev/null @@ -1,24 +0,0 @@ -//===- FuzzerFork.h - run fuzzing in sub-processes --------------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_FORK_H -#define LLVM_FUZZER_FORK_H - -#include "FuzzerDefs.h" -#include "FuzzerOptions.h" -#include "FuzzerRandom.h" - -#include <string> - -namespace fuzzer { -void FuzzWithFork(Random &Rand, const FuzzingOptions &Options, - const Vector<std::string> &Args, - const Vector<std::string> &CorpusDirs, int NumJobs); -} // namespace fuzzer - -#endif // LLVM_FUZZER_FORK_H diff --git a/contrib/libs/libfuzzer12/FuzzerIO.cpp b/contrib/libs/libfuzzer12/FuzzerIO.cpp deleted file mode 100644 index 54a7219fc0e..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerIO.cpp +++ /dev/null @@ -1,204 +0,0 @@ -//===- FuzzerIO.cpp - IO utils. -------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// IO functions. -//===----------------------------------------------------------------------===// - -#include "FuzzerDefs.h" -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" -#include "FuzzerUtil.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) { - WriteToFile(U.data(), U.size(), Path); -} - -void WriteToFile(const std::string &Data, const std::string &Path) { - WriteToFile(reinterpret_cast<const uint8_t *>(Data.c_str()), Data.size(), - Path); -} - -void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) { - // Use raw C interface because this function may be called from a sig handler. - FILE *Out = fopen(Path.c_str(), "wb"); - if (!Out) return; - fwrite(Data, sizeof(Data[0]), Size, Out); - fclose(Out); -} - -void AppendToFile(const std::string &Data, const std::string &Path) { - AppendToFile(reinterpret_cast<const uint8_t *>(Data.data()), Data.size(), - Path); -} - -void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path) { - FILE *Out = fopen(Path.c_str(), "a"); - if (!Out) - return; - fwrite(Data, sizeof(Data[0]), 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); -} - -void VPrintf(bool Verbose, const char *Fmt, ...) { - if (!Verbose) return; - va_list ap; - va_start(ap, Fmt); - vfprintf(OutputFile, Fmt, ap); - va_end(ap); - fflush(OutputFile); -} - -static bool MkDirRecursiveInner(const std::string &Leaf) { - // Prevent chance of potential infinite recursion - if (Leaf == ".") - return true; - - const std::string &Dir = DirName(Leaf); - - if (IsDirectory(Dir)) { - MkDir(Leaf); - return IsDirectory(Leaf); - } - - bool ret = MkDirRecursiveInner(Dir); - if (!ret) { - // Give up early if a previous MkDir failed - return ret; - } - - MkDir(Leaf); - return IsDirectory(Leaf); -} - -bool MkDirRecursive(const std::string &Dir) { - if (Dir.empty()) - return false; - - if (IsDirectory(Dir)) - return true; - - return MkDirRecursiveInner(Dir); -} - -void RmDirRecursive(const std::string &Dir) { - IterateDirRecursive( - Dir, [](const std::string &Path) {}, - [](const std::string &Path) { RmDir(Path); }, - [](const std::string &Path) { RemoveFile(Path); }); -} - -std::string TempPath(const char *Prefix, const char *Extension) { - return DirPlusFile(TmpDir(), std::string("libFuzzerTemp.") + Prefix + - std::to_string(GetPid()) + Extension); -} - -} // namespace fuzzer diff --git a/contrib/libs/libfuzzer12/FuzzerIO.h b/contrib/libs/libfuzzer12/FuzzerIO.h deleted file mode 100644 index abd25110d07..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerIO.h +++ /dev/null @@ -1,112 +0,0 @@ -//===- FuzzerIO.h - Internal header for IO utils ----------------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 uint8_t *Data, size_t Size, const std::string &Path); -// Write Data.c_str() to the file without terminating null character. -void WriteToFile(const std::string &Data, const std::string &Path); -void WriteToFile(const Unit &U, const std::string &Path); - -void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path); -void AppendToFile(const std::string &Data, 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(); - -std::string TempPath(const char *Prefix, const char *Extension); - -bool IsInterestingCoverageFile(const std::string &FileName); - -void DupAndCloseStderr(); - -void CloseStdout(); - -void Printf(const char *Fmt, ...); -void VPrintf(bool Verbose, 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); -bool IsDirectory(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); - -bool MkDirRecursive(const std::string &Dir); -void RmDirRecursive(const std::string &Dir); - -// Iterate files and dirs inside Dir, recursively. -// Call DirPreCallback/DirPostCallback on dirs before/after -// calling FileCallback on files. -void IterateDirRecursive(const std::string &Dir, - void (*DirPreCallback)(const std::string &Dir), - void (*DirPostCallback)(const std::string &Dir), - void (*FileCallback)(const std::string &Dir)); - -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(); -bool IsSeparator(char C); -// 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 RenameFile(const std::string &OldPath, const std::string &NewPath); - -intptr_t GetHandleFromFd(int fd); - -void MkDir(const std::string &Path); -void RmDir(const std::string &Path); - -const std::string &getDevNull(); - -} // namespace fuzzer - -#endif // LLVM_FUZZER_IO_H diff --git a/contrib/libs/libfuzzer12/FuzzerIOPosix.cpp b/contrib/libs/libfuzzer12/FuzzerIOPosix.cpp deleted file mode 100644 index 4706a40959b..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerIOPosix.cpp +++ /dev/null @@ -1,180 +0,0 @@ -//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// IO functions implementation using Posix API. -//===----------------------------------------------------------------------===// -#include "FuzzerPlatform.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); -} - -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; -} - - -void IterateDirRecursive(const std::string &Dir, - void (*DirPreCallback)(const std::string &Dir), - void (*DirPostCallback)(const std::string &Dir), - void (*FileCallback)(const std::string &Dir)) { - DirPreCallback(Dir); - DIR *D = opendir(Dir.c_str()); - if (!D) return; - 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))) - FileCallback(Path); - else if ((E->d_type == DT_DIR || - (E->d_type == DT_UNKNOWN && IsDirectory(Path))) && - *E->d_name != '.') - IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback); - } - closedir(D); - DirPostCallback(Dir); -} - -char GetSeparator() { - return '/'; -} - -bool IsSeparator(char C) { - return C == '/'; -} - -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 RenameFile(const std::string &OldPath, const std::string &NewPath) { - rename(OldPath.c_str(), NewPath.c_str()); -} - -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) { - (void)write(2, Str, strlen(Str)); -} - -void MkDir(const std::string &Path) { - mkdir(Path.c_str(), 0700); -} - -void RmDir(const std::string &Path) { - rmdir(Path.c_str()); -} - -const std::string &getDevNull() { - static const std::string devNull = "/dev/null"; - return devNull; -} - -} // namespace fuzzer - -#endif // LIBFUZZER_POSIX diff --git a/contrib/libs/libfuzzer12/FuzzerIOWindows.cpp b/contrib/libs/libfuzzer12/FuzzerIOWindows.cpp deleted file mode 100644 index 61ad35e281f..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerIOWindows.cpp +++ /dev/null @@ -1,425 +0,0 @@ -//===- FuzzerIOWindows.cpp - IO utils for Windows. ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// IO functions implementation for Windows. -//===----------------------------------------------------------------------===// -#include "FuzzerPlatform.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); -} - -static bool IsDir(DWORD FileAttrs) { - if (FileAttrs == INVALID_FILE_ATTRIBUTES) return false; - return FileAttrs & FILE_ATTRIBUTE_DIRECTORY; -} - -bool IsDirectory(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 IsDir(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)) { - DWORD LastError = GetLastError(); - if (LastError != ERROR_FILE_NOT_FOUND) - Printf("GetFileAttributesExA() failed for \"%s\" (Error code: %lu).\n", - Path.c_str(), LastError); - 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; -} - - -void IterateDirRecursive(const std::string &Dir, - void (*DirPreCallback)(const std::string &Dir), - void (*DirPostCallback)(const std::string &Dir), - void (*FileCallback)(const std::string &Dir)) { - // TODO(metzman): Implement ListFilesInDirRecursive via this function. - DirPreCallback(Dir); - - DWORD DirAttrs = GetFileAttributesA(Dir.c_str()); - if (!IsDir(DirAttrs)) return; - - std::string TargetDir(Dir); - assert(!TargetDir.empty()); - if (TargetDir.back() != '\\') TargetDir.push_back('\\'); - TargetDir.push_back('*'); - - WIN32_FIND_DATAA FindInfo; - // Find the directory's first file. - HANDLE FindHandle = FindFirstFileA(TargetDir.c_str(), &FindInfo); - if (FindHandle == INVALID_HANDLE_VALUE) { - DWORD LastError = GetLastError(); - if (LastError != ERROR_FILE_NOT_FOUND) { - // If the directory isn't empty, then something abnormal is going on. - Printf("FindFirstFileA failed for %s (Error code: %lu).\n", Dir.c_str(), - LastError); - } - return; - } - - do { - std::string Path = DirPlusFile(Dir, FindInfo.cFileName); - DWORD PathAttrs = FindInfo.dwFileAttributes; - if (IsDir(PathAttrs)) { - // Is Path the current directory (".") or the parent ("..")? - if (strcmp(FindInfo.cFileName, ".") == 0 || - strcmp(FindInfo.cFileName, "..") == 0) - continue; - IterateDirRecursive(Path, DirPreCallback, DirPostCallback, FileCallback); - } else if (PathAttrs != INVALID_FILE_ATTRIBUTES) { - FileCallback(Path); - } - } while (FindNextFileA(FindHandle, &FindInfo)); - - DWORD LastError = GetLastError(); - if (LastError != ERROR_NO_MORE_FILES) - Printf("FindNextFileA failed for %s (Error code: %lu).\n", Dir.c_str(), - LastError); - - FindClose(FindHandle); - DirPostCallback(Dir); -} - -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 RenameFile(const std::string &OldPath, const std::string &NewPath) { - rename(OldPath.c_str(), NewPath.c_str()); -} - -intptr_t GetHandleFromFd(int fd) { - return _get_osfhandle(fd); -} - -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) { - _write(2, Str, strlen(Str)); -} - -void MkDir(const std::string &Path) { - if (CreateDirectoryA(Path.c_str(), nullptr)) return; - Printf("CreateDirectoryA failed for %s (Error code: %lu).\n", Path.c_str(), - GetLastError()); -} - -void RmDir(const std::string &Path) { - if (RemoveDirectoryA(Path.c_str())) return; - Printf("RemoveDirectoryA failed for %s (Error code: %lu).\n", Path.c_str(), - GetLastError()); -} - -const std::string &getDevNull() { - static const std::string devNull = "NUL"; - return devNull; -} - -} // namespace fuzzer - -#endif // LIBFUZZER_WINDOWS diff --git a/contrib/libs/libfuzzer12/FuzzerInterface.h b/contrib/libs/libfuzzer12/FuzzerInterface.h deleted file mode 100644 index f1130dc3968..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerInterface.h +++ /dev/null @@ -1,80 +0,0 @@ -//===- FuzzerInterface.h - Interface header for the Fuzzer ------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 - -// Define FUZZER_INTERFACE_VISIBILITY to set default visibility in a way that -// doesn't break MSVC. -#if defined(_WIN32) -#define FUZZER_INTERFACE_VISIBILITY __declspec(dllexport) -#else -#define FUZZER_INTERFACE_VISIBILITY __attribute__((visibility("default"))) -#endif - -// 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. -FUZZER_INTERFACE_VISIBILITY 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. -FUZZER_INTERFACE_VISIBILITY int LLVMFuzzerInitialize(int *argc, char ***argv); -FUZZER_INTERFACE_VISIBILITY void LLVMFuzzerCleanup(); - -// 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. -FUZZER_INTERFACE_VISIBILITY 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. -FUZZER_INTERFACE_VISIBILITY 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. -FUZZER_INTERFACE_VISIBILITY size_t -LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize); - -#undef FUZZER_INTERFACE_VISIBILITY - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#endif // LLVM_FUZZER_INTERFACE_H diff --git a/contrib/libs/libfuzzer12/FuzzerInternal.h b/contrib/libs/libfuzzer12/FuzzerInternal.h deleted file mode 100644 index 37c8a01dc3c..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerInternal.h +++ /dev/null @@ -1,174 +0,0 @@ -//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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(Vector<SizedFile> &CorporaFiles); - void ReadAndExecuteSeedCorpora(Vector<SizedFile> &CorporaFiles); - 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); - bool RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile = false, - InputInfo *II = nullptr, bool ForceAddToCorpus = false, - bool *FoundUniqFeatures = nullptr); - void TPCUpdateObservedPCs(); - - // Merge Corpora[1:] into Corpora[0]. - void Merge(const Vector<std::string> &Corpora); - 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); - static void MaybeExitGracefully(); - std::string WriteToOutputCorpus(const Unit &U); - -private: - void AlarmCallback(); - void CrashCallback(); - void ExitCallback(); - 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 WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix); - void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0, - size_t Features = 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/contrib/libs/libfuzzer12/FuzzerLoop.cpp b/contrib/libs/libfuzzer12/FuzzerLoop.cpp deleted file mode 100644 index fc53ac086b9..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerLoop.cpp +++ /dev/null @@ -1,921 +0,0 @@ -//===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Fuzzer's main loop. -//===----------------------------------------------------------------------===// - -#include "FuzzerCorpus.h" -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include "FuzzerMutate.h" -#include "FuzzerPlatform.h" -#include "FuzzerRandom.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; - -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.OOMExitCode); // 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 = 0; // Will be set once we load the corpus. - AllocateCurrentUnitData(); - CurrentUnitSize = 0; - memset(BaseSha1, 0, sizeof(BaseSha1)); -} - -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()) - return; - 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 (!F->GracefulExitRequested) return; - Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid()); - RmDirRecursive(TempPath("FuzzWithFork", ".dir")); - F->PrintFinalStats(); - _Exit(0); -} - -void Fuzzer::InterruptCallback() { - if (Options.DumpInterrupted) - DumpCurrentUnit("interrupted-"); - Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); - PrintFinalStats(); - ScopedDisableMsanInterceptorChecks S; // RmDirRecursive may call opendir(). - RmDirRecursive(TempPath("FuzzWithFork", ".dir")); - // Stop right now, don't perform any at-exit actions. - _Exit(Options.InterruptExitCode); -} - -NO_SANITIZE_MEMORY -void Fuzzer::AlarmCallback() { - assert(Options.UnitTimeoutSec > 0); - // In Windows and Fuchsia, Alarm callback is executed by a different thread. - // NetBSD's current behavior needs this change too. -#if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD && !LIBFUZZER_FUCHSIA - 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.OOMExitCode); // Stop right now. -} - -void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units, - size_t Features) { - 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 = Features ? Features : 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.PrintFullCoverage) - TPC.PrintCoverage(/*PrintAllCounters=*/true); - if (Options.PrintCoverage) - TPC.PrintCoverage(/*PrintAllCounters=*/false); - 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 = [&](const TracePC::PCTableEntry *TE) { - if (!PCsSet->insert(TE->PC).second) - return; - std::string Descr = DescribePC("%F %L", TE->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-"); - } -} - -static void WriteFeatureSetToFile(const std::string &FeaturesDir, - const std::string &FileName, - const Vector<uint32_t> &FeatureSet) { - if (FeaturesDir.empty() || FeatureSet.empty()) return; - WriteToFile(reinterpret_cast<const uint8_t *>(FeatureSet.data()), - FeatureSet.size() * sizeof(FeatureSet[0]), - DirPlusFile(FeaturesDir, FileName)); -} - -static void RenameFeatureSetFile(const std::string &FeaturesDir, - const std::string &OldFile, - const std::string &NewFile) { - if (FeaturesDir.empty()) return; - RenameFile(DirPlusFile(FeaturesDir, OldFile), - DirPlusFile(FeaturesDir, NewFile)); -} - -static void WriteEdgeToMutationGraphFile(const std::string &MutationGraphFile, - const InputInfo *II, - const InputInfo *BaseII, - const std::string &MS) { - if (MutationGraphFile.empty()) - return; - - std::string Sha1 = Sha1ToString(II->Sha1); - - std::string OutputString; - - // Add a new vertex. - OutputString.append("\""); - OutputString.append(Sha1); - OutputString.append("\"\n"); - - // Add a new edge if there is base input. - if (BaseII) { - std::string BaseSha1 = Sha1ToString(BaseII->Sha1); - OutputString.append("\""); - OutputString.append(BaseSha1); - OutputString.append("\" -> \""); - OutputString.append(Sha1); - OutputString.append("\" [label=\""); - OutputString.append(MS); - OutputString.append("\"];\n"); - } - - AppendToFile(OutputString, MutationGraphFile); -} - -bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, - InputInfo *II, bool ForceAddToCorpus, - bool *FoundUniqFeatures) { - if (!Size) - return false; - - ExecuteCallback(Data, Size); - auto TimeOfUnit = duration_cast<microseconds>(UnitStopTime - UnitStartTime); - - UniqFeatureSetTmp.clear(); - size_t FoundUniqFeaturesOfII = 0; - size_t NumUpdatesBefore = Corpus.NumFeatureUpdates(); - TPC.CollectFeatures([&](size_t Feature) { - if (Corpus.AddFeature(Feature, Size, Options.Shrink)) - UniqFeatureSetTmp.push_back(Feature); - if (Options.Entropic) - Corpus.UpdateFeatureFrequency(II, Feature); - if (Options.ReduceInputs && II && !II->NeverReduce) - 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 || ForceAddToCorpus) { - TPC.UpdateObservedPCs(); - auto NewII = - Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile, - TPC.ObservedFocusFunction(), ForceAddToCorpus, - TimeOfUnit, UniqFeatureSetTmp, DFT, II); - WriteFeatureSetToFile(Options.FeaturesDir, Sha1ToString(NewII->Sha1), - NewII->UniqFeatureSet); - WriteEdgeToMutationGraphFile(Options.MutationGraphFile, NewII, II, - MD.MutationSequence()); - return true; - } - if (II && FoundUniqFeaturesOfII && - II->DataFlowTraceForFocusFunction.empty() && - FoundUniqFeaturesOfII == II->UniqFeatureSet.size() && - II->U.size() > Size) { - auto OldFeaturesFile = Sha1ToString(II->Sha1); - Corpus.Replace(II, {Data, Data + Size}); - RenameFeatureSetFile(Options.FeaturesDir, OldFeaturesFile, - Sha1ToString(II->Sha1)); - return true; - } - return false; -} - -void Fuzzer::TPCUpdateObservedPCs() { TPC.UpdateObservedPCs(); } - -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 its const input\n", - GetPid()); - PrintStackTrace(); - Printf("SUMMARY: libFuzzer: overwrites-const-input\n"); - DumpCurrentUnit("crash-"); - PrintFinalStats(); - _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()); - // 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 (EF->__msan_unpoison_param) - EF->__msan_unpoison_param(2); - 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; -} - -std::string 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()); - return Path; -} - -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(Options.Verbosity >= 2); - 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()); - if (Options.DoCrossOver) { - auto &CrossOverII = Corpus.ChooseUnitToCrossOverWith( - MD.GetRand(), Options.CrossOverUniformDist); - MD.SetCrossOverWith(&CrossOverII.U); - } - 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); - - // If MutateWithMask either failed or wasn't called, call default Mutate. - if (!NewSize) - NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen); - assert(NewSize > 0 && "Mutator returned empty unit"); - assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit"); - Size = NewSize; - II.NumExecutedMutations++; - Corpus.IncrementNumExecutedMutations(); - - bool FoundUniqFeatures = false; - bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II, - /*ForceAddToCorpus*/ false, &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; - } - - II.NeedsEnergyUpdate = true; -} - -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(Vector<SizedFile> &CorporaFiles) { - const size_t kMaxSaneLen = 1 << 20; - const size_t kMinDefaultLen = 4096; - size_t MaxSize = 0; - size_t MinSize = -1; - size_t TotalSize = 0; - for (auto &File : CorporaFiles) { - 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 (CorporaFiles.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", - CorporaFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb()); - if (Options.ShuffleAtStartUp) - std::shuffle(CorporaFiles.begin(), CorporaFiles.end(), MD.GetRand()); - - if (Options.PreferSmall) { - std::stable_sort(CorporaFiles.begin(), CorporaFiles.end()); - assert(CorporaFiles.front().Size <= CorporaFiles.back().Size); - } - - // Load and execute inputs one by one. - for (auto &SF : CorporaFiles) { - auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false); - assert(U.size() <= MaxInputLen); - RunOne(U.data(), U.size(), /*MayDeleteFile*/ false, /*II*/ nullptr, - /*ForceAddToCorpus*/ Options.KeepSeed, - /*FoundUniqFeatures*/ nullptr); - 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.NumInputsThatTouchFocusFunction()); - } - - 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(Vector<SizedFile> &CorporaFiles) { - auto FocusFunctionOrAuto = Options.FocusFunction; - DFT.Init(Options.DataFlowTrace, &FocusFunctionOrAuto, CorporaFiles, - MD.GetRand()); - TPC.SetFocusFunction(FocusFunctionOrAuto); - ReadAndExecuteSeedCorpora(CorporaFiles); - DFT.Clear(); // No need for DFT any more. - TPC.SetPrintNewPCs(Options.PrintNewCovPcs); - TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs); - system_clock::time_point LastCorpusReload = system_clock::now(); - - TmpMaxMutationLen = - Min(MaxMutationLen, Max(size_t(4), Corpus.MaxInputSize())); - - while (true) { - auto Now = system_clock::now(); - if (!Options.StopFile.empty() && - !FileToVector(Options.StopFile, 1, false).empty()) - break; - 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); - } - } -} - -} // namespace fuzzer - -extern "C" { - -ATTRIBUTE_INTERFACE size_t -LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { - assert(fuzzer::F); - return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize); -} - -} // extern "C" diff --git a/contrib/libs/libfuzzer12/FuzzerMain.cpp b/contrib/libs/libfuzzer12/FuzzerMain.cpp deleted file mode 100644 index 75f2f8e75c9..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerMain.cpp +++ /dev/null @@ -1,21 +0,0 @@ -//===- FuzzerMain.cpp - main() function and flags -------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// main() and flags. -//===----------------------------------------------------------------------===// - -#include "FuzzerDefs.h" -#include "FuzzerPlatform.h" - -extern "C" { -// This function should be defined by the user. -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); -} // extern "C" - -ATTRIBUTE_INTERFACE int main(int argc, char **argv) { - return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput); -} diff --git a/contrib/libs/libfuzzer12/FuzzerMerge.cpp b/contrib/libs/libfuzzer12/FuzzerMerge.cpp deleted file mode 100644 index e3ad8b3851e..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerMerge.cpp +++ /dev/null @@ -1,402 +0,0 @@ -//===- FuzzerMerge.cpp - merging corpora ----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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> -#include <unordered_set> - -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 -// FT 0 1 4 6 8 # FileID COV1 COV2 ... -// COV 0 7 8 9 # FileID COV1 COV1 -// STARTED 1 456 # If FT is missing, the input crashed while processing. -// STARTED 2 567 -// FT 2 8 9 -// COV 2 11 12 -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, FT, and COV lines. - size_t ExpectedStartMarker = 0; - const size_t kInvalidStartMarker = -1; - size_t LastSeenStartMarker = kInvalidStartMarker; - Vector<uint32_t> TmpFeatures; - Set<uint32_t> PCs; - 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 == "FT") { - // FT 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 >> N) - TmpFeatures.push_back(N); - std::sort(TmpFeatures.begin(), TmpFeatures.end()); - Files[CurrentFileIdx].Features = TmpFeatures; - } - } else if (Marker == "COV") { - size_t CurrentFileIdx = N; - if (ParseCoverage) - while (ISS1 >> N) - if (PCs.insert(N).second) - Files[CurrentFileIdx].Cov.push_back(N); - } 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 those to NewFiles). -// Returns the number of new features added. -size_t Merger::Merge(const Set<uint32_t> &InitialFeatures, - Set<uint32_t> *NewFeatures, - const Set<uint32_t> &InitialCov, Set<uint32_t> *NewCov, - 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()); - } - // 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()); - bool FoundNewFeatures = false; - for (auto Fe: Cur) { - if (AllFeatures.insert(Fe).second) { - FoundNewFeatures = true; - NewFeatures->insert(Fe); - } - } - if (FoundNewFeatures) - NewFiles->push_back(Files[i].Name); - for (auto Cov : Files[i].Cov) - if (InitialCov.find(Cov) == InitialCov.end()) - NewCov->insert(Cov); - } - return NewFeatures->size(); -} - -Set<uint32_t> Merger::AllFeatures() const { - Set<uint32_t> S; - for (auto &File : Files) - S.insert(File.Features.begin(), File.Features.end()); - return S; -} - -// 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; - auto PrintStatsWrapper = [this, &AllFeatures](const char* Where) { - this->PrintStats(Where, "\n", 0, AllFeatures.size()); - }; - Set<const TracePC::PCTableEntry *> AllPCs; - for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) { - Fuzzer::MaybeExitGracefully(); - auto U = FileToVector(M.Files[i].Name); - if (U.size() > MaxInputLen) { - U.resize(MaxInputLen); - U.shrink_to_fit(); - } - - // Write the pre-run marker. - OF << "STARTED " << 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); - }); - TPC.UpdateObservedPCs(); - // Show stats. - if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1))) - PrintStatsWrapper("pulse "); - if (TotalNumberOfRuns == M.NumFilesInFirstCorpus) - PrintStatsWrapper("LOADED"); - // Write the post-run marker and the coverage. - OF << "FT " << i; - for (size_t F : UniqFeatures) - OF << " " << F; - OF << "\n"; - OF << "COV " << i; - TPC.ForEachObservedPC([&](const TracePC::PCTableEntry *TE) { - if (AllPCs.insert(TE).second) - OF << " " << TPC.PCTableEntryIdx(TE); - }); - OF << "\n"; - OF.flush(); - } - PrintStatsWrapper("DONE "); -} - -static size_t WriteNewControlFile(const std::string &CFPath, - const Vector<SizedFile> &OldCorpus, - const Vector<SizedFile> &NewCorpus, - const Vector<MergeFileInfo> &KnownFiles) { - std::unordered_set<std::string> FilesToSkip; - for (auto &SF: KnownFiles) - FilesToSkip.insert(SF.Name); - - Vector<std::string> FilesToUse; - auto MaybeUseFile = [=, &FilesToUse](std::string Name) { - if (FilesToSkip.find(Name) == FilesToSkip.end()) - FilesToUse.push_back(Name); - }; - for (auto &SF: OldCorpus) - MaybeUseFile(SF.File); - auto FilesToUseFromOldCorpus = FilesToUse.size(); - for (auto &SF: NewCorpus) - MaybeUseFile(SF.File); - - RemoveFile(CFPath); - std::ofstream ControlFile(CFPath); - ControlFile << FilesToUse.size() << "\n"; - ControlFile << FilesToUseFromOldCorpus << "\n"; - for (auto &FN: FilesToUse) - ControlFile << FN << "\n"; - - if (!ControlFile) { - Printf("MERGE-OUTER: failed to write to the control file: %s\n", - CFPath.c_str()); - exit(1); - } - - return FilesToUse.size(); -} - -// Outer process. Does not call the target code and thus should not fail. -void CrashResistantMerge(const Vector<std::string> &Args, - const Vector<SizedFile> &OldCorpus, - const Vector<SizedFile> &NewCorpus, - Vector<std::string> *NewFiles, - const Set<uint32_t> &InitialFeatures, - Set<uint32_t> *NewFeatures, - const Set<uint32_t> &InitialCov, - Set<uint32_t> *NewCov, - const std::string &CFPath, - bool V /*Verbose*/) { - if (NewCorpus.empty() && OldCorpus.empty()) return; // Nothing to merge. - size_t NumAttempts = 0; - Vector<MergeFileInfo> KnownFiles; - if (FileSize(CFPath)) { - VPrintf(V, "MERGE-OUTER: non-empty control file provided: '%s'\n", - CFPath.c_str()); - Merger M; - std::ifstream IF(CFPath); - if (M.Parse(IF, /*ParseCoverage=*/true)) { - VPrintf(V, "MERGE-OUTER: control file ok, %zd files total," - " first not processed file %zd\n", - M.Files.size(), M.FirstNotProcessedFile); - if (!M.LastFailure.empty()) - VPrintf(V, "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()) { - // Merge has already been completed with the given merge control file. - if (M.Files.size() == OldCorpus.size() + NewCorpus.size()) { - VPrintf( - V, - "MERGE-OUTER: nothing to do, merge has been completed before\n"); - exit(0); - } - - // Number of input files likely changed, start merge from scratch, but - // reuse coverage information from the given merge control file. - VPrintf( - V, - "MERGE-OUTER: starting merge from scratch, but reusing coverage " - "information from the given control file\n"); - KnownFiles = M.Files; - } else { - // There is a merge in progress, continue. - NumAttempts = M.Files.size() - M.FirstNotProcessedFile; - } - } else { - VPrintf(V, "MERGE-OUTER: bad control file, will overwrite it\n"); - } - } - - if (!NumAttempts) { - // The supplied control file is empty or bad, create a fresh one. - VPrintf(V, "MERGE-OUTER: " - "%zd files, %zd in the initial corpus, %zd processed earlier\n", - OldCorpus.size() + NewCorpus.size(), OldCorpus.size(), - KnownFiles.size()); - NumAttempts = WriteNewControlFile(CFPath, OldCorpus, NewCorpus, KnownFiles); - } - - // Execute the inner process until it passes. - // Every inner process should execute at least one input. - Command BaseCmd(Args); - BaseCmd.removeFlag("merge"); - BaseCmd.removeFlag("fork"); - BaseCmd.removeFlag("collect_data_flow"); - for (size_t Attempt = 1; Attempt <= NumAttempts; Attempt++) { - Fuzzer::MaybeExitGracefully(); - VPrintf(V, "MERGE-OUTER: attempt %zd\n", Attempt); - Command Cmd(BaseCmd); - Cmd.addFlag("merge_control_file", CFPath); - Cmd.addFlag("merge_inner", "1"); - if (!V) { - Cmd.setOutputFile(getDevNull()); - Cmd.combineOutAndErr(); - } - auto ExitCode = ExecuteCommand(Cmd); - if (!ExitCode) { - VPrintf(V, "MERGE-OUTER: succesfull in %zd attempt(s)\n", Attempt); - break; - } - } - // Read the control file and do the merge. - Merger M; - std::ifstream IF(CFPath); - IF.seekg(0, IF.end); - VPrintf(V, "MERGE-OUTER: the control file has %zd bytes\n", - (size_t)IF.tellg()); - IF.seekg(0, IF.beg); - M.ParseOrExit(IF, true); - IF.close(); - VPrintf(V, - "MERGE-OUTER: consumed %zdMb (%zdMb rss) to parse the control file\n", - M.ApproximateMemoryConsumption() >> 20, GetPeakRSSMb()); - - M.Files.insert(M.Files.end(), KnownFiles.begin(), KnownFiles.end()); - M.Merge(InitialFeatures, NewFeatures, InitialCov, NewCov, NewFiles); - VPrintf(V, "MERGE-OUTER: %zd new files with %zd new features added; " - "%zd new coverage edges\n", - NewFiles->size(), NewFeatures->size(), NewCov->size()); -} - -} // namespace fuzzer diff --git a/contrib/libs/libfuzzer12/FuzzerMerge.h b/contrib/libs/libfuzzer12/FuzzerMerge.h deleted file mode 100644 index e0c6bc539bd..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerMerge.h +++ /dev/null @@ -1,87 +0,0 @@ -//===- FuzzerMerge.h - merging corpa ----------------------------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 outer 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 writes the following lines: -// FT INPUT_ID Feature1 Feature2 Feature3 ... -// COV INPUT_ID Coverage1 Coverage2 Coverage3 ... -// 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 inner 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, Cov; -}; - -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); - size_t Merge(const Set<uint32_t> &InitialFeatures, Set<uint32_t> *NewFeatures, - const Set<uint32_t> &InitialCov, Set<uint32_t> *NewCov, - Vector<std::string> *NewFiles); - size_t ApproximateMemoryConsumption() const; - Set<uint32_t> AllFeatures() const; -}; - -void CrashResistantMerge(const Vector<std::string> &Args, - const Vector<SizedFile> &OldCorpus, - const Vector<SizedFile> &NewCorpus, - Vector<std::string> *NewFiles, - const Set<uint32_t> &InitialFeatures, - Set<uint32_t> *NewFeatures, - const Set<uint32_t> &InitialCov, - Set<uint32_t> *NewCov, - const std::string &CFPath, - bool Verbose); - -} // namespace fuzzer - -#endif // LLVM_FUZZER_MERGE_H diff --git a/contrib/libs/libfuzzer12/FuzzerMutate.cpp b/contrib/libs/libfuzzer12/FuzzerMutate.cpp deleted file mode 100644 index cf34a9fe8e2..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerMutate.cpp +++ /dev/null @@ -1,578 +0,0 @@ -//===- FuzzerMutate.cpp - Mutate a test input -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Mutate a test input. -//===----------------------------------------------------------------------===// - -#include "FuzzerDefs.h" -#include "FuzzerExtFunctions.h" -#include "FuzzerIO.h" -#include "FuzzerMutate.h" -#include "FuzzerOptions.h" -#include "FuzzerTracePC.h" - -namespace fuzzer { - -const size_t Dictionary::kMaxDictSize; -static const size_t kMaxMutationsToPrint = 10; - -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 (Size == 0) - return 0; - if (!CrossOverWith) return 0; - const Unit &Other = *CrossOverWith; - 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 (Size == 0) return 0; - if (!CrossOverWith) return 0; - const Unit &O = *CrossOverWith; - if (O.empty()) return 0; - size_t NewSize = 0; - switch(Rand(3)) { - case 0: - MutateInPlaceHere.resize(MaxSize); - NewSize = CrossOver(Data, Size, O.data(), O.size(), - MutateInPlaceHere.data(), MaxSize); - memcpy(Data, MutateInPlaceHere.data(), NewSize); - break; - case 1: - NewSize = InsertPartOf(O.data(), O.size(), Data, Size, MaxSize); - if (!NewSize) - NewSize = CopyPartOf(O.data(), O.size(), Data, Size); - break; - case 2: - NewSize = CopyPartOf(O.data(), O.size(), Data, Size); - break; - default: assert(0); - } - assert(NewSize > 0 && "CrossOver returned empty unit"); - assert(NewSize <= MaxSize && "CrossOver returned overisized unit"); - 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(bool Verbose) { - Printf("MS: %zd ", CurrentMutatorSequence.size()); - size_t EntriesToPrint = - Verbose ? CurrentMutatorSequence.size() - : std::min(kMaxMutationsToPrint, CurrentMutatorSequence.size()); - for (size_t i = 0; i < EntriesToPrint; i++) - Printf("%s-", CurrentMutatorSequence[i].Name); - if (!CurrentDictionaryEntrySequence.empty()) { - Printf(" DE: "); - EntriesToPrint = Verbose ? CurrentDictionaryEntrySequence.size() - : std::min(kMaxMutationsToPrint, - CurrentDictionaryEntrySequence.size()); - for (size_t i = 0; i < EntriesToPrint; i++) { - Printf("\""); - PrintASCII(CurrentDictionaryEntrySequence[i]->GetW(), "\"-"); - } - } -} - -std::string MutationDispatcher::MutationSequence() { - std::string MS; - for (auto M : CurrentMutatorSequence) { - MS += M.Name; - MS += "-"; - } - return MS; -} - -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) { - size_t MaskedSize = std::min(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 < MaskedSize; I++) - if (Mask[I]) - T[OneBits++] = Data[I]; - - if (!OneBits) return 0; - 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 < MaskedSize; 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/contrib/libs/libfuzzer12/FuzzerMutate.h b/contrib/libs/libfuzzer12/FuzzerMutate.h deleted file mode 100644 index fd37191156d..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerMutate.h +++ /dev/null @@ -1,156 +0,0 @@ -//===- FuzzerMutate.h - Internal header for the Fuzzer ----------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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. Only prints the full sequence - /// when Verbose is true. - void PrintMutationSequence(bool Verbose = true); - /// Return the current sequence of mutations. - std::string MutationSequence(); - /// 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 changing one byte. - size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize); - /// Mutates data by changing 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 CrossOverWith. - 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 SetCrossOverWith(const Unit *U) { CrossOverWith = U; } - - 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; - // 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 Unit *CrossOverWith = 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/contrib/libs/libfuzzer12/FuzzerOptions.h b/contrib/libs/libfuzzer12/FuzzerOptions.h deleted file mode 100644 index 2e8501626ba..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerOptions.h +++ /dev/null @@ -1,93 +0,0 @@ -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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; - bool KeepSeed = false; - int UnitTimeoutSec = 300; - int TimeoutExitCode = 70; - int OOMExitCode = 71; - int InterruptExitCode = 72; - int ErrorExitCode = 77; - bool DumpInterrupted = false; - bool IgnoreTimeouts = true; - bool IgnoreOOMs = true; - bool IgnoreCrashes = false; - int MaxTotalTimeSec = 0; - int RssLimitMb = 0; - int MallocLimitMb = 0; - bool DoCrossOver = true; - bool CrossOverUniformDist = false; - 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; - bool Entropic = true; - size_t EntropicFeatureFrequencyThreshold = 0xFF; - size_t EntropicNumberOfRarestFeatures = 100; - bool EntropicScalePerExecTime = false; - std::string OutputCorpus; - std::string ArtifactPrefix = "./"; - std::string ExactArtifactPath; - std::string ExitOnSrcPos; - std::string ExitOnItem; - std::string FocusFunction; - std::string DataFlowTrace; - std::string CollectDataFlow; - std::string FeaturesDir; - std::string MutationGraphFile; - std::string StopFile; - 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 PrintFullCoverage = false; - bool DumpCoverage = false; - bool DetectLeaks = true; - int PurgeAllocatorIntervalSec = 1; - int TraceMalloc = 0; - bool HandleAbrt = false; - bool HandleAlrm = 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; - bool HandleWinExcept = false; -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_OPTIONS_H diff --git a/contrib/libs/libfuzzer12/FuzzerPlatform.h b/contrib/libs/libfuzzer12/FuzzerPlatform.h deleted file mode 100644 index 1602e678950..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerPlatform.h +++ /dev/null @@ -1,147 +0,0 @@ -//===-- FuzzerPlatform.h --------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Common platform macros. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_PLATFORM_H -#define LLVM_FUZZER_PLATFORM_H - -// 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_WINDOWS 0 -#define LIBFUZZER_EMSCRIPTEN 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_WINDOWS 0 -#define LIBFUZZER_EMSCRIPTEN 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_WINDOWS 0 -#define LIBFUZZER_EMSCRIPTEN 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_WINDOWS 0 -#define LIBFUZZER_EMSCRIPTEN 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_WINDOWS 1 -#define LIBFUZZER_EMSCRIPTEN 0 -#elif __Fuchsia__ -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_FUCHSIA 1 -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_WINDOWS 0 -#define LIBFUZZER_EMSCRIPTEN 0 -#elif __EMSCRIPTEN__ -#define LIBFUZZER_APPLE 0 -#define LIBFUZZER_FUCHSIA 0 -#define LIBFUZZER_LINUX 0 -#define LIBFUZZER_NETBSD 0 -#define LIBFUZZER_FREEBSD 0 -#define LIBFUZZER_WINDOWS 0 -#define LIBFUZZER_EMSCRIPTEN 1 -#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_EMSCRIPTEN) - -#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__ - -#if LIBFUZZER_WINDOWS -#define ATTRIBUTE_NO_SANITIZE_ADDRESS -#else -#define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) -#endif - -#if LIBFUZZER_WINDOWS -#define ATTRIBUTE_ALIGNED(X) __declspec(align(X)) -#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 static -#define ATTRIBUTE_NOINLINE __declspec(noinline) -#else -#define ATTRIBUTE_ALIGNED(X) __attribute__((aligned(X))) -#define ATTRIBUTE_INTERFACE __attribute__((visibility("default"))) -#define ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC \ - ATTRIBUTE_INTERFACE __attribute__((tls_model("initial-exec"))) thread_local - -#define ATTRIBUTE_NOINLINE __attribute__((noinline)) -#endif - -#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 - -#endif // LLVM_FUZZER_PLATFORM_H diff --git a/contrib/libs/libfuzzer12/FuzzerRandom.h b/contrib/libs/libfuzzer12/FuzzerRandom.h deleted file mode 100644 index 659283eee20..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerRandom.h +++ /dev/null @@ -1,38 +0,0 @@ -//===- FuzzerRandom.h - Internal header for the Fuzzer ----------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// fuzzer::Random -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_RANDOM_H -#define LLVM_FUZZER_RANDOM_H - -#include <random> - -namespace fuzzer { -class Random : public std::minstd_rand { - public: - Random(unsigned int seed) : std::minstd_rand(seed) {} - result_type operator()() { return this->std::minstd_rand::operator()(); } - size_t Rand() { return this->operator()(); } - size_t RandBool() { return Rand() % 2; } - size_t SkewTowardsLast(size_t n) { - size_t T = this->operator()(n * n); - size_t Res = sqrt(T); - return Res; - } - 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/contrib/libs/libfuzzer12/FuzzerSHA1.cpp b/contrib/libs/libfuzzer12/FuzzerSHA1.cpp deleted file mode 100644 index 2005dc70030..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerSHA1.cpp +++ /dev/null @@ -1,223 +0,0 @@ -//===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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" -#include "FuzzerPlatform.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 -// Windows is always little endian and MSVC doesn't have <endian.h> -#elif defined __LITTLE_ENDIAN__ || LIBFUZZER_WINDOWS -/* 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/contrib/libs/libfuzzer12/FuzzerSHA1.h b/contrib/libs/libfuzzer12/FuzzerSHA1.h deleted file mode 100644 index 05cbacda87d..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerSHA1.h +++ /dev/null @@ -1,32 +0,0 @@ -//===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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/contrib/libs/libfuzzer12/FuzzerTracePC.cpp b/contrib/libs/libfuzzer12/FuzzerTracePC.cpp deleted file mode 100644 index 91e94d82400..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerTracePC.cpp +++ /dev/null @@ -1,673 +0,0 @@ -//===- FuzzerTracePC.cpp - PC tracing--------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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 "FuzzerPlatform.h" -#include "FuzzerUtil.h" -#include "FuzzerValueBitMap.h" -#include <set> - -// Used by -fsanitize-coverage=stack-depth to track stack depth -ATTRIBUTES_INTERFACE_TLS_INITIAL_EXEC uintptr_t __sancov_lowest_stack; - -namespace fuzzer { - -TracePC TPC; - -size_t TracePC::GetTotalPCCoverage() { - return ObservedPCs.size(); -} - - -void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) { - if (Start == Stop) return; - if (NumModules && - Modules[NumModules - 1].Start() == Start) - return; - assert(NumModules < - sizeof(Modules) / sizeof(Modules[0])); - auto &M = Modules[NumModules++]; - uint8_t *AlignedStart = RoundUpByPage(Start); - uint8_t *AlignedStop = RoundDownByPage(Stop); - size_t NumFullPages = AlignedStop > AlignedStart ? - (AlignedStop - AlignedStart) / PageSize() : 0; - bool NeedFirst = Start < AlignedStart || !NumFullPages; - bool NeedLast = Stop > AlignedStop && AlignedStop >= AlignedStart; - M.NumRegions = NumFullPages + NeedFirst + NeedLast;; - assert(M.NumRegions > 0); - M.Regions = new Module::Region[M.NumRegions]; - assert(M.Regions); - size_t R = 0; - if (NeedFirst) - M.Regions[R++] = {Start, std::min(Stop, AlignedStart), true, false}; - for (uint8_t *P = AlignedStart; P < AlignedStop; P += PageSize()) - M.Regions[R++] = {P, P + PageSize(), true, true}; - if (NeedLast) - M.Regions[R++] = {AlignedStop, Stop, true, false}; - assert(R == M.NumRegions); - assert(M.Size() == (size_t)(Stop - Start)); - assert(M.Stop() == Stop); - assert(M.Start() == Start); - NumInline8bitCounters += M.Size(); -} - -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::PrintModuleInfo() { - if (NumModules) { - Printf("INFO: Loaded %zd modules (%zd inline 8-bit counters): ", - NumModules, NumInline8bitCounters); - for (size_t i = 0; i < NumModules; i++) - Printf("%zd [%p, %p), ", Modules[i].Size(), Modules[i].Start(), - Modules[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 (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.cpp` -ALWAYS_INLINE uintptr_t TracePC::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 = [&](const PCTableEntry *TE) { - if (ObservedPCs.insert(TE).second && DoPrintNewPCs) { - PrintPC("\tNEW_PC: %p %F %L", "\tNEW_PC: %p", - GetNextInstructionPc(TE->PC)); - Printf("\n"); - } - }; - - auto Observe = [&](const PCTableEntry *TE) { - if (PcIsFuncEntry(TE)) - if (++ObservedFuncs[TE->PC] == 1 && NumPrintNewFuncs) - CoveredFuncs.push_back(TE->PC); - ObservePC(TE); - }; - - if (NumPCsInPCTables) { - if (NumInline8bitCounters == NumPCsInPCTables) { - for (size_t i = 0; i < NumModules; i++) { - auto &M = Modules[i]; - assert(M.Size() == - (size_t)(ModulePCTable[i].Stop - ModulePCTable[i].Start)); - for (size_t r = 0; r < M.NumRegions; r++) { - auto &R = M.Regions[r]; - if (!R.Enabled) continue; - for (uint8_t *P = R.Start; P < R.Stop; P++) - if (*P) - Observe(&ModulePCTable[i].Start[M.Idx(P)]); - } - } - } - } - - 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"); - } -} - -uintptr_t TracePC::PCTableEntryIdx(const PCTableEntry *TE) { - size_t TotalTEs = 0; - for (size_t i = 0; i < NumPCTables; i++) { - auto &M = ModulePCTable[i]; - if (TE >= M.Start && TE < M.Stop) - return TotalTEs + TE - M.Start; - TotalTEs += M.Stop - M.Start; - } - assert(0); - return 0; -} - -const TracePC::PCTableEntry *TracePC::PCTableEntryByIdx(uintptr_t Idx) { - for (size_t i = 0; i < NumPCTables; i++) { - auto &M = ModulePCTable[i]; - size_t Size = M.Stop - M.Start; - if (Idx < Size) return &M.Start[Idx]; - Idx -= Size; - } - return nullptr; -} - -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(PcIsFuncEntry(FE) && "Not a function entry point"); - do { - NextFE++; - } while (NextFE < M.Stop && !(PcIsFuncEntry(NextFE))); - CB(FE, NextFE, ObservedFuncs[FE->PC]); - } - } -} - -void TracePC::SetFocusFunction(const std::string &FuncName) { - // This function should be called once. - assert(!FocusFunctionCounterPtr); - // "auto" is not a valid function name. If this function is called with "auto" - // that means the auto focus functionality failed. - if (FuncName.empty() || FuncName == "auto") - return; - for (size_t M = 0; M < NumModules; M++) { - auto &PCTE = ModulePCTable[M]; - size_t N = PCTE.Stop - PCTE.Start; - for (size_t I = 0; I < N; I++) { - if (!(PcIsFuncEntry(&PCTE.Start[I]))) 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()); - FocusFunctionCounterPtr = Modules[M].Start() + I; - return; - } - } - - Printf("ERROR: Failed to set focus function. Make sure the function name is " - "valid (%s) and symbolization is enabled.\n", FuncName.c_str()); - exit(1); -} - -bool TracePC::ObservedFocusFunction() { - return FocusFunctionCounterPtr && *FocusFunctionCounterPtr; -} - -void TracePC::PrintCoverage(bool PrintAllCounters) { - 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(PrintAllCounters ? "FULL COVERAGE:\n" : "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 NumEdges = Last - First; - Vector<uintptr_t> UncoveredPCs; - Vector<uintptr_t> CoveredPCs; - for (auto TE = First; TE < Last; TE++) - if (!ObservedPCs.count(TE)) - UncoveredPCs.push_back(TE->PC); - else - CoveredPCs.push_back(TE->PC); - - if (PrintAllCounters) { - Printf("U"); - for (auto PC : UncoveredPCs) - Printf(DescribePC(" %l", GetNextInstructionPc(PC)).c_str()); - Printf("\n"); - - Printf("C"); - for (auto PC : CoveredPCs) - Printf(DescribePC(" %l", GetNextInstructionPc(PC)).c_str()); - Printf("\n"); - } else { - Printf("%sCOVERED_FUNC: hits: %zd", Counter ? "" : "UN", Counter); - Printf(" edges: %zd/%zd", NumEdges - UncoveredPCs.size(), NumEdges); - Printf(" %s %s:%s\n", FunctionStr.c_str(), FileStr.c_str(), - LineStr.c_str()); - if (Counter) - for (auto PC : UncoveredPCs) - Printf(" UNCOVERED_PC: %s\n", - DescribePC("%s:%l", GetNextInstructionPc(PC)).c_str()); - } - }; - - IterateCoveredFunctions(CoveredFunctionCallback); -} - -// 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; - uint8_t HammingDistance = 0; - for (; I < Len; I++) { - if (B1[I] != B2[I] || (StopAtZero && B1[I] == 0)) { - HammingDistance = Popcountll(B1[I] ^ B2[I]); - break; - } - } - size_t PC = reinterpret_cast<size_t>(caller_pc); - size_t Idx = (PC & 4095) | (I << 12); - Idx += HammingDistance; - 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() { - IterateCounterRegions([](const Module::Region &R){ - if (R.Enabled) - memset(R.Start, 0, R.Stop - R.Start); - }); -} - -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 -} - -void WarnAboutDeprecatedInstrumentation(const char *flag) { - // Use RawPrint because Printf cannot be used on Windows before OutputFile is - // initialized. - RawPrint(flag); - RawPrint( - " is no longer supported by libFuzzer.\n" - "Please either migrate to a compiler that supports -fsanitize=fuzzer\n" - "or use an older version of libFuzzer\n"); - exit(1); -} - -} // namespace fuzzer - -extern "C" { -ATTRIBUTE_INTERFACE -ATTRIBUTE_NO_SANITIZE_ALL -void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) { - fuzzer::WarnAboutDeprecatedInstrumentation( - "-fsanitize-coverage=trace-pc-guard"); -} - -// 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() { - fuzzer::WarnAboutDeprecatedInstrumentation("-fsanitize-coverage=trace-pc"); -} - -ATTRIBUTE_INTERFACE -void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) { - fuzzer::WarnAboutDeprecatedInstrumentation( - "-fsanitize-coverage=trace-pc-guard"); -} - -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: all switch values are small. - // We may want to skip this at compile-time, but it will make the - // instrumentation less general. - if (Vals[N - 1] < 256) - return; - // Also skip small inputs values, they won't give good signal. - if (Val < 256) - return; - uintptr_t PC = reinterpret_cast<uintptr_t>(GET_CALLER_PC()); - size_t i; - uint64_t Smaller = 0; - uint64_t Larger = ~(uint64_t)0; - // Find two switch values such that Smaller < Val < Larger. - // Use 0 and 0xfff..f as the defaults. - for (i = 0; i < N; i++) { - if (Val < Vals[i]) { - Larger = Vals[i]; - break; - } - if (Val > Vals[i]) Smaller = Vals[i]; - } - - // Apply HandleCmp to {Val,Smaller} and {Val, Larger}, - // use i as the PC modifier for HandleCmp. - if (ValSizeInBits == 16) { - fuzzer::TPC.HandleCmp(PC + 2 * i, static_cast<uint16_t>(Val), - (uint16_t)(Smaller)); - fuzzer::TPC.HandleCmp(PC + 2 * i + 1, static_cast<uint16_t>(Val), - (uint16_t)(Larger)); - } else if (ValSizeInBits == 32) { - fuzzer::TPC.HandleCmp(PC + 2 * i, static_cast<uint32_t>(Val), - (uint32_t)(Smaller)); - fuzzer::TPC.HandleCmp(PC + 2 * i + 1, static_cast<uint32_t>(Val), - (uint32_t)(Larger)); - } else { - fuzzer::TPC.HandleCmp(PC + 2*i, Val, Smaller); - fuzzer::TPC.HandleCmp(PC + 2*i + 1, Val, Larger); - } -} - -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/contrib/libs/libfuzzer12/FuzzerTracePC.h b/contrib/libs/libfuzzer12/FuzzerTracePC.h deleted file mode 100644 index 00909230731..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerTracePC.h +++ /dev/null @@ -1,291 +0,0 @@ -//===- FuzzerTracePC.h - Internal header for the Fuzzer ---------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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: - 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(); - ClearExtraCounters(); - ClearInlineCounters(); - } - - void ClearInlineCounters(); - - void UpdateFeatureSet(size_t CurrentElementIdx, size_t CurrentElementSize); - void PrintFeatureSet(); - - void PrintModuleInfo(); - - void PrintCoverage(bool PrintAllCounters); - - 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; - - 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(); - - struct PCTableEntry { - uintptr_t PC, PCFlags; - }; - - uintptr_t PCTableEntryIdx(const PCTableEntry *TE); - const PCTableEntry *PCTableEntryByIdx(uintptr_t Idx); - static uintptr_t GetNextInstructionPc(uintptr_t PC); - bool PcIsFuncEntry(const PCTableEntry *TE) { return TE->PCFlags & 1; } - -private: - bool UseCounters = false; - uint32_t UseValueProfileMask = false; - bool DoPrintNewPCs = false; - size_t NumPrintNewFuncs = 0; - - // Module represents the array of 8-bit counters split into regions - // such that every region, except maybe the first and the last one, is one - // full page. - struct Module { - struct Region { - uint8_t *Start, *Stop; - bool Enabled; - bool OneFullPage; - }; - Region *Regions; - size_t NumRegions; - uint8_t *Start() { return Regions[0].Start; } - uint8_t *Stop() { return Regions[NumRegions - 1].Stop; } - size_t Size() { return Stop() - Start(); } - size_t Idx(uint8_t *P) { - assert(P >= Start() && P < Stop()); - return P - Start(); - } - }; - - Module Modules[4096]; - size_t NumModules; // linker-initialized. - size_t NumInline8bitCounters; - - template <class Callback> - void IterateCounterRegions(Callback CB) { - for (size_t m = 0; m < NumModules; m++) - for (size_t r = 0; r < Modules[m].NumRegions; r++) - CB(Modules[m].Regions[r]); - } - - struct { const PCTableEntry *Start, *Stop; } ModulePCTable[4096]; - size_t NumPCTables; - size_t NumPCsInPCTables; - - Set<const PCTableEntry*> ObservedPCs; - std::unordered_map<uintptr_t, uintptr_t> ObservedFuncs; // PC => Counter. - - uint8_t *FocusFunctionCounterPtr = nullptr; - - ValueBitMap ValueProfileMap; - uintptr_t InitialStack; -}; - -template <class Callback> -// void Callback(size_t FirstFeature, size_t Idx, uint8_t Value); -ATTRIBUTE_NO_SANITIZE_ALL -size_t 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)) { - Bundle = HostToLE(Bundle); - 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); - return End - Begin; -} - -// 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 { - 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; - - for (size_t i = 0; i < NumModules; i++) { - for (size_t r = 0; r < Modules[i].NumRegions; r++) { - if (!Modules[i].Regions[r].Enabled) continue; - FirstFeature += 8 * ForEachNonZeroByte(Modules[i].Regions[r].Start, - Modules[i].Regions[r].Stop, - FirstFeature, Handle8bitCounter); - } - } - - FirstFeature += - 8 * ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), - FirstFeature, Handle8bitCounter); - - 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/contrib/libs/libfuzzer12/FuzzerUtil.cpp b/contrib/libs/libfuzzer12/FuzzerUtil.cpp deleted file mode 100644 index 7eecb68d072..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerUtil.cpp +++ /dev/null @@ -1,236 +0,0 @@ -//===- FuzzerUtil.cpp - Misc utils ----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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; -} - -// Code duplicated (and tested) in llvm/include/llvm/Support/Base64.h -std::string Base64(const Unit &U) { - static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - std::string Buffer; - Buffer.resize(((U.size() + 2) / 3) * 4); - - size_t i = 0, j = 0; - for (size_t n = U.size() / 3 * 3; i < n; i += 3, j += 4) { - uint32_t x = ((unsigned char)U[i] << 16) | ((unsigned char)U[i + 1] << 8) | - (unsigned char)U[i + 2]; - Buffer[j + 0] = Table[(x >> 18) & 63]; - Buffer[j + 1] = Table[(x >> 12) & 63]; - Buffer[j + 2] = Table[(x >> 6) & 63]; - Buffer[j + 3] = Table[x & 63]; - } - if (i + 1 == U.size()) { - uint32_t x = ((unsigned char)U[i] << 16); - Buffer[j + 0] = Table[(x >> 18) & 63]; - Buffer[j + 1] = Table[(x >> 12) & 63]; - Buffer[j + 2] = '='; - Buffer[j + 3] = '='; - } else if (i + 2 == U.size()) { - uint32_t x = ((unsigned char)U[i] << 16) | ((unsigned char)U[i + 1] << 8); - Buffer[j + 0] = Table[(x >> 18) & 63]; - Buffer[j + 1] = Table[(x >> 12) & 63]; - Buffer[j + 2] = Table[(x >> 6) & 63]; - Buffer[j + 3] = '='; - } - return Buffer; -} - -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/contrib/libs/libfuzzer12/FuzzerUtil.h b/contrib/libs/libfuzzer12/FuzzerUtil.h deleted file mode 100644 index e90be085008..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerUtil.h +++ /dev/null @@ -1,117 +0,0 @@ -//===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// 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); -bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput); - -// Fuchsia does not have popen/pclose. -FILE *OpenProcessPipe(const char *Command, const char *Mode); -int CloseProcessPipe(FILE *F); - -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)); -} - -void DiscardOutput(int Fd); - -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; } - -inline size_t PageSize() { return 4096; } -inline uint8_t *RoundUpByPage(uint8_t *P) { - uintptr_t X = reinterpret_cast<uintptr_t>(P); - size_t Mask = PageSize() - 1; - X = (X + Mask) & ~Mask; - return reinterpret_cast<uint8_t *>(X); -} -inline uint8_t *RoundDownByPage(uint8_t *P) { - uintptr_t X = reinterpret_cast<uintptr_t>(P); - size_t Mask = PageSize() - 1; - X = X & ~Mask; - return reinterpret_cast<uint8_t *>(X); -} - -#if __BYTE_ORDER == __LITTLE_ENDIAN -template <typename T> T HostToLE(T X) { return X; } -#else -template <typename T> T HostToLE(T X) { return Bswap(X); } -#endif - -} // namespace fuzzer - -#endif // LLVM_FUZZER_UTIL_H diff --git a/contrib/libs/libfuzzer12/FuzzerUtilDarwin.cpp b/contrib/libs/libfuzzer12/FuzzerUtilDarwin.cpp deleted file mode 100644 index a5bed658a44..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerUtilDarwin.cpp +++ /dev/null @@ -1,170 +0,0 @@ -//===- FuzzerUtilDarwin.cpp - Misc utils ----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Misc utils for Darwin. -//===----------------------------------------------------------------------===// -#include "FuzzerPlatform.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> -#include <unistd.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; -} - -void DiscardOutput(int Fd) { - FILE* Temp = fopen("/dev/null", "w"); - if (!Temp) - return; - dup2(fileno(Temp), Fd); - fclose(Temp); -} - -} // namespace fuzzer - -#endif // LIBFUZZER_APPLE diff --git a/contrib/libs/libfuzzer12/FuzzerUtilLinux.cpp b/contrib/libs/libfuzzer12/FuzzerUtilLinux.cpp deleted file mode 100644 index 981f9a8b429..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerUtilLinux.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===- FuzzerUtilLinux.cpp - Misc utils for Linux. ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Misc utils for Linux. -//===----------------------------------------------------------------------===// -#include "FuzzerPlatform.h" -#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \ - LIBFUZZER_EMSCRIPTEN -#include "FuzzerCommand.h" - -#include <stdlib.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - - -namespace fuzzer { - -int ExecuteCommand(const Command &Cmd) { - std::string CmdLine = Cmd.toString(); - int exit_code = system(CmdLine.c_str()); - if (WIFEXITED(exit_code)) - return WEXITSTATUS(exit_code); - return exit_code; -} - -void DiscardOutput(int Fd) { - FILE* Temp = fopen("/dev/null", "w"); - if (!Temp) - return; - dup2(fileno(Temp), Fd); - fclose(Temp); -} - -} // namespace fuzzer - -#endif diff --git a/contrib/libs/libfuzzer12/FuzzerUtilPosix.cpp b/contrib/libs/libfuzzer12/FuzzerUtilPosix.cpp deleted file mode 100644 index afb733409ab..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerUtilPosix.cpp +++ /dev/null @@ -1,185 +0,0 @@ -//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Misc utils implementation using Posix API. -//===----------------------------------------------------------------------===// -#include "FuzzerPlatform.h" -#if LIBFUZZER_POSIX -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include "FuzzerTracePC.h" -#include <cassert> -#include <chrono> -#include <cstring> -#include <errno.h> -#include <iomanip> -#include <signal.h> -#include <stdio.h> -#include <sys/mman.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 (*upstream_segv_handler)(int, siginfo_t *, void *); - -static void SegvHandler(int sig, siginfo_t *si, void *ucontext) { - assert(si->si_signo == SIGSEGV); - if (upstream_segv_handler) - return upstream_segv_handler(sig, si, ucontext); - Fuzzer::StaticCrashSignalCallback(); -} - -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) { - if (signum != SIGSEGV) - return; - upstream_segv_handler = sigact.sa_sigaction; - } - } else { - if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && - sigact.sa_handler != SIG_ERR) - return; - } - - sigact = {}; - sigact.sa_flags = SA_SIGINFO; - sigact.sa_sigaction = callback; - if (sigaction(signum, &sigact, 0)) { - Printf("libFuzzer: sigaction failed with %d\n", errno); - exit(1); - } -} - -// Return true on success, false otherwise. -bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) { - FILE *Pipe = popen(Cmd.toString().c_str(), "r"); - if (!Pipe) - return false; - - if (CmdOutput) { - char TmpBuffer[128]; - while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe)) - CmdOutput->append(TmpBuffer); - } - return pclose(Pipe) == 0; -} - -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) { - // setitimer is not implemented in emscripten. - if (Options.HandleAlrm && Options.UnitTimeoutSec > 0 && !LIBFUZZER_EMSCRIPTEN) - SetTimer(Options.UnitTimeoutSec / 2 + 1); - if (Options.HandleInt) - SetSigaction(SIGINT, InterruptHandler); - if (Options.HandleTerm) - SetSigaction(SIGTERM, InterruptHandler); - if (Options.HandleSegv) - SetSigaction(SIGSEGV, SegvHandler); - 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_EMSCRIPTEN) { - // 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); -} - -int CloseProcessPipe(FILE *F) { - return pclose(F); -} - -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/contrib/libs/libfuzzer12/FuzzerUtilWindows.cpp b/contrib/libs/libfuzzer12/FuzzerUtilWindows.cpp deleted file mode 100644 index 1a54bb569ec..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerUtilWindows.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// Misc utils implementation for Windows. -//===----------------------------------------------------------------------===// -#include "FuzzerPlatform.h" -#if LIBFUZZER_WINDOWS -#include "FuzzerCommand.h" -#include "FuzzerIO.h" -#include "FuzzerInternal.h" -#include <cassert> -#include <chrono> -#include <cstring> -#include <errno.h> -#include <io.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; - // This is an undocumented exception code corresponding to a Visual C++ - // Exception. - // - // See: https://devblogs.microsoft.com/oldnewthing/20100730-00/?p=13273 - case 0xE06D7363: - if (HandlerOpt->HandleWinExcept) - 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.HandleAlrm && 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 || Options.HandleWinExcept) - 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 CloseProcessPipe(FILE *F) { - return _pclose(F); -} - -int ExecuteCommand(const Command &Cmd) { - std::string CmdLine = Cmd.toString(); - return system(CmdLine.c_str()); -} - -bool ExecuteCommand(const Command &Cmd, std::string *CmdOutput) { - FILE *Pipe = _popen(Cmd.toString().c_str(), "r"); - if (!Pipe) - return false; - - if (CmdOutput) { - char TmpBuffer[128]; - while (fgets(TmpBuffer, sizeof(TmpBuffer), Pipe)) - CmdOutput->append(TmpBuffer); - } - return _pclose(Pipe) == 0; -} - -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 + "\""; -} - -void DiscardOutput(int Fd) { - FILE* Temp = fopen("nul", "w"); - if (!Temp) - return; - _dup2(_fileno(Temp), Fd); - fclose(Temp); -} - -} // namespace fuzzer - -#endif // LIBFUZZER_WINDOWS diff --git a/contrib/libs/libfuzzer12/FuzzerValueBitMap.h b/contrib/libs/libfuzzer12/FuzzerValueBitMap.h deleted file mode 100644 index ddbfe200af9..00000000000 --- a/contrib/libs/libfuzzer12/FuzzerValueBitMap.h +++ /dev/null @@ -1,73 +0,0 @@ -//===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// ValueBitMap. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_FUZZER_VALUE_BIT_MAP_H -#define LLVM_FUZZER_VALUE_BIT_MAP_H - -#include "FuzzerPlatform.h" -#include <cstdint> - -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 | (1ULL << 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] & (1ULL << 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: - ATTRIBUTE_ALIGNED(512) uintptr_t Map[kMapSizeInWords]; -}; - -} // namespace fuzzer - -#endif // LLVM_FUZZER_VALUE_BIT_MAP_H diff --git a/contrib/libs/libfuzzer12/LICENSE.TXT b/contrib/libs/libfuzzer12/LICENSE.TXT deleted file mode 100644 index 5a79a1b9d5c..00000000000 --- a/contrib/libs/libfuzzer12/LICENSE.TXT +++ /dev/null @@ -1,311 +0,0 @@ -============================================================================== -The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: -============================================================================== - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - ----- LLVM Exceptions to the Apache 2.0 License ---- - -As an exception, if, as a result of your compiling your source code, portions -of this Software are embedded into an Object form of such source code, you -may redistribute such embedded portions in such Object form without complying -with the conditions of Sections 4(a), 4(b) and 4(d) of the License. - -In addition, if you combine or link compiled forms of this Software with -software that is licensed under the GPLv2 ("Combined Software") and if a -court of competent jurisdiction determines that the patent provision (Section -3), the indemnity provision (Section 9) or other Section of the License -conflicts with the conditions of the GPLv2, you may retroactively and -prospectively choose to deem waived or otherwise exclude such Section(s) of -the License, but only in their entirety and only with respect to the Combined -Software. - -============================================================================== -Software from third parties included in the LLVM Project: -============================================================================== -The LLVM Project contains third party software which is under different license -terms. All such code will be identified clearly using at least one of two -mechanisms: -1) It will be in a separate directory tree with its own `LICENSE.txt` or - `LICENSE` file at the top containing the specific license and restrictions - which apply to that software, or -2) It will contain specific license and restriction terms at the top of every - file. - -============================================================================== -Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): -============================================================================== - -The compiler_rt library is dual licensed under both the University of Illinois -"BSD-Like" license and the MIT license. As a user of this code you may choose -to use it under either license. As a contributor, you agree to allow your code -to be used under both. - -Full text of the relevant licenses is included below. - -============================================================================== - -University of Illinois/NCSA -Open Source License - -Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT - -All rights reserved. - -Developed by: - - LLVM Team - - University of Illinois at Urbana-Champaign - - http://llvm.org - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal with -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimers. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimers in the - documentation and/or other materials provided with the distribution. - - * Neither the names of the LLVM Team, University of Illinois at - Urbana-Champaign, nor the names of its contributors may be used to - endorse or promote products derived from this Software without specific - prior written permission. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE -SOFTWARE. - -============================================================================== - -Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/contrib/libs/libfuzzer12/README.txt b/contrib/libs/libfuzzer12/README.txt deleted file mode 100644 index 3eee01c7767..00000000000 --- a/contrib/libs/libfuzzer12/README.txt +++ /dev/null @@ -1 +0,0 @@ -See http://llvm.org/docs/LibFuzzer.html |