summaryrefslogtreecommitdiff
path: root/json4cpp/tests/thirdparty/Fuzzer
diff options
context:
space:
mode:
Diffstat (limited to 'json4cpp/tests/thirdparty/Fuzzer')
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/CMakeLists.txt45
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerCorpus.h217
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerCrossOver.cpp52
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerDefs.h89
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerDictionary.h124
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerDriver.cpp545
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctions.def50
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctions.h35
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsDlsym.cpp52
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsWeak.cpp53
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp56
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerFlags.def115
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerIO.cpp117
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerIO.h64
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerIOPosix.cpp88
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerIOWindows.cpp282
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerInterface.h67
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerInternal.h182
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerLoop.cpp792
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerMain.cpp21
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerMerge.cpp261
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerMerge.h70
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerMutate.cpp527
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerMutate.h145
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerOptions.h68
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerRandom.h36
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerSHA1.cpp222
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerSHA1.h33
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerTracePC.cpp339
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerTracePC.h158
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerTraceState.cpp325
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerUtil.cpp218
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerUtil.h72
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilDarwin.cpp152
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilLinux.cpp24
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilPosix.cpp117
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilWindows.cpp182
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/FuzzerValueBitMap.h87
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/README.txt2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/afl/afl_driver.cpp295
-rwxr-xr-xjson4cpp/tests/thirdparty/Fuzzer/build.sh10
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/cxx.dict122
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/standalone/StandaloneFuzzTargetMain.c41
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/AFLDriverTest.cpp22
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/AbsNegAndConstant64Test.cpp23
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/AbsNegAndConstantTest.cpp23
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/AccumulateAllocationsTest.cpp17
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/BufferOverflowOnInput.cpp23
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/CMakeLists.txt217
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/CallerCalleeTest.cpp59
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/CounterTest.cpp18
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/CustomCrossOverTest.cpp63
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/CustomMutatorTest.cpp38
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/DSO1.cpp12
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/DSO2.cpp12
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/DSOTestExtra.cpp11
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/DSOTestMain.cpp31
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/DivTest.cpp20
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/EmptyTest.cpp11
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/FourIndependentBranchesTest.cpp22
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/FullCoverageSetTest.cpp24
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/FuzzerUnittest.cpp738
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/InitializeTest.cpp28
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/LeakTest.cpp17
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/LeakTimeoutTest.cpp17
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/LoadTest.cpp22
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/MemcmpTest.cpp31
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/NthRunCrashTest.cpp18
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/NullDerefOnEmptyTest.cpp19
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/NullDerefTest.cpp26
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/OneHugeAllocTest.cpp28
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp27
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/OutOfMemoryTest.cpp31
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/RepeatedBytesTest.cpp29
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/RepeatedMemcmp.cpp22
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/ShrinkControlFlowTest.cpp28
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/ShrinkValueProfileTest.cpp22
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SignedIntOverflowTest.cpp28
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SimpleCmpTest.cpp46
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SimpleDictionaryTest.cpp29
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SimpleHashTest.cpp40
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SimpleTest.cpp27
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SimpleThreadedTest.cpp25
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SingleMemcmpTest.cpp17
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SingleStrcmpTest.cpp17
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SingleStrncmpTest.cpp17
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SpamyTest.cpp21
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/StrcmpTest.cpp32
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/StrncmpOOBTest.cpp21
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/StrncmpTest.cpp28
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/StrstrTest.cpp28
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SwapCmpTest.cpp34
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/Switch2Test.cpp35
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/SwitchTest.cpp58
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/ThreadedLeakTest.cpp18
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/ThreadedTest.cpp26
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/TimeoutEmptyTest.cpp14
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/TimeoutTest.cpp26
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/TraceMallocTest.cpp27
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/UninstrumentedTest.cpp11
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/afl-driver-extra-stats.test28
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/afl-driver-stderr.test10
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/caller-callee.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/coverage.test19
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/dict1.txt4
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/dump_coverage.test16
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-customcrossover.test10
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-custommutator.test4
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-dict.test6
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-dirs.test15
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-fdmask.test30
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-finalstats.test11
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-flags.test10
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-jobs.test29
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-leak.test35
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-oom-with-profile.test6
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-oom.test11
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-printcovpcs.test8
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-runs.test8
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-seed.test3
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-segv.test5
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-singleinputs.test16
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-threaded.test7
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-timeout.test19
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-traces-hooks.test25
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-ubsan.test4
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/fuzzer.test57
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/hi.txt1
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/lit.cfg29
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/lit.site.cfg.in4
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/merge.test46
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/minimize_crash.test6
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/no-coverage/CMakeLists.txt29
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/repeated-bytes.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/shrink.test7
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/simple-cmp.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/standalone.test4
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/swap-cmp.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/trace-malloc.test10
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/ubsan/CMakeLists.txt15
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/ulimit.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/uninstrumented/CMakeLists.txt16
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/unit/lit.cfg7
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/unit/lit.site.cfg.in2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp2.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp3.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp4.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-div.test3
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-load.test3
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-mem.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-set.test3
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-strcmp.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-strncmp.test2
-rw-r--r--json4cpp/tests/thirdparty/Fuzzer/test/value-profile-switch.test3
155 files changed, 9534 insertions, 0 deletions
diff --git a/json4cpp/tests/thirdparty/Fuzzer/CMakeLists.txt b/json4cpp/tests/thirdparty/Fuzzer/CMakeLists.txt
new file mode 100644
index 0000000000..70bd017bae
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/CMakeLists.txt
@@ -0,0 +1,45 @@
+set(LIBFUZZER_FLAGS_BASE "${CMAKE_CXX_FLAGS}")
+# Disable the coverage and sanitizer instrumentation for the fuzzer itself.
+set(CMAKE_CXX_FLAGS "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=trace-pc-guard,edge,trace-cmp,indirect-calls,8bit-counters -Werror")
+if( LLVM_USE_SANITIZE_COVERAGE )
+ if(NOT "${LLVM_USE_SANITIZER}" STREQUAL "Address")
+ message(FATAL_ERROR
+ "LibFuzzer and its tests require LLVM_USE_SANITIZER=Address and "
+ "LLVM_USE_SANITIZE_COVERAGE=YES to be set."
+ )
+ endif()
+ add_library(LLVMFuzzerNoMainObjects OBJECT
+ FuzzerCrossOver.cpp
+ FuzzerDriver.cpp
+ FuzzerExtFunctionsDlsym.cpp
+ FuzzerExtFunctionsWeak.cpp
+ FuzzerExtFunctionsWeakAlias.cpp
+ FuzzerIO.cpp
+ FuzzerIOPosix.cpp
+ FuzzerIOWindows.cpp
+ FuzzerLoop.cpp
+ FuzzerMerge.cpp
+ FuzzerMutate.cpp
+ FuzzerSHA1.cpp
+ FuzzerTracePC.cpp
+ FuzzerTraceState.cpp
+ FuzzerUtil.cpp
+ FuzzerUtilDarwin.cpp
+ FuzzerUtilLinux.cpp
+ FuzzerUtilPosix.cpp
+ FuzzerUtilWindows.cpp
+ )
+ add_library(LLVMFuzzerNoMain STATIC
+ $<TARGET_OBJECTS:LLVMFuzzerNoMainObjects>
+ )
+ target_link_libraries(LLVMFuzzerNoMain ${PTHREAD_LIB})
+ add_library(LLVMFuzzer STATIC
+ FuzzerMain.cpp
+ $<TARGET_OBJECTS:LLVMFuzzerNoMainObjects>
+ )
+ target_link_libraries(LLVMFuzzer ${PTHREAD_LIB})
+
+ if( LLVM_INCLUDE_TESTS )
+ add_subdirectory(test)
+ endif()
+endif()
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerCorpus.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerCorpus.h
new file mode 100644
index 0000000000..663c5854b4
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerCorpus.h
@@ -0,0 +1,217 @@
+//===- FuzzerCorpus.h - Internal header for the Fuzzer ----------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// fuzzer::InputCorpus
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_CORPUS
+#define LLVM_FUZZER_CORPUS
+
+#include "FuzzerDefs.h"
+#include "FuzzerIO.h"
+#include "FuzzerRandom.h"
+#include "FuzzerSHA1.h"
+#include "FuzzerTracePC.h"
+#include <numeric>
+#include <random>
+#include <unordered_set>
+
+namespace fuzzer {
+
+struct InputInfo {
+ Unit U; // The actual input data.
+ uint8_t Sha1[kSHA1NumBytes]; // Checksum.
+ // Number of features that this input has and no smaller input has.
+ size_t NumFeatures = 0;
+ size_t Tmp = 0; // Used by ValidateFeatureSet.
+ // Stats.
+ size_t NumExecutedMutations = 0;
+ size_t NumSuccessfullMutations = 0;
+ bool MayDeleteFile = false;
+};
+
+class InputCorpus {
+ public:
+ static const size_t kFeatureSetSize = 1 << 16;
+ InputCorpus(const std::string &OutputCorpus) : OutputCorpus(OutputCorpus) {
+ memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature));
+ memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature));
+ }
+ ~InputCorpus() {
+ for (auto II : Inputs)
+ delete II;
+ }
+ size_t size() const { return Inputs.size(); }
+ size_t SizeInBytes() const {
+ size_t Res = 0;
+ for (auto II : Inputs)
+ Res += II->U.size();
+ return Res;
+ }
+ size_t NumActiveUnits() const {
+ size_t Res = 0;
+ for (auto II : Inputs)
+ Res += !II->U.empty();
+ return Res;
+ }
+ bool empty() const { return Inputs.empty(); }
+ const Unit &operator[] (size_t Idx) const { return Inputs[Idx]->U; }
+ void AddToCorpus(const Unit &U, size_t NumFeatures, bool MayDeleteFile = false) {
+ assert(!U.empty());
+ uint8_t Hash[kSHA1NumBytes];
+ if (FeatureDebug)
+ Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures);
+ ComputeSHA1(U.data(), U.size(), Hash);
+ Hashes.insert(Sha1ToString(Hash));
+ Inputs.push_back(new InputInfo());
+ InputInfo &II = *Inputs.back();
+ II.U = U;
+ II.NumFeatures = NumFeatures;
+ II.MayDeleteFile = MayDeleteFile;
+ memcpy(II.Sha1, Hash, kSHA1NumBytes);
+ UpdateCorpusDistribution();
+ ValidateFeatureSet();
+ }
+
+ bool HasUnit(const Unit &U) { return Hashes.count(Hash(U)); }
+ bool HasUnit(const std::string &H) { return Hashes.count(H); }
+ InputInfo &ChooseUnitToMutate(Random &Rand) {
+ InputInfo &II = *Inputs[ChooseUnitIdxToMutate(Rand)];
+ assert(!II.U.empty());
+ return II;
+ };
+
+ // Returns an index of random unit from the corpus to mutate.
+ // Hypothesis: units added to the corpus last are more likely to be
+ // interesting. This function gives more weight to the more recent units.
+ size_t ChooseUnitIdxToMutate(Random &Rand) {
+ size_t Idx = static_cast<size_t>(CorpusDistribution(Rand.Get_mt19937()));
+ assert(Idx < Inputs.size());
+ return Idx;
+ }
+
+ void PrintStats() {
+ for (size_t i = 0; i < Inputs.size(); i++) {
+ const auto &II = *Inputs[i];
+ Printf(" [%zd %s]\tsz: %zd\truns: %zd\tsucc: %zd\n", i,
+ Sha1ToString(II.Sha1).c_str(), II.U.size(),
+ II.NumExecutedMutations, II.NumSuccessfullMutations);
+ }
+ }
+
+ 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 DeleteInput(size_t Idx) {
+ InputInfo &II = *Inputs[Idx];
+ if (!OutputCorpus.empty() && II.MayDeleteFile)
+ RemoveFile(DirPlusFile(OutputCorpus, Sha1ToString(II.Sha1)));
+ Unit().swap(II.U);
+ if (FeatureDebug)
+ Printf("EVICTED %zd\n", Idx);
+ }
+
+ bool AddFeature(size_t Idx, uint32_t NewSize, bool Shrink) {
+ assert(NewSize);
+ Idx = Idx % kFeatureSetSize;
+ uint32_t OldSize = GetFeature(Idx);
+ if (OldSize == 0 || (Shrink && OldSize > NewSize)) {
+ if (OldSize > 0) {
+ size_t OldIdx = SmallestElementPerFeature[Idx];
+ InputInfo &II = *Inputs[OldIdx];
+ assert(II.NumFeatures > 0);
+ II.NumFeatures--;
+ if (II.NumFeatures == 0)
+ DeleteInput(OldIdx);
+ }
+ if (FeatureDebug)
+ Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize);
+ SmallestElementPerFeature[Idx] = Inputs.size();
+ InputSizesPerFeature[Idx] = NewSize;
+ CountingFeatures = true;
+ return true;
+ }
+ return false;
+ }
+
+ size_t NumFeatures() const {
+ size_t Res = 0;
+ for (size_t i = 0; i < kFeatureSetSize; i++)
+ Res += GetFeature(i) != 0;
+ return Res;
+ }
+
+ void ResetFeatureSet() {
+ assert(Inputs.empty());
+ memset(InputSizesPerFeature, 0, sizeof(InputSizesPerFeature));
+ memset(SmallestElementPerFeature, 0, sizeof(SmallestElementPerFeature));
+ }
+
+private:
+
+ static const bool FeatureDebug = false;
+
+ size_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; }
+
+ void ValidateFeatureSet() {
+ if (!CountingFeatures) return;
+ 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.
+ void UpdateCorpusDistribution() {
+ size_t N = Inputs.size();
+ Intervals.resize(N + 1);
+ Weights.resize(N);
+ std::iota(Intervals.begin(), Intervals.end(), 0);
+ if (CountingFeatures)
+ for (size_t i = 0; i < N; i++)
+ Weights[i] = Inputs[i]->NumFeatures * (i + 1);
+ else
+ std::iota(Weights.begin(), Weights.end(), 1);
+ CorpusDistribution = std::piecewise_constant_distribution<double>(
+ Intervals.begin(), Intervals.end(), Weights.begin());
+ }
+ std::piecewise_constant_distribution<double> CorpusDistribution;
+
+ std::vector<double> Intervals;
+ std::vector<double> Weights;
+
+ std::unordered_set<std::string> Hashes;
+ std::vector<InputInfo*> Inputs;
+
+ bool CountingFeatures = false;
+ uint32_t InputSizesPerFeature[kFeatureSetSize];
+ uint32_t SmallestElementPerFeature[kFeatureSetSize];
+
+ std::string OutputCorpus;
+};
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_CORPUS
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerCrossOver.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerCrossOver.cpp
new file mode 100644
index 0000000000..8b0fd7d529
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerCrossOver.cpp
@@ -0,0 +1,52 @@
+//===- FuzzerCrossOver.cpp - Cross over two test inputs -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Cross over test inputs.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerDefs.h"
+#include "FuzzerMutate.h"
+#include "FuzzerRandom.h"
+#include <cstring>
+
+namespace fuzzer {
+
+// Cross Data1 and Data2, store the result (up to MaxOutSize bytes) in Out.
+size_t MutationDispatcher::CrossOver(const uint8_t *Data1, size_t Size1,
+ const uint8_t *Data2, size_t Size2,
+ uint8_t *Out, size_t MaxOutSize) {
+ assert(Size1 || Size2);
+ MaxOutSize = Rand(MaxOutSize) + 1;
+ size_t OutPos = 0;
+ size_t Pos1 = 0;
+ size_t Pos2 = 0;
+ size_t *InPos = &Pos1;
+ size_t InSize = Size1;
+ const uint8_t *Data = Data1;
+ bool CurrentlyUsingFirstData = true;
+ while (OutPos < MaxOutSize && (Pos1 < Size1 || Pos2 < Size2)) {
+ // Merge a part of Data into Out.
+ size_t OutSizeLeft = MaxOutSize - OutPos;
+ if (*InPos < InSize) {
+ size_t InSizeLeft = InSize - *InPos;
+ size_t MaxExtraSize = std::min(OutSizeLeft, InSizeLeft);
+ size_t ExtraSize = Rand(MaxExtraSize) + 1;
+ memcpy(Out + OutPos, Data + *InPos, ExtraSize);
+ OutPos += ExtraSize;
+ (*InPos) += ExtraSize;
+ }
+ // Use the other input data on the next iteration.
+ InPos = CurrentlyUsingFirstData ? &Pos2 : &Pos1;
+ InSize = CurrentlyUsingFirstData ? Size2 : Size1;
+ Data = CurrentlyUsingFirstData ? Data2 : Data1;
+ CurrentlyUsingFirstData = !CurrentlyUsingFirstData;
+ }
+ return OutPos;
+}
+
+} // namespace fuzzer
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerDefs.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerDefs.h
new file mode 100644
index 0000000000..0f5b8a7cf2
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerDefs.h
@@ -0,0 +1,89 @@
+//===- FuzzerDefs.h - Internal header for the Fuzzer ------------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Basic definitions.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_DEFS_H
+#define LLVM_FUZZER_DEFS_H
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <string>
+#include <vector>
+
+// Platform detection.
+#ifdef __linux__
+#define LIBFUZZER_APPLE 0
+#define LIBFUZZER_LINUX 1
+#define LIBFUZZER_WINDOWS 0
+#elif __APPLE__
+#define LIBFUZZER_APPLE 1
+#define LIBFUZZER_LINUX 0
+#define LIBFUZZER_WINDOWS 0
+#elif _WIN32
+#define LIBFUZZER_APPLE 0
+#define LIBFUZZER_LINUX 0
+#define LIBFUZZER_WINDOWS 1
+#else
+#error "Support for your platform has not been implemented"
+#endif
+
+#define LIBFUZZER_POSIX LIBFUZZER_APPLE || LIBFUZZER_LINUX
+
+#ifdef __x86_64
+#define ATTRIBUTE_TARGET_POPCNT __attribute__((target("popcnt")))
+#else
+#define ATTRIBUTE_TARGET_POPCNT
+#endif
+
+
+#ifdef __clang__ // avoid gcc warning.
+# define ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
+#else
+# define ATTRIBUTE_NO_SANITIZE_MEMORY
+#endif
+
+namespace fuzzer {
+
+template <class T> T Min(T a, T b) { return a < b ? a : b; }
+template <class T> T Max(T a, T b) { return a > b ? a : b; }
+
+class Random;
+class Dictionary;
+class DictionaryEntry;
+class MutationDispatcher;
+struct FuzzingOptions;
+class InputCorpus;
+struct InputInfo;
+struct ExternalFunctions;
+
+// Global interface to functions that may or may not be available.
+extern ExternalFunctions *EF;
+
+typedef std::vector<uint8_t> Unit;
+typedef std::vector<Unit> UnitVector;
+typedef int (*UserCallback)(const uint8_t *Data, size_t Size);
+
+int FuzzerDriver(int *argc, char ***argv, UserCallback Callback);
+
+struct ScopedDoingMyOwnMemmem {
+ ScopedDoingMyOwnMemmem();
+ ~ScopedDoingMyOwnMemmem();
+};
+
+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); }
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_DEFS_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerDictionary.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerDictionary.h
new file mode 100644
index 0000000000..eba0eabb68
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerDictionary.h
@@ -0,0 +1,124 @@
+//===- FuzzerDictionary.h - Internal header for the Fuzzer ------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// fuzzer::Dictionary
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_DICTIONARY_H
+#define LLVM_FUZZER_DICTIONARY_H
+
+#include "FuzzerDefs.h"
+#include "FuzzerIO.h"
+#include "FuzzerUtil.h"
+#include <algorithm>
+#include <limits>
+
+namespace fuzzer {
+// A simple POD sized array of bytes.
+template <size_t kMaxSize> class FixedWord {
+public:
+ 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);
+ }
+
+ bool operator<(const FixedWord<kMaxSize> &w) const {
+ if (Size != w.Size)
+ return Size < w.Size;
+ return memcmp(Data, w.Data, Size) < 0;
+ }
+
+ 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<27> Word; // 28 bytes.
+
+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 successfull, 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 succesfully.
+bool ParseDictionaryFile(const std::string &Text, std::vector<Unit> *Units);
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_DICTIONARY_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerDriver.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerDriver.cpp
new file mode 100644
index 0000000000..5ab6df2d56
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerDriver.cpp
@@ -0,0 +1,545 @@
+//===- FuzzerDriver.cpp - FuzzerDriver function and flags -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// FuzzerDriver and flag parsing.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerCorpus.h"
+#include "FuzzerInterface.h"
+#include "FuzzerInternal.h"
+#include "FuzzerIO.h"
+#include "FuzzerMutate.h"
+#include "FuzzerRandom.h"
+#include "FuzzerTracePC.h"
+#include <algorithm>
+#include <atomic>
+#include <chrono>
+#include <cstring>
+#include <mutex>
+#include <string>
+#include <thread>
+
+// This function should be present in the libFuzzer so that the client
+// binary can test for its existence.
+extern "C" __attribute__((used)) void __libfuzzer_is_present() {}
+
+namespace fuzzer {
+
+// Program arguments.
+struct FlagDescription {
+ const char *Name;
+ const char *Description;
+ int Default;
+ int *IntFlag;
+ const char **StrFlag;
+ unsigned int *UIntFlag;
+};
+
+struct {
+#define FUZZER_DEPRECATED_FLAG(Name)
+#define FUZZER_FLAG_INT(Name, Default, Description) int Name;
+#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) unsigned int Name;
+#define FUZZER_FLAG_STRING(Name, Description) const char *Name;
+#include "FuzzerFlags.def"
+#undef FUZZER_DEPRECATED_FLAG
+#undef FUZZER_FLAG_INT
+#undef FUZZER_FLAG_UNSIGNED
+#undef FUZZER_FLAG_STRING
+} Flags;
+
+static const FlagDescription FlagDescriptions [] {
+#define FUZZER_DEPRECATED_FLAG(Name) \
+ {#Name, "Deprecated; don't use", 0, nullptr, nullptr, nullptr},
+#define FUZZER_FLAG_INT(Name, Default, Description) \
+ {#Name, Description, Default, &Flags.Name, nullptr, nullptr},
+#define FUZZER_FLAG_UNSIGNED(Name, Default, Description) \
+ {#Name, Description, static_cast<int>(Default), \
+ nullptr, nullptr, &Flags.Name},
+#define FUZZER_FLAG_STRING(Name, Description) \
+ {#Name, Description, 0, nullptr, &Flags.Name, nullptr},
+#include "FuzzerFlags.def"
+#undef FUZZER_DEPRECATED_FLAG
+#undef FUZZER_FLAG_INT
+#undef FUZZER_FLAG_UNSIGNED
+#undef FUZZER_FLAG_STRING
+};
+
+static const size_t kNumFlags =
+ sizeof(FlagDescriptions) / sizeof(FlagDescriptions[0]);
+
+static std::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 std::vector<std::string> &Args) {
+ for (size_t F = 0; F < kNumFlags; F++) {
+ if (FlagDescriptions[F].IntFlag)
+ *FlagDescriptions[F].IntFlag = FlagDescriptions[F].Default;
+ if (FlagDescriptions[F].UIntFlag)
+ *FlagDescriptions[F].UIntFlag =
+ static_cast<unsigned int>(FlagDescriptions[F].Default);
+ if (FlagDescriptions[F].StrFlag)
+ *FlagDescriptions[F].StrFlag = nullptr;
+ }
+ Inputs = new std::vector<std::string>;
+ for (size_t A = 1; A < Args.size(); A++) {
+ if (ParseOneFlag(Args[A].c_str())) 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 std::string &Cmd, 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";
+ std::string ToRun = Cmd + " > " + Log + " 2>&1\n";
+ if (Flags.verbosity)
+ Printf("%s", ToRun.c_str());
+ int ExitCode = ExecuteCommand(ToRun);
+ if (ExitCode != 0)
+ *HasErrors = true;
+ std::lock_guard<std::mutex> Lock(Mu);
+ Printf("================== Job %u exited with exit code %d ============\n",
+ C, ExitCode);
+ fuzzer::CopyFileToErr(Log);
+ }
+}
+
+std::string CloneArgsWithoutX(const std::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 std::vector<std::string> &Args,
+ unsigned NumWorkers, unsigned NumJobs) {
+ std::atomic<unsigned> Counter(0);
+ std::atomic<bool> HasErrors(false);
+ std::string Cmd = CloneArgsWithoutX(Args, "jobs", "workers");
+ std::vector<std::thread> V;
+ std::thread Pulse(PulseThread);
+ Pulse.detach();
+ for (unsigned i = 0; i < NumWorkers; i++)
+ V.push_back(std::thread(WorkerThread, 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->RunOne(U.data(), U.size());
+ F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
+ return 0;
+}
+
+static bool AllInputsAreFiles() {
+ if (Inputs->empty()) return false;
+ for (auto &Path : *Inputs)
+ if (!IsFile(Path))
+ return false;
+ return true;
+}
+
+int MinimizeCrashInput(const std::vector<std::string> &Args) {
+ if (Inputs->size() != 1) {
+ Printf("ERROR: -minimize_crash should be given one input file\n");
+ exit(1);
+ }
+ std::string InputFilePath = Inputs->at(0);
+ std::string BaseCmd =
+ CloneArgsWithoutX(Args, "minimize_crash", "exact_artifact_path");
+ auto InputPos = BaseCmd.find(" " + InputFilePath + " ");
+ assert(InputPos != std::string::npos);
+ BaseCmd.erase(InputPos, InputFilePath.size() + 1);
+ 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 += " -max_total_time=600";
+ }
+ // BaseCmd += " > /dev/null 2>&1 ";
+
+ std::string CurrentFilePath = InputFilePath;
+ while (true) {
+ Unit U = FileToVector(CurrentFilePath);
+ if (U.size() < 2) {
+ Printf("CRASH_MIN: '%s' is small enough\n", CurrentFilePath.c_str());
+ return 0;
+ }
+ Printf("CRASH_MIN: minimizing crash input: '%s' (%zd bytes)\n",
+ CurrentFilePath.c_str(), U.size());
+
+ auto Cmd = BaseCmd + " " + CurrentFilePath;
+
+ Printf("CRASH_MIN: executing: %s\n", Cmd.c_str());
+ int ExitCode = ExecuteCommand(Cmd);
+ if (ExitCode == 0) {
+ Printf("ERROR: the input %s did not crash\n", CurrentFilePath.c_str());
+ exit(1);
+ }
+ Printf("CRASH_MIN: '%s' (%zd bytes) caused a crash. Will try to minimize "
+ "it further\n",
+ CurrentFilePath.c_str(), U.size());
+
+ std::string ArtifactPath = "minimized-from-" + Hash(U);
+ Cmd += " -minimize_crash_internal_step=1 -exact_artifact_path=" +
+ ArtifactPath;
+ Printf("CRASH_MIN: executing: %s\n", Cmd.c_str());
+ ExitCode = ExecuteCommand(Cmd);
+ if (ExitCode == 0) {
+ if (Flags.exact_artifact_path) {
+ CurrentFilePath = Flags.exact_artifact_path;
+ WriteToFile(U, CurrentFilePath);
+ }
+ Printf("CRASH_MIN: failed to minimize beyond %s (%d bytes), exiting\n",
+ CurrentFilePath.c_str(), U.size());
+ return 0;
+ }
+ CurrentFilePath = ArtifactPath;
+ Printf("\n\n\n\n\n\n*********************************\n");
+ }
+ return 0;
+}
+
+int MinimizeCrashInputInternalStep(Fuzzer *F, InputCorpus *Corpus) {
+ assert(Inputs->size() == 1);
+ std::string InputFilePath = Inputs->at(0);
+ Unit U = FileToVector(InputFilePath);
+ assert(U.size() > 2);
+ Printf("INFO: Starting MinimizeCrashInputInternalStep: %zd\n", U.size());
+ Corpus->AddToCorpus(U, 0);
+ F->SetMaxInputLen(U.size());
+ F->SetMaxMutationLen(U.size() - 1);
+ F->MinimizeCrashLoop(U);
+ Printf("INFO: Done MinimizeCrashInputInternalStep, no crashes found\n");
+ exit(0);
+ return 0;
+}
+
+int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
+ using namespace fuzzer;
+ assert(argc && argv && "Argument pointers cannot be nullptr");
+ EF = new ExternalFunctions();
+ if (EF->LLVMFuzzerInitialize)
+ EF->LLVMFuzzerInitialize(argc, argv);
+ const std::vector<std::string> Args(*argv, *argv + *argc);
+ assert(!Args.empty());
+ ProgName = new std::string(Args[0]);
+ ParseFlags(Args);
+ if (Flags.help) {
+ PrintHelp();
+ return 0;
+ }
+
+ if (Flags.minimize_crash)
+ return MinimizeCrashInput(Args);
+
+ 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);
+
+ const size_t kMaxSaneLen = 1 << 20;
+ const size_t kMinDefaultLen = 64;
+ FuzzingOptions Options;
+ Options.Verbosity = Flags.verbosity;
+ Options.MaxLen = Flags.max_len;
+ Options.UnitTimeoutSec = Flags.timeout;
+ Options.ErrorExitCode = Flags.error_exitcode;
+ Options.TimeoutExitCode = Flags.timeout_exitcode;
+ Options.MaxTotalTimeSec = Flags.max_total_time;
+ Options.DoCrossOver = Flags.cross_over;
+ Options.MutateDepth = Flags.mutate_depth;
+ Options.UseCounters = Flags.use_counters;
+ Options.UseIndirCalls = Flags.use_indir_calls;
+ Options.UseMemcmp = Flags.use_memcmp;
+ Options.UseMemmem = Flags.use_memmem;
+ Options.UseCmp = Flags.use_cmp;
+ Options.UseValueProfile = Flags.use_value_profile;
+ Options.Shrink = Flags.shrink;
+ Options.ShuffleAtStartUp = Flags.shuffle;
+ Options.PreferSmall = Flags.prefer_small;
+ Options.ReloadIntervalSec = Flags.reload;
+ Options.OnlyASCII = Flags.only_ascii;
+ Options.OutputCSV = Flags.output_csv;
+ Options.DetectLeaks = Flags.detect_leaks;
+ Options.TraceMalloc = Flags.trace_malloc;
+ Options.RssLimitMb = Flags.rss_limit_mb;
+ if (Flags.runs >= 0)
+ Options.MaxNumberOfRuns = Flags.runs;
+ if (!Inputs->empty() && !Flags.minimize_crash_internal_step)
+ Options.OutputCorpus = (*Inputs)[0];
+ Options.ReportSlowUnits = Flags.report_slow_units;
+ if (Flags.artifact_prefix)
+ Options.ArtifactPrefix = Flags.artifact_prefix;
+ if (Flags.exact_artifact_path)
+ Options.ExactArtifactPath = Flags.exact_artifact_path;
+ std::vector<Unit> Dictionary;
+ if (Flags.dict)
+ if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary))
+ return 1;
+ if (Flags.verbosity > 0 && !Dictionary.empty())
+ Printf("Dictionary: %zd entries\n", Dictionary.size());
+ bool DoPlainRun = AllInputsAreFiles();
+ Options.SaveArtifacts =
+ !DoPlainRun || Flags.minimize_crash_internal_step;
+ Options.PrintNewCovPcs = Flags.print_pcs;
+ Options.PrintFinalStats = Flags.print_final_stats;
+ Options.PrintCorpusStats = Flags.print_corpus_stats;
+ Options.PrintCoverage = Flags.print_coverage;
+ Options.DumpCoverage = Flags.dump_coverage;
+ if (Flags.exit_on_src_pos)
+ Options.ExitOnSrcPos = Flags.exit_on_src_pos;
+ if (Flags.exit_on_item)
+ Options.ExitOnItem = Flags.exit_on_item;
+
+ unsigned Seed = Flags.seed;
+ // Initialize Seed.
+ if (Seed == 0)
+ Seed = (std::chrono::system_clock::now().time_since_epoch().count() << 10) +
+ GetPid();
+ if (Flags.verbosity)
+ Printf("INFO: Seed: %u\n", Seed);
+
+ Random Rand(Seed);
+ auto *MD = new MutationDispatcher(Rand, Options);
+ auto *Corpus = new InputCorpus(Options.OutputCorpus);
+ auto *F = new Fuzzer(Callback, *Corpus, *MD, Options);
+
+ for (auto &U: Dictionary)
+ if (U.size() <= Word::GetMaxSize())
+ MD->AddWordToManualDictionary(Word(U.data(), U.size()));
+
+ StartRssThread(F, Flags.rss_limit_mb);
+
+ Options.HandleAbrt = Flags.handle_abrt;
+ Options.HandleBus = Flags.handle_bus;
+ Options.HandleFpe = Flags.handle_fpe;
+ Options.HandleIll = Flags.handle_ill;
+ Options.HandleInt = Flags.handle_int;
+ Options.HandleSegv = Flags.handle_segv;
+ Options.HandleTerm = Flags.handle_term;
+ SetSignalHandler(Options);
+
+ if (Flags.minimize_crash_internal_step)
+ return MinimizeCrashInputInternalStep(F, Corpus);
+
+ if (DoPlainRun) {
+ Options.SaveArtifacts = false;
+ int Runs = std::max(1, Flags.runs);
+ Printf("%s: Running %zd inputs %d time(s) each.\n", ProgName->c_str(),
+ Inputs->size(), Runs);
+ for (auto &Path : *Inputs) {
+ auto StartTime = system_clock::now();
+ Printf("Running: %s\n", Path.c_str());
+ for (int Iter = 0; Iter < Runs; Iter++)
+ RunOneTest(F, Path.c_str(), Options.MaxLen);
+ auto StopTime = system_clock::now();
+ auto MS = duration_cast<milliseconds>(StopTime - StartTime).count();
+ Printf("Executed %s in %zd ms\n", Path.c_str(), (long)MS);
+ }
+ Printf("***\n"
+ "*** NOTE: fuzzing was not performed, you have only\n"
+ "*** executed the target code on a fixed set of inputs.\n"
+ "***\n");
+ F->PrintFinalStats();
+ exit(0);
+ }
+
+ if (Flags.merge) {
+ if (Options.MaxLen == 0)
+ F->SetMaxInputLen(kMaxSaneLen);
+ if (TPC.UsingTracePcGuard()) {
+ if (Flags.merge_control_file)
+ F->CrashResistantMergeInternalStep(Flags.merge_control_file);
+ else
+ F->CrashResistantMerge(Args, *Inputs);
+ } else {
+ F->Merge(*Inputs);
+ }
+ exit(0);
+ }
+
+ size_t TemporaryMaxLen = Options.MaxLen ? Options.MaxLen : kMaxSaneLen;
+
+ UnitVector InitialCorpus;
+ for (auto &Inp : *Inputs) {
+ Printf("Loading corpus dir: %s\n", Inp.c_str());
+ ReadDirToVectorOfUnits(Inp.c_str(), &InitialCorpus, nullptr,
+ TemporaryMaxLen, /*ExitOnError=*/false);
+ }
+
+ if (Options.MaxLen == 0) {
+ size_t MaxLen = 0;
+ for (auto &U : InitialCorpus)
+ MaxLen = std::max(U.size(), MaxLen);
+ F->SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxLen), kMaxSaneLen));
+ }
+
+ if (InitialCorpus.empty()) {
+ InitialCorpus.push_back(Unit({'\n'})); // Valid ASCII input.
+ if (Options.Verbosity)
+ Printf("INFO: A corpus is not provided, starting from an empty corpus\n");
+ }
+ F->ShuffleAndMinimize(&InitialCorpus);
+ InitialCorpus.clear(); // Don't need this memory any more.
+ F->Loop();
+
+ if (Flags.verbosity)
+ Printf("Done %d runs in %zd second(s)\n", F->getTotalNumberOfRuns(),
+ F->secondsSinceProcessStartUp());
+ F->PrintFinalStats();
+
+ exit(0); // Don't let F destroy itself.
+}
+
+// Storage for global ExternalFunctions object.
+ExternalFunctions *EF = nullptr;
+
+} // namespace fuzzer
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctions.def b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctions.def
new file mode 100644
index 0000000000..61c72e4a20
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctions.def
@@ -0,0 +1,50 @@
+//===- FuzzerExtFunctions.def - External functions --------------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This defines the external function pointers that
+// ``fuzzer::ExternalFunctions`` should contain and try to initialize. The
+// EXT_FUNC macro must be defined at the point of inclusion. The signature of
+// the macro is:
+//
+// EXT_FUNC(<name>, <return_type>, <function_signature>, <warn_if_missing>)
+//===----------------------------------------------------------------------===//
+
+// Optional user functions
+EXT_FUNC(LLVMFuzzerInitialize, int, (int *argc, char ***argv), false);
+EXT_FUNC(LLVMFuzzerCustomMutator, size_t,
+ (uint8_t * Data, size_t Size, size_t MaxSize, unsigned int Seed),
+ false);
+EXT_FUNC(LLVMFuzzerCustomCrossOver, size_t,
+ (const uint8_t * Data1, size_t Size1,
+ const uint8_t * Data2, size_t Size2,
+ uint8_t * Out, size_t MaxOutSize, unsigned int Seed),
+ false);
+
+// Sanitizer functions
+EXT_FUNC(__lsan_enable, void, (), false);
+EXT_FUNC(__lsan_disable, void, (), false);
+EXT_FUNC(__lsan_do_recoverable_leak_check, int, (), false);
+EXT_FUNC(__sanitizer_get_number_of_counters, size_t, (), false);
+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_get_total_unique_caller_callee_pairs, size_t, (), false);
+EXT_FUNC(__sanitizer_get_total_unique_coverage, size_t, (), true);
+EXT_FUNC(__sanitizer_print_memory_profile, int, (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_reset_coverage, void, (), true);
+EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true);
+EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false);
+EXT_FUNC(__sanitizer_update_counter_bitset_and_clear_counters, uintptr_t,
+ (uint8_t*), false);
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctions.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctions.h
new file mode 100644
index 0000000000..2672a38547
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctions.h
@@ -0,0 +1,35 @@
+//===- FuzzerExtFunctions.h - Interface to external functions ---*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Defines an interface to (possibly optional) functions.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_EXT_FUNCTIONS_H
+#define LLVM_FUZZER_EXT_FUNCTIONS_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace fuzzer {
+
+struct ExternalFunctions {
+ // Initialize function pointers. Functions that are not available will be set
+ // to nullptr. Do not call this constructor before ``main()`` has been
+ // entered.
+ ExternalFunctions();
+
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
+ RETURN_TYPE(*NAME) FUNC_SIG = nullptr
+
+#include "FuzzerExtFunctions.def"
+
+#undef EXT_FUNC
+};
+} // namespace fuzzer
+
+#endif
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsDlsym.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsDlsym.cpp
new file mode 100644
index 0000000000..06bddd5de3
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsDlsym.cpp
@@ -0,0 +1,52 @@
+//===- FuzzerExtFunctionsDlsym.cpp - Interface to external functions ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Implementation for operating systems that support dlsym(). We only use it on
+// Apple platforms for now. We don't use this approach on Linux because it
+// requires that clients of LibFuzzer pass ``--export-dynamic`` to the linker.
+// That is a complication we don't wish to expose to clients right now.
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#if LIBFUZZER_APPLE
+
+#include "FuzzerExtFunctions.h"
+#include "FuzzerIO.h"
+#include <dlfcn.h>
+
+using namespace fuzzer;
+
+template <typename T>
+static T GetFnPtr(const char *FnName, bool WarnIfMissing) {
+ dlerror(); // Clear any previous errors.
+ void *Fn = dlsym(RTLD_DEFAULT, FnName);
+ if (Fn == nullptr) {
+ if (WarnIfMissing) {
+ const char *ErrorMsg = dlerror();
+ Printf("WARNING: Failed to find function \"%s\".", FnName);
+ if (ErrorMsg)
+ Printf(" Reason %s.", ErrorMsg);
+ Printf("\n");
+ }
+ }
+ return reinterpret_cast<T>(Fn);
+}
+
+namespace fuzzer {
+
+ExternalFunctions::ExternalFunctions() {
+#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
+ this->NAME = GetFnPtr<decltype(ExternalFunctions::NAME)>(#NAME, WARN)
+
+#include "FuzzerExtFunctions.def"
+
+#undef EXT_FUNC
+}
+
+} // namespace fuzzer
+
+#endif // LIBFUZZER_APPLE
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsWeak.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsWeak.cpp
new file mode 100644
index 0000000000..7b02b6f0b7
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsWeak.cpp
@@ -0,0 +1,53 @@
+//===- FuzzerExtFunctionsWeak.cpp - Interface to external functions -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Implementation for Linux. This relies on the linker's support for weak
+// symbols. We don't use this approach on Apple platforms because it requires
+// clients of LibFuzzer to pass ``-U _<symbol_name>`` to the linker to allow
+// weak symbols to be undefined. That is a complication we don't want to expose
+// to clients right now.
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#if LIBFUZZER_LINUX
+
+#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)) 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((void *)::NAME, #NAME, WARN);
+
+#include "FuzzerExtFunctions.def"
+
+#undef EXT_FUNC
+}
+
+} // namespace fuzzer
+
+#endif // LIBFUZZER_LINUX
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp
new file mode 100644
index 0000000000..e10f7b4dca
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerExtFunctionsWeakAlias.cpp
@@ -0,0 +1,56 @@
+//===- FuzzerExtFunctionsWeakAlias.cpp - Interface to external functions --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Implementation using weak aliases. Works for Windows.
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#if LIBFUZZER_WINDOWS
+
+#include "FuzzerExtFunctions.h"
+#include "FuzzerIO.h"
+
+using namespace fuzzer;
+
+extern "C" {
+// Declare these symbols as weak to allow them to be optionally defined.
+#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); \
+ } \
+ RETURN_TYPE NAME FUNC_SIG __attribute__((weak, alias(#NAME "Def")));
+
+#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/json4cpp/tests/thirdparty/Fuzzer/FuzzerFlags.def b/json4cpp/tests/thirdparty/Fuzzer/FuzzerFlags.def
new file mode 100644
index 0000000000..25ef1741a9
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerFlags.def
@@ -0,0 +1,115 @@
+//===- FuzzerFlags.def - Run-time flags -------------------------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Flags. FUZZER_FLAG_INT/FUZZER_FLAG_STRING macros should be defined at the
+// point of inclusion. We are not using any flag parsing library for better
+// portability and independence.
+//===----------------------------------------------------------------------===//
+FUZZER_FLAG_INT(verbosity, 1, "Verbosity level.")
+FUZZER_FLAG_UNSIGNED(seed, 0, "Random seed. If 0, seed is generated.")
+FUZZER_FLAG_INT(runs, -1,
+ "Number of individual test runs (-1 for infinite runs).")
+FUZZER_FLAG_INT(max_len, 0, "Maximum length of the test input. "
+ "If 0, libFuzzer tries to guess a good value based on the corpus "
+ "and reports it. ")
+FUZZER_FLAG_INT(cross_over, 1, "If 1, cross over inputs.")
+FUZZER_FLAG_INT(mutate_depth, 5,
+ "Apply this number of consecutive mutations to each input.")
+FUZZER_FLAG_INT(shuffle, 1, "Shuffle inputs at startup")
+FUZZER_FLAG_INT(prefer_small, 1,
+ "If 1, always prefer smaller inputs during the corpus shuffle.")
+FUZZER_FLAG_INT(
+ timeout, 1200,
+ "Timeout in seconds (if positive). "
+ "If one unit runs more than this number of seconds the process will abort.")
+FUZZER_FLAG_INT(error_exitcode, 77, "When libFuzzer itself reports a bug "
+ "this exit code will be used.")
+FUZZER_FLAG_INT(timeout_exitcode, 77, "When libFuzzer reports a timeout "
+ "this exit code will be used.")
+FUZZER_FLAG_INT(max_total_time, 0, "If positive, indicates the maximal total "
+ "time in seconds to run the fuzzer.")
+FUZZER_FLAG_INT(help, 0, "Print help.")
+FUZZER_FLAG_INT(merge, 0, "If 1, the 2-nd, 3-rd, etc corpora will be "
+ "merged into the 1-st corpus. Only interesting units will be taken. "
+ "This flag can be used to minimize a corpus.")
+FUZZER_FLAG_STRING(merge_control_file, "internal flag")
+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")
+FUZZER_FLAG_INT(minimize_crash_internal_step, 0, "internal flag")
+FUZZER_FLAG_INT(use_counters, 1, "Use coverage counters")
+FUZZER_FLAG_INT(use_indir_calls, 1, "Use indirect caller-callee counters")
+FUZZER_FLAG_INT(use_memcmp, 1,
+ "Use hints from intercepting memcmp, strcmp, etc")
+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 elements.")
+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(output_csv, 0, "Enable pulse output in CSV format.")
+FUZZER_FLAG_INT(print_pcs, 0, "If 1, print out newly covered PCs.")
+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 at exit."
+ " Experimental, only with trace-pc-guard")
+FUZZER_FLAG_INT(dump_coverage, 0, "If 1, dump coverage information at exit."
+ " Experimental, only with trace-pc-guard")
+FUZZER_FLAG_INT(handle_segv, 1, "If 1, try to intercept SIGSEGV.")
+FUZZER_FLAG_INT(handle_bus, 1, "If 1, try to intercept SIGSEGV.")
+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(close_fd_mask, 0, "If 1, close stdout at startup; "
+ "if 2, close stderr; if 3, close both. "
+ "Be careful, this will also close e.g. asan's stderr/stdout.")
+FUZZER_FLAG_INT(detect_leaks, 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(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_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_DEPRECATED_FLAG(exit_on_first)
+FUZZER_DEPRECATED_FLAG(save_minimized_corpus)
+FUZZER_DEPRECATED_FLAG(sync_command)
+FUZZER_DEPRECATED_FLAG(sync_timeout)
+FUZZER_DEPRECATED_FLAG(test_single_input)
+FUZZER_DEPRECATED_FLAG(drill)
+FUZZER_DEPRECATED_FLAG(truncate_units)
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerIO.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerIO.cpp
new file mode 100644
index 0000000000..eda8e87729
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerIO.cpp
@@ -0,0 +1,117 @@
+//===- FuzzerIO.cpp - IO utils. -------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// IO functions.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerIO.h"
+#include "FuzzerDefs.h"
+#include "FuzzerExtFunctions.h"
+#include <algorithm>
+#include <cstdarg>
+#include <fstream>
+#include <iterator>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+namespace fuzzer {
+
+static FILE *OutputFile = stderr;
+
+long GetEpoch(const std::string &Path) {
+ struct stat St;
+ if (stat(Path.c_str(), &St))
+ return 0; // Can't stat, be conservative.
+ return St.st_mtime;
+}
+
+Unit FileToVector(const std::string &Path, size_t MaxSize, bool ExitOnError) {
+ std::ifstream T(Path);
+ if (ExitOnError && !T) {
+ Printf("No such directory: %s; exiting\n", Path.c_str());
+ exit(1);
+ }
+
+ T.seekg(0, T.end);
+ size_t FileLen = T.tellg();
+ 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);
+ return std::string((std::istreambuf_iterator<char>(T)),
+ std::istreambuf_iterator<char>());
+}
+
+void CopyFileToErr(const std::string &Path) {
+ Printf("%s", FileToString(Path).c_str());
+}
+
+void WriteToFile(const Unit &U, const std::string &Path) {
+ // Use raw C interface because this function may be called from a sig handler.
+ FILE *Out = fopen(Path.c_str(), "w");
+ if (!Out) return;
+ fwrite(U.data(), sizeof(U[0]), U.size(), Out);
+ fclose(Out);
+}
+
+void ReadDirToVectorOfUnits(const char *Path, std::vector<Unit> *V,
+ long *Epoch, size_t MaxSize, bool ExitOnError) {
+ long E = Epoch ? *Epoch : 0;
+ std::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);
+ }
+}
+
+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 *>(OutputFd));
+ CloseFile(2);
+ }
+ }
+}
+
+void CloseStdout() {
+ CloseFile(1);
+}
+
+void Printf(const char *Fmt, ...) {
+ va_list ap;
+ va_start(ap, Fmt);
+ vfprintf(OutputFile, Fmt, ap);
+ va_end(ap);
+ fflush(OutputFile);
+}
+
+} // namespace fuzzer
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerIO.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerIO.h
new file mode 100644
index 0000000000..741fecf415
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerIO.h
@@ -0,0 +1,64 @@
+//===- FuzzerIO.h - Internal header for IO utils ----------------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// IO interface.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_IO_H
+#define LLVM_FUZZER_IO_H
+
+#include "FuzzerDefs.h"
+
+namespace fuzzer {
+
+long GetEpoch(const std::string &Path);
+
+Unit FileToVector(const std::string &Path, size_t MaxSize = 0,
+ bool ExitOnError = true);
+
+std::string FileToString(const std::string &Path);
+
+void CopyFileToErr(const std::string &Path);
+
+void WriteToFile(const Unit &U, const std::string &Path);
+
+void ReadDirToVectorOfUnits(const char *Path, std::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);
+
+void DupAndCloseStderr();
+
+void CloseStdout();
+
+void Printf(const char *Fmt, ...);
+
+// Platform specific functions:
+bool IsFile(const std::string &Path);
+
+void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
+ std::vector<std::string> *V, bool TopDir);
+
+char GetSeparator();
+
+FILE* OpenFile(int Fd, const char *Mode);
+
+int CloseFile(int Fd);
+
+int DuplicateFile(int Fd);
+
+void RemoveFile(const std::string &Path);
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_IO_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerIOPosix.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerIOPosix.cpp
new file mode 100644
index 0000000000..720bc13045
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerIOPosix.cpp
@@ -0,0 +1,88 @@
+//===- FuzzerIOPosix.cpp - IO utils for Posix. ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// IO functions implementation using Posix API.
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#if LIBFUZZER_POSIX
+
+#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);
+}
+
+void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
+ std::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("No such directory: %s; exiting\n", 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)
+ V->push_back(Path);
+ else if (E->d_type == DT_DIR && *E->d_name != '.')
+ ListFilesInDirRecursive(Path, Epoch, V, false);
+ }
+ closedir(D);
+ if (Epoch && TopDir)
+ *Epoch = E;
+}
+
+char GetSeparator() {
+ return '/';
+}
+
+FILE* OpenFile(int Fd, const char* Mode) {
+ return fdopen(Fd, Mode);
+}
+
+int CloseFile(int fd) {
+ return close(fd);
+}
+
+int DuplicateFile(int Fd) {
+ return dup(Fd);
+}
+
+void RemoveFile(const std::string &Path) {
+ unlink(Path.c_str());
+}
+
+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;
+}
+
+} // namespace fuzzer
+
+#endif // LIBFUZZER_POSIX
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerIOWindows.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerIOWindows.cpp
new file mode 100644
index 0000000000..a4738eb9df
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerIOWindows.cpp
@@ -0,0 +1,282 @@
+//===- FuzzerIOWindows.cpp - IO utils for Windows. ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// IO functions implementation for Windows.
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#if LIBFUZZER_WINDOWS
+
+#include "FuzzerExtFunctions.h"
+#include "FuzzerIO.h"
+#include <cstdarg>
+#include <cstdio>
+#include <fstream>
+#include <io.h>
+#include <iterator>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <windows.h>
+
+namespace fuzzer {
+
+static bool IsFile(const std::string &Path, const DWORD &FileAttributes) {
+
+ if (FileAttributes & FILE_ATTRIBUTE_NORMAL)
+ return true;
+
+ if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ return false;
+
+ HANDLE FileHandle(
+ CreateFileA(Path.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, 0));
+
+ if (FileHandle == INVALID_HANDLE_VALUE) {
+ Printf("CreateFileA() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
+ GetLastError());
+ return false;
+ }
+
+ DWORD FileType = GetFileType(FileHandle);
+
+ if (FileType == FILE_TYPE_UNKNOWN) {
+ Printf("GetFileType() failed for \"%s\" (Error code: %lu).\n", Path.c_str(),
+ GetLastError());
+ CloseHandle(FileHandle);
+ return false;
+ }
+
+ if (FileType != FILE_TYPE_DISK) {
+ CloseHandle(FileHandle);
+ return false;
+ }
+
+ CloseHandle(FileHandle);
+ return true;
+}
+
+bool IsFile(const std::string &Path) {
+ DWORD Att = GetFileAttributesA(Path.c_str());
+
+ if (Att == INVALID_FILE_ATTRIBUTES) {
+ Printf("GetFileAttributesA() failed for \"%s\" (Error code: %lu).\n",
+ Path.c_str(), GetLastError());
+ return false;
+ }
+
+ return IsFile(Path, Att);
+}
+
+void ListFilesInDirRecursive(const std::string &Dir, long *Epoch,
+ std::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)
+ {
+ Printf("No file found in: %s.\n", Dir.c_str());
+ return;
+ }
+
+ do {
+ std::string FileName = DirPlusFile(Dir, FindInfo.cFileName);
+
+ if (FindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ size_t FilenameLen = strlen(FindInfo.cFileName);
+ if ((FilenameLen == 1 && FindInfo.cFileName[0] == '.') ||
+ (FilenameLen == 2 && FindInfo.cFileName[0] == '.' &&
+ FindInfo.cFileName[1] == '.'))
+ continue;
+
+ ListFilesInDirRecursive(FileName, Epoch, V, false);
+ }
+ else if (IsFile(FileName, FindInfo.dwFileAttributes))
+ V->push_back(FileName);
+ } while (FindNextFileA(FindHandle, &FindInfo));
+
+ DWORD LastError = GetLastError();
+ if (LastError != ERROR_NO_MORE_FILES)
+ Printf("FindNextFileA failed (Error code: %lu).\n", LastError);
+
+ FindClose(FindHandle);
+
+ if (Epoch && TopDir)
+ *Epoch = E;
+}
+
+char GetSeparator() {
+ return '\\';
+}
+
+FILE* OpenFile(int Fd, const char* Mode) {
+ return _fdopen(Fd, Mode);
+}
+
+int CloseFile(int Fd) {
+ return _close(Fd);
+}
+
+int DuplicateFile(int Fd) {
+ return _dup(Fd);
+}
+
+void RemoveFile(const std::string &Path) {
+ _unlink(Path.c_str());
+}
+
+static bool IsSeparator(char C) {
+ return C == '\\' || C == '/';
+}
+
+// Parse disk designators, like "C:\". If Relative == true, also accepts: "C:".
+// Returns number of characters considered if successful.
+static size_t ParseDrive(const std::string &FileName, const size_t Offset,
+ bool Relative = true) {
+ if (Offset + 1 >= FileName.size() || FileName[Offset + 1] != ':')
+ return 0;
+ if (Offset + 2 >= FileName.size() || !IsSeparator(FileName[Offset + 2])) {
+ if (!Relative) // Accept relative path?
+ return 0;
+ else
+ return 2;
+ }
+ return 3;
+}
+
+// Parse a file name, like: SomeFile.txt
+// Returns number of characters considered if successful.
+static size_t ParseFileName(const std::string &FileName, const size_t Offset) {
+ size_t Pos = Offset;
+ const size_t End = FileName.size();
+ for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
+ ;
+ return Pos - Offset;
+}
+
+// Parse a directory ending in separator, like: SomeDir\
+// Returns number of characters considered if successful.
+static size_t ParseDir(const std::string &FileName, const size_t Offset) {
+ size_t Pos = Offset;
+ const size_t End = FileName.size();
+ if (Pos >= End || IsSeparator(FileName[Pos]))
+ return 0;
+ for(; Pos < End && !IsSeparator(FileName[Pos]); ++Pos)
+ ;
+ if (Pos >= End)
+ return 0;
+ ++Pos; // Include separator.
+ return Pos - Offset;
+}
+
+// Parse a servername and share, like: SomeServer\SomeShare\
+// Returns number of characters considered if successful.
+static size_t ParseServerAndShare(const std::string &FileName,
+ const size_t Offset) {
+ size_t Pos = Offset, Res;
+ if (!(Res = ParseDir(FileName, Pos)))
+ return 0;
+ Pos += Res;
+ if (!(Res = ParseDir(FileName, Pos)))
+ return 0;
+ Pos += Res;
+ return Pos - Offset;
+}
+
+// Parse the given Ref string from the position Offset, to exactly match the given
+// string Patt.
+// Returns number of characters considered if successful.
+static size_t ParseCustomString(const std::string &Ref, size_t Offset,
+ const char *Patt) {
+ size_t Len = strlen(Patt);
+ if (Offset + Len > Ref.size())
+ return 0;
+ return Ref.compare(Offset, Len, Patt) == 0 ? Len : 0;
+}
+
+// Parse a location, like:
+// \\?\UNC\Server\Share\ \\?\C:\ \\Server\Share\ \ C:\ C:
+// Returns number of characters considered if successful.
+static size_t ParseLocation(const std::string &FileName) {
+ size_t Pos = 0, Res;
+
+ if ((Res = ParseCustomString(FileName, Pos, R"(\\?\)"))) {
+ Pos += Res;
+ if ((Res = ParseCustomString(FileName, Pos, R"(UNC\)"))) {
+ Pos += Res;
+ if ((Res = ParseServerAndShare(FileName, Pos)))
+ return Pos + Res;
+ return 0;
+ }
+ if ((Res = ParseDrive(FileName, Pos, false)))
+ return Pos + Res;
+ return 0;
+ }
+
+ if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
+ ++Pos;
+ if (Pos < FileName.size() && IsSeparator(FileName[Pos])) {
+ ++Pos;
+ if ((Res = ParseServerAndShare(FileName, Pos)))
+ return Pos + Res;
+ return 0;
+ }
+ return Pos;
+ }
+
+ if ((Res = ParseDrive(FileName, Pos)))
+ return Pos + Res;
+
+ return Pos;
+}
+
+std::string DirName(const std::string &FileName) {
+ size_t LocationLen = ParseLocation(FileName);
+ size_t DirLen = 0, Res;
+ while ((Res = ParseDir(FileName, LocationLen + DirLen)))
+ DirLen += Res;
+ size_t FileLen = ParseFileName(FileName, LocationLen + DirLen);
+
+ if (LocationLen + DirLen + FileLen != FileName.size()) {
+ Printf("DirName() failed for \"%s\", invalid path.\n", FileName.c_str());
+ exit(1);
+ }
+
+ if (DirLen) {
+ --DirLen; // Remove trailing separator.
+ if (!FileLen) { // Path ended in separator.
+ assert(DirLen);
+ // Remove file name from Dir.
+ while (DirLen && !IsSeparator(FileName[LocationLen + DirLen - 1]))
+ --DirLen;
+ if (DirLen) // Remove trailing separator.
+ --DirLen;
+ }
+ }
+
+ if (!LocationLen) { // Relative path.
+ if (!DirLen)
+ return ".";
+ return std::string(".\\").append(FileName, 0, DirLen);
+ }
+
+ return FileName.substr(0, LocationLen + DirLen);
+}
+
+} // namespace fuzzer
+
+#endif // LIBFUZZER_WINDOWS
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerInterface.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerInterface.h
new file mode 100644
index 0000000000..d47e20e3a2
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerInterface.h
@@ -0,0 +1,67 @@
+//===- FuzzerInterface.h - Interface header for the Fuzzer ------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Define the interface between libFuzzer and the library being tested.
+//===----------------------------------------------------------------------===//
+
+// NOTE: the libFuzzer interface is thin and in the majority of cases
+// you should not include this file into your target. In 95% of cases
+// all you need is to define the following function in your file:
+// extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+
+// WARNING: keep the interface in C.
+
+#ifndef LLVM_FUZZER_INTERFACE_H
+#define LLVM_FUZZER_INTERFACE_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+// Mandatory user-provided target function.
+// Executes the code under test with [Data, Data+Size) as the input.
+// libFuzzer will invoke this function *many* times with different inputs.
+// Must return 0.
+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.
+int LLVMFuzzerInitialize(int *argc, char ***argv);
+
+// Optional user-provided custom mutator.
+// Mutates raw data in [Data, Data+Size) inplace.
+// Returns the new size, which is not greater than MaxSize.
+// Given the same Seed produces the same mutation.
+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.
+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 LLVMFuzzerTestOneInput.
+// Mutates raw data in [Data, Data+Size) inplace.
+// Returns the new size, which is not greater than MaxSize.
+size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // LLVM_FUZZER_INTERFACE_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerInternal.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerInternal.h
new file mode 100644
index 0000000000..c041706092
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerInternal.h
@@ -0,0 +1,182 @@
+//===- FuzzerInternal.h - Internal header for the Fuzzer --------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Define the main class fuzzer::Fuzzer and most functions.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_INTERNAL_H
+#define LLVM_FUZZER_INTERNAL_H
+
+#include "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:
+
+ // Aggregates all available coverage measurements.
+ struct Coverage {
+ Coverage() { Reset(); }
+
+ void Reset() {
+ BlockCoverage = 0;
+ CallerCalleeCoverage = 0;
+ CounterBitmapBits = 0;
+ CounterBitmap.clear();
+ VPMap.Reset();
+ }
+
+ size_t BlockCoverage;
+ size_t CallerCalleeCoverage;
+ // Precalculated number of bits in CounterBitmap.
+ size_t CounterBitmapBits;
+ std::vector<uint8_t> CounterBitmap;
+ ValueBitMap VPMap;
+ };
+
+ Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
+ FuzzingOptions Options);
+ ~Fuzzer();
+ void Loop();
+ void MinimizeCrashLoop(const Unit &U);
+ void ShuffleAndMinimize(UnitVector *V);
+ void InitializeTraceState();
+ 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 StaticInterruptCallback();
+
+ void ExecuteCallback(const uint8_t *Data, size_t Size);
+ size_t RunOne(const uint8_t *Data, size_t Size);
+
+ // Merge Corpora[1:] into Corpora[0].
+ void Merge(const std::vector<std::string> &Corpora);
+ void CrashResistantMerge(const std::vector<std::string> &Args,
+ const std::vector<std::string> &Corpora);
+ void CrashResistantMergeInternalStep(const std::string &ControlFilePath);
+ // Returns a subset of 'Extra' that adds coverage to 'Initial'.
+ UnitVector FindExtraUnits(const UnitVector &Initial, const UnitVector &Extra);
+ MutationDispatcher &GetMD() { return MD; }
+ void PrintFinalStats();
+ void SetMaxInputLen(size_t MaxInputLen);
+ void SetMaxMutationLen(size_t MaxMutationLen);
+ void RssLimitCallback();
+
+ // Public for tests.
+ void ResetCoverage();
+
+ 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);
+
+private:
+ void AlarmCallback();
+ void CrashCallback();
+ void InterruptCallback();
+ void MutateAndTestOne();
+ void ReportNewCoverage(InputInfo *II, const Unit &U);
+ size_t RunOne(const Unit &U) { return RunOne(U.data(), U.size()); }
+ void WriteToOutputCorpus(const Unit &U);
+ void WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix);
+ void PrintStats(const char *Where, const char *End = "\n", size_t Units = 0);
+ void PrintStatusForNewUnit(const Unit &U);
+ void ShuffleCorpus(UnitVector *V);
+ void AddToCorpus(const Unit &U);
+ void CheckExitOnSrcPosOrItem();
+
+ // Trace-based fuzzing: we run a unit with some kind of tracing
+ // enabled and record potentially useful mutations. Then
+ // We apply these mutations one by one to the unit and run it again.
+
+ // Start tracing; forget all previously proposed mutations.
+ void StartTraceRecording();
+ // Stop tracing.
+ void StopTraceRecording();
+
+ void SetDeathCallback();
+ static void StaticDeathCallback();
+ void DumpCurrentUnit(const char *Prefix);
+ void DeathCallback();
+
+ void ResetEdgeCoverage();
+ void ResetCounters();
+ void PrepareCounters(Fuzzer::Coverage *C);
+ bool RecordMaxCoverage(Fuzzer::Coverage *C);
+
+ void AllocateCurrentUnitData();
+ uint8_t *CurrentUnitData = nullptr;
+ std::atomic<size_t> CurrentUnitSize;
+ uint8_t BaseSha1[kSHA1NumBytes]; // Checksum of the base unit.
+ bool RunningCB = false;
+
+ size_t TotalNumberOfRuns = 0;
+ size_t NumberOfNewUnitsAdded = 0;
+
+ bool HasMoreMallocsThanFrees = false;
+ size_t NumberOfLeakDetectionAttempts = 0;
+
+ UserCallback CB;
+ InputCorpus &Corpus;
+ MutationDispatcher &MD;
+ FuzzingOptions Options;
+
+ system_clock::time_point ProcessStartTime = system_clock::now();
+ system_clock::time_point UnitStartTime, UnitStopTime;
+ long TimeOfLongestUnitInSeconds = 0;
+ long EpochOfLastReadOfOutputCorpus = 0;
+
+ // Maximum recorded coverage.
+ Coverage MaxCoverage;
+
+ size_t MaxInputLen = 0;
+ size_t MaxMutationLen = 0;
+
+ // Need to know our own thread.
+ static thread_local bool IsMyThread;
+
+ bool InMergeMode = false;
+};
+
+}; // namespace fuzzer
+
+#endif // LLVM_FUZZER_INTERNAL_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerLoop.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerLoop.cpp
new file mode 100644
index 0000000000..73e058ff34
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerLoop.cpp
@@ -0,0 +1,792 @@
+//===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Fuzzer's main loop.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerCorpus.h"
+#include "FuzzerInternal.h"
+#include "FuzzerIO.h"
+#include "FuzzerMutate.h"
+#include "FuzzerRandom.h"
+#include "FuzzerTracePC.h"
+#include <algorithm>
+#include <cstring>
+#include <memory>
+#include <set>
+
+#if defined(__has_include)
+#if __has_include(<sanitizer / coverage_interface.h>)
+#include <sanitizer/coverage_interface.h>
+#endif
+#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;
+
+static void MissingExternalApiFunction(const char *FnName) {
+ Printf("ERROR: %s is not defined. Exiting.\n"
+ "Did you use -fsanitize-coverage=... to build your code?\n",
+ FnName);
+ exit(1);
+}
+
+#define CHECK_EXTERNAL_FUNCTION(fn) \
+ do { \
+ if (!(EF->fn)) \
+ MissingExternalApiFunction(#fn); \
+ } while (false)
+
+// Only one Fuzzer per process.
+static Fuzzer *F;
+
+void Fuzzer::ResetEdgeCoverage() {
+ CHECK_EXTERNAL_FUNCTION(__sanitizer_reset_coverage);
+ EF->__sanitizer_reset_coverage();
+}
+
+void Fuzzer::ResetCounters() {
+ if (Options.UseCounters)
+ EF->__sanitizer_update_counter_bitset_and_clear_counters(0);
+}
+
+void Fuzzer::PrepareCounters(Fuzzer::Coverage *C) {
+ if (Options.UseCounters) {
+ size_t NumCounters = EF->__sanitizer_get_number_of_counters();
+ C->CounterBitmap.resize(NumCounters);
+ }
+}
+
+// Records data to a maximum coverage tracker. Returns true if additional
+// coverage was discovered.
+bool Fuzzer::RecordMaxCoverage(Fuzzer::Coverage *C) {
+ bool Res = false;
+
+ uint64_t NewBlockCoverage = EF->__sanitizer_get_total_unique_coverage();
+ if (NewBlockCoverage > C->BlockCoverage) {
+ Res = true;
+ C->BlockCoverage = NewBlockCoverage;
+ }
+
+ if (Options.UseIndirCalls &&
+ EF->__sanitizer_get_total_unique_caller_callee_pairs) {
+ uint64_t NewCallerCalleeCoverage =
+ EF->__sanitizer_get_total_unique_caller_callee_pairs();
+ if (NewCallerCalleeCoverage > C->CallerCalleeCoverage) {
+ Res = true;
+ C->CallerCalleeCoverage = NewCallerCalleeCoverage;
+ }
+ }
+
+ if (Options.UseCounters) {
+ uint64_t CounterDelta =
+ EF->__sanitizer_update_counter_bitset_and_clear_counters(
+ C->CounterBitmap.data());
+ if (CounterDelta > 0) {
+ Res = true;
+ C->CounterBitmapBits += CounterDelta;
+ }
+ }
+
+ return Res;
+}
+
+// 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;
+};
+
+static MallocFreeTracer AllocTracer;
+
+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) {
+ Printf("MALLOC[%zd] %p %zd\n", N, ptr, size);
+ if (TraceLevel >= 2 && EF)
+ EF->__sanitizer_print_stack_trace();
+ }
+}
+
+ATTRIBUTE_NO_SANITIZE_MEMORY
+void FreeHook(const volatile void *ptr) {
+ size_t N = AllocTracer.Frees++;
+ if (int TraceLevel = AllocTracer.TraceLevel) {
+ Printf("FREE[%zd] %p\n", N, ptr);
+ if (TraceLevel >= 2 && EF)
+ EF->__sanitizer_print_stack_trace();
+ }
+}
+
+// Crash on a single malloc that exceeds the rss limit.
+void Fuzzer::HandleMalloc(size_t Size) {
+ if (!Options.RssLimitMb || (Size >> 20) < (size_t)Options.RssLimitMb)
+ 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");
+ if (EF->__sanitizer_print_stack_trace)
+ EF->__sanitizer_print_stack_trace();
+ DumpCurrentUnit("oom-");
+ Printf("SUMMARY: libFuzzer: out-of-memory\n");
+ PrintFinalStats();
+ _Exit(Options.ErrorExitCode); // Stop right now.
+}
+
+Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD,
+ FuzzingOptions Options)
+ : CB(CB), Corpus(Corpus), MD(MD), Options(Options) {
+ SetDeathCallback();
+ InitializeTraceState();
+ assert(!F);
+ F = this;
+ TPC.ResetMaps();
+ ResetCoverage();
+ 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.SetUseValueProfile(Options.UseValueProfile);
+ TPC.SetPrintNewPCs(Options.PrintNewCovPcs);
+
+ if (Options.Verbosity)
+ TPC.PrintModuleInfo();
+ if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec)
+ EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus);
+ MaxInputLen = MaxMutationLen = Options.MaxLen;
+ 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::SetDeathCallback() {
+ CHECK_EXTERNAL_FUNCTION(__sanitizer_set_death_callback);
+ EF->__sanitizer_set_death_callback(StaticDeathCallback);
+}
+
+void Fuzzer::StaticDeathCallback() {
+ assert(F);
+ F->DeathCallback();
+}
+
+static void WarnOnUnsuccessfullMerge(bool DoWarn) {
+ if (!DoWarn) return;
+ Printf(
+ "***\n"
+ "***\n"
+ "***\n"
+ "*** NOTE: merge did not succeed due to a failure on one of the inputs.\n"
+ "*** You will need to filter out crashes from the corpus, e.g. like this:\n"
+ "*** for f in WITH_CRASHES/*; do ./fuzzer $f && cp $f NO_CRASHES; done\n"
+ "*** Future versions may have crash-resistant merge, stay tuned.\n"
+ "***\n"
+ "***\n"
+ "***\n");
+}
+
+void Fuzzer::DumpCurrentUnit(const char *Prefix) {
+ WarnOnUnsuccessfullMerge(InMergeMode);
+ if (!CurrentUnitData) return; // Happens when running individual inputs.
+ 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::StaticInterruptCallback() {
+ assert(F);
+ F->InterruptCallback();
+}
+
+void Fuzzer::CrashCallback() {
+ Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid());
+ if (EF->__sanitizer_print_stack_trace)
+ EF->__sanitizer_print_stack_trace();
+ 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);
+}
+
+void Fuzzer::InterruptCallback() {
+ Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid());
+ PrintFinalStats();
+ _Exit(0); // Stop right now, don't perform any at-exit actions.
+}
+
+NO_SANITIZE_MEMORY
+void Fuzzer::AlarmCallback() {
+ assert(Options.UnitTimeoutSec > 0);
+ if (!InFuzzingThread()) return;
+ if (!RunningCB)
+ 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) {
+ 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);
+ if (EF->__sanitizer_print_stack_trace)
+ EF->__sanitizer_print_stack_trace();
+ Printf("SUMMARY: libFuzzer: timeout\n");
+ PrintFinalStats();
+ _Exit(Options.TimeoutExitCode); // Stop right now.
+ }
+}
+
+void Fuzzer::RssLimitCallback() {
+ 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");
+ if (EF->__sanitizer_print_memory_profile)
+ EF->__sanitizer_print_memory_profile(95);
+ DumpCurrentUnit("oom-");
+ Printf("SUMMARY: libFuzzer: out-of-memory\n");
+ PrintFinalStats();
+ _Exit(Options.ErrorExitCode); // Stop right now.
+}
+
+void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) {
+ size_t ExecPerSec = execPerSec();
+ if (Options.OutputCSV) {
+ static bool csvHeaderPrinted = false;
+ if (!csvHeaderPrinted) {
+ csvHeaderPrinted = true;
+ Printf("runs,block_cov,bits,cc_cov,corpus,execs_per_sec,tbms,reason\n");
+ }
+ Printf("%zd,%zd,%zd,%zd,%zd,%zd,%s\n", TotalNumberOfRuns,
+ MaxCoverage.BlockCoverage, MaxCoverage.CounterBitmapBits,
+ MaxCoverage.CallerCalleeCoverage, Corpus.size(), ExecPerSec, Where);
+ }
+
+ if (!Options.Verbosity)
+ return;
+ Printf("#%zd\t%s", TotalNumberOfRuns, Where);
+ if (MaxCoverage.BlockCoverage)
+ Printf(" cov: %zd", MaxCoverage.BlockCoverage);
+ if (size_t N = MaxCoverage.VPMap.GetNumBitsSinceLastMerge())
+ Printf(" vp: %zd", N);
+ if (size_t N = TPC.GetTotalPCCoverage())
+ Printf(" cov: %zd", N);
+ if (auto TB = MaxCoverage.CounterBitmapBits)
+ Printf(" bits: %zd", TB);
+ if (size_t N = Corpus.NumFeatures())
+ Printf( " ft: %zd", N);
+ if (MaxCoverage.CallerCalleeCoverage)
+ Printf(" indir: %zd", MaxCoverage.CallerCalleeCoverage);
+ 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 (Units)
+ Printf(" units: %zd", Units);
+
+ Printf(" exec/s: %zd", ExecPerSec);
+ Printf(" rss: %zdMb", GetPeakRSSMb());
+ Printf("%s", End);
+}
+
+void Fuzzer::PrintFinalStats() {
+ if (Options.PrintCoverage)
+ TPC.PrintCoverage();
+ if (Options.DumpCoverage)
+ TPC.DumpCoverage();
+ if (Options.PrintCorpusStats)
+ Corpus.PrintStats();
+ if (!Options.PrintFinalStats) return;
+ size_t ExecPerSec = execPerSec();
+ Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns);
+ Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec);
+ Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded);
+ Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds);
+ Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb());
+}
+
+void Fuzzer::SetMaxInputLen(size_t MaxInputLen) {
+ assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0.
+ assert(MaxInputLen);
+ this->MaxInputLen = MaxInputLen;
+ this->MaxMutationLen = MaxInputLen;
+ AllocateCurrentUnitData();
+ Printf("INFO: -max_len is not provided, using %zd\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 std::set<uintptr_t>;
+ for (size_t i = 1, N = TPC.GetNumPCs(); i < N; i++) {
+ uintptr_t PC = TPC.GetPC(i);
+ if (!PC) continue;
+ if (!PCsSet->insert(PC).second) continue;
+ std::string Descr = DescribePC("%L", PC);
+ if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) {
+ Printf("INFO: found line matching '%s', exiting.\n",
+ Options.ExitOnSrcPos.c_str());
+ _Exit(0);
+ }
+ }
+ }
+ 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;
+ std::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 (size_t NumFeatures = RunOne(U)) {
+ CheckExitOnSrcPosOrItem();
+ Corpus.AddToCorpus(U, NumFeatures);
+ Reloaded = true;
+ }
+ }
+ }
+ if (Reloaded)
+ PrintStats("RELOAD");
+}
+
+void Fuzzer::ShuffleCorpus(UnitVector *V) {
+ std::random_shuffle(V->begin(), V->end(), MD.GetRand());
+ if (Options.PreferSmall)
+ std::stable_sort(V->begin(), V->end(), [](const Unit &A, const Unit &B) {
+ return A.size() < B.size();
+ });
+}
+
+void Fuzzer::ShuffleAndMinimize(UnitVector *InitialCorpus) {
+ Printf("#0\tREAD units: %zd\n", InitialCorpus->size());
+ if (Options.ShuffleAtStartUp)
+ ShuffleCorpus(InitialCorpus);
+
+ // Test the callback with empty input and never try it again.
+ uint8_t dummy;
+ ExecuteCallback(&dummy, 0);
+
+ for (const auto &U : *InitialCorpus) {
+ if (size_t NumFeatures = RunOne(U)) {
+ CheckExitOnSrcPosOrItem();
+ Corpus.AddToCorpus(U, NumFeatures);
+ if (Options.Verbosity >= 2)
+ Printf("NEW0: %zd L %zd\n", MaxCoverage.BlockCoverage, U.size());
+ }
+ TryDetectingAMemoryLeak(U.data(), U.size(),
+ /*DuringInitialCorpusExecution*/ true);
+ }
+ PrintStats("INITED");
+ if (Corpus.empty()) {
+ Printf("ERROR: no interesting inputs were found. "
+ "Is the code instrumented for coverage? Exiting.\n");
+ exit(1);
+ }
+}
+
+size_t Fuzzer::RunOne(const uint8_t *Data, size_t Size) {
+ if (!Size) return 0;
+ TotalNumberOfRuns++;
+
+ ExecuteCallback(Data, Size);
+
+ size_t Res = 0;
+ if (size_t NumFeatures = TPC.CollectFeatures([&](size_t Feature) -> bool {
+ return Corpus.AddFeature(Feature, Size, Options.Shrink);
+ }))
+ Res = NumFeatures;
+
+ if (!TPC.UsingTracePcGuard()) {
+ if (TPC.UpdateValueProfileMap(&MaxCoverage.VPMap))
+ Res = 1;
+ if (!Res && RecordMaxCoverage(&MaxCoverage))
+ Res = 1;
+ }
+
+ 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-");
+ }
+ return Res;
+}
+
+size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const {
+ assert(InFuzzingThread());
+ *Data = CurrentUnitData;
+ return CurrentUnitSize;
+}
+
+void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
+ 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 (CurrentUnitData && CurrentUnitData != Data)
+ memcpy(CurrentUnitData, Data, Size);
+ CurrentUnitSize = Size;
+ AllocTracer.Start(Options.TraceMalloc);
+ UnitStartTime = system_clock::now();
+ ResetCounters(); // Reset coverage right before the callback.
+ TPC.ResetMaps();
+ RunningCB = true;
+ int Res = CB(DataCopy, Size);
+ RunningCB = false;
+ UnitStopTime = system_clock::now();
+ (void)Res;
+ assert(Res == 0);
+ HasMoreMallocsThanFrees = AllocTracer.Stop();
+ CurrentUnitSize = 0;
+ delete[] DataCopy;
+}
+
+void Fuzzer::WriteToOutputCorpus(const Unit &U) {
+ if (Options.OnlyASCII)
+ assert(IsASCII(U));
+ if (Options.OutputCorpus.empty())
+ return;
+ std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U));
+ WriteToFile(U, Path);
+ if (Options.Verbosity >= 2)
+ Printf("Written to %s\n", Path.c_str());
+}
+
+void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
+ if (!Options.SaveArtifacts)
+ return;
+ std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
+ if (!Options.ExactArtifactPath.empty())
+ Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix.
+ WriteToFile(U, Path);
+ Printf("artifact_prefix='%s'; Test unit written to %s\n",
+ Options.ArtifactPrefix.c_str(), Path.c_str());
+ if (U.size() <= kMaxUnitSizeToPrint)
+ Printf("Base64: %s\n", Base64(U).c_str());
+}
+
+void Fuzzer::PrintStatusForNewUnit(const Unit &U) {
+ if (!Options.PrintNEW)
+ return;
+ PrintStats("NEW ", "");
+ if (Options.Verbosity) {
+ Printf(" L: %zd ", U.size());
+ MD.PrintMutationSequence();
+ Printf("\n");
+ }
+}
+
+void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) {
+ II->NumSuccessfullMutations++;
+ MD.RecordSuccessfulMutationSequence();
+ PrintStatusForNewUnit(U);
+ WriteToOutputCorpus(U);
+ NumberOfNewUnitsAdded++;
+ TPC.PrintNewPCs();
+}
+
+// Finds minimal number of units in 'Extra' that add coverage to 'Initial'.
+// We do it by actually executing the units, sometimes more than once,
+// because we may be using different coverage-like signals and the only
+// common thing between them is that we can say "this unit found new stuff".
+UnitVector Fuzzer::FindExtraUnits(const UnitVector &Initial,
+ const UnitVector &Extra) {
+ UnitVector Res = Extra;
+ UnitVector Tmp;
+ size_t OldSize = Res.size();
+ for (int Iter = 0; Iter < 10; Iter++) {
+ ShuffleCorpus(&Res);
+ TPC.ResetMaps();
+ Corpus.ResetFeatureSet();
+ ResetCoverage();
+
+ for (auto &U : Initial) {
+ TPC.ResetMaps();
+ RunOne(U);
+ }
+
+ Tmp.clear();
+ for (auto &U : Res) {
+ TPC.ResetMaps();
+ if (RunOne(U))
+ Tmp.push_back(U);
+ }
+
+ char Stat[7] = "MIN ";
+ Stat[3] = '0' + Iter;
+ PrintStats(Stat, "\n", Tmp.size());
+
+ size_t NewSize = Tmp.size();
+ assert(NewSize <= OldSize);
+ Res.swap(Tmp);
+
+ if (NewSize + 5 >= OldSize)
+ break;
+ OldSize = NewSize;
+ }
+ return Res;
+}
+
+void Fuzzer::Merge(const std::vector<std::string> &Corpora) {
+ if (Corpora.size() <= 1) {
+ Printf("Merge requires two or more corpus dirs\n");
+ return;
+ }
+ InMergeMode = true;
+ std::vector<std::string> ExtraCorpora(Corpora.begin() + 1, Corpora.end());
+
+ assert(MaxInputLen > 0);
+ UnitVector Initial, Extra;
+ ReadDirToVectorOfUnits(Corpora[0].c_str(), &Initial, nullptr, MaxInputLen,
+ true);
+ for (auto &C : ExtraCorpora)
+ ReadDirToVectorOfUnits(C.c_str(), &Extra, nullptr, MaxInputLen, true);
+
+ if (!Initial.empty()) {
+ Printf("=== Minimizing the initial corpus of %zd units\n", Initial.size());
+ Initial = FindExtraUnits({}, Initial);
+ }
+
+ Printf("=== Merging extra %zd units\n", Extra.size());
+ auto Res = FindExtraUnits(Initial, Extra);
+
+ for (auto &U: Res)
+ WriteToOutputCorpus(U);
+
+ Printf("=== Merge: written %zd units\n", Res.size());
+}
+
+// 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 (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) ||
+ !(EF->__lsan_do_recoverable_leak_check))
+ return; // No lsan.
+ // Run the target once again, but with lsan disabled so that if there is
+ // a real leak we do not report it twice.
+ EF->__lsan_disable();
+ ExecuteCallback(Data, Size);
+ EF->__lsan_enable();
+ if (!HasMoreMallocsThanFrees) return; // a leak is unlikely.
+ if (NumberOfLeakDetectionAttempts++ > 1000) {
+ Options.DetectLeaks = false;
+ Printf("INFO: libFuzzer disabled leak detection after every mutation.\n"
+ " Most likely the target function accumulates allocated\n"
+ " memory in a global state w/o actually leaking it.\n"
+ " You may try running this binary with -trace_malloc=[12]"
+ " to get a trace of mallocs and frees.\n"
+ " If LeakSanitizer is enabled in this process it will still\n"
+ " run on the process shutdown.\n");
+ return;
+ }
+ // Now perform the actual lsan pass. This is expensive and we must ensure
+ // we don't call it too often.
+ if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it.
+ if (DuringInitialCorpusExecution)
+ Printf("\nINFO: a leak has been found in the initial corpus.\n\n");
+ Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n");
+ CurrentUnitSize = Size;
+ DumpCurrentUnit("leak-");
+ PrintFinalStats();
+ _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on.
+ }
+}
+
+void Fuzzer::MutateAndTestOne() {
+ MD.StartMutationSequence();
+
+ auto &II = Corpus.ChooseUnitToMutate(MD.GetRand());
+ const auto &U = II.U;
+ memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1));
+ assert(CurrentUnitData);
+ size_t Size = U.size();
+ assert(Size <= MaxInputLen && "Oversized Unit");
+ memcpy(CurrentUnitData, U.data(), Size);
+
+ assert(MaxMutationLen > 0);
+
+ for (int i = 0; i < Options.MutateDepth; i++) {
+ if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
+ break;
+ size_t NewSize = 0;
+ NewSize = MD.Mutate(CurrentUnitData, Size, MaxMutationLen);
+ assert(NewSize > 0 && "Mutator returned empty unit");
+ assert(NewSize <= MaxMutationLen && "Mutator return overisized unit");
+ Size = NewSize;
+ if (i == 0)
+ StartTraceRecording();
+ II.NumExecutedMutations++;
+ if (size_t NumFeatures = RunOne(CurrentUnitData, Size)) {
+ Corpus.AddToCorpus({CurrentUnitData, CurrentUnitData + Size}, NumFeatures,
+ /*MayDeleteFile=*/true);
+ ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size});
+ CheckExitOnSrcPosOrItem();
+ }
+ StopTraceRecording();
+ TryDetectingAMemoryLeak(CurrentUnitData, Size,
+ /*DuringInitialCorpusExecution*/ false);
+ }
+}
+
+void Fuzzer::ResetCoverage() {
+ ResetEdgeCoverage();
+ MaxCoverage.Reset();
+ PrepareCounters(&MaxCoverage);
+}
+
+void Fuzzer::Loop() {
+ system_clock::time_point LastCorpusReload = system_clock::now();
+ if (Options.DoCrossOver)
+ MD.SetCorpus(&Corpus);
+ while (true) {
+ auto Now = system_clock::now();
+ if (duration_cast<seconds>(Now - LastCorpusReload).count() >=
+ Options.ReloadIntervalSec) {
+ RereadOutputCorpus(MaxInputLen);
+ LastCorpusReload = system_clock::now();
+ }
+ if (TotalNumberOfRuns >= Options.MaxNumberOfRuns)
+ break;
+ if (TimedOut()) break;
+ // Perform several mutations and runs.
+ MutateAndTestOne();
+ }
+
+ PrintStats("DONE ", "\n");
+ MD.PrintRecommendedDictionary();
+}
+
+void Fuzzer::MinimizeCrashLoop(const Unit &U) {
+ if (U.size() <= 2) 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);
+ RunOne(CurrentUnitData, NewSize);
+ TryDetectingAMemoryLeak(CurrentUnitData, NewSize,
+ /*DuringInitialCorpusExecution*/ false);
+ }
+ }
+}
+
+} // namespace fuzzer
+
+extern "C" {
+
+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/json4cpp/tests/thirdparty/Fuzzer/FuzzerMain.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMain.cpp
new file mode 100644
index 0000000000..af8657200b
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMain.cpp
@@ -0,0 +1,21 @@
+//===- FuzzerMain.cpp - main() function and flags -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// main() and flags.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerDefs.h"
+
+extern "C" {
+// This function should be defined by the user.
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+} // extern "C"
+
+int main(int argc, char **argv) {
+ return fuzzer::FuzzerDriver(&argc, &argv, LLVMFuzzerTestOneInput);
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerMerge.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMerge.cpp
new file mode 100644
index 0000000000..84660e0fe5
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMerge.cpp
@@ -0,0 +1,261 @@
+//===- FuzzerMerge.cpp - merging corpora ----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Merging corpora.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerInternal.h"
+#include "FuzzerIO.h"
+#include "FuzzerMerge.h"
+#include "FuzzerTracePC.h"
+#include "FuzzerUtil.h"
+
+#include <fstream>
+#include <iterator>
+#include <sstream>
+
+namespace fuzzer {
+
+bool Merger::Parse(const std::string &Str, bool ParseCoverage) {
+ std::istringstream SS(Str);
+ return Parse(SS, ParseCoverage);
+}
+
+void Merger::ParseOrExit(std::istream &IS, bool ParseCoverage) {
+ if (!Parse(IS, ParseCoverage)) {
+ Printf("MERGE: failed to parse the control file (unexpected error)\n");
+ exit(1);
+ }
+}
+
+// The control file example:
+//
+// 3 # The number of inputs
+// 1 # The number of inputs in the first corpus, <= the previous number
+// file0
+// file1
+// file2 # One file name per line.
+// STARTED 0 123 # FileID, file size
+// DONE 0 1 4 6 8 # FileID COV1 COV2 ...
+// STARTED 1 456 # If DONE is missing, the input crashed while processing.
+// STARTED 2 567
+// DONE 2 8 9
+bool Merger::Parse(std::istream &IS, bool ParseCoverage) {
+ LastFailure.clear();
+ std::string Line;
+
+ // Parse NumFiles.
+ if (!std::getline(IS, Line, '\n')) return false;
+ std::istringstream L1(Line);
+ size_t NumFiles = 0;
+ L1 >> NumFiles;
+ if (NumFiles == 0 || NumFiles > 10000000) return false;
+
+ // Parse NumFilesInFirstCorpus.
+ if (!std::getline(IS, Line, '\n')) return false;
+ std::istringstream L2(Line);
+ NumFilesInFirstCorpus = NumFiles + 1;
+ L2 >> NumFilesInFirstCorpus;
+ if (NumFilesInFirstCorpus > NumFiles) return false;
+
+ // Parse file names.
+ Files.resize(NumFiles);
+ for (size_t i = 0; i < NumFiles; i++)
+ if (!std::getline(IS, Files[i].Name, '\n'))
+ return false;
+
+ // Parse STARTED and DONE lines.
+ size_t ExpectedStartMarker = 0;
+ const size_t kInvalidStartMarker = -1;
+ size_t LastSeenStartMarker = kInvalidStartMarker;
+ while (std::getline(IS, Line, '\n')) {
+ std::istringstream ISS1(Line);
+ std::string Marker;
+ size_t N;
+ ISS1 >> Marker;
+ ISS1 >> N;
+ if (Marker == "STARTED") {
+ // STARTED FILE_ID FILE_SIZE
+ if (ExpectedStartMarker != N)
+ return false;
+ ISS1 >> Files[ExpectedStartMarker].Size;
+ LastSeenStartMarker = ExpectedStartMarker;
+ assert(ExpectedStartMarker < Files.size());
+ ExpectedStartMarker++;
+ } else if (Marker == "DONE") {
+ // DONE FILE_SIZE COV1 COV2 COV3 ...
+ size_t CurrentFileIdx = N;
+ if (CurrentFileIdx != LastSeenStartMarker)
+ return false;
+ LastSeenStartMarker = kInvalidStartMarker;
+ if (ParseCoverage) {
+ auto &V = Files[CurrentFileIdx].Features;
+ V.clear();
+ while (ISS1 >> std::hex >> N)
+ V.push_back(N);
+ std::sort(V.begin(), V.end());
+ }
+ } else {
+ return false;
+ }
+ }
+ if (LastSeenStartMarker != kInvalidStartMarker)
+ LastFailure = Files[LastSeenStartMarker].Name;
+
+ FirstNotProcessedFile = ExpectedStartMarker;
+ return true;
+}
+
+// Decides which files need to be merged (add thost to NewFiles).
+// Returns the number of new features added.
+size_t Merger::Merge(std::vector<std::string> *NewFiles) {
+ NewFiles->clear();
+ assert(NumFilesInFirstCorpus <= Files.size());
+ std::set<uint32_t> AllFeatures;
+
+ // What features are in the initial corpus?
+ for (size_t i = 0; i < NumFilesInFirstCorpus; i++) {
+ auto &Cur = Files[i].Features;
+ AllFeatures.insert(Cur.begin(), Cur.end());
+ }
+ size_t InitialNumFeatures = AllFeatures.size();
+
+ // Remove all features that we already know from all other inputs.
+ for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) {
+ auto &Cur = Files[i].Features;
+ std::vector<uint32_t> Tmp;
+ std::set_difference(Cur.begin(), Cur.end(), AllFeatures.begin(),
+ AllFeatures.end(), std::inserter(Tmp, Tmp.begin()));
+ Cur.swap(Tmp);
+ }
+
+ // Sort. Give preference to
+ // * smaller files
+ // * files with more features.
+ std::sort(Files.begin() + NumFilesInFirstCorpus, Files.end(),
+ [&](const MergeFileInfo &a, const MergeFileInfo &b) -> bool {
+ if (a.Size != b.Size)
+ return a.Size < b.Size;
+ return a.Features.size() > b.Features.size();
+ });
+
+ // One greedy pass: add the file's features to AllFeatures.
+ // If new features were added, add this file to NewFiles.
+ for (size_t i = NumFilesInFirstCorpus; i < Files.size(); i++) {
+ auto &Cur = Files[i].Features;
+ // Printf("%s -> sz %zd ft %zd\n", Files[i].Name.c_str(),
+ // Files[i].Size, Cur.size());
+ size_t OldSize = AllFeatures.size();
+ AllFeatures.insert(Cur.begin(), Cur.end());
+ if (AllFeatures.size() > OldSize)
+ NewFiles->push_back(Files[i].Name);
+ }
+ return AllFeatures.size() - InitialNumFeatures;
+}
+
+// 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);
+ for (size_t i = M.FirstNotProcessedFile; i < M.Files.size(); i++) {
+ auto U = FileToVector(M.Files[i].Name);
+ if (U.size() > MaxInputLen) {
+ U.resize(MaxInputLen);
+ U.shrink_to_fit();
+ }
+ std::ostringstream StartedLine;
+ // Write the pre-run marker.
+ OF << "STARTED " << std::dec << i << " " << U.size() << "\n";
+ OF.flush(); // Flush is important since ExecuteCommand may crash.
+ // Run.
+ TPC.ResetMaps();
+ ExecuteCallback(U.data(), U.size());
+ // Collect coverage.
+ std::set<size_t> Features;
+ TPC.CollectFeatures([&](size_t Feature) -> bool {
+ Features.insert(Feature);
+ return true;
+ });
+ // Show stats.
+ TotalNumberOfRuns++;
+ if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)))
+ PrintStats("pulse ");
+ // Write the post-run marker and the coverage.
+ OF << "DONE " << i;
+ for (size_t F : Features)
+ OF << " " << std::hex << F;
+ OF << "\n";
+ }
+}
+
+// Outer process. Does not call the target code and thus sohuld not fail.
+void Fuzzer::CrashResistantMerge(const std::vector<std::string> &Args,
+ const std::vector<std::string> &Corpora) {
+ if (Corpora.size() <= 1) {
+ Printf("Merge requires two or more corpus dirs\n");
+ return;
+ }
+ std::vector<std::string> AllFiles;
+ ListFilesInDirRecursive(Corpora[0], nullptr, &AllFiles, /*TopDir*/true);
+ size_t NumFilesInFirstCorpus = AllFiles.size();
+ for (size_t i = 1; i < Corpora.size(); i++)
+ ListFilesInDirRecursive(Corpora[i], nullptr, &AllFiles, /*TopDir*/true);
+ Printf("MERGE-OUTER: %zd files, %zd in the initial corpus\n",
+ AllFiles.size(), NumFilesInFirstCorpus);
+ std::string CFPath =
+ "libFuzzerTemp." + std::to_string(GetPid()) + ".txt";
+ // Write the control file.
+ RemoveFile(CFPath);
+ std::ofstream ControlFile(CFPath);
+ ControlFile << AllFiles.size() << "\n";
+ ControlFile << NumFilesInFirstCorpus << "\n";
+ for (auto &Path: AllFiles)
+ ControlFile << Path << "\n";
+ ControlFile.close();
+
+ // Execute the inner process untill it passes.
+ // Every inner process should execute at least one input.
+ std::string BaseCmd = CloneArgsWithoutX(Args, "keep-all-flags");
+ for (size_t i = 1; i <= AllFiles.size(); i++) {
+ Printf("MERGE-OUTER: attempt %zd\n", i);
+ auto ExitCode =
+ ExecuteCommand(BaseCmd + " -merge_control_file=" + CFPath);
+ if (!ExitCode) {
+ Printf("MERGE-OUTER: succesfull in %zd attempt(s)\n", i);
+ break;
+ }
+ }
+ // Read the control file and do the merge.
+ Merger M;
+ std::ifstream IF(CFPath);
+ M.ParseOrExit(IF, true);
+ IF.close();
+ std::vector<std::string> NewFiles;
+ size_t NumNewFeatures = M.Merge(&NewFiles);
+ Printf("MERGE-OUTER: %zd new files with %zd new features added\n",
+ NewFiles.size(), NumNewFeatures);
+ for (auto &F: NewFiles)
+ WriteToOutputCorpus(FileToVector(F));
+ // We are done, delete the control file.
+ RemoveFile(CFPath);
+}
+
+} // namespace fuzzer
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerMerge.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMerge.h
new file mode 100644
index 0000000000..8a2fe5d74f
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMerge.h
@@ -0,0 +1,70 @@
+//===- FuzzerMerge.h - merging corpa ----------------------------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Merging Corpora.
+//
+// The task:
+// Take the existing corpus (possibly empty) and merge new inputs into
+// it so that only inputs with new coverage ('features') are added.
+// The process should tolerate the crashes, OOMs, leaks, etc.
+//
+// Algorithm:
+// The outter process collects the set of files and writes their names
+// into a temporary "control" file, then repeatedly launches the inner
+// process until all inputs are processed.
+// The outer process does not actually execute the target code.
+//
+// The inner process reads the control file and sees a) list of all the inputs
+// and b) the last processed input. Then it starts processing the inputs one
+// by one. Before processing every input it writes one line to control file:
+// STARTED INPUT_ID INPUT_SIZE
+// After processing an input it write another line:
+// DONE INPUT_ID Feature1 Feature2 Feature3 ...
+// If a crash happens while processing an input the last line in the control
+// file will be "STARTED INPUT_ID" and so the next process will know
+// where to resume.
+//
+// Once all inputs are processed by the innner process(es) the outer process
+// reads the control files and does the merge based entirely on the contents
+// of control file.
+// It uses a single pass greedy algorithm choosing first the smallest inputs
+// within the same size the inputs that have more new features.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_MERGE_H
+#define LLVM_FUZZER_MERGE_H
+
+#include "FuzzerDefs.h"
+
+#include <istream>
+#include <set>
+
+namespace fuzzer {
+
+struct MergeFileInfo {
+ std::string Name;
+ size_t Size = 0;
+ std::vector<uint32_t> Features;
+};
+
+struct Merger {
+ std::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(std::vector<std::string> *NewFiles);
+};
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_MERGE_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerMutate.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMutate.cpp
new file mode 100644
index 0000000000..80b7a5f961
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMutate.cpp
@@ -0,0 +1,527 @@
+//===- FuzzerMutate.cpp - Mutate a test input -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Mutate a test input.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerCorpus.h"
+#include "FuzzerDefs.h"
+#include "FuzzerExtFunctions.h"
+#include "FuzzerIO.h"
+#include "FuzzerMutate.h"
+#include "FuzzerOptions.h"
+
+namespace fuzzer {
+
+const size_t Dictionary::kMaxDictSize;
+
+static void PrintASCII(const Word &W, const char *PrintAfter) {
+ PrintASCII(W.data(), W.size(), PrintAfter);
+}
+
+MutationDispatcher::MutationDispatcher(Random &Rand,
+ const FuzzingOptions &Options)
+ : Rand(Rand), Options(Options) {
+ DefaultMutators.insert(
+ DefaultMutators.begin(),
+ {
+ {&MutationDispatcher::Mutate_EraseBytes, "EraseBytes"},
+ {&MutationDispatcher::Mutate_InsertByte, "InsertByte"},
+ {&MutationDispatcher::Mutate_InsertRepeatedBytes,
+ "InsertRepeatedBytes"},
+ {&MutationDispatcher::Mutate_ChangeByte, "ChangeByte"},
+ {&MutationDispatcher::Mutate_ChangeBit, "ChangeBit"},
+ {&MutationDispatcher::Mutate_ShuffleBytes, "ShuffleBytes"},
+ {&MutationDispatcher::Mutate_ChangeASCIIInteger, "ChangeASCIIInt"},
+ {&MutationDispatcher::Mutate_ChangeBinaryInteger, "ChangeBinInt"},
+ {&MutationDispatcher::Mutate_CopyPart, "CopyPart"},
+ {&MutationDispatcher::Mutate_CrossOver, "CrossOver"},
+ {&MutationDispatcher::Mutate_AddWordFromManualDictionary,
+ "ManualDict"},
+ {&MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary,
+ "TempAutoDict"},
+ {&MutationDispatcher::Mutate_AddWordFromPersistentAutoDictionary,
+ "PersAutoDict"},
+ });
+ if(Options.UseCmp)
+ DefaultMutators.push_back(
+ {&MutationDispatcher::Mutate_AddWordFromTORC, "CMP"});
+
+ if (EF->LLVMFuzzerCustomMutator)
+ Mutators.push_back({&MutationDispatcher::Mutate_Custom, "Custom"});
+ else
+ Mutators = DefaultMutators;
+
+ if (EF->LLVMFuzzerCustomCrossOver)
+ Mutators.push_back(
+ {&MutationDispatcher::Mutate_CustomCrossOver, "CustomCrossOver"});
+}
+
+static char RandCh(Random &Rand) {
+ if (Rand.RandBool()) return Rand(256);
+ const char *Special = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
+ return Special[Rand(sizeof(Special) - 1)];
+}
+
+size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
+ size_t MaxSize) {
+ return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand());
+}
+
+size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
+ size_t MaxSize) {
+ if (!Corpus || Corpus->size() < 2 || Size == 0)
+ return 0;
+ size_t Idx = Rand(Corpus->size());
+ const Unit &Other = (*Corpus)[Idx];
+ if (Other.empty())
+ return 0;
+ MutateInPlaceHere.resize(MaxSize);
+ auto &U = MutateInPlaceHere;
+ 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) return 0;
+ assert(Size);
+ 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::random_shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount,
+ Rand);
+ return Size;
+}
+
+size_t MutationDispatcher::Mutate_EraseBytes(uint8_t *Data, size_t Size,
+ size_t MaxSize) {
+ assert(Size);
+ 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::Mutate_AddWordFromTemporaryAutoDictionary(
+ uint8_t *Data, size_t Size, size_t MaxSize) {
+ return AddWordFromDictionary(TempAutoDictionary, 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.
+template <class T>
+DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
+ T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
+ ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem;
+ bool HandleFirst = Rand.RandBool();
+ T ExistingBytes, DesiredBytes;
+ Word W;
+ const uint8_t *End = Data + Size;
+ for (int Arg = 0; Arg < 2; Arg++) {
+ ExistingBytes = HandleFirst ? Arg1 : Arg2;
+ DesiredBytes = HandleFirst ? Arg2 : Arg1;
+ DesiredBytes += Rand(-1, 1);
+ if (Rand.RandBool()) ExistingBytes = Bswap(ExistingBytes);
+ if (Rand.RandBool()) DesiredBytes = Bswap(DesiredBytes);
+ HandleFirst = !HandleFirst;
+ W.Set(reinterpret_cast<uint8_t*>(&DesiredBytes), sizeof(T));
+ 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 = (uint8_t *)SearchMemory(Cur, End - Cur, &ExistingBytes, sizeof(T));
+ if (!Cur) break;
+ Positions[NumPositions++] = Cur - Data;
+ }
+ if (!NumPositions) break;
+ return DictionaryEntry(W, Positions[Rand(NumPositions)]);
+ }
+ DictionaryEntry DE(W);
+ return DE;
+}
+
+size_t MutationDispatcher::Mutate_AddWordFromTORC(
+ uint8_t *Data, size_t Size, size_t MaxSize) {
+ Word W;
+ DictionaryEntry DE;
+ if (Rand.RandBool()) {
+ auto X = TPC.TORC8.Get(Rand.Rand());
+ DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
+ } else {
+ 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);
+ }
+ 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) return 0;
+ if (Rand.RandBool())
+ return CopyPartOf(Data, Size, Data, Size);
+ else
+ return InsertPartOf(Data, Size, Data, Size, MaxSize);
+}
+
+size_t MutationDispatcher::Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size,
+ size_t MaxSize) {
+ if (Size > MaxSize) return 0;
+ size_t B = Rand(Size);
+ while (B < Size && !isdigit(Data[B])) B++;
+ if (B == Size) return 0;
+ size_t E = B;
+ while (E < Size && isdigit(Data[E])) E++;
+ assert(B < E);
+ // now we have digits in [B, E).
+ // strtol and friends don't accept non-zero-teminated data, parse it manually.
+ uint64_t Val = Data[B] - '0';
+ for (size_t i = B + 1; i < E; i++)
+ Val = Val * 10 + Data[i] - '0';
+
+ // Mutate the integer value.
+ switch(Rand(5)) {
+ case 0: Val++; break;
+ case 1: Val--; break;
+ case 2: Val /= 2; break;
+ case 3: Val *= 2; break;
+ case 4: Val = Rand(Val * Val); break;
+ default: assert(0);
+ }
+ // Just replace the bytes with the new ones, don't bother moving bytes.
+ for (size_t i = B; i < E; i++) {
+ size_t Idx = E + B - i - 1;
+ assert(Idx >= B && Idx < E);
+ Data[Idx] = (Val % 10) + '0';
+ Val /= 10;
+ }
+ return Size;
+}
+
+template<class T>
+size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
+ if (Size < sizeof(T)) return 0;
+ size_t Off = Rand(Size - sizeof(T) + 1);
+ assert(Off + sizeof(T) <= Size);
+ T Val;
+ if (Off < 64 && !Rand(4)) {
+ Val = Size;
+ if (Rand.RandBool())
+ Val = Bswap(Val);
+ } else {
+ memcpy(&Val, Data + Off, sizeof(Val));
+ T Add = Rand(21);
+ Add -= 10;
+ if (Rand.RandBool())
+ Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
+ else
+ Val = Val + Add; // Add assuming current endiannes.
+ if (Add == 0 || Rand.RandBool()) // Maybe negate.
+ Val = -Val;
+ }
+ memcpy(Data + Off, &Val, sizeof(Val));
+ return Size;
+}
+
+size_t MutationDispatcher::Mutate_ChangeBinaryInteger(uint8_t *Data,
+ size_t Size,
+ size_t MaxSize) {
+ if (Size > MaxSize) return 0;
+ switch (Rand(4)) {
+ case 3: return ChangeBinaryInteger<uint64_t>(Data, Size, Rand);
+ case 2: return ChangeBinaryInteger<uint32_t>(Data, Size, Rand);
+ case 1: return ChangeBinaryInteger<uint16_t>(Data, Size, Rand);
+ case 0: return ChangeBinaryInteger<uint8_t>(Data, Size, Rand);
+ default: assert(0);
+ }
+ return 0;
+}
+
+size_t MutationDispatcher::Mutate_CrossOver(uint8_t *Data, size_t Size,
+ size_t MaxSize) {
+ if (Size > MaxSize) return 0;
+ if (!Corpus || Corpus->size() < 2 || Size == 0) return 0;
+ size_t Idx = Rand(Corpus->size());
+ const Unit &O = (*Corpus)[Idx];
+ if (O.empty()) return 0;
+ MutateInPlaceHere.resize(MaxSize);
+ auto &U = MutateInPlaceHere;
+ size_t NewSize = 0;
+ switch(Rand(3)) {
+ case 0:
+ NewSize = CrossOver(Data, Size, O.data(), O.size(), U.data(), U.size());
+ break;
+ case 1:
+ NewSize = InsertPartOf(O.data(), O.size(), U.data(), U.size(), MaxSize);
+ if (NewSize)
+ break;
+ // LLVM_FALLTHROUGH;
+ case 2:
+ NewSize = CopyPartOf(O.data(), O.size(), U.data(), U.size());
+ break;
+ default: assert(0);
+ }
+ assert(NewSize > 0 && "CrossOver returned empty unit");
+ assert(NewSize <= MaxSize && "CrossOver returned overisized unit");
+ memcpy(Data, U.data(), NewSize);
+ return NewSize;
+}
+
+void MutationDispatcher::StartMutationSequence() {
+ CurrentMutatorSequence.clear();
+ CurrentDictionaryEntrySequence.clear();
+}
+
+// Copy successful dictionary entries to PersistentAutoDictionary.
+void MutationDispatcher::RecordSuccessfulMutationSequence() {
+ for (auto DE : CurrentDictionaryEntrySequence) {
+ // PersistentAutoDictionary.AddWithSuccessCountOne(DE);
+ DE->IncSuccessCount();
+ // Linear search is fine here as this happens seldom.
+ if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
+ PersistentAutoDictionary.push_back({DE->GetW(), 1});
+ }
+}
+
+void MutationDispatcher::PrintRecommendedDictionary() {
+ std::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) {
+ Printf("\"");
+ PrintASCII(DE.GetW(), "\"");
+ Printf(" # Uses: %zd\n", DE.GetUseCount());
+ }
+ Printf("###### End of recommended dictionary. ######\n");
+}
+
+void MutationDispatcher::PrintMutationSequence() {
+ Printf("MS: %zd ", CurrentMutatorSequence.size());
+ for (auto M : CurrentMutatorSequence)
+ Printf("%s-", M.Name);
+ if (!CurrentDictionaryEntrySequence.empty()) {
+ Printf(" DE: ");
+ for (auto DE : CurrentDictionaryEntrySequence) {
+ Printf("\"");
+ PrintASCII(DE->GetW(), "\"-");
+ }
+ }
+}
+
+size_t MutationDispatcher::Mutate(uint8_t *Data, size_t Size, size_t MaxSize) {
+ return MutateImpl(Data, Size, MaxSize, Mutators);
+}
+
+size_t MutationDispatcher::DefaultMutate(uint8_t *Data, size_t Size,
+ size_t MaxSize) {
+ return MutateImpl(Data, Size, MaxSize, DefaultMutators);
+}
+
+// Mutates Data in place, returns new size.
+size_t MutationDispatcher::MutateImpl(uint8_t *Data, size_t Size,
+ size_t MaxSize,
+ const std::vector<Mutator> &Mutators) {
+ assert(MaxSize > 0);
+ if (Size == 0) {
+ for (size_t i = 0; i < MaxSize; i++)
+ Data[i] = RandCh(Rand);
+ if (Options.OnlyASCII)
+ ToASCII(Data, MaxSize);
+ return MaxSize;
+ }
+ assert(Size > 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;
+ }
+ }
+ return std::min(Size, MaxSize);
+}
+
+void MutationDispatcher::AddWordToManualDictionary(const Word &W) {
+ ManualDictionary.push_back(
+ {W, std::numeric_limits<size_t>::max()});
+}
+
+void MutationDispatcher::AddWordToAutoDictionary(DictionaryEntry DE) {
+ static const size_t kMaxAutoDictSize = 1 << 14;
+ if (TempAutoDictionary.size() >= kMaxAutoDictSize) return;
+ TempAutoDictionary.push_back(DE);
+}
+
+void MutationDispatcher::ClearAutoDictionary() {
+ TempAutoDictionary.clear();
+}
+
+} // namespace fuzzer
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerMutate.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMutate.h
new file mode 100644
index 0000000000..d3c0b00124
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerMutate.h
@@ -0,0 +1,145 @@
+//===- FuzzerMutate.h - Internal header for the Fuzzer ----------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// fuzzer::MutationDispatcher
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_MUTATE_H
+#define LLVM_FUZZER_MUTATE_H
+
+#include "FuzzerDefs.h"
+#include "FuzzerDictionary.h"
+#include "FuzzerRandom.h"
+
+namespace fuzzer {
+
+class MutationDispatcher {
+public:
+ MutationDispatcher(Random &Rand, const FuzzingOptions &Options);
+ ~MutationDispatcher() {}
+ /// Indicate that we are about to start a new sequence of mutations.
+ void StartMutationSequence();
+ /// Print the current sequence of mutations.
+ void PrintMutationSequence();
+ /// Indicate that the current sequence of mutations was successfull.
+ void RecordSuccessfulMutationSequence();
+ /// Mutates data by invoking user-provided mutator.
+ size_t Mutate_Custom(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by invoking user-provided crossover.
+ size_t Mutate_CustomCrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by shuffling bytes.
+ size_t Mutate_ShuffleBytes(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by erasing bytes.
+ size_t Mutate_EraseBytes(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by inserting a byte.
+ size_t Mutate_InsertByte(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by inserting several repeated bytes.
+ size_t Mutate_InsertRepeatedBytes(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by chanding one byte.
+ size_t Mutate_ChangeByte(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by chanding one bit.
+ size_t Mutate_ChangeBit(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Mutates data by copying/inserting a part of data into a different place.
+ size_t Mutate_CopyPart(uint8_t *Data, size_t Size, size_t MaxSize);
+
+ /// Mutates data by adding a word from the manual dictionary.
+ size_t Mutate_AddWordFromManualDictionary(uint8_t *Data, size_t Size,
+ size_t MaxSize);
+
+ /// Mutates data by adding a word from the temporary automatic dictionary.
+ size_t Mutate_AddWordFromTemporaryAutoDictionary(uint8_t *Data, size_t Size,
+ size_t MaxSize);
+
+ /// Mutates data by adding a word from the TORC.
+ size_t Mutate_AddWordFromTORC(uint8_t *Data, size_t Size, size_t MaxSize);
+
+ /// Mutates data by adding a word from the persistent automatic dictionary.
+ size_t Mutate_AddWordFromPersistentAutoDictionary(uint8_t *Data, size_t Size,
+ size_t MaxSize);
+
+ /// Tries to find an ASCII integer in Data, changes it to another ASCII int.
+ size_t Mutate_ChangeASCIIInteger(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Change a 1-, 2-, 4-, or 8-byte integer in interesting ways.
+ size_t Mutate_ChangeBinaryInteger(uint8_t *Data, size_t Size, size_t MaxSize);
+
+ /// CrossOver Data with some other element of the corpus.
+ size_t Mutate_CrossOver(uint8_t *Data, size_t Size, size_t MaxSize);
+
+ /// Applies one of the configured mutations.
+ /// Returns the new size of data which could be up to MaxSize.
+ size_t Mutate(uint8_t *Data, size_t Size, size_t MaxSize);
+ /// Applies one of the 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 AddWordToAutoDictionary(DictionaryEntry DE);
+ void ClearAutoDictionary();
+ void PrintRecommendedDictionary();
+
+ void SetCorpus(const InputCorpus *Corpus) { this->Corpus = Corpus; }
+
+ Random &GetRand() { return Rand; }
+
+private:
+
+ struct Mutator {
+ size_t (MutationDispatcher::*Fn)(uint8_t *Data, size_t Size, size_t Max);
+ const char *Name;
+ };
+
+ size_t AddWordFromDictionary(Dictionary &D, uint8_t *Data, size_t Size,
+ size_t MaxSize);
+ size_t MutateImpl(uint8_t *Data, size_t Size, size_t MaxSize,
+ const std::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);
+
+ Random &Rand;
+ const FuzzingOptions &Options;
+
+ // Dictionary provided by the user via -dict=DICT_FILE.
+ Dictionary ManualDictionary;
+ // Temporary dictionary modified by the fuzzer itself,
+ // recreated periodically.
+ Dictionary TempAutoDictionary;
+ // Persistent dictionary modified by the fuzzer, consists of
+ // entries that led to successfull discoveries in the past mutations.
+ Dictionary PersistentAutoDictionary;
+
+ std::vector<Mutator> CurrentMutatorSequence;
+ std::vector<DictionaryEntry *> CurrentDictionaryEntrySequence;
+
+ static const size_t kCmpDictionaryEntriesDequeSize = 16;
+ DictionaryEntry CmpDictionaryEntriesDeque[kCmpDictionaryEntriesDequeSize];
+ size_t CmpDictionaryEntriesDequeIdx = 0;
+
+ const InputCorpus *Corpus = nullptr;
+ std::vector<uint8_t> MutateInPlaceHere;
+
+ std::vector<Mutator> Mutators;
+ std::vector<Mutator> DefaultMutators;
+};
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_MUTATE_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerOptions.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerOptions.h
new file mode 100644
index 0000000000..34e93fc34a
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerOptions.h
@@ -0,0 +1,68 @@
+//===- FuzzerOptions.h - Internal header for the Fuzzer ---------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// fuzzer::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;
+ int UnitTimeoutSec = 300;
+ int TimeoutExitCode = 77;
+ int ErrorExitCode = 77;
+ int MaxTotalTimeSec = 0;
+ int RssLimitMb = 0;
+ bool DoCrossOver = true;
+ int MutateDepth = 5;
+ bool UseCounters = false;
+ bool UseIndirCalls = true;
+ bool UseMemcmp = true;
+ bool UseMemmem = true;
+ bool UseCmp = false;
+ bool UseValueProfile = false;
+ bool Shrink = false;
+ int ReloadIntervalSec = 1;
+ bool ShuffleAtStartUp = true;
+ bool PreferSmall = true;
+ size_t MaxNumberOfRuns = -1L;
+ int ReportSlowUnits = 10;
+ bool OnlyASCII = false;
+ std::string OutputCorpus;
+ std::string ArtifactPrefix = "./";
+ std::string ExactArtifactPath;
+ std::string ExitOnSrcPos;
+ std::string ExitOnItem;
+ bool SaveArtifacts = true;
+ bool PrintNEW = true; // Print a status line when new units are found;
+ bool OutputCSV = false;
+ bool PrintNewCovPcs = false;
+ bool PrintFinalStats = false;
+ bool PrintCorpusStats = false;
+ bool PrintCoverage = false;
+ bool DumpCoverage = false;
+ bool DetectLeaks = true;
+ int TraceMalloc = 0;
+ bool HandleAbrt = false;
+ bool HandleBus = false;
+ bool HandleFpe = false;
+ bool HandleIll = false;
+ bool HandleInt = false;
+ bool HandleSegv = false;
+ bool HandleTerm = false;
+};
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_OPTIONS_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerRandom.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerRandom.h
new file mode 100644
index 0000000000..b1be0bb935
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerRandom.h
@@ -0,0 +1,36 @@
+//===- FuzzerRandom.h - Internal header for the Fuzzer ----------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// fuzzer::Random
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_RANDOM_H
+#define LLVM_FUZZER_RANDOM_H
+
+#include <random>
+
+namespace fuzzer {
+class Random {
+ public:
+ Random(unsigned int seed) : R(seed) {}
+ size_t Rand() { return R(); }
+ size_t RandBool() { return Rand() % 2; }
+ size_t operator()(size_t n) { return n ? Rand() % n : 0; }
+ intptr_t operator()(intptr_t From, intptr_t To) {
+ assert(From < To);
+ intptr_t RangeSize = To - From + 1;
+ return operator()(RangeSize) + From;
+ }
+ std::mt19937 &Get_mt19937() { return R; }
+ private:
+ std::mt19937 R;
+};
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_RANDOM_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerSHA1.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerSHA1.cpp
new file mode 100644
index 0000000000..d2f8e811bb
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerSHA1.cpp
@@ -0,0 +1,222 @@
+//===- FuzzerSHA1.h - Private copy of the SHA1 implementation ---*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This code is taken from public domain
+// (http://oauth.googlecode.com/svn/code/c/liboauth/src/sha1.c)
+// and modified by adding anonymous namespace, adding an interface
+// function fuzzer::ComputeSHA1() and removing unnecessary code.
+//
+// lib/Fuzzer can not use SHA1 implementation from openssl because
+// openssl may not be available and because we may be fuzzing openssl itself.
+// For the same reason we do not want to depend on SHA1 from LLVM tree.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerSHA1.h"
+#include "FuzzerDefs.h"
+
+/* This code is public-domain - it is based on libcrypt
+ * placed in the public domain by Wei Dai and other contributors.
+ */
+
+#include <iomanip>
+#include <sstream>
+#include <stdint.h>
+#include <string.h>
+
+namespace { // Added for LibFuzzer
+
+#ifdef __BIG_ENDIAN__
+# define SHA_BIG_ENDIAN
+#elif defined __LITTLE_ENDIAN__
+/* override */
+#elif defined __BYTE_ORDER
+# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define SHA_BIG_ENDIAN
+# endif
+#else // ! defined __LITTLE_ENDIAN__
+# include <endian.h> // machine/endian.h
+# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define SHA_BIG_ENDIAN
+# endif
+#endif
+
+
+/* header */
+
+#define HASH_LENGTH 20
+#define BLOCK_LENGTH 64
+
+typedef struct sha1nfo {
+ uint32_t buffer[BLOCK_LENGTH/4];
+ uint32_t state[HASH_LENGTH/4];
+ uint32_t byteCount;
+ uint8_t bufferOffset;
+ uint8_t keyBuffer[BLOCK_LENGTH];
+ uint8_t innerHash[HASH_LENGTH];
+} sha1nfo;
+
+/* public API - prototypes - TODO: doxygen*/
+
+/**
+ */
+void sha1_init(sha1nfo *s);
+/**
+ */
+void sha1_writebyte(sha1nfo *s, uint8_t data);
+/**
+ */
+void sha1_write(sha1nfo *s, const char *data, size_t len);
+/**
+ */
+uint8_t* sha1_result(sha1nfo *s);
+
+
+/* code */
+#define SHA1_K0 0x5a827999
+#define SHA1_K20 0x6ed9eba1
+#define SHA1_K40 0x8f1bbcdc
+#define SHA1_K60 0xca62c1d6
+
+void sha1_init(sha1nfo *s) {
+ s->state[0] = 0x67452301;
+ s->state[1] = 0xefcdab89;
+ s->state[2] = 0x98badcfe;
+ s->state[3] = 0x10325476;
+ s->state[4] = 0xc3d2e1f0;
+ s->byteCount = 0;
+ s->bufferOffset = 0;
+}
+
+uint32_t sha1_rol32(uint32_t number, uint8_t bits) {
+ return ((number << bits) | (number >> (32-bits)));
+}
+
+void sha1_hashBlock(sha1nfo *s) {
+ uint8_t i;
+ uint32_t a,b,c,d,e,t;
+
+ a=s->state[0];
+ b=s->state[1];
+ c=s->state[2];
+ d=s->state[3];
+ e=s->state[4];
+ for (i=0; i<80; i++) {
+ if (i>=16) {
+ t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15];
+ s->buffer[i&15] = sha1_rol32(t,1);
+ }
+ if (i<20) {
+ t = (d ^ (b & (c ^ d))) + SHA1_K0;
+ } else if (i<40) {
+ t = (b ^ c ^ d) + SHA1_K20;
+ } else if (i<60) {
+ t = ((b & c) | (d & (b | c))) + SHA1_K40;
+ } else {
+ t = (b ^ c ^ d) + SHA1_K60;
+ }
+ t+=sha1_rol32(a,5) + e + s->buffer[i&15];
+ e=d;
+ d=c;
+ c=sha1_rol32(b,30);
+ b=a;
+ a=t;
+ }
+ s->state[0] += a;
+ s->state[1] += b;
+ s->state[2] += c;
+ s->state[3] += d;
+ s->state[4] += e;
+}
+
+void sha1_addUncounted(sha1nfo *s, uint8_t data) {
+ uint8_t * const b = (uint8_t*) s->buffer;
+#ifdef SHA_BIG_ENDIAN
+ b[s->bufferOffset] = data;
+#else
+ b[s->bufferOffset ^ 3] = data;
+#endif
+ s->bufferOffset++;
+ if (s->bufferOffset == BLOCK_LENGTH) {
+ sha1_hashBlock(s);
+ s->bufferOffset = 0;
+ }
+}
+
+void sha1_writebyte(sha1nfo *s, uint8_t data) {
+ ++s->byteCount;
+ sha1_addUncounted(s, data);
+}
+
+void sha1_write(sha1nfo *s, const char *data, size_t len) {
+ for (;len--;) sha1_writebyte(s, (uint8_t) *data++);
+}
+
+void sha1_pad(sha1nfo *s) {
+ // Implement SHA-1 padding (fips180-2 §5.1.1)
+
+ // Pad with 0x80 followed by 0x00 until the end of the block
+ sha1_addUncounted(s, 0x80);
+ while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00);
+
+ // Append length in the last 8 bytes
+ sha1_addUncounted(s, 0); // We're only using 32 bit lengths
+ sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
+ sha1_addUncounted(s, 0); // So zero pad the top bits
+ sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
+ sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
+ sha1_addUncounted(s, s->byteCount >> 13); // byte.
+ sha1_addUncounted(s, s->byteCount >> 5);
+ sha1_addUncounted(s, s->byteCount << 3);
+}
+
+uint8_t* sha1_result(sha1nfo *s) {
+ // Pad to complete the last block
+ sha1_pad(s);
+
+#ifndef SHA_BIG_ENDIAN
+ // Swap byte order back
+ int i;
+ for (i=0; i<5; i++) {
+ s->state[i]=
+ (((s->state[i])<<24)& 0xff000000)
+ | (((s->state[i])<<8) & 0x00ff0000)
+ | (((s->state[i])>>8) & 0x0000ff00)
+ | (((s->state[i])>>24)& 0x000000ff);
+ }
+#endif
+
+ // Return pointer to hash (20 characters)
+ return (uint8_t*) s->state;
+}
+
+} // namespace; Added for LibFuzzer
+
+namespace fuzzer {
+
+// The rest is added for LibFuzzer
+void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out) {
+ sha1nfo s;
+ sha1_init(&s);
+ sha1_write(&s, (const char*)Data, Len);
+ memcpy(Out, sha1_result(&s), HASH_LENGTH);
+}
+
+std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]) {
+ std::stringstream SS;
+ for (int i = 0; i < kSHA1NumBytes; i++)
+ SS << std::hex << std::setfill('0') << std::setw(2) << (unsigned)Sha1[i];
+ return SS.str();
+}
+
+std::string Hash(const Unit &U) {
+ uint8_t Hash[kSHA1NumBytes];
+ ComputeSHA1(U.data(), U.size(), Hash);
+ return Sha1ToString(Hash);
+}
+
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerSHA1.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerSHA1.h
new file mode 100644
index 0000000000..3b5e6e807f
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerSHA1.h
@@ -0,0 +1,33 @@
+//===- FuzzerSHA1.h - Internal header for the SHA1 utils --------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// SHA1 utils.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_SHA1_H
+#define LLVM_FUZZER_SHA1_H
+
+#include "FuzzerDefs.h"
+#include <cstddef>
+#include <stdint.h>
+
+namespace fuzzer {
+
+// Private copy of SHA1 implementation.
+static const int kSHA1NumBytes = 20;
+
+// Computes SHA1 hash of 'Len' bytes in 'Data', writes kSHA1NumBytes to 'Out'.
+void ComputeSHA1(const uint8_t *Data, size_t Len, uint8_t *Out);
+
+std::string Sha1ToString(const uint8_t Sha1[kSHA1NumBytes]);
+
+std::string Hash(const Unit &U);
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_SHA1_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerTracePC.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerTracePC.cpp
new file mode 100644
index 0000000000..81c084b589
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerTracePC.cpp
@@ -0,0 +1,339 @@
+//===- FuzzerTracePC.cpp - PC tracing--------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Trace PCs.
+// This module implements __sanitizer_cov_trace_pc_guard[_init],
+// the callback required for -fsanitize-coverage=trace-pc-guard instrumentation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerCorpus.h"
+#include "FuzzerDefs.h"
+#include "FuzzerDictionary.h"
+#include "FuzzerExtFunctions.h"
+#include "FuzzerIO.h"
+#include "FuzzerTracePC.h"
+#include "FuzzerValueBitMap.h"
+#include <map>
+#include <sanitizer/coverage_interface.h>
+#include <set>
+#include <sstream>
+
+namespace fuzzer {
+
+TracePC TPC;
+
+void TracePC::HandleTrace(uint32_t *Guard, uintptr_t PC) {
+ uint32_t Idx = *Guard;
+ if (!Idx) return;
+ PCs[Idx % kNumPCs] = PC;
+ Counters[Idx % kNumCounters]++;
+}
+
+size_t TracePC::GetTotalPCCoverage() {
+ size_t Res = 0;
+ for (size_t i = 1; i < GetNumPCs(); i++)
+ if (PCs[i])
+ Res++;
+ return Res;
+}
+
+void TracePC::HandleInit(uint32_t *Start, uint32_t *Stop) {
+ if (Start == Stop || *Start) return;
+ assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
+ for (uint32_t *P = Start; P < Stop; P++)
+ *P = ++NumGuards;
+ Modules[NumModules].Start = Start;
+ Modules[NumModules].Stop = Stop;
+ NumModules++;
+}
+
+void TracePC::PrintModuleInfo() {
+ Printf("INFO: Loaded %zd modules (%zd guards): ", NumModules, NumGuards);
+ for (size_t i = 0; i < NumModules; i++)
+ Printf("[%p, %p), ", Modules[i].Start, Modules[i].Stop);
+ Printf("\n");
+}
+
+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);
+ HandleValueProfile(Idx);
+}
+
+static bool IsInterestingCoverageFile(std::string &File) {
+ if (File.find("compiler-rt/lib/") != std::string::npos)
+ return false; // sanitizer internal.
+ if (File.find("/usr/lib/") != std::string::npos)
+ return false;
+ if (File.find("/usr/include/") != std::string::npos)
+ return false;
+ if (File == "<null>")
+ return false;
+ return true;
+}
+
+void TracePC::PrintNewPCs() {
+ if (DoPrintNewPCs) {
+ if (!PrintedPCs)
+ PrintedPCs = new std::set<uintptr_t>;
+ for (size_t i = 1; i < GetNumPCs(); i++)
+ if (PCs[i] && PrintedPCs->insert(PCs[i]).second)
+ PrintPC("\tNEW_PC: %p %F %L\n", "\tNEW_PC: %p\n", PCs[i]);
+ }
+}
+
+void TracePC::PrintCoverage() {
+ if (!EF->__sanitizer_symbolize_pc ||
+ !EF->__sanitizer_get_module_and_offset_for_pc) {
+ Printf("INFO: __sanitizer_symbolize_pc or "
+ "__sanitizer_get_module_and_offset_for_pc is not available,"
+ " not printing coverage\n");
+ return;
+ }
+ std::map<std::string, std::vector<uintptr_t>> CoveredPCsPerModule;
+ std::map<std::string, uintptr_t> ModuleOffsets;
+ std::set<std::string> CoveredDirs, CoveredFiles, CoveredFunctions,
+ CoveredLines;
+ Printf("COVERAGE:\n");
+ for (size_t i = 1; i < GetNumPCs(); i++) {
+ if (!PCs[i]) continue;
+ std::string FileStr = DescribePC("%s", PCs[i]);
+ if (!IsInterestingCoverageFile(FileStr)) continue;
+ std::string FixedPCStr = DescribePC("%p", PCs[i]);
+ std::string FunctionStr = DescribePC("%F", PCs[i]);
+ std::string LineStr = DescribePC("%l", PCs[i]);
+ 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 *>(PCs[i]), ModulePathRaw,
+ sizeof(ModulePathRaw), &OffsetRaw))
+ continue;
+ std::string Module = ModulePathRaw;
+ uintptr_t FixedPC = std::stol(FixedPCStr, 0, 16);
+ uintptr_t PcOffset = reinterpret_cast<uintptr_t>(OffsetRaw);
+ ModuleOffsets[Module] = FixedPC - PcOffset;
+ CoveredPCsPerModule[Module].push_back(PcOffset);
+ CoveredFunctions.insert(FunctionStr);
+ CoveredFiles.insert(FileStr);
+ CoveredDirs.insert(DirName(FileStr));
+ if (!CoveredLines.insert(FileStr + ":" + LineStr).second)
+ continue;
+ Printf("COVERED: %s %s:%s\n", FunctionStr.c_str(),
+ FileStr.c_str(), LineStr.c_str());
+ }
+
+ std::string CoveredDirsStr;
+ for (auto &Dir : CoveredDirs) {
+ if (!CoveredDirsStr.empty())
+ CoveredDirsStr += ",";
+ CoveredDirsStr += Dir;
+ }
+ Printf("COVERED_DIRS: %s\n", CoveredDirsStr.c_str());
+
+ for (auto &M : CoveredPCsPerModule) {
+ std::set<std::string> UncoveredFiles, UncoveredFunctions;
+ std::map<std::string, std::set<int> > UncoveredLines; // Func+File => lines
+ auto &ModuleName = M.first;
+ auto &CoveredOffsets = M.second;
+ uintptr_t ModuleOffset = ModuleOffsets[ModuleName];
+ std::sort(CoveredOffsets.begin(), CoveredOffsets.end());
+ Printf("MODULE_WITH_COVERAGE: %s\n", ModuleName.c_str());
+ // sancov does not yet fully support DSOs.
+ // std::string Cmd = "sancov -print-coverage-pcs " + ModuleName;
+ std::string Cmd = "objdump -d " + ModuleName +
+ " | grep 'call.*__sanitizer_cov_trace_pc_guard' | awk -F: '{print $1}'";
+ std::string SanCovOutput;
+ if (!ExecuteCommandAndReadOutput(Cmd, &SanCovOutput)) {
+ Printf("INFO: Command failed: %s\n", Cmd.c_str());
+ continue;
+ }
+ std::istringstream ISS(SanCovOutput);
+ std::string S;
+ while (std::getline(ISS, S, '\n')) {
+ uintptr_t PcOffset = std::stol(S, 0, 16);
+ if (!std::binary_search(CoveredOffsets.begin(), CoveredOffsets.end(),
+ PcOffset)) {
+ uintptr_t PC = ModuleOffset + PcOffset;
+ auto FileStr = DescribePC("%s", PC);
+ if (!IsInterestingCoverageFile(FileStr)) continue;
+ if (CoveredFiles.count(FileStr) == 0) {
+ UncoveredFiles.insert(FileStr);
+ continue;
+ }
+ auto FunctionStr = DescribePC("%F", PC);
+ if (CoveredFunctions.count(FunctionStr) == 0) {
+ UncoveredFunctions.insert(FunctionStr);
+ continue;
+ }
+ std::string LineStr = DescribePC("%l", PC);
+ uintptr_t Line = std::stoi(LineStr);
+ std::string FileLineStr = FileStr + ":" + LineStr;
+ if (CoveredLines.count(FileLineStr) == 0)
+ UncoveredLines[FunctionStr + " " + FileStr].insert(Line);
+ }
+ }
+ for (auto &FileLine: UncoveredLines)
+ for (int Line : FileLine.second)
+ Printf("UNCOVERED_LINE: %s:%d\n", FileLine.first.c_str(), Line);
+ for (auto &Func : UncoveredFunctions)
+ Printf("UNCOVERED_FUNC: %s\n", Func.c_str());
+ for (auto &File : UncoveredFiles)
+ Printf("UNCOVERED_FILE: %s\n", File.c_str());
+ }
+}
+
+void TracePC::DumpCoverage() {
+ __sanitizer_dump_coverage(PCs, GetNumPCs());
+}
+
+// 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_MEMORY
+void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
+ size_t n) {
+ if (!n) return;
+ size_t Len = std::min(n, (size_t)32);
+ const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1);
+ const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2);
+ size_t I = 0;
+ for (; I < Len; I++)
+ if (A1[I] != A2[I])
+ break;
+ size_t PC = reinterpret_cast<size_t>(caller_pc);
+ size_t Idx = I;
+ // if (I < Len)
+ // Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1;
+ TPC.HandleValueProfile((PC & 4095) | (Idx << 12));
+}
+
+ATTRIBUTE_NO_SANITIZE_MEMORY
+void TracePC::AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2,
+ size_t n) {
+ if (!n) return;
+ size_t Len = std::min(n, (size_t)32);
+ const uint8_t *A1 = reinterpret_cast<const uint8_t *>(s1);
+ const uint8_t *A2 = reinterpret_cast<const uint8_t *>(s2);
+ size_t I = 0;
+ for (; I < Len; I++)
+ if (A1[I] != A2[I] || A1[I] == 0)
+ break;
+ size_t PC = reinterpret_cast<size_t>(caller_pc);
+ size_t Idx = I;
+ // if (I < Len && A1[I])
+ // Idx += __builtin_popcountl((A1[I] ^ A2[I])) - 1;
+ TPC.HandleValueProfile((PC & 4095) | (Idx << 12));
+}
+
+template <class T>
+ATTRIBUTE_TARGET_POPCNT
+#ifdef __clang__ // g++ can't handle this __attribute__ here :(
+__attribute__((always_inline))
+#endif // __clang__
+void TracePC::HandleCmp(void *PC, T Arg1, T Arg2) {
+ uintptr_t PCuint = reinterpret_cast<uintptr_t>(PC);
+ uint64_t ArgXor = Arg1 ^ Arg2;
+ uint64_t ArgDistance = __builtin_popcountl(ArgXor) + 1; // [1,65]
+ uintptr_t Idx = ((PCuint & 4095) + 1) * ArgDistance;
+ if (sizeof(T) == 4)
+ TORC4.Insert(ArgXor, Arg1, Arg2);
+ else if (sizeof(T) == 8)
+ TORC8.Insert(ArgXor, Arg1, Arg2);
+ HandleValueProfile(Idx);
+}
+
+} // namespace fuzzer
+
+extern "C" {
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_pc_guard(uint32_t *Guard) {
+ uintptr_t PC = (uintptr_t)__builtin_return_address(0);
+ fuzzer::TPC.HandleTrace(Guard, PC);
+}
+
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) {
+ fuzzer::TPC.HandleInit(Start, Stop);
+}
+
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
+ uintptr_t PC = (uintptr_t)__builtin_return_address(0);
+ fuzzer::TPC.HandleCallerCallee(PC, Callee);
+}
+
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_cmp8(uint64_t Arg1, uint64_t Arg2) {
+ fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2);
+}
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_cmp4(uint32_t Arg1, uint32_t Arg2) {
+ fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2);
+}
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_cmp2(uint16_t Arg1, uint16_t Arg2) {
+ fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2);
+}
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_cmp1(uint8_t Arg1, uint8_t Arg2) {
+ fuzzer::TPC.HandleCmp(__builtin_return_address(0), Arg1, Arg2);
+}
+
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_switch(uint64_t Val, uint64_t *Cases) {
+ // Updates the value profile based on the relative position of Val and Cases.
+ // We want to handle one random case at every call (handling all is slow).
+ // Since none of the arguments contain any random bits we use a thread-local
+ // counter to choose the random case to handle.
+ static thread_local size_t Counter;
+ Counter++;
+ uint64_t N = Cases[0];
+ uint64_t *Vals = Cases + 2;
+ char *PC = (char*)__builtin_return_address(0);
+ // We need a random number < N using Counter as a seed. But w/o DIV.
+ // * find a power of two >= N
+ // * mask Counter with this power of two.
+ // * maybe subtract N.
+ size_t Nlog = sizeof(long) * 8 - __builtin_clzl((long)N);
+ size_t PowerOfTwoGeN = 1U << Nlog;
+ assert(PowerOfTwoGeN >= N);
+ size_t Idx = Counter & (PowerOfTwoGeN - 1);
+ if (Idx >= N)
+ Idx -= N;
+ assert(Idx < N);
+ uint64_t TwoIn32 = 1ULL << 32;
+ if ((Val | Vals[Idx]) < TwoIn32)
+ fuzzer::TPC.HandleCmp(PC + Idx, static_cast<uint32_t>(Val),
+ static_cast<uint32_t>(Vals[Idx]));
+ else
+ fuzzer::TPC.HandleCmp(PC + Idx, Val, Vals[Idx]);
+}
+
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_div4(uint32_t Val) {
+ fuzzer::TPC.HandleCmp(__builtin_return_address(0), Val, (uint32_t)0);
+}
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_div8(uint64_t Val) {
+ fuzzer::TPC.HandleCmp(__builtin_return_address(0), Val, (uint64_t)0);
+}
+__attribute__((visibility("default")))
+void __sanitizer_cov_trace_gep(uintptr_t Idx) {
+ fuzzer::TPC.HandleCmp(__builtin_return_address(0), Idx, (uintptr_t)0);
+}
+
+} // extern "C"
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerTracePC.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerTracePC.h
new file mode 100644
index 0000000000..68827f80cb
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerTracePC.h
@@ -0,0 +1,158 @@
+//===- FuzzerTracePC.h - Internal header for the Fuzzer ---------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// fuzzer::TracePC
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_TRACE_PC
+#define LLVM_FUZZER_TRACE_PC
+
+#include "FuzzerDefs.h"
+#include "FuzzerValueBitMap.h"
+#include <set>
+
+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;
+ };
+ void Insert(size_t Idx, T Arg1, 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];
+};
+
+class TracePC {
+ public:
+ static const size_t kFeatureSetSize = ValueBitMap::kNumberOfItems;
+
+ void HandleTrace(uint32_t *guard, uintptr_t PC);
+ void HandleInit(uint32_t *start, uint32_t *stop);
+ void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
+ void HandleValueProfile(size_t Value) { ValueProfileMap.AddValue(Value); }
+ template <class T> void HandleCmp(void *PC, T Arg1, T Arg2);
+ size_t GetTotalPCCoverage();
+ void SetUseCounters(bool UC) { UseCounters = UC; }
+ void SetUseValueProfile(bool VP) { UseValueProfile = VP; }
+ void SetPrintNewPCs(bool P) { DoPrintNewPCs = P; }
+ template <class Callback> size_t CollectFeatures(Callback CB);
+ bool UpdateValueProfileMap(ValueBitMap *MaxValueProfileMap) {
+ return UseValueProfile && MaxValueProfileMap->MergeFrom(ValueProfileMap);
+ }
+
+ void ResetMaps() {
+ ValueProfileMap.Reset();
+ memset(Counters, 0, sizeof(Counters));
+ }
+
+ void UpdateFeatureSet(size_t CurrentElementIdx, size_t CurrentElementSize);
+ void PrintFeatureSet();
+
+ void PrintModuleInfo();
+
+ void PrintCoverage();
+ void DumpCoverage();
+
+ void AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
+ size_t n);
+ void AddValueForStrcmp(void *caller_pc, const char *s1, const char *s2,
+ size_t n);
+
+ bool UsingTracePcGuard() const {return NumModules; }
+
+ static const size_t kTORCSize = 1 << 5;
+ TableOfRecentCompares<uint32_t, kTORCSize> TORC4;
+ TableOfRecentCompares<uint64_t, kTORCSize> TORC8;
+
+ void PrintNewPCs();
+ size_t GetNumPCs() const { return Min(kNumPCs, NumGuards + 1); }
+ uintptr_t GetPC(size_t Idx) {
+ assert(Idx < GetNumPCs());
+ return PCs[Idx];
+ }
+
+private:
+ bool UseCounters = false;
+ bool UseValueProfile = false;
+ bool DoPrintNewPCs = false;
+
+ struct Module {
+ uint32_t *Start, *Stop;
+ };
+
+ Module Modules[4096];
+ size_t NumModules; // linker-initialized.
+ size_t NumGuards; // linker-initialized.
+
+ static const size_t kNumCounters = 1 << 14;
+ alignas(8) uint8_t Counters[kNumCounters];
+
+ static const size_t kNumPCs = 1 << 24;
+ uintptr_t PCs[kNumPCs];
+
+ std::set<uintptr_t> *PrintedPCs;
+
+ ValueBitMap ValueProfileMap;
+};
+
+template <class Callback>
+size_t TracePC::CollectFeatures(Callback CB) {
+ if (!UsingTracePcGuard()) return 0;
+ size_t Res = 0;
+ const size_t Step = 8;
+ assert(reinterpret_cast<uintptr_t>(Counters) % Step == 0);
+ size_t N = Min(kNumCounters, NumGuards + 1);
+ N = (N + Step - 1) & ~(Step - 1); // Round up.
+ for (size_t Idx = 0; Idx < N; Idx += Step) {
+ uint64_t Bundle = *reinterpret_cast<uint64_t*>(&Counters[Idx]);
+ if (!Bundle) continue;
+ for (size_t i = Idx; i < Idx + Step; i++) {
+ uint8_t Counter = (Bundle >> ((i - Idx) * 8)) & 0xff;
+ if (!Counter) continue;
+ Counters[i] = 0;
+ 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;
+ size_t Feature = (i * 8 + Bit);
+ if (CB(Feature))
+ Res++;
+ }
+ }
+ if (UseValueProfile)
+ ValueProfileMap.ForEach([&](size_t Idx) {
+ if (CB(NumGuards * 8 + Idx))
+ Res++;
+ });
+ return Res;
+}
+
+extern TracePC TPC;
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_TRACE_PC
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerTraceState.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerTraceState.cpp
new file mode 100644
index 0000000000..be62a6624b
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerTraceState.cpp
@@ -0,0 +1,325 @@
+//===- FuzzerTraceState.cpp - Trace-based fuzzer mutator ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Data tracing.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerDictionary.h"
+#include "FuzzerInternal.h"
+#include "FuzzerIO.h"
+#include "FuzzerMutate.h"
+#include "FuzzerRandom.h"
+#include "FuzzerTracePC.h"
+#include <algorithm>
+#include <cstring>
+#include <map>
+#include <set>
+#include <thread>
+
+namespace fuzzer {
+
+// For now, very simple: put Size bytes of Data at position Pos.
+struct TraceBasedMutation {
+ uint32_t Pos;
+ Word W;
+};
+
+// Declared as static globals for faster checks inside the hooks.
+static bool RecordingMemcmp = false;
+static bool RecordingMemmem = false;
+static bool DoingMyOwnMemmem = false;
+
+ScopedDoingMyOwnMemmem::ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = true; }
+ScopedDoingMyOwnMemmem::~ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = false; }
+
+class TraceState {
+public:
+ TraceState(MutationDispatcher &MD, const FuzzingOptions &Options,
+ const Fuzzer *F)
+ : MD(MD), Options(Options), F(F) {}
+
+ void TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1,
+ const uint8_t *Data2);
+
+ void TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits, uint64_t Val,
+ size_t NumCases, uint64_t *Cases);
+ int TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
+ size_t DataSize);
+ int TryToAddDesiredData(const uint8_t *PresentData,
+ const uint8_t *DesiredData, size_t DataSize);
+
+ void StartTraceRecording() {
+ if (!Options.UseMemcmp)
+ return;
+ RecordingMemcmp = Options.UseMemcmp;
+ RecordingMemmem = Options.UseMemmem;
+ NumMutations = 0;
+ InterestingWords.clear();
+ MD.ClearAutoDictionary();
+ }
+
+ void StopTraceRecording() {
+ if (!RecordingMemcmp)
+ return;
+ RecordingMemcmp = false;
+ for (size_t i = 0; i < NumMutations; i++) {
+ auto &M = Mutations[i];
+ if (Options.Verbosity >= 2) {
+ AutoDictUnitCounts[M.W]++;
+ AutoDictAdds++;
+ if ((AutoDictAdds & (AutoDictAdds - 1)) == 0) {
+ typedef std::pair<size_t, Word> CU;
+ std::vector<CU> CountedUnits;
+ for (auto &I : AutoDictUnitCounts)
+ CountedUnits.push_back(std::make_pair(I.second, I.first));
+ std::sort(CountedUnits.begin(), CountedUnits.end(),
+ [](const CU &a, const CU &b) { return a.first > b.first; });
+ Printf("AutoDict:\n");
+ for (auto &I : CountedUnits) {
+ Printf(" %zd ", I.first);
+ PrintASCII(I.second.data(), I.second.size());
+ Printf("\n");
+ }
+ }
+ }
+ MD.AddWordToAutoDictionary({M.W, M.Pos});
+ }
+ for (auto &W : InterestingWords)
+ MD.AddWordToAutoDictionary({W});
+ }
+
+ void AddMutation(uint32_t Pos, uint32_t Size, const uint8_t *Data) {
+ if (NumMutations >= kMaxMutations) return;
+ auto &M = Mutations[NumMutations++];
+ M.Pos = Pos;
+ M.W.Set(Data, Size);
+ }
+
+ void AddMutation(uint32_t Pos, uint32_t Size, uint64_t Data) {
+ assert(Size <= sizeof(Data));
+ AddMutation(Pos, Size, reinterpret_cast<uint8_t*>(&Data));
+ }
+
+ void AddInterestingWord(const uint8_t *Data, size_t Size) {
+ if (!RecordingMemmem || !F->InFuzzingThread()) return;
+ if (Size <= 1) return;
+ Size = std::min(Size, Word::GetMaxSize());
+ Word W(Data, Size);
+ InterestingWords.insert(W);
+ }
+
+ private:
+ bool IsTwoByteData(uint64_t Data) {
+ int64_t Signed = static_cast<int64_t>(Data);
+ Signed >>= 16;
+ return Signed == 0 || Signed == -1L;
+ }
+
+ // We don't want to create too many trace-based mutations as it is both
+ // expensive and useless. So after some number of mutations is collected,
+ // start rejecting some of them. The more there are mutations the more we
+ // reject.
+ bool WantToHandleOneMoreMutation() {
+ const size_t FirstN = 64;
+ // Gladly handle first N mutations.
+ if (NumMutations <= FirstN) return true;
+ size_t Diff = NumMutations - FirstN;
+ size_t DiffLog = sizeof(long) * 8 - __builtin_clzl((long)Diff);
+ assert(DiffLog > 0 && DiffLog < 64);
+ bool WantThisOne = MD.GetRand()(1 << DiffLog) == 0; // 1 out of DiffLog.
+ return WantThisOne;
+ }
+
+ static const size_t kMaxMutations = 1 << 16;
+ size_t NumMutations;
+ TraceBasedMutation Mutations[kMaxMutations];
+ // TODO: std::set is too inefficient, need to have a custom DS here.
+ std::set<Word> InterestingWords;
+ MutationDispatcher &MD;
+ const FuzzingOptions Options;
+ const Fuzzer *F;
+ std::map<Word, size_t> AutoDictUnitCounts;
+ size_t AutoDictAdds = 0;
+};
+
+int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
+ size_t DataSize) {
+ if (NumMutations >= kMaxMutations || !WantToHandleOneMoreMutation()) return 0;
+ ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem;
+ const uint8_t *UnitData;
+ auto UnitSize = F->GetCurrentUnitInFuzzingThead(&UnitData);
+ int Res = 0;
+ const uint8_t *Beg = UnitData;
+ const uint8_t *End = Beg + UnitSize;
+ for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
+ Cur = (uint8_t *)SearchMemory(Cur, End - Cur, &PresentData, DataSize);
+ if (!Cur)
+ break;
+ size_t Pos = Cur - Beg;
+ assert(Pos < UnitSize);
+ AddMutation(Pos, DataSize, DesiredData);
+ AddMutation(Pos, DataSize, DesiredData + 1);
+ AddMutation(Pos, DataSize, DesiredData - 1);
+ Res++;
+ }
+ return Res;
+}
+
+int TraceState::TryToAddDesiredData(const uint8_t *PresentData,
+ const uint8_t *DesiredData,
+ size_t DataSize) {
+ if (NumMutations >= kMaxMutations || !WantToHandleOneMoreMutation()) return 0;
+ ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem;
+ const uint8_t *UnitData;
+ auto UnitSize = F->GetCurrentUnitInFuzzingThead(&UnitData);
+ int Res = 0;
+ const uint8_t *Beg = UnitData;
+ const uint8_t *End = Beg + UnitSize;
+ for (const uint8_t *Cur = Beg; Cur < End; Cur++) {
+ Cur = (uint8_t *)SearchMemory(Cur, End - Cur, PresentData, DataSize);
+ if (!Cur)
+ break;
+ size_t Pos = Cur - Beg;
+ assert(Pos < UnitSize);
+ AddMutation(Pos, DataSize, DesiredData);
+ Res++;
+ }
+ return Res;
+}
+
+void TraceState::TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1,
+ const uint8_t *Data2) {
+ if (!RecordingMemcmp || !F->InFuzzingThread()) return;
+ CmpSize = std::min(CmpSize, Word::GetMaxSize());
+ int Added2 = TryToAddDesiredData(Data1, Data2, CmpSize);
+ int Added1 = TryToAddDesiredData(Data2, Data1, CmpSize);
+ if ((Added1 || Added2) && Options.Verbosity >= 3) {
+ Printf("MemCmp Added %d%d: ", Added1, Added2);
+ if (Added1) PrintASCII(Data1, CmpSize);
+ if (Added2) PrintASCII(Data2, CmpSize);
+ Printf("\n");
+ }
+}
+
+void TraceState::TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits,
+ uint64_t Val, size_t NumCases,
+ uint64_t *Cases) {
+ if (F->InFuzzingThread()) return;
+ size_t ValSize = ValSizeInBits / 8;
+ bool TryShort = IsTwoByteData(Val);
+ for (size_t i = 0; i < NumCases; i++)
+ TryShort &= IsTwoByteData(Cases[i]);
+
+ if (Options.Verbosity >= 3)
+ Printf("TraceSwitch: %p %zd # %zd; TryShort %d\n", PC, Val, NumCases,
+ TryShort);
+
+ for (size_t i = 0; i < NumCases; i++) {
+ TryToAddDesiredData(Val, Cases[i], ValSize);
+ if (TryShort)
+ TryToAddDesiredData(Val, Cases[i], 2);
+ }
+}
+
+static TraceState *TS;
+
+void Fuzzer::StartTraceRecording() {
+ if (!TS) return;
+ TS->StartTraceRecording();
+}
+
+void Fuzzer::StopTraceRecording() {
+ if (!TS) return;
+ TS->StopTraceRecording();
+}
+
+void Fuzzer::InitializeTraceState() {
+ if (!Options.UseMemcmp) return;
+ TS = new TraceState(MD, Options, this);
+}
+
+static size_t InternalStrnlen(const char *S, size_t MaxLen) {
+ size_t Len = 0;
+ for (; Len < MaxLen && S[Len]; Len++) {}
+ return Len;
+}
+
+} // namespace fuzzer
+
+using fuzzer::TS;
+using fuzzer::RecordingMemcmp;
+
+extern "C" {
+
+// We may need to avoid defining weak hooks to stay compatible with older clang.
+#ifndef LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
+# define LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS 1
+#endif
+
+#if LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
+void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
+ const void *s2, size_t n, int result) {
+ fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n);
+ if (!RecordingMemcmp) return;
+ if (result == 0) return; // No reason to mutate.
+ if (n <= 1) return; // Not interesting.
+ TS->TraceMemcmpCallback(n, reinterpret_cast<const uint8_t *>(s1),
+ reinterpret_cast<const uint8_t *>(s2));
+}
+
+void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
+ const char *s2, size_t n, int result) {
+ fuzzer::TPC.AddValueForStrcmp(caller_pc, s1, s2, n);
+ if (!RecordingMemcmp) 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.
+ TS->TraceMemcmpCallback(n, reinterpret_cast<const uint8_t *>(s1),
+ reinterpret_cast<const uint8_t *>(s2));
+}
+
+void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
+ const char *s2, int result) {
+ fuzzer::TPC.AddValueForStrcmp(caller_pc, s1, s2, 64);
+ if (!RecordingMemcmp) return;
+ if (result == 0) return; // No reason to mutate.
+ size_t Len1 = strlen(s1);
+ size_t Len2 = strlen(s2);
+ size_t N = std::min(Len1, Len2);
+ if (N <= 1) return; // Not interesting.
+ TS->TraceMemcmpCallback(N, reinterpret_cast<const uint8_t *>(s1),
+ reinterpret_cast<const uint8_t *>(s2));
+}
+
+void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1,
+ const char *s2, size_t n, int result) {
+ return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result);
+}
+void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1,
+ const char *s2, int result) {
+ return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result);
+}
+void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1,
+ const char *s2, char *result) {
+ TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
+}
+void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1,
+ const char *s2, char *result) {
+ TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
+}
+void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1,
+ const void *s2, size_t len2, void *result) {
+ if (fuzzer::DoingMyOwnMemmem) return;
+ TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), len2);
+}
+
+#endif // LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
+} // extern "C"
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtil.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtil.cpp
new file mode 100644
index 0000000000..f5fd3a8518
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtil.cpp
@@ -0,0 +1,218 @@
+//===- FuzzerUtil.cpp - Misc utils ----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Misc utils.
+//===----------------------------------------------------------------------===//
+
+#include "FuzzerUtil.h"
+#include "FuzzerIO.h"
+#include "FuzzerInternal.h"
+#include <cassert>
+#include <chrono>
+#include <cstring>
+#include <errno.h>
+#include <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, std::vector<Unit> *Units) {
+ if (Text.empty()) {
+ Printf("ParseDictionaryFile: file does not exist or is empty\n");
+ return false;
+ }
+ std::istringstream ISS(Text);
+ Units->clear();
+ Unit U;
+ int LineNo = 0;
+ std::string S;
+ while (std::getline(ISS, S, '\n')) {
+ LineNo++;
+ size_t Pos = 0;
+ while (Pos < S.size() && isspace(S[Pos])) Pos++; // Skip spaces.
+ if (Pos == S.size()) continue; // Empty line.
+ if (S[Pos] == '#') continue; // Comment line.
+ if (ParseOneDictionaryEntry(S, &U)) {
+ Units->push_back(U);
+ } else {
+ Printf("ParseDictionaryFile: error in line %d\n\t\t%s\n", LineNo,
+ S.c_str());
+ return false;
+ }
+ }
+ return true;
+}
+
+std::string Base64(const Unit &U) {
+ static const char Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+ std::string Res;
+ size_t i;
+ for (i = 0; i + 2 < U.size(); i += 3) {
+ uint32_t x = (U[i] << 16) + (U[i + 1] << 8) + U[i + 2];
+ Res += Table[(x >> 18) & 63];
+ Res += Table[(x >> 12) & 63];
+ Res += Table[(x >> 6) & 63];
+ Res += Table[x & 63];
+ }
+ if (i + 1 == U.size()) {
+ uint32_t x = (U[i] << 16);
+ Res += Table[(x >> 18) & 63];
+ Res += Table[(x >> 12) & 63];
+ Res += "==";
+ } else if (i + 2 == U.size()) {
+ uint32_t x = (U[i] << 16) + (U[i + 1] << 8);
+ Res += Table[(x >> 18) & 63];
+ Res += Table[(x >> 12) & 63];
+ Res += Table[(x >> 6) & 63];
+ Res += "=";
+ }
+ return Res;
+}
+
+std::string DescribePC(const char *SymbolizedFMT, uintptr_t PC) {
+ if (!EF->__sanitizer_symbolize_pc) 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);
+}
+
+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;
+}
+
+bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out) {
+ FILE *Pipe = OpenProcessPipe(Command.c_str(), "r");
+ if (!Pipe) return false;
+ char Buff[1024];
+ size_t N;
+ while ((N = fread(Buff, 1, sizeof(Buff), Pipe)) > 0)
+ Out->append(Buff, N);
+ return true;
+}
+
+} // namespace fuzzer
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtil.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtil.h
new file mode 100644
index 0000000000..08058c56e4
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtil.h
@@ -0,0 +1,72 @@
+//===- FuzzerUtil.h - Internal header for the Fuzzer Utils ------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Util functions.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_UTIL_H
+#define LLVM_FUZZER_UTIL_H
+
+#include "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);
+
+unsigned NumberOfCpuCores();
+
+bool ExecuteCommandAndReadOutput(const std::string &Command, std::string *Out);
+
+// Platform specific functions.
+void SetSignalHandler(const FuzzingOptions& Options);
+
+void SleepSeconds(int Seconds);
+
+unsigned long GetPid();
+
+size_t GetPeakRSSMb();
+
+int ExecuteCommand(const std::string &Command);
+
+FILE *OpenProcessPipe(const char *Command, const char *Mode);
+
+const void *SearchMemory(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen);
+
+std::string CloneArgsWithoutX(const std::vector<std::string> &Args,
+ const char *X1, const char *X2);
+
+inline std::string CloneArgsWithoutX(const std::vector<std::string> &Args,
+ const char *X) {
+ return CloneArgsWithoutX(Args, X, X);
+}
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_UTIL_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilDarwin.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilDarwin.cpp
new file mode 100644
index 0000000000..9674368c35
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilDarwin.cpp
@@ -0,0 +1,152 @@
+//===- FuzzerUtilDarwin.cpp - Misc utils ----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Misc utils for Darwin.
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#if LIBFUZZER_APPLE
+
+#include "FuzzerIO.h"
+#include <mutex>
+#include <signal.h>
+#include <spawn.h>
+#include <sys/wait.h>
+
+// There is no header for this on macOS so declare here
+extern "C" char **environ;
+
+namespace fuzzer {
+
+static std::mutex SignalMutex;
+// Global variables used to keep track of how signal handling should be
+// restored. They should **not** be accessed without holding `SignalMutex`.
+static int ActiveThreadCount = 0;
+static struct sigaction OldSigIntAction;
+static struct sigaction OldSigQuitAction;
+static sigset_t OldBlockedSignalsSet;
+
+// This is a reimplementation of Libc's `system()`. On Darwin the Libc
+// implementation contains a mutex which prevents it from being used
+// concurrently. This implementation **can** be used concurrently. It sets the
+// signal handlers when the first thread enters and restores them when the last
+// thread finishes execution of the function and ensures this is not racey by
+// using a mutex.
+int ExecuteCommand(const std::string &Command) {
+ 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 = Command.c_str();
+ const char *Argv[] = {"sh", "-c", CommandCStr, NULL};
+ int ErrorCode = 0, ProcessStatus = 0;
+ // FIXME: We probably shouldn't hardcode the shell path.
+ ErrorCode = posix_spawn(&Pid, "/bin/sh", NULL, &SpawnAttributes,
+ (char *const *)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);
+ }
+
+ // Restore the signal handlers of the current process when the last thread
+ // using this function finishes.
+ {
+ std::lock_guard<std::mutex> Lock(SignalMutex);
+ --ActiveThreadCount;
+ if (ActiveThreadCount == 0) {
+ bool FailedRestore = false;
+ if (sigaction(SIGINT, &OldSigIntAction, NULL) == -1) {
+ Printf("Failed to restore SIGINT handling\n");
+ FailedRestore = true;
+ }
+ if (sigaction(SIGQUIT, &OldSigQuitAction, NULL) == -1) {
+ Printf("Failed to restore SIGQUIT handling\n");
+ FailedRestore = true;
+ }
+ if (sigprocmask(SIG_BLOCK, &OldBlockedSignalsSet, NULL) == -1) {
+ Printf("Failed to unblock SIGCHLD\n");
+ FailedRestore = true;
+ }
+ if (FailedRestore)
+ ProcessStatus = -1;
+ }
+ }
+ return ProcessStatus;
+}
+
+} // namespace fuzzer
+
+#endif // LIBFUZZER_APPLE
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilLinux.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilLinux.cpp
new file mode 100644
index 0000000000..dfe7e6f4e1
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilLinux.cpp
@@ -0,0 +1,24 @@
+//===- FuzzerUtilLinux.cpp - Misc utils for Linux. ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Misc utils for Linux.
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#if LIBFUZZER_LINUX
+
+#include <stdlib.h>
+
+namespace fuzzer {
+
+int ExecuteCommand(const std::string &Command) {
+ return system(Command.c_str());
+}
+
+} // namespace fuzzer
+
+#endif // LIBFUZZER_LINUX
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilPosix.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilPosix.cpp
new file mode 100644
index 0000000000..8b484b8eff
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilPosix.cpp
@@ -0,0 +1,117 @@
+//===- FuzzerUtilPosix.cpp - Misc utils for Posix. ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Misc utils implementation using Posix API.
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#if LIBFUZZER_POSIX
+#include "FuzzerIO.h"
+#include "FuzzerInternal.h"
+#include <cassert>
+#include <chrono>
+#include <cstring>
+#include <errno.h>
+#include <iomanip>
+#include <signal.h>
+#include <sstream>
+#include <stdio.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <thread>
+#include <unistd.h>
+
+namespace fuzzer {
+
+static void AlarmHandler(int, siginfo_t *, void *) {
+ Fuzzer::StaticAlarmCallback();
+}
+
+static void CrashHandler(int, siginfo_t *, void *) {
+ Fuzzer::StaticCrashSignalCallback();
+}
+
+static void InterruptHandler(int, siginfo_t *, void *) {
+ Fuzzer::StaticInterruptCallback();
+}
+
+static void SetSigaction(int signum,
+ void (*callback)(int, siginfo_t *, void *)) {
+ struct sigaction sigact;
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_sigaction = callback;
+ if (sigaction(signum, &sigact, 0)) {
+ Printf("libFuzzer: sigaction failed with %d\n", errno);
+ exit(1);
+ }
+}
+
+void SetTimer(int Seconds) {
+ struct itimerval T {
+ {Seconds, 0}, { Seconds, 0 }
+ };
+ if (setitimer(ITIMER_REAL, &T, nullptr)) {
+ Printf("libFuzzer: setitimer failed with %d\n", errno);
+ exit(1);
+ }
+ SetSigaction(SIGALRM, AlarmHandler);
+}
+
+void SetSignalHandler(const FuzzingOptions& Options) {
+ if (Options.UnitTimeoutSec > 0)
+ SetTimer(Options.UnitTimeoutSec / 2 + 1);
+ if (Options.HandleInt)
+ SetSigaction(SIGINT, InterruptHandler);
+ if (Options.HandleTerm)
+ SetSigaction(SIGTERM, InterruptHandler);
+ if (Options.HandleSegv)
+ SetSigaction(SIGSEGV, CrashHandler);
+ if (Options.HandleBus)
+ SetSigaction(SIGBUS, CrashHandler);
+ if (Options.HandleAbrt)
+ SetSigaction(SIGABRT, CrashHandler);
+ if (Options.HandleIll)
+ SetSigaction(SIGILL, CrashHandler);
+ if (Options.HandleFpe)
+ SetSigaction(SIGFPE, CrashHandler);
+}
+
+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) {
+ // ru_maxrss is in KiB
+ return usage.ru_maxrss >> 10;
+ } else if (LIBFUZZER_APPLE) {
+ // ru_maxrss is in bytes
+ return usage.ru_maxrss >> 20;
+ }
+ assert(0 && "GetPeakRSSMb() is not implemented for your platform");
+ return 0;
+}
+
+FILE *OpenProcessPipe(const char *Command, const char *Mode) {
+ return popen(Command, Mode);
+}
+
+const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
+ size_t PattLen) {
+ return memmem(Data, DataLen, Patt, PattLen);
+}
+
+} // namespace fuzzer
+
+#endif // LIBFUZZER_POSIX
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilWindows.cpp b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilWindows.cpp
new file mode 100644
index 0000000000..64adb7cd13
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerUtilWindows.cpp
@@ -0,0 +1,182 @@
+//===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Misc utils implementation for Windows.
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#if LIBFUZZER_WINDOWS
+#include "FuzzerIO.h"
+#include "FuzzerInternal.h"
+#include <cassert>
+#include <chrono>
+#include <cstring>
+#include <errno.h>
+#include <iomanip>
+#include <signal.h>
+#include <sstream>
+#include <stdio.h>
+#include <sys/types.h>
+#include <windows.h>
+#include <Psapi.h>
+
+namespace fuzzer {
+
+static const FuzzingOptions* HandlerOpt = nullptr;
+
+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;
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+BOOL WINAPI CtrlHandler(DWORD dwCtrlType) {
+ switch (dwCtrlType) {
+ case CTRL_C_EVENT:
+ if (HandlerOpt->HandleInt)
+ Fuzzer::StaticInterruptCallback();
+ return TRUE;
+ case CTRL_BREAK_EVENT:
+ if (HandlerOpt->HandleTerm)
+ Fuzzer::StaticInterruptCallback();
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void CALLBACK AlarmHandler(PVOID, BOOLEAN) {
+ Fuzzer::StaticAlarmCallback();
+}
+
+class TimerQ {
+ HANDLE TimerQueue;
+ public:
+ TimerQ() : TimerQueue(NULL) {};
+ ~TimerQ() {
+ if (TimerQueue)
+ DeleteTimerQueueEx(TimerQueue, NULL);
+ };
+ void SetTimer(int Seconds) {
+ if (!TimerQueue) {
+ TimerQueue = CreateTimerQueue();
+ if (!TimerQueue) {
+ Printf("libFuzzer: CreateTimerQueue failed.\n");
+ exit(1);
+ }
+ }
+ HANDLE Timer;
+ if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL,
+ Seconds*1000, Seconds*1000, 0)) {
+ Printf("libFuzzer: CreateTimerQueueTimer failed.\n");
+ exit(1);
+ }
+ };
+};
+
+static TimerQ Timer;
+
+static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); }
+
+void SetSignalHandler(const FuzzingOptions& Options) {
+ HandlerOpt = &Options;
+
+ if (Options.UnitTimeoutSec > 0)
+ Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1);
+
+ if (Options.HandleInt || Options.HandleTerm)
+ if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
+ DWORD LastError = GetLastError();
+ Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n",
+ LastError);
+ exit(1);
+ }
+
+ if (Options.HandleSegv || Options.HandleBus || Options.HandleIll ||
+ Options.HandleFpe)
+ if (!AddVectoredExceptionHandler(1, ExceptionHandler)) {
+ Printf("libFuzzer: AddVectoredExceptionHandler failed.\n");
+ exit(1);
+ }
+
+ if (Options.HandleAbrt)
+ if (SIG_ERR == signal(SIGABRT, CrashHandler)) {
+ Printf("libFuzzer: signal failed with %d\n", errno);
+ exit(1);
+ }
+}
+
+void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); }
+
+unsigned long GetPid() { return GetCurrentProcessId(); }
+
+size_t GetPeakRSSMb() {
+ PROCESS_MEMORY_COUNTERS info;
+ if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info)))
+ return 0;
+ return info.PeakWorkingSetSize >> 20;
+}
+
+FILE *OpenProcessPipe(const char *Command, const char *Mode) {
+ return _popen(Command, Mode);
+}
+
+int ExecuteCommand(const std::string &Command) {
+ return system(Command.c_str());
+}
+
+const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt,
+ size_t PattLen) {
+ // TODO: make this implementation more efficient.
+ const char *Cdata = (const char *)Data;
+ const char *Cpatt = (const char *)Patt;
+
+ if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen)
+ return NULL;
+
+ if (PattLen == 1)
+ return memchr(Data, *Cpatt, DataLen);
+
+ const char *End = Cdata + DataLen - PattLen + 1;
+
+ for (const char *It = Cdata; It < End; ++It)
+ if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0)
+ return It;
+
+ return NULL;
+}
+
+} // namespace fuzzer
+
+#endif // LIBFUZZER_WINDOWS
diff --git a/json4cpp/tests/thirdparty/Fuzzer/FuzzerValueBitMap.h b/json4cpp/tests/thirdparty/Fuzzer/FuzzerValueBitMap.h
new file mode 100644
index 0000000000..0692acd13e
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/FuzzerValueBitMap.h
@@ -0,0 +1,87 @@
+//===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// ValueBitMap.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_VALUE_BIT_MAP_H
+#define LLVM_FUZZER_VALUE_BIT_MAP_H
+
+#include "FuzzerDefs.h"
+
+namespace fuzzer {
+
+// A bit map containing kMapSizeInWords bits.
+struct ValueBitMap {
+ static const size_t kMapSizeInBits = 65371; // Prime.
+ static const size_t kMapSizeInBitsAligned = 65536; // 2^16
+ static const size_t kBitsInWord = (sizeof(uintptr_t) * 8);
+ static const size_t kMapSizeInWords = kMapSizeInBitsAligned / kBitsInWord;
+ public:
+ static const size_t kNumberOfItems = kMapSizeInBits;
+ // 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.
+ inline bool AddValue(uintptr_t Value) {
+ uintptr_t Idx = Value < kMapSizeInBits ? Value : Value % kMapSizeInBits;
+ uintptr_t WordIdx = Idx / kBitsInWord;
+ uintptr_t BitIdx = Idx % kBitsInWord;
+ uintptr_t Old = Map[WordIdx];
+ uintptr_t New = Old | (1UL << BitIdx);
+ Map[WordIdx] = New;
+ return New != Old;
+ }
+
+ inline bool Get(uintptr_t Idx) {
+ assert(Idx < kMapSizeInBits);
+ uintptr_t WordIdx = Idx / kBitsInWord;
+ uintptr_t BitIdx = Idx % kBitsInWord;
+ return Map[WordIdx] & (1UL << BitIdx);
+ }
+
+ size_t GetNumBitsSinceLastMerge() const { return NumBits; }
+
+ // Merges 'Other' into 'this', clears 'Other', updates NumBits,
+ // returns true if new bits were added.
+ ATTRIBUTE_TARGET_POPCNT
+ bool MergeFrom(ValueBitMap &Other) {
+ uintptr_t Res = 0;
+ size_t OldNumBits = NumBits;
+ for (size_t i = 0; i < kMapSizeInWords; i++) {
+ auto O = Other.Map[i];
+ auto M = Map[i];
+ if (O) {
+ Map[i] = (M |= O);
+ Other.Map[i] = 0;
+ }
+ if (M)
+ Res += __builtin_popcountl(M);
+ }
+ NumBits = Res;
+ return OldNumBits < NumBits;
+ }
+
+ template <class Callback>
+ void ForEach(Callback CB) {
+ 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:
+ size_t NumBits = 0;
+ uintptr_t Map[kMapSizeInWords] __attribute__((aligned(512)));
+};
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_VALUE_BIT_MAP_H
diff --git a/json4cpp/tests/thirdparty/Fuzzer/README.txt b/json4cpp/tests/thirdparty/Fuzzer/README.txt
new file mode 100644
index 0000000000..79f49b5509
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/README.txt
@@ -0,0 +1,2 @@
+Move to http://llvm.org/docs/LibFuzzer.html
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/afl/afl_driver.cpp b/json4cpp/tests/thirdparty/Fuzzer/afl/afl_driver.cpp
new file mode 100644
index 0000000000..57ee56109d
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/afl/afl_driver.cpp
@@ -0,0 +1,295 @@
+//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===//
+
+/* This file allows to fuzz libFuzzer-style target functions
+ (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode.
+
+Usage:
+################################################################################
+cat << EOF > test_fuzzer.cc
+#include <stdint.h>
+#include <stddef.h>
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size > 0 && data[0] == 'H')
+ if (size > 1 && data[1] == 'I')
+ if (size > 2 && data[2] == '!')
+ __builtin_trap();
+ return 0;
+}
+EOF
+# Build your target with -fsanitize-coverage=trace-pc using fresh clang.
+clang -g -fsanitize-coverage=trace-pc test_fuzzer.cc -c
+# Build afl-llvm-rt.o.c from the AFL distribution.
+clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c
+# Build this file, link it with afl-llvm-rt.o.o and the target code.
+clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o
+# Run AFL:
+rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
+$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
+################################################################################
+Environment Variables:
+There are a few environment variables that can be set to use features that
+afl-fuzz doesn't have.
+
+AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file
+specified. If the file does not exist, it is created. This is useful for getting
+stack traces (when using ASAN for example) or original error messages on hard to
+reproduce bugs.
+
+AFL_DRIVER_EXTRA_STATS_FILENAME: Setting this causes afl_driver to write extra
+statistics to the file specified. Currently these are peak_rss_mb
+(the peak amount of virtual memory used in MB) and slowest_unit_time_secs. If
+the file does not exist it is created. If the file does exist then
+afl_driver assumes it was restarted by afl-fuzz and will try to read old
+statistics from the file. If that fails then the process will quit.
+
+*/
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+// Platform detection. Copied from FuzzerInternal.h
+#ifdef __linux__
+#define LIBFUZZER_LINUX 1
+#define LIBFUZZER_APPLE 0
+#elif __APPLE__
+#define LIBFUZZER_LINUX 0
+#define LIBFUZZER_APPLE 1
+#else
+#error "Support for your platform has not been implemented"
+#endif
+
+// Used to avoid repeating error checking boilerplate. If cond is false, a
+// fatal error has occurred in the program. In this event print error_message
+// to stderr and abort(). Otherwise do nothing. Note that setting
+// AFL_DRIVER_STDERR_DUPLICATE_FILENAME may cause error_message to be appended
+// to the file as well, if the error occurs after the duplication is performed.
+#define CHECK_ERROR(cond, error_message) \
+ if (!(cond)) { \
+ fprintf(stderr, (error_message)); \
+ abort(); \
+ }
+
+// libFuzzer interface is thin, so we don't include any libFuzzer headers.
+extern "C" {
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
+__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
+}
+
+// Notify AFL about persistent mode.
+static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
+extern "C" int __afl_persistent_loop(unsigned int);
+static volatile char suppress_warning2 = AFL_PERSISTENT[0];
+
+// Notify AFL about deferred forkserver.
+static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
+extern "C" void __afl_manual_init();
+static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0];
+
+// Input buffer.
+static const size_t kMaxAflInputSize = 1 << 20;
+static uint8_t AflInputBuf[kMaxAflInputSize];
+
+// Variables we need for writing to the extra stats file.
+static FILE *extra_stats_file = NULL;
+static uint32_t previous_peak_rss = 0;
+static time_t slowest_unit_time_secs = 0;
+static const int kNumExtraStats = 2;
+static const char *kExtraStatsFormatString = "peak_rss_mb : %u\n"
+ "slowest_unit_time_sec : %u\n";
+
+// Copied from FuzzerUtil.cpp.
+size_t GetPeakRSSMb() {
+ struct rusage usage;
+ if (getrusage(RUSAGE_SELF, &usage))
+ return 0;
+ if (LIBFUZZER_LINUX) {
+ // ru_maxrss is in KiB
+ return usage.ru_maxrss >> 10;
+ } else if (LIBFUZZER_APPLE) {
+ // ru_maxrss is in bytes
+ return usage.ru_maxrss >> 20;
+ }
+ assert(0 && "GetPeakRSSMb() is not implemented for your platform");
+ return 0;
+}
+
+// Based on SetSigaction in FuzzerUtil.cpp
+static void SetSigaction(int signum,
+ void (*callback)(int, siginfo_t *, void *)) {
+ struct sigaction sigact;
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_sigaction = callback;
+ if (sigaction(signum, &sigact, 0)) {
+ fprintf(stderr, "libFuzzer: sigaction failed with %d\n", errno);
+ exit(1);
+ }
+}
+
+// Write extra stats to the file specified by the user. If none is specified
+// this function will never be called.
+static void write_extra_stats() {
+ uint32_t peak_rss = GetPeakRSSMb();
+
+ if (peak_rss < previous_peak_rss)
+ peak_rss = previous_peak_rss;
+
+ int chars_printed = fprintf(extra_stats_file, kExtraStatsFormatString,
+ peak_rss, slowest_unit_time_secs);
+
+ CHECK_ERROR(chars_printed != 0, "Failed to write extra_stats_file");
+
+ CHECK_ERROR(fclose(extra_stats_file) == 0,
+ "Failed to close extra_stats_file");
+}
+
+// Call write_extra_stats before we exit.
+static void crash_handler(int, siginfo_t *, void *) {
+ // Make sure we don't try calling write_extra_stats again if we crashed while
+ // trying to call it.
+ static bool first_crash = true;
+ CHECK_ERROR(first_crash,
+ "Crashed in crash signal handler. This is a bug in the fuzzer.");
+
+ first_crash = false;
+ write_extra_stats();
+}
+
+// If the user has specified an extra_stats_file through the environment
+// variable AFL_DRIVER_EXTRA_STATS_FILENAME, then perform necessary set up
+// to write stats to it on exit. If no file is specified, do nothing. Otherwise
+// install signal and exit handlers to write to the file when the process exits.
+// Then if the file doesn't exist create it and set extra stats to 0. But if it
+// does exist then read the initial values of the extra stats from the file
+// and check that the file is writable.
+static void maybe_initialize_extra_stats() {
+ // If AFL_DRIVER_EXTRA_STATS_FILENAME isn't set then we have nothing to do.
+ char *extra_stats_filename = getenv("AFL_DRIVER_EXTRA_STATS_FILENAME");
+ if (!extra_stats_filename)
+ return;
+
+ // Open the file and find the previous peak_rss_mb value.
+ // This is necessary because the fuzzing process is restarted after N
+ // iterations are completed. So we may need to get this value from a previous
+ // process to be accurate.
+ extra_stats_file = fopen(extra_stats_filename, "r");
+
+ // If extra_stats_file already exists: read old stats from it.
+ if (extra_stats_file) {
+ int matches = fscanf(extra_stats_file, kExtraStatsFormatString,
+ &previous_peak_rss, &slowest_unit_time_secs);
+
+ // Make sure we have read a real extra stats file and that we have used it
+ // to set slowest_unit_time_secs and previous_peak_rss.
+ CHECK_ERROR(matches == kNumExtraStats, "Extra stats file is corrupt");
+
+ CHECK_ERROR(fclose(extra_stats_file) == 0, "Failed to close file");
+
+ // Now open the file for writing.
+ extra_stats_file = fopen(extra_stats_filename, "w");
+ CHECK_ERROR(extra_stats_file,
+ "Failed to open extra stats file for writing");
+ } else {
+ // Looks like this is the first time in a fuzzing job this is being called.
+ extra_stats_file = fopen(extra_stats_filename, "w+");
+ CHECK_ERROR(extra_stats_file, "failed to create extra stats file");
+ }
+
+ // Make sure that crash_handler gets called on any kind of fatal error.
+ int crash_signals[] = {SIGSEGV, SIGBUS, SIGABRT, SIGILL, SIGFPE, SIGINT,
+ SIGTERM};
+
+ const size_t num_signals = sizeof(crash_signals) / sizeof(crash_signals[0]);
+
+ for (size_t idx = 0; idx < num_signals; idx++)
+ SetSigaction(crash_signals[idx], crash_handler);
+
+ // Make sure it gets called on other kinds of exits.
+ atexit(write_extra_stats);
+}
+
+// If the user asks us to duplicate stderr, then do it.
+static void maybe_duplicate_stderr() {
+ char* stderr_duplicate_filename =
+ getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
+
+ if (!stderr_duplicate_filename)
+ return;
+
+ FILE* stderr_duplicate_stream =
+ freopen(stderr_duplicate_filename, "a+", stderr);
+
+ if (!stderr_duplicate_stream) {
+ fprintf(
+ stderr,
+ "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
+ abort();
+ }
+}
+
+int main(int argc, char **argv) {
+ fprintf(stderr, "======================= INFO =========================\n"
+ "This binary is built for AFL-fuzz.\n"
+ "To run the target function on a single input execute this:\n"
+ " %s < INPUT_FILE\n"
+ "To run the fuzzing execute this:\n"
+ " afl-fuzz [afl-flags] %s [N] "
+ "-- run N fuzzing iterations before "
+ "re-spawning the process (default: 1000)\n"
+ "======================================================\n",
+ argv[0], argv[0]);
+ if (LLVMFuzzerInitialize)
+ LLVMFuzzerInitialize(&argc, &argv);
+ // Do any other expensive one-time initialization here.
+
+ maybe_duplicate_stderr();
+ maybe_initialize_extra_stats();
+
+ __afl_manual_init();
+
+ int N = 1000;
+ if (argc >= 2)
+ N = atoi(argv[1]);
+ assert(N > 0);
+ time_t unit_time_secs;
+ int num_runs = 0;
+ while (__afl_persistent_loop(N)) {
+ ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize);
+ if (n_read > 0) {
+ // Copy AflInputBuf into a separate buffer to let asan find buffer
+ // overflows. Don't use unique_ptr/etc to avoid extra dependencies.
+ uint8_t *copy = new uint8_t[n_read];
+ memcpy(copy, AflInputBuf, n_read);
+
+ struct timeval unit_start_time;
+ CHECK_ERROR(gettimeofday(&unit_start_time, NULL) == 0,
+ "Calling gettimeofday failed");
+
+ num_runs++;
+ LLVMFuzzerTestOneInput(copy, n_read);
+
+ struct timeval unit_stop_time;
+ CHECK_ERROR(gettimeofday(&unit_stop_time, NULL) == 0,
+ "Calling gettimeofday failed");
+
+ // Update slowest_unit_time_secs if we see a new max.
+ unit_time_secs = unit_stop_time.tv_sec - unit_start_time.tv_sec;
+ if (slowest_unit_time_secs < unit_time_secs)
+ slowest_unit_time_secs = unit_time_secs;
+
+ delete[] copy;
+ }
+ }
+ fprintf(stderr, "%s: successfully executed %d input(s)\n", argv[0], num_runs);
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/build.sh b/json4cpp/tests/thirdparty/Fuzzer/build.sh
new file mode 100755
index 0000000000..27c148ad43
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/build.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+LIBFUZZER_SRC_DIR=$(dirname $0)
+for f in $LIBFUZZER_SRC_DIR/*.cpp; do
+ clang -g -O2 -fno-omit-frame-pointer -std=c++11 $f -c &
+done
+wait
+rm -f libFuzzer.a
+ar ru libFuzzer.a Fuzzer*.o
+rm -f Fuzzer*.o
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/cxx.dict b/json4cpp/tests/thirdparty/Fuzzer/cxx.dict
new file mode 100644
index 0000000000..41350f4755
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/cxx.dict
@@ -0,0 +1,122 @@
+"++"
+"--"
+"<<"
+">>"
+"+="
+"-="
+"*="
+"/="
+">>="
+"<<="
+"&="
+"|="
+"^="
+"%="
+"!="
+"&&"
+"||"
+"=="
+">="
+"<="
+"->"
+"alignas"
+"alignof"
+"and"
+"and_eq"
+"asm"
+"auto"
+"bitand"
+"bitor"
+"bool"
+"break"
+"case"
+"catch"
+"char"
+"char16_t"
+"char32_t"
+"class"
+"compl"
+"concept"
+"const"
+"constexpr"
+"const_cast"
+"continue"
+"decltype"
+"default"
+"delete"
+"do"
+"double"
+"dynamic_cast"
+"else"
+"enum"
+"explicit"
+"export"
+"extern"
+"false"
+"float"
+"for"
+"friend"
+"goto"
+"if"
+"inline"
+"int"
+"long"
+"mutable"
+"namespace"
+"new"
+"noexcept"
+"not"
+"not_eq"
+"nullptr"
+"operator"
+"or"
+"or_eq"
+"private"
+"protected"
+"public"
+"register"
+"reinterpret_cast"
+"requires"
+"return"
+"short"
+"signed"
+"sizeof"
+"static"
+"static_assert"
+"static_cast"
+"struct"
+"switch"
+"template"
+"this"
+"thread_local"
+"throw"
+"true"
+"try"
+"typedef"
+"typeid"
+"typename"
+"union"
+"unsigned"
+"using"
+"virtual"
+"void"
+"volatile"
+"wchar_t"
+"while"
+"xor"
+"xor_eq"
+"if"
+"elif"
+"else"
+"endif"
+"defined"
+"ifdef"
+"ifndef"
+"define"
+"undef"
+"include"
+"line"
+"error"
+"pragma"
+"override"
+"final"
diff --git a/json4cpp/tests/thirdparty/Fuzzer/standalone/StandaloneFuzzTargetMain.c b/json4cpp/tests/thirdparty/Fuzzer/standalone/StandaloneFuzzTargetMain.c
new file mode 100644
index 0000000000..0d76ea49e7
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/standalone/StandaloneFuzzTargetMain.c
@@ -0,0 +1,41 @@
+/*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This main() function can be linked to a fuzz target (i.e. a library
+// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize())
+// instead of libFuzzer. This main() function will not perform any fuzzing
+// but will simply feed all input files one by one to the fuzz target.
+//
+// Use this file to provide reproducers for bugs when linking against libFuzzer
+// or other fuzzing engine is undesirable.
+//===----------------------------------------------------------------------===*/
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
+__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv);
+int main(int argc, char **argv) {
+ fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
+ if (LLVMFuzzerInitialize)
+ LLVMFuzzerInitialize(&argc, &argv);
+ for (int i = 1; i < argc; i++) {
+ fprintf(stderr, "Running: %s\n", argv[i]);
+ FILE *f = fopen(argv[i], "r");
+ assert(f);
+ fseek(f, 0, SEEK_END);
+ size_t len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ unsigned char *buf = (unsigned char*)malloc(len);
+ size_t n_read = fread(buf, 1, len, f);
+ assert(n_read == len);
+ LLVMFuzzerTestOneInput(buf, len);
+ free(buf);
+ fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
+ }
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/AFLDriverTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/AFLDriverTest.cpp
new file mode 100644
index 0000000000..3dd0b61173
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/AFLDriverTest.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Contains dummy functions used to avoid dependency on AFL.
+#include <stdint.h>
+#include <stdlib.h>
+
+extern "C" void __afl_manual_init() {}
+
+extern "C" int __afl_persistent_loop(unsigned int) {
+ return 0;
+}
+
+// This declaration exists to prevent the Darwin linker
+// from complaining about this being a missing weak symbol.
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/AbsNegAndConstant64Test.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/AbsNegAndConstant64Test.cpp
new file mode 100644
index 0000000000..577481431a
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/AbsNegAndConstant64Test.cpp
@@ -0,0 +1,23 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// abs(x) < 0 and y == Const puzzle, 64-bit variant.
+#include <cstring>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <cstdio>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 16) return 0;
+ int64_t x;
+ uint64_t y;
+ memcpy(&x, Data, sizeof(x));
+ memcpy(&y, Data + sizeof(x), sizeof(y));
+ if (labs(x) < 0 && y == 0xbaddcafedeadbeefUL) {
+ printf("BINGO; Found the target, exiting; x = 0x%lx y 0x%lx\n", x, y);
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/AbsNegAndConstantTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/AbsNegAndConstantTest.cpp
new file mode 100644
index 0000000000..69075a454c
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/AbsNegAndConstantTest.cpp
@@ -0,0 +1,23 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// abs(x) < 0 and y == Const puzzle.
+#include <cstring>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <cstdio>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 8) return 0;
+ int x;
+ unsigned y;
+ memcpy(&x, Data, sizeof(x));
+ memcpy(&y, Data + sizeof(x), sizeof(y));
+ if (abs(x) < 0 && y == 0xbaddcafe) {
+ printf("BINGO; Found the target, exiting; x = 0x%x y 0x%x\n", x, y);
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/AccumulateAllocationsTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/AccumulateAllocationsTest.cpp
new file mode 100644
index 0000000000..604d8fa299
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/AccumulateAllocationsTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test with a more mallocs than frees, but no leak.
+#include <cstdint>
+#include <cstddef>
+
+const int kAllocatedPointersSize = 10000;
+int NumAllocatedPointers = 0;
+int *AllocatedPointers[kAllocatedPointersSize];
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (NumAllocatedPointers < kAllocatedPointersSize)
+ AllocatedPointers[NumAllocatedPointers++] = new int;
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/BufferOverflowOnInput.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/BufferOverflowOnInput.cpp
new file mode 100644
index 0000000000..b9d14052ae
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/BufferOverflowOnInput.cpp
@@ -0,0 +1,23 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+static volatile bool SeedLargeBuffer;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ if (Size >= 4)
+ SeedLargeBuffer = true;
+ if (Size == 3 && SeedLargeBuffer && Data[3]) {
+ std::cout << "Woops, reading Data[3] w/o crashing\n";
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/CMakeLists.txt b/json4cpp/tests/thirdparty/Fuzzer/test/CMakeLists.txt
new file mode 100644
index 0000000000..c0457746a0
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/CMakeLists.txt
@@ -0,0 +1,217 @@
+# Build all these tests with -O0, otherwise optimizations may merge some
+# basic blocks and we'll fail to discover the targets.
+# We change the flags for every build type because we might be doing
+# a multi-configuration build (e.g. Xcode) where CMAKE_BUILD_TYPE doesn't
+# mean anything.
+set(variables_to_filter
+ CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_CXX_FLAGS_DEBUG
+ CMAKE_CXX_FLAGS_RELWITHDEBINFO
+ CMAKE_CXX_FLAGS_MINSIZEREL
+ LIBFUZZER_FLAGS_BASE
+ )
+foreach (VARNAME ${variables_to_filter})
+ string(REPLACE " " ";" BUILD_FLAGS_AS_LIST "${${VARNAME}}")
+ set(new_flags "")
+ foreach (flag ${BUILD_FLAGS_AS_LIST})
+ # NOTE: Use of XX here is to avoid a CMake warning due to CMP0054
+ if (NOT ("XX${flag}" MATCHES "XX-O[0123s]"))
+ set(new_flags "${new_flags} ${flag}")
+ else()
+ set(new_flags "${new_flags} -O0")
+ endif()
+ endforeach()
+ set(${VARNAME} "${new_flags}")
+endforeach()
+
+# Enable the coverage instrumentation (it is disabled for the Fuzzer lib).
+set(CMAKE_CXX_FLAGS "${LIBFUZZER_FLAGS_BASE} -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp,trace-div,trace-gep -g")
+
+# add_libfuzzer_test(<name>
+# SOURCES source0.cpp [source1.cpp ...]
+# )
+#
+# Declares a LibFuzzer test executable with target name LLVMFuzzer-<name>.
+#
+# One or more source files to be compiled into the binary must be declared
+# after the SOURCES keyword.
+function(add_libfuzzer_test name)
+ set(multi_arg_options "SOURCES")
+ cmake_parse_arguments(
+ "add_libfuzzer_test" "" "" "${multi_arg_options}" ${ARGN})
+ if ("${add_libfuzzer_test_SOURCES}" STREQUAL "")
+ message(FATAL_ERROR "Source files must be specified")
+ endif()
+ add_executable(LLVMFuzzer-${name}
+ ${add_libfuzzer_test_SOURCES}
+ )
+ target_link_libraries(LLVMFuzzer-${name} LLVMFuzzer)
+ # Place binary where llvm-lit expects to find it
+ set_target_properties(LLVMFuzzer-${name}
+ PROPERTIES RUNTIME_OUTPUT_DIRECTORY
+ "${CMAKE_BINARY_DIR}/lib/Fuzzer/test"
+ )
+ set(TestBinaries ${TestBinaries} LLVMFuzzer-${name} PARENT_SCOPE)
+endfunction()
+
+# Variable to keep track of all test targets
+set(TestBinaries)
+
+###############################################################################
+# Basic tests
+###############################################################################
+
+set(Tests
+ AbsNegAndConstantTest
+ AbsNegAndConstant64Test
+ AccumulateAllocationsTest
+ BufferOverflowOnInput
+ CallerCalleeTest
+ CounterTest
+ CustomCrossOverTest
+ CustomMutatorTest
+ DivTest
+ EmptyTest
+ FourIndependentBranchesTest
+ FullCoverageSetTest
+ InitializeTest
+ MemcmpTest
+ LeakTest
+ LeakTimeoutTest
+ LoadTest
+ NullDerefTest
+ NullDerefOnEmptyTest
+ NthRunCrashTest
+ OneHugeAllocTest
+ OutOfMemoryTest
+ OutOfMemorySingleLargeMallocTest
+ RepeatedMemcmp
+ RepeatedBytesTest
+ SimpleCmpTest
+ SimpleDictionaryTest
+ SimpleHashTest
+ SimpleTest
+ SimpleThreadedTest
+ SingleMemcmpTest
+ SingleStrcmpTest
+ SingleStrncmpTest
+ SpamyTest
+ ShrinkControlFlowTest
+ ShrinkValueProfileTest
+ StrcmpTest
+ StrncmpOOBTest
+ StrncmpTest
+ StrstrTest
+ SwapCmpTest
+ SwitchTest
+ Switch2Test
+ ThreadedLeakTest
+ ThreadedTest
+ TimeoutTest
+ TimeoutEmptyTest
+ TraceMallocTest
+ )
+
+if(APPLE)
+ # LeakSanitizer is not supported on OSX right now
+ set(HAS_LSAN 0)
+ message(WARNING "LeakSanitizer is not supported on Apple platforms."
+ " Building and running LibFuzzer LeakSanitizer tests is disabled."
+ )
+else()
+ set(HAS_LSAN 1)
+endif()
+
+foreach(Test ${Tests})
+ add_libfuzzer_test(${Test} SOURCES ${Test}.cpp)
+endforeach()
+
+
+###############################################################################
+# Unit tests
+###############################################################################
+
+add_executable(LLVMFuzzer-Unittest
+ FuzzerUnittest.cpp
+ )
+
+add_executable(LLVMFuzzer-StandaloneInitializeTest
+ InitializeTest.cpp
+ ../standalone/StandaloneFuzzTargetMain.c
+ )
+
+target_link_libraries(LLVMFuzzer-Unittest
+ gtest
+ gtest_main
+ LLVMFuzzerNoMain
+ )
+
+target_include_directories(LLVMFuzzer-Unittest PRIVATE
+ "${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include"
+ )
+
+set(TestBinaries ${TestBinaries} LLVMFuzzer-Unittest)
+set_target_properties(LLVMFuzzer-Unittest
+ PROPERTIES RUNTIME_OUTPUT_DIRECTORY
+ "${CMAKE_CURRENT_BINARY_DIR}"
+)
+
+set(TestBinaries ${TestBinaries} LLVMFuzzer-StandaloneInitializeTest)
+set_target_properties(LLVMFuzzer-StandaloneInitializeTest
+ PROPERTIES RUNTIME_OUTPUT_DIRECTORY
+ "${CMAKE_CURRENT_BINARY_DIR}"
+)
+
+###############################################################################
+# Additional tests
+###############################################################################
+
+include_directories(..)
+
+# add_subdirectory(uninstrumented)
+add_subdirectory(no-coverage)
+add_subdirectory(ubsan)
+
+add_library(LLVMFuzzer-DSO1 SHARED DSO1.cpp)
+add_library(LLVMFuzzer-DSO2 SHARED DSO2.cpp)
+
+add_executable(LLVMFuzzer-DSOTest
+ DSOTestMain.cpp
+ DSOTestExtra.cpp)
+
+target_link_libraries(LLVMFuzzer-DSOTest
+ LLVMFuzzer-DSO1
+ LLVMFuzzer-DSO2
+ LLVMFuzzer
+ )
+
+set_target_properties(LLVMFuzzer-DSOTest PROPERTIES RUNTIME_OUTPUT_DIRECTORY
+ "${CMAKE_BINARY_DIR}/lib/Fuzzer/test")
+set_target_properties(LLVMFuzzer-DSO1 PROPERTIES LIBRARY_OUTPUT_DIRECTORY
+ "${CMAKE_BINARY_DIR}/lib/Fuzzer/lib")
+set_target_properties(LLVMFuzzer-DSO2 PROPERTIES LIBRARY_OUTPUT_DIRECTORY
+ "${CMAKE_BINARY_DIR}/lib/Fuzzer/lib")
+
+set(TestBinaries ${TestBinaries} LLVMFuzzer-DSOTest)
+
+###############################################################################
+# Configure lit to run the tests
+#
+# Note this is done after declaring all tests so we can inform lit if any tests
+# need to be disabled.
+###############################################################################
+
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
+ )
+
+configure_lit_site_cfg(
+ ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.in
+ ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg
+ )
+
+add_lit_testsuite(check-fuzzer "Running Fuzzer tests"
+ ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS ${TestBinaries} FileCheck not
+ )
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/CallerCalleeTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/CallerCalleeTest.cpp
new file mode 100644
index 0000000000..3ec025d023
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/CallerCalleeTest.cpp
@@ -0,0 +1,59 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer.
+// Try to find the target using the indirect caller-callee pairs.
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
+
+typedef void (*F)();
+static F t[256];
+
+void f34() {
+ std::cerr << "BINGO\n";
+ exit(1);
+}
+void f23() { t[(unsigned)'d'] = f34;}
+void f12() { t[(unsigned)'c'] = f23;}
+void f01() { t[(unsigned)'b'] = f12;}
+void f00() {}
+
+static F t0[256] = {
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+ f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00, f00,
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 4) return 0;
+ // Spoof the counters.
+ for (int i = 0; i < 200; i++) {
+ f23();
+ f12();
+ f01();
+ }
+ memcpy(t, t0, sizeof(t));
+ t[(unsigned)'a'] = f01;
+ t[Data[0]]();
+ t[Data[1]]();
+ t[Data[2]]();
+ t[Data[3]]();
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/CounterTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/CounterTest.cpp
new file mode 100644
index 0000000000..4917934c62
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/CounterTest.cpp
@@ -0,0 +1,18 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test for a fuzzer: must find the case where a particular basic block is
+// executed many times.
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int Num = 0;
+ for (size_t i = 0; i < Size; i++)
+ if (Data[i] == 'A' + i)
+ Num++;
+ if (Num >= 4) {
+ std::cerr << "BINGO!\n";
+ exit(1);
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/CustomCrossOverTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/CustomCrossOverTest.cpp
new file mode 100644
index 0000000000..b624088b90
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/CustomCrossOverTest.cpp
@@ -0,0 +1,63 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a cutom mutator.
+#include <assert.h>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <iostream>
+#include <random>
+#include <string.h>
+
+#include "FuzzerInterface.h"
+
+static const char *Separator = "-_^_-";
+static const char *Target = "012-_^_-abc";
+
+static volatile int sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ std::string Str(reinterpret_cast<const char *>(Data), Size);
+
+ // Ensure that two different elements exist in the corpus.
+ if (Size && Data[0] == '0') sink++;
+ if (Size && Data[0] == 'a') sink--;
+
+ if (Str.find(Target) != std::string::npos) {
+ std::cout << "BINGO; Found the target, exiting\n";
+ exit(1);
+ }
+ return 0;
+}
+
+extern "C" 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) {
+ static bool Printed;
+ static size_t SeparatorLen = strlen(Separator);
+
+ if (!Printed) {
+ std::cerr << "In LLVMFuzzerCustomCrossover\n";
+ Printed = true;
+ }
+
+ std::mt19937 R(Seed);
+
+ size_t Offset1 = 0;
+ size_t Len1 = R() % (Size1 - Offset1);
+ size_t Offset2 = 0;
+ size_t Len2 = R() % (Size2 - Offset2);
+ size_t Size = Len1 + Len2 + SeparatorLen;
+
+ if (Size > MaxOutSize)
+ return 0;
+
+ memcpy(Out, Data1 + Offset1, Len1);
+ memcpy(Out + Len1, Separator, SeparatorLen);
+ memcpy(Out + Len1 + SeparatorLen, Data2 + Offset2, Len2);
+
+ return Len1 + Len2 + SeparatorLen;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/CustomMutatorTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/CustomMutatorTest.cpp
new file mode 100644
index 0000000000..4f84519a90
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/CustomMutatorTest.cpp
@@ -0,0 +1,38 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a cutom mutator.
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+#include "FuzzerInterface.h"
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ std::cout << "BINGO; Found the target, exiting\n";
+ exit(1);
+ }
+ }
+ }
+ return 0;
+}
+
+extern "C" size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
+ size_t MaxSize, unsigned int Seed) {
+ static bool Printed;
+ if (!Printed) {
+ std::cerr << "In LLVMFuzzerCustomMutator\n";
+ Printed = true;
+ }
+ return LLVMFuzzerMutate(Data, Size, MaxSize);
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/DSO1.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/DSO1.cpp
new file mode 100644
index 0000000000..4a293890f4
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/DSO1.cpp
@@ -0,0 +1,12 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+int DSO1(int a) {
+ if (a < 123456)
+ return 0;
+ return 1;
+}
+
+void Uncovered1() { }
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/DSO2.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/DSO2.cpp
new file mode 100644
index 0000000000..04b308d193
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/DSO2.cpp
@@ -0,0 +1,12 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+int DSO2(int a) {
+ if (a < 3598235)
+ return 0;
+ return 1;
+}
+
+void Uncovered2() {}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/DSOTestExtra.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/DSOTestExtra.cpp
new file mode 100644
index 0000000000..a2274d070e
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/DSOTestExtra.cpp
@@ -0,0 +1,11 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+int DSOTestExtra(int a) {
+ if (a < 452345)
+ return 0;
+ return 1;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/DSOTestMain.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/DSOTestMain.cpp
new file mode 100644
index 0000000000..3e225d8861
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/DSOTestMain.cpp
@@ -0,0 +1,31 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Source code for a simple DSO.
+
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+extern int DSO1(int a);
+extern int DSO2(int a);
+extern int DSOTestExtra(int a);
+
+static volatile int *nil = 0;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int x, y, z;
+ if (Size < sizeof(int) * 3) {
+ x = y = z = 0;
+ } else {
+ memcpy(&x, Data + 0 * sizeof(int), sizeof(int));
+ memcpy(&y, Data + 1 * sizeof(int), sizeof(int));
+ memcpy(&z, Data + 2 * sizeof(int), sizeof(int));
+ }
+ int sum = DSO1(x) + DSO2(y) + (z ? DSOTestExtra(z) : 0);
+ if (sum == 3) {
+ fprintf(stderr, "BINGO %d %d %d\n", x, y, z);
+ *nil = 0;
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/DivTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/DivTest.cpp
new file mode 100644
index 0000000000..63f6960f4e
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/DivTest.cpp
@@ -0,0 +1,20 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer: find the interesting argument for div.
+#include <assert.h>
+#include <cstdint>
+#include <cstring>
+#include <cstddef>
+#include <iostream>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 4) return 0;
+ int a;
+ memcpy(&a, Data, 4);
+ Sink = 12345678 / (987654 - a);
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/EmptyTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/EmptyTest.cpp
new file mode 100644
index 0000000000..5e843308fa
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/EmptyTest.cpp
@@ -0,0 +1,11 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// A fuzzer with empty target function.
+
+#include <cstdint>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/FourIndependentBranchesTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/FourIndependentBranchesTest.cpp
new file mode 100644
index 0000000000..62b3be76e3
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/FourIndependentBranchesTest.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "FUZZ".
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int bits = 0;
+ if (Size > 0 && Data[0] == 'F') bits |= 1;
+ if (Size > 1 && Data[1] == 'U') bits |= 2;
+ if (Size > 2 && Data[2] == 'Z') bits |= 4;
+ if (Size > 3 && Data[3] == 'Z') bits |= 8;
+ if (bits == 15) {
+ std::cerr << "BINGO!\n";
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/FullCoverageSetTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/FullCoverageSetTest.cpp
new file mode 100644
index 0000000000..415e0b4760
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/FullCoverageSetTest.cpp
@@ -0,0 +1,24 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "FUZZER".
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int bits = 0;
+ if (Size > 0 && Data[0] == 'F') bits |= 1;
+ if (Size > 1 && Data[1] == 'U') bits |= 2;
+ if (Size > 2 && Data[2] == 'Z') bits |= 4;
+ if (Size > 3 && Data[3] == 'Z') bits |= 8;
+ if (Size > 4 && Data[4] == 'E') bits |= 16;
+ if (Size > 5 && Data[5] == 'R') bits |= 32;
+ if (bits == 63) {
+ std::cerr << "BINGO!\n";
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/FuzzerUnittest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/FuzzerUnittest.cpp
new file mode 100644
index 0000000000..4992ef57b6
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/FuzzerUnittest.cpp
@@ -0,0 +1,738 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Avoid ODR violations (LibFuzzer is built without ASan and this test is built
+// with ASan) involving C++ standard library types when using libcxx.
+#define _LIBCPP_HAS_NO_ASAN
+
+#include "FuzzerCorpus.h"
+#include "FuzzerInternal.h"
+#include "FuzzerDictionary.h"
+#include "FuzzerMerge.h"
+#include "FuzzerMutate.h"
+#include "FuzzerRandom.h"
+#include "gtest/gtest.h"
+#include <memory>
+#include <set>
+
+using namespace fuzzer;
+
+// For now, have LLVMFuzzerTestOneInput just to make it link.
+// Later we may want to make unittests that actually call LLVMFuzzerTestOneInput.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ abort();
+}
+
+TEST(Fuzzer, CrossOver) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ Unit A({0, 1, 2}), B({5, 6, 7});
+ Unit C;
+ Unit Expected[] = {
+ { 0 },
+ { 0, 1 },
+ { 0, 5 },
+ { 0, 1, 2 },
+ { 0, 1, 5 },
+ { 0, 5, 1 },
+ { 0, 5, 6 },
+ { 0, 1, 2, 5 },
+ { 0, 1, 5, 2 },
+ { 0, 1, 5, 6 },
+ { 0, 5, 1, 2 },
+ { 0, 5, 1, 6 },
+ { 0, 5, 6, 1 },
+ { 0, 5, 6, 7 },
+ { 0, 1, 2, 5, 6 },
+ { 0, 1, 5, 2, 6 },
+ { 0, 1, 5, 6, 2 },
+ { 0, 1, 5, 6, 7 },
+ { 0, 5, 1, 2, 6 },
+ { 0, 5, 1, 6, 2 },
+ { 0, 5, 1, 6, 7 },
+ { 0, 5, 6, 1, 2 },
+ { 0, 5, 6, 1, 7 },
+ { 0, 5, 6, 7, 1 },
+ { 0, 1, 2, 5, 6, 7 },
+ { 0, 1, 5, 2, 6, 7 },
+ { 0, 1, 5, 6, 2, 7 },
+ { 0, 1, 5, 6, 7, 2 },
+ { 0, 5, 1, 2, 6, 7 },
+ { 0, 5, 1, 6, 2, 7 },
+ { 0, 5, 1, 6, 7, 2 },
+ { 0, 5, 6, 1, 2, 7 },
+ { 0, 5, 6, 1, 7, 2 },
+ { 0, 5, 6, 7, 1, 2 }
+ };
+ for (size_t Len = 1; Len < 8; Len++) {
+ std::set<Unit> FoundUnits, ExpectedUnitsWitThisLength;
+ for (int Iter = 0; Iter < 3000; Iter++) {
+ C.resize(Len);
+ size_t NewSize = MD.CrossOver(A.data(), A.size(), B.data(), B.size(),
+ C.data(), C.size());
+ C.resize(NewSize);
+ FoundUnits.insert(C);
+ }
+ for (const Unit &U : Expected)
+ if (U.size() <= Len)
+ ExpectedUnitsWitThisLength.insert(U);
+ EXPECT_EQ(ExpectedUnitsWitThisLength, FoundUnits);
+ }
+}
+
+TEST(Fuzzer, Hash) {
+ uint8_t A[] = {'a', 'b', 'c'};
+ fuzzer::Unit U(A, A + sizeof(A));
+ EXPECT_EQ("a9993e364706816aba3e25717850c26c9cd0d89d", fuzzer::Hash(U));
+ U.push_back('d');
+ EXPECT_EQ("81fe8bfe87576c3ecb22426f8e57847382917acf", fuzzer::Hash(U));
+}
+
+typedef size_t (MutationDispatcher::*Mutator)(uint8_t *Data, size_t Size,
+ size_t MaxSize);
+
+void TestEraseBytes(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ uint8_t REM0[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t REM1[8] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t REM2[8] = {0x00, 0x11, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t REM3[8] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x77};
+ uint8_t REM4[8] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x66, 0x77};
+ uint8_t REM5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66, 0x77};
+ uint8_t REM6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x77};
+ uint8_t REM7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+
+ uint8_t REM8[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t REM9[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
+ uint8_t REM10[6] = {0x00, 0x11, 0x22, 0x55, 0x66, 0x77};
+
+ uint8_t REM11[5] = {0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t REM12[5] = {0x00, 0x11, 0x22, 0x33, 0x44};
+ uint8_t REM13[5] = {0x00, 0x44, 0x55, 0x66, 0x77};
+
+
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ int FoundMask = 0;
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ size_t NewSize = (MD.*M)(T, sizeof(T), sizeof(T));
+ if (NewSize == 7 && !memcmp(REM0, T, 7)) FoundMask |= 1 << 0;
+ if (NewSize == 7 && !memcmp(REM1, T, 7)) FoundMask |= 1 << 1;
+ if (NewSize == 7 && !memcmp(REM2, T, 7)) FoundMask |= 1 << 2;
+ if (NewSize == 7 && !memcmp(REM3, T, 7)) FoundMask |= 1 << 3;
+ if (NewSize == 7 && !memcmp(REM4, T, 7)) FoundMask |= 1 << 4;
+ if (NewSize == 7 && !memcmp(REM5, T, 7)) FoundMask |= 1 << 5;
+ if (NewSize == 7 && !memcmp(REM6, T, 7)) FoundMask |= 1 << 6;
+ if (NewSize == 7 && !memcmp(REM7, T, 7)) FoundMask |= 1 << 7;
+
+ if (NewSize == 6 && !memcmp(REM8, T, 6)) FoundMask |= 1 << 8;
+ if (NewSize == 6 && !memcmp(REM9, T, 6)) FoundMask |= 1 << 9;
+ if (NewSize == 6 && !memcmp(REM10, T, 6)) FoundMask |= 1 << 10;
+
+ if (NewSize == 5 && !memcmp(REM11, T, 5)) FoundMask |= 1 << 11;
+ if (NewSize == 5 && !memcmp(REM12, T, 5)) FoundMask |= 1 << 12;
+ if (NewSize == 5 && !memcmp(REM13, T, 5)) FoundMask |= 1 << 13;
+ }
+ EXPECT_EQ(FoundMask, (1 << 14) - 1);
+}
+
+TEST(FuzzerMutate, EraseBytes1) {
+ TestEraseBytes(&MutationDispatcher::Mutate_EraseBytes, 200);
+}
+TEST(FuzzerMutate, EraseBytes2) {
+ TestEraseBytes(&MutationDispatcher::Mutate, 2000);
+}
+
+void TestInsertByte(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ int FoundMask = 0;
+ uint8_t INS0[8] = {0xF1, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+ uint8_t INS1[8] = {0x00, 0xF2, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+ uint8_t INS2[8] = {0x00, 0x11, 0xF3, 0x22, 0x33, 0x44, 0x55, 0x66};
+ uint8_t INS3[8] = {0x00, 0x11, 0x22, 0xF4, 0x33, 0x44, 0x55, 0x66};
+ uint8_t INS4[8] = {0x00, 0x11, 0x22, 0x33, 0xF5, 0x44, 0x55, 0x66};
+ uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF6, 0x55, 0x66};
+ uint8_t INS6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF7, 0x66};
+ uint8_t INS7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF8};
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+ size_t NewSize = (MD.*M)(T, 7, 8);
+ if (NewSize == 8 && !memcmp(INS0, T, 8)) FoundMask |= 1 << 0;
+ if (NewSize == 8 && !memcmp(INS1, T, 8)) FoundMask |= 1 << 1;
+ if (NewSize == 8 && !memcmp(INS2, T, 8)) FoundMask |= 1 << 2;
+ if (NewSize == 8 && !memcmp(INS3, T, 8)) FoundMask |= 1 << 3;
+ if (NewSize == 8 && !memcmp(INS4, T, 8)) FoundMask |= 1 << 4;
+ if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
+ if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
+ if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
+ }
+ EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, InsertByte1) {
+ TestInsertByte(&MutationDispatcher::Mutate_InsertByte, 1 << 15);
+}
+TEST(FuzzerMutate, InsertByte2) {
+ TestInsertByte(&MutationDispatcher::Mutate, 1 << 17);
+}
+
+void TestInsertRepeatedBytes(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ int FoundMask = 0;
+ uint8_t INS0[7] = {0x00, 0x11, 0x22, 0x33, 'a', 'a', 'a'};
+ uint8_t INS1[7] = {0x00, 0x11, 0x22, 'a', 'a', 'a', 0x33};
+ uint8_t INS2[7] = {0x00, 0x11, 'a', 'a', 'a', 0x22, 0x33};
+ uint8_t INS3[7] = {0x00, 'a', 'a', 'a', 0x11, 0x22, 0x33};
+ uint8_t INS4[7] = {'a', 'a', 'a', 0x00, 0x11, 0x22, 0x33};
+
+ uint8_t INS5[8] = {0x00, 0x11, 0x22, 0x33, 'b', 'b', 'b', 'b'};
+ uint8_t INS6[8] = {0x00, 0x11, 0x22, 'b', 'b', 'b', 'b', 0x33};
+ uint8_t INS7[8] = {0x00, 0x11, 'b', 'b', 'b', 'b', 0x22, 0x33};
+ uint8_t INS8[8] = {0x00, 'b', 'b', 'b', 'b', 0x11, 0x22, 0x33};
+ uint8_t INS9[8] = {'b', 'b', 'b', 'b', 0x00, 0x11, 0x22, 0x33};
+
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[8] = {0x00, 0x11, 0x22, 0x33};
+ size_t NewSize = (MD.*M)(T, 4, 8);
+ if (NewSize == 7 && !memcmp(INS0, T, 7)) FoundMask |= 1 << 0;
+ if (NewSize == 7 && !memcmp(INS1, T, 7)) FoundMask |= 1 << 1;
+ if (NewSize == 7 && !memcmp(INS2, T, 7)) FoundMask |= 1 << 2;
+ if (NewSize == 7 && !memcmp(INS3, T, 7)) FoundMask |= 1 << 3;
+ if (NewSize == 7 && !memcmp(INS4, T, 7)) FoundMask |= 1 << 4;
+
+ if (NewSize == 8 && !memcmp(INS5, T, 8)) FoundMask |= 1 << 5;
+ if (NewSize == 8 && !memcmp(INS6, T, 8)) FoundMask |= 1 << 6;
+ if (NewSize == 8 && !memcmp(INS7, T, 8)) FoundMask |= 1 << 7;
+ if (NewSize == 8 && !memcmp(INS8, T, 8)) FoundMask |= 1 << 8;
+ if (NewSize == 8 && !memcmp(INS9, T, 8)) FoundMask |= 1 << 9;
+
+ }
+ EXPECT_EQ(FoundMask, (1 << 10) - 1);
+}
+
+TEST(FuzzerMutate, InsertRepeatedBytes1) {
+ TestInsertRepeatedBytes(&MutationDispatcher::Mutate_InsertRepeatedBytes, 10000);
+}
+TEST(FuzzerMutate, InsertRepeatedBytes2) {
+ TestInsertRepeatedBytes(&MutationDispatcher::Mutate, 300000);
+}
+
+void TestChangeByte(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ int FoundMask = 0;
+ uint8_t CH0[8] = {0xF0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH1[8] = {0x00, 0xF1, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH2[8] = {0x00, 0x11, 0xF2, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH3[8] = {0x00, 0x11, 0x22, 0xF3, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0xF4, 0x55, 0x66, 0x77};
+ uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xF5, 0x66, 0x77};
+ uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0xF5, 0x77};
+ uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ size_t NewSize = (MD.*M)(T, 8, 9);
+ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
+ if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
+ if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
+ if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
+ if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
+ if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
+ if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
+ if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
+ }
+ EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, ChangeByte1) {
+ TestChangeByte(&MutationDispatcher::Mutate_ChangeByte, 1 << 15);
+}
+TEST(FuzzerMutate, ChangeByte2) {
+ TestChangeByte(&MutationDispatcher::Mutate, 1 << 17);
+}
+
+void TestChangeBit(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ int FoundMask = 0;
+ uint8_t CH0[8] = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH1[8] = {0x00, 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH2[8] = {0x00, 0x11, 0x02, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH3[8] = {0x00, 0x11, 0x22, 0x37, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x54, 0x55, 0x66, 0x77};
+ uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x54, 0x66, 0x77};
+ uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x76, 0x77};
+ uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0xF7};
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[9] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ size_t NewSize = (MD.*M)(T, 8, 9);
+ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
+ if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
+ if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
+ if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
+ if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
+ if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
+ if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
+ if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
+ }
+ EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, ChangeBit1) {
+ TestChangeBit(&MutationDispatcher::Mutate_ChangeBit, 1 << 16);
+}
+TEST(FuzzerMutate, ChangeBit2) {
+ TestChangeBit(&MutationDispatcher::Mutate, 1 << 18);
+}
+
+void TestShuffleBytes(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ int FoundMask = 0;
+ uint8_t CH0[7] = {0x00, 0x22, 0x11, 0x33, 0x44, 0x55, 0x66};
+ uint8_t CH1[7] = {0x11, 0x00, 0x33, 0x22, 0x44, 0x55, 0x66};
+ uint8_t CH2[7] = {0x00, 0x33, 0x11, 0x22, 0x44, 0x55, 0x66};
+ uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x44, 0x55, 0x66, 0x33};
+ uint8_t CH4[7] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x44, 0x66};
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+ size_t NewSize = (MD.*M)(T, 7, 7);
+ if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
+ if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
+ if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
+ if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
+ if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
+ }
+ EXPECT_EQ(FoundMask, 31);
+}
+
+TEST(FuzzerMutate, ShuffleBytes1) {
+ TestShuffleBytes(&MutationDispatcher::Mutate_ShuffleBytes, 1 << 16);
+}
+TEST(FuzzerMutate, ShuffleBytes2) {
+ TestShuffleBytes(&MutationDispatcher::Mutate, 1 << 20);
+}
+
+void TestCopyPart(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ int FoundMask = 0;
+ uint8_t CH0[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11};
+ uint8_t CH1[7] = {0x55, 0x66, 0x22, 0x33, 0x44, 0x55, 0x66};
+ uint8_t CH2[7] = {0x00, 0x55, 0x66, 0x33, 0x44, 0x55, 0x66};
+ uint8_t CH3[7] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x66};
+ uint8_t CH4[7] = {0x00, 0x11, 0x11, 0x22, 0x33, 0x55, 0x66};
+
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[7] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+ size_t NewSize = (MD.*M)(T, 7, 7);
+ if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
+ if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
+ if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
+ if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
+ if (NewSize == 7 && !memcmp(CH4, T, 7)) FoundMask |= 1 << 4;
+ }
+
+ uint8_t CH5[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x00, 0x11, 0x22};
+ uint8_t CH6[8] = {0x22, 0x33, 0x44, 0x00, 0x11, 0x22, 0x33, 0x44};
+ uint8_t CH7[8] = {0x00, 0x11, 0x22, 0x00, 0x11, 0x22, 0x33, 0x44};
+ uint8_t CH8[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x22, 0x33, 0x44};
+ uint8_t CH9[8] = {0x00, 0x11, 0x22, 0x22, 0x33, 0x44, 0x33, 0x44};
+
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ size_t NewSize = (MD.*M)(T, 5, 8);
+ if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
+ if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
+ if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
+ if (NewSize == 8 && !memcmp(CH8, T, 8)) FoundMask |= 1 << 8;
+ if (NewSize == 8 && !memcmp(CH9, T, 8)) FoundMask |= 1 << 9;
+ }
+
+ EXPECT_EQ(FoundMask, 1023);
+}
+
+TEST(FuzzerMutate, CopyPart1) {
+ TestCopyPart(&MutationDispatcher::Mutate_CopyPart, 1 << 10);
+}
+TEST(FuzzerMutate, CopyPart2) {
+ TestCopyPart(&MutationDispatcher::Mutate, 1 << 13);
+}
+
+void TestAddWordFromDictionary(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ uint8_t Word1[4] = {0xAA, 0xBB, 0xCC, 0xDD};
+ uint8_t Word2[3] = {0xFF, 0xEE, 0xEF};
+ MD.AddWordToManualDictionary(Word(Word1, sizeof(Word1)));
+ MD.AddWordToManualDictionary(Word(Word2, sizeof(Word2)));
+ int FoundMask = 0;
+ uint8_t CH0[7] = {0x00, 0x11, 0x22, 0xAA, 0xBB, 0xCC, 0xDD};
+ uint8_t CH1[7] = {0x00, 0x11, 0xAA, 0xBB, 0xCC, 0xDD, 0x22};
+ uint8_t CH2[7] = {0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22};
+ uint8_t CH3[7] = {0xAA, 0xBB, 0xCC, 0xDD, 0x00, 0x11, 0x22};
+ uint8_t CH4[6] = {0x00, 0x11, 0x22, 0xFF, 0xEE, 0xEF};
+ uint8_t CH5[6] = {0x00, 0x11, 0xFF, 0xEE, 0xEF, 0x22};
+ uint8_t CH6[6] = {0x00, 0xFF, 0xEE, 0xEF, 0x11, 0x22};
+ uint8_t CH7[6] = {0xFF, 0xEE, 0xEF, 0x00, 0x11, 0x22};
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[7] = {0x00, 0x11, 0x22};
+ size_t NewSize = (MD.*M)(T, 3, 7);
+ if (NewSize == 7 && !memcmp(CH0, T, 7)) FoundMask |= 1 << 0;
+ if (NewSize == 7 && !memcmp(CH1, T, 7)) FoundMask |= 1 << 1;
+ if (NewSize == 7 && !memcmp(CH2, T, 7)) FoundMask |= 1 << 2;
+ if (NewSize == 7 && !memcmp(CH3, T, 7)) FoundMask |= 1 << 3;
+ if (NewSize == 6 && !memcmp(CH4, T, 6)) FoundMask |= 1 << 4;
+ if (NewSize == 6 && !memcmp(CH5, T, 6)) FoundMask |= 1 << 5;
+ if (NewSize == 6 && !memcmp(CH6, T, 6)) FoundMask |= 1 << 6;
+ if (NewSize == 6 && !memcmp(CH7, T, 6)) FoundMask |= 1 << 7;
+ }
+ EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionary1) {
+ TestAddWordFromDictionary(
+ &MutationDispatcher::Mutate_AddWordFromManualDictionary, 1 << 15);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionary2) {
+ TestAddWordFromDictionary(&MutationDispatcher::Mutate, 1 << 15);
+}
+
+void TestAddWordFromDictionaryWithHint(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+ uint8_t W[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xFF, 0xEE, 0xEF};
+ size_t PosHint = 7777;
+ MD.AddWordToAutoDictionary({Word(W, sizeof(W)), PosHint});
+ int FoundMask = 0;
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[10000];
+ memset(T, 0, sizeof(T));
+ size_t NewSize = (MD.*M)(T, 9000, 10000);
+ if (NewSize >= PosHint + sizeof(W) &&
+ !memcmp(W, T + PosHint, sizeof(W)))
+ FoundMask = 1;
+ }
+ EXPECT_EQ(FoundMask, 1);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionaryWithHint1) {
+ TestAddWordFromDictionaryWithHint(
+ &MutationDispatcher::Mutate_AddWordFromTemporaryAutoDictionary, 1 << 5);
+}
+
+TEST(FuzzerMutate, AddWordFromDictionaryWithHint2) {
+ TestAddWordFromDictionaryWithHint(&MutationDispatcher::Mutate, 1 << 10);
+}
+
+void TestChangeASCIIInteger(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+
+ uint8_t CH0[8] = {'1', '2', '3', '4', '5', '6', '7', '7'};
+ uint8_t CH1[8] = {'1', '2', '3', '4', '5', '6', '7', '9'};
+ uint8_t CH2[8] = {'2', '4', '6', '9', '1', '3', '5', '6'};
+ uint8_t CH3[8] = {'0', '6', '1', '7', '2', '8', '3', '9'};
+ int FoundMask = 0;
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[8] = {'1', '2', '3', '4', '5', '6', '7', '8'};
+ size_t NewSize = (MD.*M)(T, 8, 8);
+ /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
+ else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
+ else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
+ else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
+ else if (NewSize == 8) FoundMask |= 1 << 4;
+ }
+ EXPECT_EQ(FoundMask, 31);
+}
+
+TEST(FuzzerMutate, ChangeASCIIInteger1) {
+ TestChangeASCIIInteger(&MutationDispatcher::Mutate_ChangeASCIIInteger,
+ 1 << 15);
+}
+
+TEST(FuzzerMutate, ChangeASCIIInteger2) {
+ TestChangeASCIIInteger(&MutationDispatcher::Mutate, 1 << 15);
+}
+
+void TestChangeBinaryInteger(Mutator M, int NumIter) {
+ std::unique_ptr<ExternalFunctions> t(new ExternalFunctions());
+ fuzzer::EF = t.get();
+ Random Rand(0);
+ MutationDispatcher MD(Rand, {});
+
+ uint8_t CH0[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x79};
+ uint8_t CH1[8] = {0x00, 0x11, 0x22, 0x31, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH2[8] = {0xff, 0x10, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH3[8] = {0x00, 0x11, 0x2a, 0x33, 0x44, 0x55, 0x66, 0x77};
+ uint8_t CH4[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x4f, 0x66, 0x77};
+ uint8_t CH5[8] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88};
+ uint8_t CH6[8] = {0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x08, 0x77}; // Size
+ uint8_t CH7[8] = {0x00, 0x08, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77}; // Sw(Size)
+
+ int FoundMask = 0;
+ for (int i = 0; i < NumIter; i++) {
+ uint8_t T[8] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+ size_t NewSize = (MD.*M)(T, 8, 8);
+ /**/ if (NewSize == 8 && !memcmp(CH0, T, 8)) FoundMask |= 1 << 0;
+ else if (NewSize == 8 && !memcmp(CH1, T, 8)) FoundMask |= 1 << 1;
+ else if (NewSize == 8 && !memcmp(CH2, T, 8)) FoundMask |= 1 << 2;
+ else if (NewSize == 8 && !memcmp(CH3, T, 8)) FoundMask |= 1 << 3;
+ else if (NewSize == 8 && !memcmp(CH4, T, 8)) FoundMask |= 1 << 4;
+ else if (NewSize == 8 && !memcmp(CH5, T, 8)) FoundMask |= 1 << 5;
+ else if (NewSize == 8 && !memcmp(CH6, T, 8)) FoundMask |= 1 << 6;
+ else if (NewSize == 8 && !memcmp(CH7, T, 8)) FoundMask |= 1 << 7;
+ }
+ EXPECT_EQ(FoundMask, 255);
+}
+
+TEST(FuzzerMutate, ChangeBinaryInteger1) {
+ TestChangeBinaryInteger(&MutationDispatcher::Mutate_ChangeBinaryInteger,
+ 1 << 12);
+}
+
+TEST(FuzzerMutate, ChangeBinaryInteger2) {
+ TestChangeBinaryInteger(&MutationDispatcher::Mutate, 1 << 15);
+}
+
+
+TEST(FuzzerDictionary, ParseOneDictionaryEntry) {
+ Unit U;
+ EXPECT_FALSE(ParseOneDictionaryEntry("", &U));
+ EXPECT_FALSE(ParseOneDictionaryEntry(" ", &U));
+ EXPECT_FALSE(ParseOneDictionaryEntry("\t ", &U));
+ EXPECT_FALSE(ParseOneDictionaryEntry(" \" ", &U));
+ EXPECT_FALSE(ParseOneDictionaryEntry(" zz\" ", &U));
+ EXPECT_FALSE(ParseOneDictionaryEntry(" \"zz ", &U));
+ EXPECT_FALSE(ParseOneDictionaryEntry(" \"\" ", &U));
+ EXPECT_TRUE(ParseOneDictionaryEntry("\"a\"", &U));
+ EXPECT_EQ(U, Unit({'a'}));
+ EXPECT_TRUE(ParseOneDictionaryEntry("\"abc\"", &U));
+ EXPECT_EQ(U, Unit({'a', 'b', 'c'}));
+ EXPECT_TRUE(ParseOneDictionaryEntry("abc=\"abc\"", &U));
+ EXPECT_EQ(U, Unit({'a', 'b', 'c'}));
+ EXPECT_FALSE(ParseOneDictionaryEntry("\"\\\"", &U));
+ EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\\\"", &U));
+ EXPECT_EQ(U, Unit({'\\'}));
+ EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xAB\"", &U));
+ EXPECT_EQ(U, Unit({0xAB}));
+ EXPECT_TRUE(ParseOneDictionaryEntry("\"\\xABz\\xDE\"", &U));
+ EXPECT_EQ(U, Unit({0xAB, 'z', 0xDE}));
+ EXPECT_TRUE(ParseOneDictionaryEntry("\"#\"", &U));
+ EXPECT_EQ(U, Unit({'#'}));
+ EXPECT_TRUE(ParseOneDictionaryEntry("\"\\\"\"", &U));
+ EXPECT_EQ(U, Unit({'"'}));
+}
+
+TEST(FuzzerDictionary, ParseDictionaryFile) {
+ std::vector<Unit> Units;
+ EXPECT_FALSE(ParseDictionaryFile("zzz\n", &Units));
+ EXPECT_FALSE(ParseDictionaryFile("", &Units));
+ EXPECT_TRUE(ParseDictionaryFile("\n", &Units));
+ EXPECT_EQ(Units.size(), 0U);
+ EXPECT_TRUE(ParseDictionaryFile("#zzzz a b c d\n", &Units));
+ EXPECT_EQ(Units.size(), 0U);
+ EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units));
+ EXPECT_EQ(Units.size(), 0U);
+ EXPECT_TRUE(ParseDictionaryFile(" #zzzz\n", &Units));
+ EXPECT_EQ(Units.size(), 0U);
+ EXPECT_TRUE(ParseDictionaryFile(" #zzzz\naaa=\"aa\"", &Units));
+ EXPECT_EQ(Units, std::vector<Unit>({Unit({'a', 'a'})}));
+ EXPECT_TRUE(
+ ParseDictionaryFile(" #zzzz\naaa=\"aa\"\n\nabc=\"abc\"", &Units));
+ EXPECT_EQ(Units,
+ std::vector<Unit>({Unit({'a', 'a'}), Unit({'a', 'b', 'c'})}));
+}
+
+TEST(FuzzerUtil, Base64) {
+ EXPECT_EQ("", Base64({}));
+ EXPECT_EQ("YQ==", Base64({'a'}));
+ EXPECT_EQ("eA==", Base64({'x'}));
+ EXPECT_EQ("YWI=", Base64({'a', 'b'}));
+ EXPECT_EQ("eHk=", Base64({'x', 'y'}));
+ EXPECT_EQ("YWJj", Base64({'a', 'b', 'c'}));
+ EXPECT_EQ("eHl6", Base64({'x', 'y', 'z'}));
+ EXPECT_EQ("YWJjeA==", Base64({'a', 'b', 'c', 'x'}));
+ EXPECT_EQ("YWJjeHk=", Base64({'a', 'b', 'c', 'x', 'y'}));
+ EXPECT_EQ("YWJjeHl6", Base64({'a', 'b', 'c', 'x', 'y', 'z'}));
+}
+
+TEST(Corpus, Distribution) {
+ Random Rand(0);
+ InputCorpus C("");
+ size_t N = 10;
+ size_t TriesPerUnit = 1<<16;
+ for (size_t i = 0; i < N; i++)
+ C.AddToCorpus(Unit{ static_cast<uint8_t>(i) }, 0);
+
+ std::vector<size_t> Hist(N);
+ for (size_t i = 0; i < N * TriesPerUnit; i++) {
+ Hist[C.ChooseUnitIdxToMutate(Rand)]++;
+ }
+ for (size_t i = 0; i < N; i++) {
+ // A weak sanity check that every unit gets invoked.
+ EXPECT_GT(Hist[i], TriesPerUnit / N / 3);
+ }
+}
+
+TEST(Merge, Bad) {
+ const char *kInvalidInputs[] = {
+ "",
+ "x",
+ "3\nx",
+ "2\n3",
+ "2\n2",
+ "2\n2\nA\n",
+ "2\n2\nA\nB\nC\n",
+ "0\n0\n",
+ "1\n1\nA\nDONE 0",
+ "1\n1\nA\nSTARTED 1",
+ };
+ Merger M;
+ for (auto S : kInvalidInputs) {
+ // fprintf(stderr, "TESTING:\n%s\n", S);
+ EXPECT_FALSE(M.Parse(S, false));
+ }
+}
+
+void EQ(const std::vector<uint32_t> &A, const std::vector<uint32_t> &B) {
+ EXPECT_EQ(A, B);
+}
+
+void EQ(const std::vector<std::string> &A, const std::vector<std::string> &B) {
+ std::set<std::string> a(A.begin(), A.end());
+ std::set<std::string> b(B.begin(), B.end());
+ EXPECT_EQ(a, b);
+}
+
+static void Merge(const std::string &Input,
+ const std::vector<std::string> Result,
+ size_t NumNewFeatures) {
+ Merger M;
+ std::vector<std::string> NewFiles;
+ EXPECT_TRUE(M.Parse(Input, true));
+ EXPECT_EQ(NumNewFeatures, M.Merge(&NewFiles));
+ EQ(NewFiles, Result);
+}
+
+TEST(Merge, Good) {
+ Merger M;
+
+ EXPECT_TRUE(M.Parse("1\n0\nAA\n", false));
+ EXPECT_EQ(M.Files.size(), 1U);
+ EXPECT_EQ(M.NumFilesInFirstCorpus, 0U);
+ EXPECT_EQ(M.Files[0].Name, "AA");
+ EXPECT_TRUE(M.LastFailure.empty());
+ EXPECT_EQ(M.FirstNotProcessedFile, 0U);
+
+ EXPECT_TRUE(M.Parse("2\n1\nAA\nBB\nSTARTED 0 42\n", false));
+ EXPECT_EQ(M.Files.size(), 2U);
+ EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
+ EXPECT_EQ(M.Files[0].Name, "AA");
+ EXPECT_EQ(M.Files[1].Name, "BB");
+ EXPECT_EQ(M.LastFailure, "AA");
+ EXPECT_EQ(M.FirstNotProcessedFile, 1U);
+
+ EXPECT_TRUE(M.Parse("3\n1\nAA\nBB\nC\n"
+ "STARTED 0 1000\n"
+ "DONE 0 1 2 3\n"
+ "STARTED 1 1001\n"
+ "DONE 1 4 5 6 \n"
+ "STARTED 2 1002\n"
+ "", true));
+ EXPECT_EQ(M.Files.size(), 3U);
+ EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
+ EXPECT_EQ(M.Files[0].Name, "AA");
+ EXPECT_EQ(M.Files[0].Size, 1000U);
+ EXPECT_EQ(M.Files[1].Name, "BB");
+ EXPECT_EQ(M.Files[1].Size, 1001U);
+ EXPECT_EQ(M.Files[2].Name, "C");
+ EXPECT_EQ(M.Files[2].Size, 1002U);
+ EXPECT_EQ(M.LastFailure, "C");
+ EXPECT_EQ(M.FirstNotProcessedFile, 3U);
+ EQ(M.Files[0].Features, {1, 2, 3});
+ EQ(M.Files[1].Features, {4, 5, 6});
+
+
+ std::vector<std::string> NewFiles;
+
+ EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n"
+ "STARTED 0 1000\nDONE 0 1 2 3\n"
+ "STARTED 1 1001\nDONE 1 4 5 6 \n"
+ "STARTED 2 1002\nDONE 2 6 1 3 \n"
+ "", true));
+ EXPECT_EQ(M.Files.size(), 3U);
+ EXPECT_EQ(M.NumFilesInFirstCorpus, 2U);
+ EXPECT_TRUE(M.LastFailure.empty());
+ EXPECT_EQ(M.FirstNotProcessedFile, 3U);
+ EQ(M.Files[0].Features, {1, 2, 3});
+ EQ(M.Files[1].Features, {4, 5, 6});
+ EQ(M.Files[2].Features, {1, 3, 6});
+ EXPECT_EQ(0U, M.Merge(&NewFiles));
+ EQ(NewFiles, {});
+
+ EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n"
+ "STARTED 0 1000\nDONE 0 1 2 3\n"
+ "STARTED 1 1001\nDONE 1 4 5 6 \n"
+ "STARTED 2 1002\nDONE 2 6 1 3\n"
+ "", true));
+ EQ(M.Files[0].Features, {1, 2, 3});
+ EQ(M.Files[1].Features, {4, 5, 6});
+ EQ(M.Files[2].Features, {1, 3, 6});
+ EXPECT_EQ(3U, M.Merge(&NewFiles));
+ EQ(NewFiles, {"B"});
+}
+
+TEST(Merge, Merge) {
+
+ Merge("3\n1\nA\nB\nC\n"
+ "STARTED 0 1000\nDONE 0 1 2 3\n"
+ "STARTED 1 1001\nDONE 1 4 5 6 \n"
+ "STARTED 2 1002\nDONE 2 6 1 3 \n",
+ {"B"}, 3);
+
+ Merge("3\n0\nA\nB\nC\n"
+ "STARTED 0 2000\nDONE 0 1 2 3\n"
+ "STARTED 1 1001\nDONE 1 4 5 6 \n"
+ "STARTED 2 1002\nDONE 2 6 1 3 \n",
+ {"A", "B", "C"}, 6);
+
+ Merge("4\n0\nA\nB\nC\nD\n"
+ "STARTED 0 2000\nDONE 0 1 2 3\n"
+ "STARTED 1 1101\nDONE 1 4 5 6 \n"
+ "STARTED 2 1102\nDONE 2 6 1 3 100 \n"
+ "STARTED 3 1000\nDONE 3 1 \n",
+ {"A", "B", "C", "D"}, 7);
+
+ Merge("4\n1\nA\nB\nC\nD\n"
+ "STARTED 0 2000\nDONE 0 4 5 6 7 8\n"
+ "STARTED 1 1100\nDONE 1 1 2 3 \n"
+ "STARTED 2 1100\nDONE 2 2 3 \n"
+ "STARTED 3 1000\nDONE 3 1 \n",
+ {"B", "D"}, 3);
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/InitializeTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/InitializeTest.cpp
new file mode 100644
index 0000000000..0d6a0fda09
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/InitializeTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Make sure LLVMFuzzerInitialize is called.
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char *argv0;
+
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ assert(*argc > 0);
+ argv0 = **argv;
+ fprintf(stderr, "LLVMFuzzerInitialize: %s\n", argv0);
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size == strlen(argv0) &&
+ !strncmp(reinterpret_cast<const char *>(Data), argv0, Size)) {
+ fprintf(stderr, "BINGO %s\n", argv0);
+ exit(1);
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/LeakTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/LeakTest.cpp
new file mode 100644
index 0000000000..22e5164050
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/LeakTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test with a leak.
+#include <cstdint>
+#include <cstddef>
+
+static volatile void *Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && *Data == 'H') {
+ Sink = new int;
+ Sink = nullptr;
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/LeakTimeoutTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/LeakTimeoutTest.cpp
new file mode 100644
index 0000000000..4f31b3e52c
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/LeakTimeoutTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test with a leak.
+#include <cstdint>
+#include <cstddef>
+
+static volatile int *Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (!Size) return 0;
+ Sink = new int;
+ Sink = new int;
+ while (Sink) *Sink = 0; // Infinite loop.
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/LoadTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/LoadTest.cpp
new file mode 100644
index 0000000000..c1780d5c7b
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/LoadTest.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer: find interesting value of array index.
+#include <assert.h>
+#include <cstdint>
+#include <cstring>
+#include <cstddef>
+#include <iostream>
+
+static volatile int Sink;
+const int kArraySize = 1234567;
+int array[kArraySize];
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 8) return 0;
+ size_t a = 0;
+ memcpy(&a, Data, 8);
+ Sink = array[a % (kArraySize + 1)];
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/MemcmpTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/MemcmpTest.cpp
new file mode 100644
index 0000000000..fdbf94683f
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/MemcmpTest.cpp
@@ -0,0 +1,31 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstring>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ // TODO: check other sizes.
+ if (Size >= 8 && memcmp(Data, "01234567", 8) == 0) {
+ if (Size >= 12 && memcmp(Data + 8, "ABCD", 4) == 0) {
+ if (Size >= 14 && memcmp(Data + 12, "XY", 2) == 0) {
+ if (Size >= 17 && memcmp(Data + 14, "KLM", 3) == 0) {
+ if (Size >= 27 && memcmp(Data + 17, "ABCDE-GHIJ", 10) == 0){
+ fprintf(stderr, "BINGO %zd\n", Size);
+ for (size_t i = 0; i < Size; i++) {
+ uint8_t C = Data[i];
+ if (C >= 32 && C < 127)
+ fprintf(stderr, "%c", C);
+ }
+ fprintf(stderr, "\n");
+ exit(1);
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/NthRunCrashTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/NthRunCrashTest.cpp
new file mode 100644
index 0000000000..b43e69e51b
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/NthRunCrashTest.cpp
@@ -0,0 +1,18 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Crash on the N-th execution.
+#include <cstdint>
+#include <cstddef>
+#include <iostream>
+
+static int Counter;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Counter++ == 1000) {
+ std::cout << "BINGO; Found the target, exiting\n";
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/NullDerefOnEmptyTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/NullDerefOnEmptyTest.cpp
new file mode 100644
index 0000000000..153710920a
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/NullDerefOnEmptyTest.cpp
@@ -0,0 +1,19 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the empty string.
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+static volatile int *Null = 0;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size == 0) {
+ std::cout << "Found the target, dereferencing NULL\n";
+ *Null = 1;
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/NullDerefTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/NullDerefTest.cpp
new file mode 100644
index 0000000000..3f03d24981
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/NullDerefTest.cpp
@@ -0,0 +1,26 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+static volatile int Sink;
+static volatile int *Null = 0;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ std::cout << "Found the target, dereferencing NULL\n";
+ *Null = 1;
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/OneHugeAllocTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/OneHugeAllocTest.cpp
new file mode 100644
index 0000000000..8d3d1d6d30
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/OneHugeAllocTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Tests OOM handling when there is a single large allocation.
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
+
+static volatile char *SinkPtr;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ if (Size > 1 && Data[1] == 'i') {
+ if (Size > 2 && Data[2] == '!') {
+ size_t kSize = (size_t)1 << 31;
+ char *p = new char[kSize];
+ memset(p, 0, kSize);
+ SinkPtr = p;
+ delete [] p;
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp
new file mode 100644
index 0000000000..ea23a601aa
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/OutOfMemorySingleLargeMallocTest.cpp
@@ -0,0 +1,27 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Tests OOM handling.
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
+
+static volatile char *SinkPtr;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ if (Size > 1 && Data[1] == 'i') {
+ if (Size > 2 && Data[2] == '!') {
+ size_t kSize = 0xff000000U;
+ char *p = new char[kSize];
+ SinkPtr = p;
+ delete [] p;
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/OutOfMemoryTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/OutOfMemoryTest.cpp
new file mode 100644
index 0000000000..078a39ee1f
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/OutOfMemoryTest.cpp
@@ -0,0 +1,31 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Tests OOM handling.
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
+#include <thread>
+
+static volatile char *SinkPtr;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ if (Size > 1 && Data[1] == 'i') {
+ if (Size > 2 && Data[2] == '!') {
+ while (true) {
+ size_t kSize = 1 << 28;
+ char *p = new char[kSize];
+ memset(p, 0, kSize);
+ SinkPtr = p;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/RepeatedBytesTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/RepeatedBytesTest.cpp
new file mode 100644
index 0000000000..2fa6c78c26
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/RepeatedBytesTest.cpp
@@ -0,0 +1,29 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find repeated bytes.
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ // Looking for AAAAAAAAAAAAAAAAAAAAAA or some such.
+ size_t CurA = 0, MaxA = 0;
+ for (size_t i = 0; i < Size; i++) {
+ // Make sure there are no conditionals in the loop so that
+ // coverage can't help the fuzzer.
+ int EQ = Data[i] == 'A';
+ CurA = EQ * (CurA + 1);
+ int GT = CurA > MaxA;
+ MaxA = GT * CurA + (!GT) * MaxA;
+ }
+ if (MaxA >= 20) {
+ std::cout << "BINGO; Found the target (Max: " << MaxA << "), exiting\n";
+ exit(0);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/RepeatedMemcmp.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/RepeatedMemcmp.cpp
new file mode 100644
index 0000000000..a327bbee78
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/RepeatedMemcmp.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+
+#include <cstring>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int Matches = 0;
+ for (size_t i = 0; i + 2 < Size; i += 3) {
+ const char *Pat = i % 2 ? "foo" : "bar";
+ if (!memcmp(Data + i, Pat, 3))
+ Matches++;
+ }
+ if (Matches > 20) {
+ fprintf(stderr, "BINGO!\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/ShrinkControlFlowTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/ShrinkControlFlowTest.cpp
new file mode 100644
index 0000000000..0fd7c5e9a1
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/ShrinkControlFlowTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test that we can find the minimal item in the corpus (3 bytes: "FUZ").
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <cstring>
+#include <cstdio>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ int8_t Ids[256];
+ memset(Ids, -1, sizeof(Ids));
+ for (size_t i = 0; i < Size; i++)
+ if (Ids[Data[i]] == -1)
+ Ids[Data[i]] = i;
+ int F = Ids[(unsigned char)'F'];
+ int U = Ids[(unsigned char)'U'];
+ int Z = Ids[(unsigned char)'Z'];
+ if (F >= 0 && U > F && Z > U) {
+ Sink++;
+ //fprintf(stderr, "IDS: %d %d %d\n", F, U, Z);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/ShrinkValueProfileTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/ShrinkValueProfileTest.cpp
new file mode 100644
index 0000000000..026b8ce265
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/ShrinkValueProfileTest.cpp
@@ -0,0 +1,22 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test that we can find the minimal item in the corpus (3 bytes: "FUZ").
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <cstring>
+#include <cstdio>
+
+static volatile uint32_t Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < sizeof(uint32_t)) return 0;
+ uint32_t X, Y;
+ size_t Offset = Size < 8 ? 0 : Size / 2;
+ memcpy(&X, Data + Offset, sizeof(uint32_t));
+ memcpy(&Y, "FUZZ", sizeof(uint32_t));
+ Sink = X == Y;
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SignedIntOverflowTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SignedIntOverflowTest.cpp
new file mode 100644
index 0000000000..7df32ad579
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SignedIntOverflowTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test for signed-integer-overflow.
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+#include <climits>
+
+static volatile int Sink;
+static int Large = INT_MAX;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ Large++; // int overflow.
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SimpleCmpTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleCmpTest.cpp
new file mode 100644
index 0000000000..0220c30f9a
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleCmpTest.cpp
@@ -0,0 +1,46 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find several narrow ranges.
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+
+extern int AllLines[];
+
+bool PrintOnce(int Line) {
+ if (!AllLines[Line])
+ fprintf(stderr, "Seen line %d\n", Line);
+ AllLines[Line] = 1;
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size != 22) return 0;
+ uint64_t x = 0;
+ int64_t y = 0;
+ int32_t z = 0;
+ uint16_t a = 0;
+ memcpy(&x, Data, 8); // 8
+ memcpy(&y, Data + 8, 8); // 16
+ memcpy(&z, Data + 16, sizeof(z)); // 20
+ memcpy(&a, Data + 20, sizeof(a)); // 22
+
+ if (x > 1234567890 && PrintOnce(__LINE__) &&
+ x < 1234567895 && PrintOnce(__LINE__) &&
+ a == 0x4242 && PrintOnce(__LINE__) &&
+ y >= 987654321 && PrintOnce(__LINE__) &&
+ y <= 987654325 && PrintOnce(__LINE__) &&
+ z < -10000 && PrintOnce(__LINE__) &&
+ z >= -10005 && PrintOnce(__LINE__) &&
+ z != -10003 && PrintOnce(__LINE__) &&
+ true) {
+ fprintf(stderr, "BINGO; Found the target: size %zd (%zd, %zd, %d, %d), exiting.\n",
+ Size, x, y, z, a);
+ exit(1);
+ }
+ return 0;
+}
+
+int AllLines[__LINE__ + 1]; // Must be the last line.
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SimpleDictionaryTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleDictionaryTest.cpp
new file mode 100644
index 0000000000..cd7292bd00
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleDictionaryTest.cpp
@@ -0,0 +1,29 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer.
+// The fuzzer must find a string based on dictionary words:
+// "Elvis"
+// "Presley"
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
+
+static volatile int Zero = 0;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ const char *Expected = "ElvisPresley";
+ if (Size < strlen(Expected)) return 0;
+ size_t Match = 0;
+ for (size_t i = 0; Expected[i]; i++)
+ if (Expected[i] + Zero == Data[i])
+ Match++;
+ if (Match == strlen(Expected)) {
+ std::cout << "BINGO; Found the target, exiting\n";
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SimpleHashTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleHashTest.cpp
new file mode 100644
index 0000000000..00599de78e
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleHashTest.cpp
@@ -0,0 +1,40 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// This test computes a checksum of the data (all but the last 4 bytes),
+// and then compares the last 4 bytes with the computed value.
+// A fuzzer with cmp traces is expected to defeat this check.
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+
+// A modified jenkins_one_at_a_time_hash initialized by non-zero,
+// so that simple_hash(0) != 0. See also
+// https://en.wikipedia.org/wiki/Jenkins_hash_function
+static uint32_t simple_hash(const uint8_t *Data, size_t Size) {
+ uint32_t Hash = 0x12039854;
+ for (uint32_t i = 0; i < Size; i++) {
+ Hash += Data[i];
+ Hash += (Hash << 10);
+ Hash ^= (Hash >> 6);
+ }
+ Hash += (Hash << 3);
+ Hash ^= (Hash >> 11);
+ Hash += (Hash << 15);
+ return Hash;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 14)
+ return 0;
+
+ uint32_t Hash = simple_hash(&Data[0], Size - 4);
+ uint32_t Want = reinterpret_cast<const uint32_t *>(&Data[Size - 4])[0];
+ if (Hash != Want)
+ return 0;
+ fprintf(stderr, "BINGO; simple_hash defeated: %x == %x\n", (unsigned int)Hash,
+ (unsigned int)Want);
+ exit(1);
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SimpleTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleTest.cpp
new file mode 100644
index 0000000000..e53ea160ed
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleTest.cpp
@@ -0,0 +1,27 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ std::cout << "BINGO; Found the target, exiting\n";
+ exit(0);
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SimpleThreadedTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleThreadedTest.cpp
new file mode 100644
index 0000000000..5f02d3f845
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SimpleThreadedTest.cpp
@@ -0,0 +1,25 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Threaded test for a fuzzer. The fuzzer should find "H"
+#include <assert.h>
+#include <cstdint>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
+#include <thread>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ auto C = [&] {
+ if (Size >= 2 && Data[0] == 'H') {
+ std::cout << "BINGO; Found the target, exiting\n";
+ abort();
+ }
+ };
+ std::thread T[] = {std::thread(C), std::thread(C), std::thread(C),
+ std::thread(C), std::thread(C), std::thread(C)};
+ for (auto &X : T)
+ X.join();
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SingleMemcmpTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SingleMemcmpTest.cpp
new file mode 100644
index 0000000000..c73f68a7ee
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SingleMemcmpTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstring>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ char *S = (char*)Data;
+ if (Size >= 6 && !memcmp(S, "qwerty", 6)) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SingleStrcmpTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SingleStrcmpTest.cpp
new file mode 100644
index 0000000000..73470b527e
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SingleStrcmpTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstring>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ char *S = (char*)Data;
+ if (Size >= 7 && !strcmp(S, "qwerty")) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SingleStrncmpTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SingleStrncmpTest.cpp
new file mode 100644
index 0000000000..dbcc464b0a
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SingleStrncmpTest.cpp
@@ -0,0 +1,17 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstring>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ char *S = (char*)Data;
+ if (Size >= 6 && !strncmp(S, "qwerty", 6)) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SpamyTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SpamyTest.cpp
new file mode 100644
index 0000000000..d294d4dc53
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SpamyTest.cpp
@@ -0,0 +1,21 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// The test spams to stderr and stdout.
+#include <assert.h>
+#include <cstdint>
+#include <cstdio>
+#include <cstddef>
+#include <iostream>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ assert(Data);
+ printf("PRINTF_STDOUT\n");
+ fflush(stdout);
+ fprintf(stderr, "PRINTF_STDERR\n");
+ std::cout << "STREAM_COUT\n";
+ std::cout.flush();
+ std::cerr << "STREAM_CERR\n";
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/StrcmpTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/StrcmpTest.cpp
new file mode 100644
index 0000000000..cd91dda76f
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/StrcmpTest.cpp
@@ -0,0 +1,32 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Break through a series of strcmp.
+#include <cstring>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cassert>
+
+bool Eq(const uint8_t *Data, size_t Size, const char *Str) {
+ char Buff[1024];
+ size_t Len = strlen(Str);
+ if (Size < Len) return false;
+ if (Len >= sizeof(Buff)) return false;
+ memcpy(Buff, (char*)Data, Len);
+ Buff[Len] = 0;
+ int res = strcmp(Buff, Str);
+ return res == 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Eq(Data, Size, "ABC") &&
+ Size >= 3 && Eq(Data + 3, Size - 3, "QWER") &&
+ Size >= 7 && Eq(Data + 7, Size - 7, "ZXCVN") &&
+ Size >= 14 && Data[13] == 42
+ ) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/StrncmpOOBTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/StrncmpOOBTest.cpp
new file mode 100644
index 0000000000..f70b003afa
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/StrncmpOOBTest.cpp
@@ -0,0 +1,21 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test that libFuzzer itself does not read out of bounds.
+#include <assert.h>
+#include <cstdint>
+#include <cstring>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 5) return 0;
+ const char *Ch = reinterpret_cast<const char *>(Data);
+ if (Ch[Size - 3] == 'a')
+ Sink = strncmp(Ch + Size - 3, "abcdefg", 6);
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/StrncmpTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/StrncmpTest.cpp
new file mode 100644
index 0000000000..5ffd011dcd
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/StrncmpTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find a particular string.
+#include <cstring>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+static volatile int sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ // TODO: check other sizes.
+ char *S = (char*)Data;
+ if (Size >= 8 && strncmp(S, "123", 8))
+ sink = 1;
+ if (Size >= 8 && strncmp(S, "01234567", 8) == 0) {
+ if (Size >= 12 && strncmp(S + 8, "ABCD", 4) == 0) {
+ if (Size >= 14 && strncmp(S + 12, "XY", 2) == 0) {
+ if (Size >= 17 && strncmp(S + 14, "KLM", 3) == 0) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ }
+ }
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/StrstrTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/StrstrTest.cpp
new file mode 100644
index 0000000000..f021e75ec0
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/StrstrTest.cpp
@@ -0,0 +1,28 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Test strstr and strcasestr hooks.
+#include <string>
+#include <string.h>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+
+// Windows does not have strcasestr and memmem, so we are not testing them.
+#ifdef _WIN32
+#define strcasestr strstr
+#define memmem(a, b, c, d) true
+#endif
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 4) return 0;
+ std::string s(reinterpret_cast<const char*>(Data), Size);
+ if (strstr(s.c_str(), "FUZZ") &&
+ strcasestr(s.c_str(), "aBcD") &&
+ memmem(s.data(), s.size(), "kuku", 4)
+ ) {
+ fprintf(stderr, "BINGO\n");
+ exit(1);
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SwapCmpTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SwapCmpTest.cpp
new file mode 100644
index 0000000000..f79db4ccf7
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SwapCmpTest.cpp
@@ -0,0 +1,34 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// The fuzzer must find several constants with swapped bytes.
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 14) return 0;
+ uint64_t x = 0;
+ uint32_t y = 0;
+ uint16_t z = 0;
+ memcpy(&x, Data, sizeof(x));
+ memcpy(&y, Data + Size / 2, sizeof(y));
+ memcpy(&z, Data + Size - sizeof(z), sizeof(z));
+
+ x = __builtin_bswap64(x);
+ y = __builtin_bswap32(y);
+ z = __builtin_bswap16(z);
+
+ if (x == 0x46555A5A5A5A5546ULL &&
+ z == 0x4F4B &&
+ y == 0x66757A7A &&
+ true
+ ) {
+ if (Data[Size - 3] == 'z') {
+ fprintf(stderr, "BINGO; Found the target\n");
+ exit(1);
+ }
+ }
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/Switch2Test.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/Switch2Test.cpp
new file mode 100644
index 0000000000..3c6a300490
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/Switch2Test.cpp
@@ -0,0 +1,35 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the interesting switch value.
+#include <cstdint>
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <cstddef>
+
+int Switch(int a) {
+ switch(a) {
+ case 100001: return 1;
+ case 100002: return 2;
+ case 100003: return 4;
+ }
+ return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ const int N = 3;
+ if (Size < N * sizeof(int)) return 0;
+ int Res = 0;
+ for (int i = 0; i < N; i++) {
+ int X;
+ memcpy(&X, Data + i * sizeof(int), sizeof(int));
+ Res += Switch(X);
+ }
+ if (Res == 5 || Res == 3 || Res == 6 || Res == 7) {
+ fprintf(stderr, "BINGO; Found the target, exiting; Res=%d\n", Res);
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/SwitchTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/SwitchTest.cpp
new file mode 100644
index 0000000000..74e86c06cb
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/SwitchTest.cpp
@@ -0,0 +1,58 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the interesting switch value.
+#include <cstdint>
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <cstddef>
+
+static volatile int Sink;
+
+template<class T>
+bool Switch(const uint8_t *Data, size_t Size) {
+ T X;
+ if (Size < sizeof(X)) return false;
+ memcpy(&X, Data, sizeof(X));
+ switch (X) {
+ case 1: Sink = __LINE__; break;
+ case 101: Sink = __LINE__; break;
+ case 1001: Sink = __LINE__; break;
+ case 10001: Sink = __LINE__; break;
+// case 100001: Sink = __LINE__; break;
+// case 1000001: Sink = __LINE__; break;
+ case 10000001: Sink = __LINE__; break;
+ case 100000001: return true;
+ }
+ return false;
+}
+
+bool ShortSwitch(const uint8_t *Data, size_t Size) {
+ short X;
+ if (Size < sizeof(short)) return false;
+ memcpy(&X, Data, sizeof(short));
+ switch(X) {
+ case 42: Sink = __LINE__; break;
+ case 402: Sink = __LINE__; break;
+ case 4002: Sink = __LINE__; break;
+ case 5002: Sink = __LINE__; break;
+ case 7002: Sink = __LINE__; break;
+ case 9002: Sink = __LINE__; break;
+ case 14002: Sink = __LINE__; break;
+ case 21402: return true;
+ }
+ return false;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size >= 4 && Switch<int>(Data, Size) &&
+ Size >= 12 && Switch<uint64_t>(Data + 4, Size - 4) &&
+ Size >= 14 && ShortSwitch(Data + 12, 2)
+ ) {
+ fprintf(stderr, "BINGO; Found the target, exiting\n");
+ exit(1);
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/ThreadedLeakTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/ThreadedLeakTest.cpp
new file mode 100644
index 0000000000..7511071108
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/ThreadedLeakTest.cpp
@@ -0,0 +1,18 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// The fuzzer should find a leak in a non-main thread.
+#include <cstdint>
+#include <cstddef>
+#include <thread>
+
+static volatile int *Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size == 0) return 0;
+ if (Data[0] != 'F') return 0;
+ std::thread T([&] { Sink = new int; });
+ T.join();
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/ThreadedTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/ThreadedTest.cpp
new file mode 100644
index 0000000000..09137a9a70
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/ThreadedTest.cpp
@@ -0,0 +1,26 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Threaded test for a fuzzer. The fuzzer should not crash.
+#include <assert.h>
+#include <cstdint>
+#include <cstddef>
+#include <cstring>
+#include <thread>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size < 8) return 0;
+ assert(Data);
+ auto C = [&] {
+ size_t Res = 0;
+ for (size_t i = 0; i < Size / 2; i++)
+ Res += memcmp(Data, Data + Size / 2, 4);
+ return Res;
+ };
+ std::thread T[] = {std::thread(C), std::thread(C), std::thread(C),
+ std::thread(C), std::thread(C), std::thread(C)};
+ for (auto &X : T)
+ X.join();
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/TimeoutEmptyTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/TimeoutEmptyTest.cpp
new file mode 100644
index 0000000000..8066f480b6
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/TimeoutEmptyTest.cpp
@@ -0,0 +1,14 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the empty string.
+#include <cstdint>
+#include <cstddef>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ static volatile int Zero = 0;
+ if (!Size)
+ while(!Zero)
+ ;
+ return 0;
+}
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/TimeoutTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/TimeoutTest.cpp
new file mode 100644
index 0000000000..f8107012c8
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/TimeoutTest.cpp
@@ -0,0 +1,26 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Simple test for a fuzzer. The fuzzer must find the string "Hi!".
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+static volatile int Sink;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 0 && Data[0] == 'H') {
+ Sink = 1;
+ if (Size > 1 && Data[1] == 'i') {
+ Sink = 2;
+ if (Size > 2 && Data[2] == '!') {
+ Sink = 2;
+ while (Sink)
+ ;
+ }
+ }
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/TraceMallocTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/TraceMallocTest.cpp
new file mode 100644
index 0000000000..43e6950e18
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/TraceMallocTest.cpp
@@ -0,0 +1,27 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// Tests -trace_malloc
+#include <assert.h>
+#include <cstdint>
+#include <cstdlib>
+#include <cstddef>
+#include <iostream>
+
+int *Ptr;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (!Size) return 0;
+ if (*Data == 1) {
+ delete Ptr;
+ Ptr = nullptr;
+ } else if (*Data == 2) {
+ delete Ptr;
+ Ptr = new int;
+ } else if (*Data == 3) {
+ if (!Ptr)
+ Ptr = new int;
+ }
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/UninstrumentedTest.cpp b/json4cpp/tests/thirdparty/Fuzzer/test/UninstrumentedTest.cpp
new file mode 100644
index 0000000000..ffe952c749
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/UninstrumentedTest.cpp
@@ -0,0 +1,11 @@
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+
+// This test should not be instrumented.
+#include <cstdint>
+#include <cstddef>
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ return 0;
+}
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/afl-driver-extra-stats.test b/json4cpp/tests/thirdparty/Fuzzer/test/afl-driver-extra-stats.test
new file mode 100644
index 0000000000..81e384e7da
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/afl-driver-extra-stats.test
@@ -0,0 +1,28 @@
+; Test that not specifying an extra stats file isn't broken.
+RUN: unset AFL_DRIVER_EXTRA_STATS_FILENAME
+RUN: AFLDriverTest
+
+; Test that specifying an invalid extra stats file causes a crash.
+RUN: ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%T not --crash AFLDriverTest
+
+; Test that specifying a corrupted stats file causes a crash.
+echo "peak_rss_mb :0" > %t
+ASAN_OPTIONS= AFL_DRIVER_EXTRA_STATS_FILENAME=%t not --crash AFLDriverTest
+
+; Test that specifying a valid nonexistent stats file works.
+RUN: rm -f %t
+RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t AFLDriverTest
+RUN: [[ $(grep "peak_rss_mb\|slowest_unit_time_sec" %t | wc -l) -eq 2 ]]
+
+; Test that specifying a valid preexisting stats file works.
+RUN: printf "peak_rss_mb : 0\nslowest_unit_time_sec: 0\n" > %t
+RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t AFLDriverTest
+; Check that both lines were printed.
+RUN: [[ $(grep "peak_rss_mb\|slowest_unit_time_sec" %t | wc -l) -eq 2 ]]
+
+; Test that peak_rss_mb and slowest_unit_time_in_secs are only updated when necessary.
+; Check that both lines have 9999 since there's no way we have exceeded that
+; amount of time or virtual memory.
+RUN: printf "peak_rss_mb : 9999\nslowest_unit_time_sec: 9999\n" > %t
+RUN: AFL_DRIVER_EXTRA_STATS_FILENAME=%t AFLDriverTest
+RUN: [[ $(grep "9999" %t | wc -l) -eq 2 ]]
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/afl-driver-stderr.test b/json4cpp/tests/thirdparty/Fuzzer/test/afl-driver-stderr.test
new file mode 100644
index 0000000000..c0f9c8398c
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/afl-driver-stderr.test
@@ -0,0 +1,10 @@
+; Test that not specifying a stderr file isn't broken.
+RUN: unset AFL_DRIVER_STDERR_DUPLICATE_FILENAME
+RUN: AFLDriverTest
+
+; Test that specifying an invalid file causes a crash.
+RUN: ASAN_OPTIONS= AFL_DRIVER_STDERR_DUPLICATE_FILENAME="%T" not --crash AFLDriverTest
+
+; Test that a file is created when specified as the duplicate stderr.
+RUN: AFL_DRIVER_STDERR_DUPLICATE_FILENAME=%t AFLDriverTest
+RUN: stat %t
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/caller-callee.test b/json4cpp/tests/thirdparty/Fuzzer/test/caller-callee.test
new file mode 100644
index 0000000000..76a951c5e0
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/caller-callee.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-CallerCalleeTest -use_value_profile=1 -cross_over=0 -max_len=6 -seed=1 -runs=10000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/coverage.test b/json4cpp/tests/thirdparty/Fuzzer/test/coverage.test
new file mode 100644
index 0000000000..fa11be502e
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/coverage.test
@@ -0,0 +1,19 @@
+CHECK: COVERAGE:
+CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:13
+CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:14
+CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:16
+CHECK-DAG: COVERED: {{.*}}in LLVMFuzzerTestOneInput {{.*}}NullDerefTest.cpp:19
+CHECK: COVERED_DIRS: {{.*}}lib/Fuzzer/test
+RUN: not LLVMFuzzer-NullDerefTest -print_coverage=1 2>&1 | FileCheck %s
+
+RUN: LLVMFuzzer-DSOTest -print_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO
+DSO: COVERAGE:
+DSO-DAG: COVERED:{{.*}}DSO1{{.*}}DSO1.cpp
+DSO-DAG: COVERED:{{.*}}DSO2{{.*}}DSO2.cpp
+DSO-DAG: COVERED:{{.*}}LLVMFuzzerTestOneInput{{.*}}DSOTestMain
+DSO-DAG: UNCOVERED_LINE:{{.*}}DSO1{{.*}}DSO1.cpp
+DSO-DAG: UNCOVERED_LINE:{{.*}}DSO2{{.*}}DSO2.cpp
+DSO-DAG: UNCOVERED_FUNC: in Uncovered1
+DSO-DAG: UNCOVERED_FUNC: in Uncovered2
+DSO-DAG: UNCOVERED_LINE: in LLVMFuzzerTestOneInput
+DSO-DAG: UNCOVERED_FILE:{{.*}}DSOTestExtra.cpp
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/dict1.txt b/json4cpp/tests/thirdparty/Fuzzer/test/dict1.txt
new file mode 100644
index 0000000000..520d0cc7b7
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/dict1.txt
@@ -0,0 +1,4 @@
+# Dictionary for SimpleDictionaryTest
+
+a="Elvis"
+b="Presley"
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/dump_coverage.test b/json4cpp/tests/thirdparty/Fuzzer/test/dump_coverage.test
new file mode 100644
index 0000000000..9bd98daa36
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/dump_coverage.test
@@ -0,0 +1,16 @@
+RUN: DIR=%t_workdir
+RUN: BUILD_DIR=$(pwd)
+RUN: rm -rf $DIR && mkdir -p $DIR && cd $DIR
+RUN: not $BUILD_DIR/LLVMFuzzer-NullDerefTest -dump_coverage=1 2>&1 | FileCheck %s
+RUN: $BUILD_DIR/LLVMFuzzer-DSOTest -dump_coverage=1 -runs=0 2>&1 | FileCheck %s --check-prefix=DSO
+RUN: not $BUILD_DIR/LLVMFuzzer-NullDerefTest -dump_coverage=0 2>&1 | FileCheck %s --check-prefix=NOCOV
+RUN: rm -rf $DIR
+
+
+CHECK: SanitizerCoverage: ./LLVMFuzzer-NullDerefTest.{{.*}}.sancov {{.*}} PCs written
+
+DSO: SanitizerCoverage: ./LLVMFuzzer-DSOTest.{{.*}}.sancov {{.*}} PCs written
+DSO-DAG: SanitizerCoverage: ./libLLVMFuzzer-DSO1.{{.*}}.sancov {{.*}} PCs written
+DSO-DAG: SanitizerCoverage: ./libLLVMFuzzer-DSO2.{{.*}}.sancov {{.*}} PCs written
+
+NOCOV-NOT: SanitizerCoverage: {{.*}} PCs written
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-customcrossover.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-customcrossover.test
new file mode 100644
index 0000000000..28d39ce31d
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-customcrossover.test
@@ -0,0 +1,10 @@
+RUN: rm -rf %t/CustomCrossover
+RUN: mkdir -p %t/CustomCrossover
+RUN: echo "0123456789" > %t/CustomCrossover/digits
+RUN: echo "abcdefghij" > %t/CustomCrossover/chars
+RUN: not LLVMFuzzer-CustomCrossOverTest -seed=1 -use_memcmp=0 -runs=100000 %t/CustomCrossover 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomCrossover
+RUN: rm -rf %t/CustomCrossover
+
+LLVMFuzzerCustomCrossover: In LLVMFuzzerCustomCrossover
+LLVMFuzzerCustomCrossover: BINGO
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-custommutator.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-custommutator.test
new file mode 100644
index 0000000000..fcd740bf54
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-custommutator.test
@@ -0,0 +1,4 @@
+RUN: not LLVMFuzzer-CustomMutatorTest 2>&1 | FileCheck %s --check-prefix=LLVMFuzzerCustomMutator
+LLVMFuzzerCustomMutator: In LLVMFuzzerCustomMutator
+LLVMFuzzerCustomMutator: BINGO
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-dict.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-dict.test
new file mode 100644
index 0000000000..dec002f6a3
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-dict.test
@@ -0,0 +1,6 @@
+CHECK: BINGO
+Done1000000: Done 1000000 runs in
+
+RUN: not LLVMFuzzer-SimpleDictionaryTest -dict=%S/dict1.txt -seed=1 -runs=1000003 2>&1 | FileCheck %s
+RUN: LLVMFuzzer-SimpleDictionaryTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-dirs.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-dirs.test
new file mode 100644
index 0000000000..63afe8dfcf
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-dirs.test
@@ -0,0 +1,15 @@
+RUN: rm -rf %t/SUB1
+RUN: mkdir -p %t/SUB1/SUB2/SUB3
+RUN: echo a > %t/SUB1/a
+RUN: echo b > %t/SUB1/SUB2/b
+RUN: echo c > %t/SUB1/SUB2/SUB3/c
+RUN: LLVMFuzzer-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=SUBDIRS
+SUBDIRS: READ units: 3
+RUN: echo zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz > %t/SUB1/long
+RUN: LLVMFuzzer-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=LONG
+LONG: INFO: -max_len is not provided, using 94
+RUN: rm -rf %t/SUB1
+
+RUN: not LLVMFuzzer-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR
+NONEXISTENT_DIR: No such directory: NONEXISTENT_DIR; exiting
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-fdmask.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-fdmask.test
new file mode 100644
index 0000000000..abbc4bd641
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-fdmask.test
@@ -0,0 +1,30 @@
+RUN: LLVMFuzzer-SpamyTest -runs=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_0
+RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=0 2>&1 | FileCheck %s --check-prefix=FD_MASK_0
+RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=1 2>&1 | FileCheck %s --check-prefix=FD_MASK_1
+RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=2 2>&1 | FileCheck %s --check-prefix=FD_MASK_2
+RUN: LLVMFuzzer-SpamyTest -runs=1 -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=FD_MASK_3
+
+FD_MASK_0: PRINTF_STDOUT
+FD_MASK_0: PRINTF_STDERR
+FD_MASK_0: STREAM_COUT
+FD_MASK_0: STREAM_CERR
+FD_MASK_0: INITED
+
+FD_MASK_1-NOT: PRINTF_STDOUT
+FD_MASK_1: PRINTF_STDERR
+FD_MASK_1-NOT: STREAM_COUT
+FD_MASK_1: STREAM_CERR
+FD_MASK_1: INITED
+
+FD_MASK_2: PRINTF_STDOUT
+FD_MASK_2-NOT: PRINTF_STDERR
+FD_MASK_2: STREAM_COUT
+FD_MASK_2-NOTE: STREAM_CERR
+FD_MASK_2: INITED
+
+FD_MASK_3-NOT: PRINTF_STDOUT
+FD_MASK_3-NOT: PRINTF_STDERR
+FD_MASK_3-NOT: STREAM_COUT
+FD_MASK_3-NOT: STREAM_CERR
+FD_MASK_3: INITED
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-finalstats.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-finalstats.test
new file mode 100644
index 0000000000..1cbcd10f04
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-finalstats.test
@@ -0,0 +1,11 @@
+RUN: LLVMFuzzer-SimpleTest -seed=1 -runs=77 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS
+FINAL_STATS: stat::number_of_executed_units: 77
+FINAL_STATS: stat::average_exec_per_sec: 0
+FINAL_STATS: stat::new_units_added:
+FINAL_STATS: stat::slowest_unit_time_sec: 0
+FINAL_STATS: stat::peak_rss_mb:
+
+RUN: LLVMFuzzer-SimpleTest %S/dict1.txt -runs=33 -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=FINAL_STATS1
+FINAL_STATS1: stat::number_of_executed_units: 33
+FINAL_STATS1: stat::peak_rss_mb:
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-flags.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-flags.test
new file mode 100644
index 0000000000..76ea277057
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-flags.test
@@ -0,0 +1,10 @@
+RUN: LLVMFuzzer-SimpleTest -foo_bar=1 2>&1 | FileCheck %s --check-prefix=FOO_BAR
+FOO_BAR: WARNING: unrecognized flag '-foo_bar=1'; use -help=1 to list all flags
+FOO_BAR: BINGO
+
+RUN: LLVMFuzzer-SimpleTest -runs=10 --max_len=100 2>&1 | FileCheck %s --check-prefix=DASH_DASH
+DASH_DASH: WARNING: did you mean '-max_len=100' (single dash)?
+DASH_DASH: INFO: A corpus is not provided, starting from an empty corpus
+
+RUN: LLVMFuzzer-SimpleTest -help=1 2>&1 | FileCheck %s --check-prefix=NO_INTERNAL
+NO_INTERNAL-NOT: internal flag
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-jobs.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-jobs.test
new file mode 100644
index 0000000000..5bf8cfadfb
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-jobs.test
@@ -0,0 +1,29 @@
+RUN: rm -rf %tmp
+RUN: mkdir %tmp && cd %tmp
+# Create a shared corpus directory
+RUN: rm -rf FuzzerJobsTestCORPUS
+RUN: mkdir FuzzerJobsTestCORPUS
+RUN: rm -f fuzz-{0,1}.log
+# Start fuzzer and in parallel check that the output files
+# that should be created exist.
+RUN: LLVMFuzzer-EmptyTest -max_total_time=4 -jobs=2 -workers=2 FuzzerJobsTestCORPUS > %t-fuzzer-jobs-test.log 2>&1 & export FUZZER_PID=$!
+# Wait a short while to give time for the child processes
+# to start fuzzing
+RUN: sleep 2
+# If the instances are running in parallel they should have created their log
+# files by now.
+RUN: ls fuzz-0.log
+RUN: ls fuzz-1.log
+# Wait for libfuzzer to finish.
+# This probably isn't portable but we need a way to block until
+# the fuzzer is done otherwise we might remove the files while
+# they are being used.
+RUN: while kill -0 ${FUZZER_PID}; do : ; done
+RUN: rm -f fuzz-{0,1}.log
+RUN: rm -rf FuzzerJobsTestCORPUS
+RUN: FileCheck -input-file=%t-fuzzer-jobs-test.log %s
+RUN: rm %t-fuzzer-jobs-test.log
+RUN: cd ../
+
+CHECK-DAG: Job 0 exited with exit code 0
+CHECK-DAG: Job 1 exited with exit code 0
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-leak.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-leak.test
new file mode 100644
index 0000000000..9cf5c743ff
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-leak.test
@@ -0,0 +1,35 @@
+REQUIRES: lsan
+RUN: not LLVMFuzzer-LeakTest -runs=100000 -detect_leaks=1 2>&1 | FileCheck %s --check-prefix=LEAK_DURING
+LEAK_DURING: ERROR: LeakSanitizer: detected memory leaks
+LEAK_DURING: Direct leak of 4 byte(s) in 1 object(s) allocated from:
+LEAK_DURING: INFO: to ignore leaks on libFuzzer side use -detect_leaks=0
+LEAK_DURING: Test unit written to ./leak-
+LEAK_DURING-NOT: DONE
+LEAK_DURING-NOT: Done
+
+RUN: not LLVMFuzzer-LeakTest -runs=0 -detect_leaks=1 %S 2>&1 | FileCheck %s --check-prefix=LEAK_IN_CORPUS
+LEAK_IN_CORPUS: ERROR: LeakSanitizer: detected memory leaks
+LEAK_IN_CORPUS: INFO: a leak has been found in the initial corpus.
+
+RUN: not LLVMFuzzer-LeakTest -runs=100000000 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=MULTI_RUN_LEAK
+MULTI_RUN_LEAK-NOT: pulse
+MULTI_RUN_LEAK: LeakSanitizer: detected memory leaks
+
+RUN: not LLVMFuzzer-LeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER
+RUN: not LLVMFuzzer-LeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING
+RUN: not LLVMFuzzer-ThreadedLeakTest -runs=100000 -detect_leaks=0 2>&1 | FileCheck %s --check-prefix=LEAK_AFTER
+RUN: not LLVMFuzzer-ThreadedLeakTest -runs=100000 2>&1 | FileCheck %s --check-prefix=LEAK_DURING
+LEAK_AFTER: Done 100000 runs in
+LEAK_AFTER: ERROR: LeakSanitizer: detected memory leaks
+
+RUN: not LLVMFuzzer-LeakTest -runs=100000 -max_len=1 2>&1 | FileCheck %s --check-prefix=MAX_LEN_1
+MAX_LEN_1: Test unit written to ./leak-7cf184f4c67ad58283ecb19349720b0cae756829
+
+RUN: not LLVMFuzzer-LeakTimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=LEAK_TIMEOUT
+LEAK_TIMEOUT: ERROR: libFuzzer: timeout after
+LEAK_TIMEOUT-NOT: LeakSanitizer
+
+RUN: LLVMFuzzer-AccumulateAllocationsTest -detect_leaks=1 -runs=100000 2>&1 | FileCheck %s --check-prefix=ACCUMULATE_ALLOCS
+ACCUMULATE_ALLOCS: INFO: libFuzzer disabled leak detection after every mutation
+
+RUN: LLVMFuzzer-LeakTest -error_exitcode=0
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-oom-with-profile.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-oom-with-profile.test
new file mode 100644
index 0000000000..2b2b0b9d5d
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-oom-with-profile.test
@@ -0,0 +1,6 @@
+REQUIRES: linux
+RUN: not LLVMFuzzer-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s
+CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb)
+CHECK: Live Heap Allocations
+CHECK: Test unit written to ./oom-
+SUMMARY: libFuzzer: out-of-memory
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-oom.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-oom.test
new file mode 100644
index 0000000000..8caf649e9f
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-oom.test
@@ -0,0 +1,11 @@
+RUN: not LLVMFuzzer-OutOfMemoryTest -rss_limit_mb=300 2>&1 | FileCheck %s
+CHECK: ERROR: libFuzzer: out-of-memory (used: {{.*}}; limit: 300Mb)
+CHECK: Test unit written to ./oom-
+SUMMARY: libFuzzer: out-of-memory
+
+RUN: not LLVMFuzzer-OutOfMemorySingleLargeMallocTest 2>&1 | FileCheck %s --check-prefix=SINGLE_LARGE_MALLOC
+SINGLE_LARGE_MALLOC: libFuzzer: out-of-memory (malloc(42{{.*}}))
+SINGLE_LARGE_MALLOC: in LLVMFuzzerTestOneInput
+
+# Check that -rss_limit_mb=0 means no limit.
+RUN: LLVMFuzzer-AccumulateAllocationsTest -runs=1000 -rss_limit_mb=0
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-printcovpcs.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-printcovpcs.test
new file mode 100644
index 0000000000..e4c6f0ed1d
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-printcovpcs.test
@@ -0,0 +1,8 @@
+RUN: LLVMFuzzer-SimpleTest -print_pcs=1 -seed=1 2>&1 | FileCheck %s --check-prefix=PCS
+PCS-NOT: NEW_PC
+PCS:INITED
+PCS:NEW_PC: {{0x[a-f0-9]+}}
+PCS:NEW_PC: {{0x[a-f0-9]+}}
+PCS:NEW
+PCS:BINGO
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-runs.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-runs.test
new file mode 100644
index 0000000000..056c44782a
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-runs.test
@@ -0,0 +1,8 @@
+RUN: mkdir -p %t
+RUN: echo abcd > %t/NthRunCrashTest.in
+RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in
+RUN: LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10
+RUN: not LLVMFuzzer-NthRunCrashTest %t/NthRunCrashTest.in -runs=10000 2>&1 | FileCheck %s
+RUN: rm %t/NthRunCrashTest.in
+CHECK: BINGO
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-seed.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-seed.test
new file mode 100644
index 0000000000..f1bdf9e4ae
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-seed.test
@@ -0,0 +1,3 @@
+RUN: LLVMFuzzer-SimpleCmpTest -seed=-1 -runs=0 2>&1 | FileCheck %s --check-prefix=CHECK_SEED_MINUS_ONE
+CHECK_SEED_MINUS_ONE: Seed: 4294967295
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-segv.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-segv.test
new file mode 100644
index 0000000000..330f03bcc4
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-segv.test
@@ -0,0 +1,5 @@
+RUN: ASAN_OPTIONS=handle_segv=0 not LLVMFuzzer-NullDerefTest 2>&1 | FileCheck %s --check-prefix=LIBFUZZER_OWN_SEGV_HANDLER
+LIBFUZZER_OWN_SEGV_HANDLER: == ERROR: libFuzzer: deadly signal
+LIBFUZZER_OWN_SEGV_HANDLER: SUMMARY: libFuzzer: deadly signal
+LIBFUZZER_OWN_SEGV_HANDLER: Test unit written to ./crash-
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-singleinputs.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-singleinputs.test
new file mode 100644
index 0000000000..ca8403bff8
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-singleinputs.test
@@ -0,0 +1,16 @@
+RUN: not LLVMFuzzer-NullDerefTest %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInput
+SingleInput-NOT: Test unit written to ./crash-
+
+RUN: rm -rf %tmp/SINGLE_INPUTS
+RUN: mkdir -p %tmp/SINGLE_INPUTS
+RUN: echo aaa > %tmp/SINGLE_INPUTS/aaa
+RUN: echo bbb > %tmp/SINGLE_INPUTS/bbb
+RUN: LLVMFuzzer-SimpleTest %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS
+RUN: LLVMFuzzer-SimpleTest -max_len=2 %tmp/SINGLE_INPUTS/aaa %tmp/SINGLE_INPUTS/bbb 2>&1 | FileCheck %s --check-prefix=SINGLE_INPUTS
+RUN: rm -rf %tmp/SINGLE_INPUTS
+SINGLE_INPUTS: LLVMFuzzer-SimpleTest: Running 2 inputs 1 time(s) each.
+SINGLE_INPUTS: aaa in
+SINGLE_INPUTS: bbb in
+SINGLE_INPUTS: NOTE: fuzzing was not performed, you have only
+SINGLE_INPUTS: executed the target code on a fixed set of inputs.
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-threaded.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-threaded.test
new file mode 100644
index 0000000000..c58a33456c
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-threaded.test
@@ -0,0 +1,7 @@
+CHECK: Done 1000 runs in
+
+RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s
+RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s
+RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s
+RUN: LLVMFuzzer-ThreadedTest -use_traces=1 -runs=1000 2>&1 | FileCheck %s
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-timeout.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-timeout.test
new file mode 100644
index 0000000000..beb0867118
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-timeout.test
@@ -0,0 +1,19 @@
+RUN: not LLVMFuzzer-TimeoutTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutTest
+TimeoutTest: ALARM: working on the last Unit for
+TimeoutTest: Test unit written to ./timeout-
+TimeoutTest: == ERROR: libFuzzer: timeout after
+TimeoutTest: #0
+TimeoutTest: #1
+TimeoutTest: #2
+TimeoutTest: SUMMARY: libFuzzer: timeout
+
+RUN: not LLVMFuzzer-TimeoutTest -timeout=1 %S/hi.txt 2>&1 | FileCheck %s --check-prefix=SingleInputTimeoutTest
+SingleInputTimeoutTest: ALARM: working on the last Unit for {{[1-3]}} seconds
+SingleInputTimeoutTest-NOT: Test unit written to ./timeout-
+
+RUN: LLVMFuzzer-TimeoutTest -timeout=1 -timeout_exitcode=0
+
+RUN: not LLVMFuzzer-TimeoutEmptyTest -timeout=1 2>&1 | FileCheck %s --check-prefix=TimeoutEmptyTest
+TimeoutEmptyTest: ALARM: working on the last Unit for
+TimeoutEmptyTest: == ERROR: libFuzzer: timeout after
+TimeoutEmptyTest: SUMMARY: libFuzzer: timeout
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-traces-hooks.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-traces-hooks.test
new file mode 100644
index 0000000000..71fe6f2daf
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-traces-hooks.test
@@ -0,0 +1,25 @@
+// FIXME: Support sanitizer hooks for memcmp and strcmp need
+// to be implemented in the sanitizer runtime for platforms other
+// than linux
+REQUIRES: linux
+CHECK: BINGO
+Done1000000: Done 1000000 runs in
+
+RUN: not LLVMFuzzer-MemcmpTest -seed=4294967295 -runs=100000 2>&1 | FileCheck %s
+RUN: LLVMFuzzer-MemcmpTest -use_memcmp=0 -seed=4294967295 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
+
+RUN: not LLVMFuzzer-StrncmpTest -seed=2 -runs=100000 2>&1 | FileCheck %s
+RUN: LLVMFuzzer-StrncmpTest -use_memcmp=0 -seed=3 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
+
+RUN: not LLVMFuzzer-StrcmpTest -seed=4 -runs=200000 2>&1 | FileCheck %s
+RUN: LLVMFuzzer-StrcmpTest -use_memcmp=0 -seed=5 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
+
+RUN: not LLVMFuzzer-StrstrTest -seed=6 -runs=200000 2>&1 | FileCheck %s
+RUN: LLVMFuzzer-StrstrTest -use_memmem=0 -seed=7 -runs=1000000 2>&1 | FileCheck %s --check-prefix=Done1000000
+
+RUN: LLVMFuzzer-RepeatedMemcmp -seed=10 -runs=100000 2>&1 | FileCheck %s --check-prefix=RECOMMENDED_DICT
+RECOMMENDED_DICT:###### Recommended dictionary. ######
+RECOMMENDED_DICT-DAG: "foo"
+RECOMMENDED_DICT-DAG: "bar"
+RECOMMENDED_DICT:###### End of recommended dictionary. ######
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-ubsan.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-ubsan.test
new file mode 100644
index 0000000000..0e8ad6c94a
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer-ubsan.test
@@ -0,0 +1,4 @@
+RUN: not LLVMFuzzer-SignedIntOverflowTest-Ubsan 2>&1 | FileCheck %s
+CHECK: runtime error: signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'
+CHECK: Test unit written to ./crash-
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer.test b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer.test
new file mode 100644
index 0000000000..2f91c2195c
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/fuzzer.test
@@ -0,0 +1,57 @@
+CHECK: BINGO
+Done1000000: Done 1000000 runs in
+
+RUN: LLVMFuzzer-SimpleTest 2>&1 | FileCheck %s
+
+# only_ascii mode. Will perform some minimal self-validation.
+RUN: LLVMFuzzer-SimpleTest -only_ascii=1 2>&1
+
+RUN: LLVMFuzzer-SimpleCmpTest -max_total_time=1 -use_cmp=0 2>&1 | FileCheck %s --check-prefix=MaxTotalTime
+MaxTotalTime: Done {{.*}} runs in {{.}} second(s)
+
+RUN: not LLVMFuzzer-NullDerefTest 2>&1 | FileCheck %s --check-prefix=NullDerefTest
+RUN: not LLVMFuzzer-NullDerefTest -close_fd_mask=3 2>&1 | FileCheck %s --check-prefix=NullDerefTest
+NullDerefTest: ERROR: AddressSanitizer: SEGV on unknown address
+NullDerefTest: Test unit written to ./crash-
+RUN: not LLVMFuzzer-NullDerefTest -artifact_prefix=ZZZ 2>&1 | FileCheck %s --check-prefix=NullDerefTestPrefix
+NullDerefTestPrefix: Test unit written to ZZZcrash-
+RUN: not LLVMFuzzer-NullDerefTest -artifact_prefix=ZZZ -exact_artifact_path=FOOBAR 2>&1 | FileCheck %s --check-prefix=NullDerefTestExactPath
+NullDerefTestExactPath: Test unit written to FOOBAR
+
+RUN: not LLVMFuzzer-NullDerefOnEmptyTest -print_final_stats=1 2>&1 | FileCheck %s --check-prefix=NULL_DEREF_ON_EMPTY
+NULL_DEREF_ON_EMPTY: stat::number_of_executed_units:
+
+#not LLVMFuzzer-FullCoverageSetTest -timeout=15 -seed=1 -mutate_depth=2 -use_full_coverage_set=1 2>&1 | FileCheck %s
+
+RUN: not LLVMFuzzer-CounterTest -max_len=6 -seed=1 -timeout=15 2>&1 | FileCheck %s --check-prefix=COUNTERS
+
+COUNTERS: INITED {{.*}} {{bits:|ft:}}
+COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}}
+COUNTERS: NEW {{.*}} {{bits:|ft:}} {{[1-9]*}}
+COUNTERS: BINGO
+
+# Don't run UninstrumentedTest for now since we build libFuzzer itself with asan.
+DISABLED: not LLVMFuzzer-UninstrumentedTest-Uninstrumented 2>&1 | FileCheck %s --check-prefix=UNINSTRUMENTED
+UNINSTRUMENTED: ERROR: __sanitizer_set_death_callback is not defined. Exiting.
+
+RUN: not LLVMFuzzer-UninstrumentedTest-NoCoverage 2>&1 | FileCheck %s --check-prefix=NO_COVERAGE
+NO_COVERAGE: ERROR: no interesting inputs were found. Is the code instrumented for coverage? Exiting
+
+RUN: not LLVMFuzzer-BufferOverflowOnInput 2>&1 | FileCheck %s --check-prefix=OOB
+OOB: AddressSanitizer: heap-buffer-overflow
+OOB: is located 0 bytes to the right of 3-byte region
+
+RUN: not LLVMFuzzer-InitializeTest -use_value_profile=1 2>&1 | FileCheck %s
+
+RUN: not LLVMFuzzer-DSOTest 2>&1 | FileCheck %s --check-prefix=DSO
+DSO: INFO: Loaded 3 modules
+DSO: BINGO
+
+RUN: LLVMFuzzer-SimpleTest -exit_on_src_pos=SimpleTest.cpp:17 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS
+RUN: LLVMFuzzer-ShrinkControlFlowTest -exit_on_src_pos=ShrinkControlFlowTest.cpp:23 2>&1 | FileCheck %s --check-prefix=EXIT_ON_SRC_POS
+EXIT_ON_SRC_POS: INFO: found line matching '{{.*}}', exiting.
+
+RUN: ASAN_OPTIONS=strict_string_checks=1 not LLVMFuzzer-StrncmpOOBTest -seed=1 -runs=1000000 2>&1 | FileCheck %s --check-prefix=STRNCMP
+STRNCMP: AddressSanitizer: heap-buffer-overflow
+STRNCMP-NOT: __sanitizer_weak_hook_strncmp
+STRNCMP: in LLVMFuzzerTestOneInput
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/hi.txt b/json4cpp/tests/thirdparty/Fuzzer/test/hi.txt
new file mode 100644
index 0000000000..2f9031f0ec
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/hi.txt
@@ -0,0 +1 @@
+Hi! \ No newline at end of file
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/lit.cfg b/json4cpp/tests/thirdparty/Fuzzer/test/lit.cfg
new file mode 100644
index 0000000000..745af0c382
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/lit.cfg
@@ -0,0 +1,29 @@
+import lit.formats
+import sys
+
+config.name = "LLVMFuzzer"
+config.test_format = lit.formats.ShTest(True)
+config.suffixes = ['.test']
+config.test_source_root = os.path.dirname(__file__)
+
+# Tweak PATH to include llvm tools dir and current exec dir.
+llvm_tools_dir = getattr(config, 'llvm_tools_dir', None)
+if (not llvm_tools_dir) or (not os.path.exists(llvm_tools_dir)):
+ lit_config.fatal("Invalid llvm_tools_dir config attribute: %r" % llvm_tools_dir)
+path = os.path.pathsep.join((llvm_tools_dir, config.test_exec_root,
+ config.environment['PATH']))
+config.environment['PATH'] = path
+
+if config.has_lsan:
+ lit_config.note('lsan feature available')
+ config.available_features.add('lsan')
+else:
+ lit_config.note('lsan feature unavailable')
+
+if sys.platform.startswith('linux'):
+ # Note the value of ``sys.platform`` is not consistent
+ # between python 2 and 3, hence the use of ``.startswith()``.
+ lit_config.note('linux feature available')
+ config.available_features.add('linux')
+else:
+ lit_config.note('linux feature unavailable')
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/lit.site.cfg.in b/json4cpp/tests/thirdparty/Fuzzer/test/lit.site.cfg.in
new file mode 100644
index 0000000000..03e86c487c
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/lit.site.cfg.in
@@ -0,0 +1,4 @@
+config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@"
+config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
+config.has_lsan = True if @HAS_LSAN@ == 1 else False
+lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg")
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/merge.test b/json4cpp/tests/thirdparty/Fuzzer/test/merge.test
new file mode 100644
index 0000000000..1f1810eb01
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/merge.test
@@ -0,0 +1,46 @@
+CHECK: BINGO
+
+RUN: rm -rf %tmp/T1 %tmp/T2
+RUN: mkdir -p %tmp/T1 %tmp/T2
+RUN: echo F..... > %tmp/T1/1
+RUN: echo .U.... > %tmp/T1/2
+RUN: echo ..Z... > %tmp/T1/3
+
+# T1 has 3 elements, T2 is empty.
+RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK1
+CHECK1: MERGE-OUTER: 3 files, 3 in the initial corpus
+CHECK1: MERGE-OUTER: 0 new files with 0 new features added
+
+RUN: echo ...Z.. > %tmp/T2/1
+RUN: echo ....E. > %tmp/T2/2
+RUN: echo .....R > %tmp/T2/3
+RUN: echo F..... > %tmp/T2/a
+RUN: echo .U.... > %tmp/T2/b
+RUN: echo ..Z... > %tmp/T2/c
+
+# T1 has 3 elements, T2 has 6 elements, only 3 are new.
+RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK2
+CHECK2: MERGE-OUTER: 9 files, 3 in the initial corpus
+CHECK2: MERGE-OUTER: 3 new files with 3 new features added
+
+# Now, T1 has 6 units and T2 has no new interesting units.
+RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=CHECK3
+CHECK3: MERGE-OUTER: 12 files, 6 in the initial corpus
+CHECK3: MERGE-OUTER: 0 new files with 0 new features added
+
+# Check that we respect max_len during the merge and don't crash.
+RUN: rm %tmp/T1/??*
+RUN: echo looooooooong > %tmp/T2/looooooooong
+RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 -max_len=6 2>&1 | FileCheck %s --check-prefix=MAX_LEN
+MAX_LEN: MERGE-OUTER: 3 new files
+
+# Check that merge tolerates failures.
+RUN: rm %tmp/T1/??*
+RUN: echo 'FUZZER' > %tmp/T2/FUZZER
+RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 2>&1 | FileCheck %s --check-prefix=MERGE_WITH_CRASH
+MERGE_WITH_CRASH: MERGE-OUTER: succesfull in 2 attempt(s)
+MERGE_WITH_CRASH: MERGE-OUTER: 3 new files
+
+# Check that we actually limit the size with max_len
+RUN: LLVMFuzzer-FullCoverageSetTest -merge=1 %tmp/T1 %tmp/T2 -max_len=5 2>&1 | FileCheck %s --check-prefix=MERGE_LEN5
+MERGE_LEN5: MERGE-OUTER: succesfull in 1 attempt(s)
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/minimize_crash.test b/json4cpp/tests/thirdparty/Fuzzer/test/minimize_crash.test
new file mode 100644
index 0000000000..7e5406598e
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/minimize_crash.test
@@ -0,0 +1,6 @@
+RUN: echo 'Hi!rv349f34t3gg' > not_minimal_crash
+RUN: LLVMFuzzer-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 2>&1 | FileCheck %s
+CHECK: CRASH_MIN: failed to minimize beyond minimized-from-{{.*}} (3 bytes), exiting
+RUN: LLVMFuzzer-NullDerefTest -minimize_crash=1 not_minimal_crash -max_total_time=2 -exact_artifact_path=exact_minimized_path 2>&1 | FileCheck %s --check-prefix=CHECK_EXACT
+CHECK_EXACT: CRASH_MIN: failed to minimize beyond exact_minimized_path (3 bytes), exiting
+RUN: rm not_minimal_crash minimized-from-* exact_minimized_path
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/no-coverage/CMakeLists.txt b/json4cpp/tests/thirdparty/Fuzzer/test/no-coverage/CMakeLists.txt
new file mode 100644
index 0000000000..d2f6f438ad
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/no-coverage/CMakeLists.txt
@@ -0,0 +1,29 @@
+# These tests are not instrumented with coverage,
+# but have coverage rt in the binary.
+
+set(CMAKE_CXX_FLAGS
+ "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard")
+
+set(NoCoverageTests
+ UninstrumentedTest
+ )
+
+foreach(Test ${NoCoverageTests})
+ add_libfuzzer_test(${Test}-NoCoverage SOURCES ../${Test}.cpp)
+endforeach()
+
+
+###############################################################################
+# AFL Driver test
+###############################################################################
+
+add_executable(AFLDriverTest
+ ../AFLDriverTest.cpp ../../afl/afl_driver.cpp)
+
+set_target_properties(AFLDriverTest
+ PROPERTIES RUNTIME_OUTPUT_DIRECTORY
+ "${CMAKE_BINARY_DIR}/lib/Fuzzer/test"
+ )
+
+# Propagate value into parent directory
+set(TestBinaries ${TestBinaries} AFLDriverTest PARENT_SCOPE)
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/repeated-bytes.test b/json4cpp/tests/thirdparty/Fuzzer/test/repeated-bytes.test
new file mode 100644
index 0000000000..7139408793
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/repeated-bytes.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: LLVMFuzzer-RepeatedBytesTest -seed=1 -runs=1000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/shrink.test b/json4cpp/tests/thirdparty/Fuzzer/test/shrink.test
new file mode 100644
index 0000000000..edb86cb193
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/shrink.test
@@ -0,0 +1,7 @@
+RUN: LLVMFuzzer-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=1 2>&1 | FileCheck %s --check-prefix=SHRINK1
+RUN: LLVMFuzzer-ShrinkControlFlowTest -seed=1 -exit_on_item=0eb8e4ed029b774d80f2b66408203801cb982a60 -runs=1000000 -shrink=0 2>&1 | FileCheck %s --check-prefix=SHRINK0
+RUN: LLVMFuzzer-ShrinkValueProfileTest -seed=1 -exit_on_item=aea2e3923af219a8956f626558ef32f30a914ebc -runs=100000 -shrink=1 -use_value_profile=1 2>&1 | FileCheck %s --check-prefix=SHRINK1_VP
+
+SHRINK0: Done 1000000 runs in
+SHRINK1: INFO: found item with checksum '0eb8e4ed029b774d80f2b66408203801cb982a60', exiting.
+SHRINK1_VP: INFO: found item with checksum 'aea2e3923af219a8956f626558ef32f30a914ebc', exiting
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/simple-cmp.test b/json4cpp/tests/thirdparty/Fuzzer/test/simple-cmp.test
new file mode 100644
index 0000000000..145a036652
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/simple-cmp.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-SimpleCmpTest -seed=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/standalone.test b/json4cpp/tests/thirdparty/Fuzzer/test/standalone.test
new file mode 100644
index 0000000000..3097b3ff35
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/standalone.test
@@ -0,0 +1,4 @@
+RUN: LLVMFuzzer-StandaloneInitializeTest %S/hi.txt %S/dict1.txt 2>&1 | FileCheck %s
+CHECK: StandaloneFuzzTargetMain: running 2 inputs
+CHECK: Done: {{.*}}hi.txt: (3 bytes)
+CHECK: Done: {{.*}}dict1.txt: (61 bytes)
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/swap-cmp.test b/json4cpp/tests/thirdparty/Fuzzer/test/swap-cmp.test
new file mode 100644
index 0000000000..908b798664
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/swap-cmp.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-SwapCmpTest -seed=1 -runs=10000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/trace-malloc.test b/json4cpp/tests/thirdparty/Fuzzer/test/trace-malloc.test
new file mode 100644
index 0000000000..c95147904d
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/trace-malloc.test
@@ -0,0 +1,10 @@
+RUN: LLVMFuzzer-TraceMallocTest -seed=1 -trace_malloc=1 -runs=10000 2>&1 | FileCheck %s
+CHECK-DAG: MallocFreeTracer: STOP 0 0 (same)
+CHECK-DAG: MallocFreeTracer: STOP 0 1 (DIFFERENT)
+CHECK-DAG: MallocFreeTracer: STOP 1 0 (DIFFERENT)
+CHECK-DAG: MallocFreeTracer: STOP 1 1 (same)
+
+RUN: LLVMFuzzer-TraceMallocTest -seed=1 -trace_malloc=2 -runs=1000 2>&1 | FileCheck %s --check-prefix=TRACE2
+TRACE2-DAG: FREE[0]
+TRACE2-DAG: MALLOC[0]
+TRACE2-DAG: in LLVMFuzzerTestOneInput
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/ubsan/CMakeLists.txt b/json4cpp/tests/thirdparty/Fuzzer/test/ubsan/CMakeLists.txt
new file mode 100644
index 0000000000..7a9eacdbe7
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/ubsan/CMakeLists.txt
@@ -0,0 +1,15 @@
+# These tests are instrumented with ubsan in non-recovery mode.
+
+set(CMAKE_CXX_FLAGS
+ "${LIBFUZZER_FLAGS_BASE} -fsanitize=undefined -fno-sanitize-recover=all")
+
+set(UbsanTests
+ SignedIntOverflowTest
+ )
+
+foreach(Test ${UbsanTests})
+ add_libfuzzer_test(${Test}-Ubsan SOURCES ../${Test}.cpp)
+endforeach()
+
+# Propagate value into parent directory
+set(TestBinaries ${TestBinaries} PARENT_SCOPE)
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/ulimit.test b/json4cpp/tests/thirdparty/Fuzzer/test/ulimit.test
new file mode 100644
index 0000000000..a60636c351
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/ulimit.test
@@ -0,0 +1,2 @@
+RUN: ulimit -s 1000
+RUN: LLVMFuzzer-SimpleTest
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/uninstrumented/CMakeLists.txt b/json4cpp/tests/thirdparty/Fuzzer/test/uninstrumented/CMakeLists.txt
new file mode 100644
index 0000000000..29b66e6e58
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/uninstrumented/CMakeLists.txt
@@ -0,0 +1,16 @@
+# These tests are not instrumented with coverage and don't
+# have coverage rt in the binary.
+
+set(CMAKE_CXX_FLAGS
+ "${LIBFUZZER_FLAGS_BASE} -fno-sanitize=all -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard")
+
+set(UninstrumentedTests
+ UninstrumentedTest
+ )
+
+foreach(Test ${UninstrumentedTests})
+ add_libfuzzer_test(${Test}-Uninstrumented SOURCES ../${Test}.cpp)
+endforeach()
+
+# Propagate value into parent directory
+set(TestBinaries ${TestBinaries} PARENT_SCOPE)
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/unit/lit.cfg b/json4cpp/tests/thirdparty/Fuzzer/test/unit/lit.cfg
new file mode 100644
index 0000000000..0cc31939c5
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/unit/lit.cfg
@@ -0,0 +1,7 @@
+import lit.formats
+
+config.name = "LLVMFuzzer-Unittest"
+print config.test_exec_root
+config.test_format = lit.formats.GoogleTest(".", "Unittest")
+config.suffixes = []
+config.test_source_root = config.test_exec_root
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/unit/lit.site.cfg.in b/json4cpp/tests/thirdparty/Fuzzer/test/unit/lit.site.cfg.in
new file mode 100644
index 0000000000..114daf474b
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/unit/lit.site.cfg.in
@@ -0,0 +1,2 @@
+config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@"
+lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/unit/lit.cfg")
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp.test
new file mode 100644
index 0000000000..48edba4f5c
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-SimpleCmpTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp2.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp2.test
new file mode 100644
index 0000000000..43d62400d9
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp2.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-SimpleHashTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp3.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp3.test
new file mode 100644
index 0000000000..8a962763f3
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp3.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-AbsNegAndConstantTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp4.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp4.test
new file mode 100644
index 0000000000..1e7131e5b5
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-cmp4.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-AbsNegAndConstant64Test -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-div.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-div.test
new file mode 100644
index 0000000000..ba45e4129d
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-div.test
@@ -0,0 +1,3 @@
+CHECK: AddressSanitizer: FPE
+RUN: not LLVMFuzzer-DivTest -seed=1 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-load.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-load.test
new file mode 100644
index 0000000000..14d3109a24
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-load.test
@@ -0,0 +1,3 @@
+CHECK: AddressSanitizer: global-buffer-overflow
+RUN: not LLVMFuzzer-LoadTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-mem.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-mem.test
new file mode 100644
index 0000000000..09d737dbe7
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-mem.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-SingleMemcmpTest -seed=1 -use_cmp=0 -use_memcmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-set.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-set.test
new file mode 100644
index 0000000000..9d06c36563
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-set.test
@@ -0,0 +1,3 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-FourIndependentBranchesTest -seed=1 -use_cmp=0 -use_value_profile=1 -runs=100000000 2>&1 | FileCheck %s
+
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-strcmp.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-strcmp.test
new file mode 100644
index 0000000000..1e7ef9b45e
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-strcmp.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-SingleStrcmpTest -seed=1 -use_cmp=0 -use_memcmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-strncmp.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-strncmp.test
new file mode 100644
index 0000000000..650973180c
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-strncmp.test
@@ -0,0 +1,2 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-SingleStrncmpTest -seed=1 -use_cmp=0 -use_memcmp=0 -use_value_profile=1 -runs=10000000 2>&1 | FileCheck %s
diff --git a/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-switch.test b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-switch.test
new file mode 100644
index 0000000000..1947f56830
--- /dev/null
+++ b/json4cpp/tests/thirdparty/Fuzzer/test/value-profile-switch.test
@@ -0,0 +1,3 @@
+CHECK: BINGO
+RUN: not LLVMFuzzer-SwitchTest -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s
+RUN: not LLVMFuzzer-Switch2Test -use_cmp=0 -use_value_profile=1 -runs=100000000 -seed=1 2>&1 | FileCheck %s