Skip to content

Commit 172eb91

Browse files
committed
Upgrade libfuzzer to 7bf89c2.
llvm/llvm-project@7bf89c2
1 parent 104fca0 commit 172eb91

30 files changed

+444
-142
lines changed

libfuzzer/CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ CHECK_CXX_SOURCE_COMPILES("
5555
}
5656
" HAS_THREAD_LOCAL)
5757

58-
set(LIBFUZZER_CFLAGS ${SANITIZER_COMMON_CFLAGS})
58+
set(LIBFUZZER_CFLAGS ${COMPILER_RT_COMMON_CFLAGS})
5959

6060
if(OS_NAME MATCHES "Linux|Fuchsia" AND
6161
COMPILER_RT_LIBCXX_PATH AND
6262
COMPILER_RT_LIBCXXABI_PATH)
63-
list(APPEND LIBFUZZER_CFLAGS -nostdinc++ -D_LIBCPP_ABI_VERSION=Fuzzer)
64-
# Remove -stdlib= which is unused when passing -nostdinc++.
65-
string(REGEX REPLACE "-stdlib=[a-zA-Z+]*" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
63+
list(APPEND LIBFUZZER_CFLAGS -D_LIBCPP_ABI_VERSION=Fuzzer)
64+
append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ LIBFUZZER_CFLAGS)
6665
elseif(TARGET cxx-headers OR HAVE_LIBCXX)
66+
# libFuzzer uses C++ standard library headers.
6767
set(LIBFUZZER_DEPS cxx-headers)
6868
endif()
6969

libfuzzer/FuzzerCorpus.h

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "FuzzerSHA1.h"
1919
#include "FuzzerTracePC.h"
2020
#include <algorithm>
21+
#include <chrono>
2122
#include <numeric>
2223
#include <random>
2324
#include <unordered_set>
@@ -26,13 +27,15 @@ namespace fuzzer {
2627

2728
struct InputInfo {
2829
Unit U; // The actual input data.
30+
std::chrono::microseconds TimeOfUnit;
2931
uint8_t Sha1[kSHA1NumBytes]; // Checksum.
3032
// Number of features that this input has and no smaller input has.
3133
size_t NumFeatures = 0;
3234
size_t Tmp = 0; // Used by ValidateFeatureSet.
3335
// Stats.
3436
size_t NumExecutedMutations = 0;
3537
size_t NumSuccessfullMutations = 0;
38+
bool NeverReduce = false;
3639
bool MayDeleteFile = false;
3740
bool Reduced = false;
3841
bool HasFocusFunction = false;
@@ -61,11 +64,15 @@ struct InputInfo {
6164
}
6265

6366
// Assign more energy to a high-entropy seed, i.e., that reveals more
64-
// information about the globally rare features in the neighborhood
65-
// of the seed. Since we do not know the entropy of a seed that has
66-
// never been executed we assign fresh seeds maximum entropy and
67-
// let II->Energy approach the true entropy from above.
68-
void UpdateEnergy(size_t GlobalNumberOfFeatures) {
67+
// information about the globally rare features in the neighborhood of the
68+
// seed. Since we do not know the entropy of a seed that has never been
69+
// executed we assign fresh seeds maximum entropy and let II->Energy approach
70+
// the true entropy from above. If ScalePerExecTime is true, the computed
71+
// entropy is scaled based on how fast this input executes compared to the
72+
// average execution time of inputs. The faster an input executes, the more
73+
// energy gets assigned to the input.
74+
void UpdateEnergy(size_t GlobalNumberOfFeatures, bool ScalePerExecTime,
75+
std::chrono::microseconds AverageUnitExecutionTime) {
6976
Energy = 0.0;
7077
SumIncidence = 0;
7178

@@ -88,6 +95,27 @@ struct InputInfo {
8895
// Normalize.
8996
if (SumIncidence != 0)
9097
Energy = (Energy / SumIncidence) + logl(SumIncidence);
98+
99+
if (ScalePerExecTime) {
100+
// Scaling to favor inputs with lower execution time.
101+
uint32_t PerfScore = 100;
102+
if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 10)
103+
PerfScore = 10;
104+
else if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 4)
105+
PerfScore = 25;
106+
else if (TimeOfUnit.count() > AverageUnitExecutionTime.count() * 2)
107+
PerfScore = 50;
108+
else if (TimeOfUnit.count() * 3 > AverageUnitExecutionTime.count() * 4)
109+
PerfScore = 75;
110+
else if (TimeOfUnit.count() * 4 < AverageUnitExecutionTime.count())
111+
PerfScore = 300;
112+
else if (TimeOfUnit.count() * 3 < AverageUnitExecutionTime.count())
113+
PerfScore = 200;
114+
else if (TimeOfUnit.count() * 2 < AverageUnitExecutionTime.count())
115+
PerfScore = 150;
116+
117+
Energy *= PerfScore;
118+
}
91119
}
92120

93121
// Increment the frequency of the feature Idx.
@@ -120,6 +148,7 @@ struct EntropicOptions {
120148
bool Enabled;
121149
size_t NumberOfRarestFeatures;
122150
size_t FeatureFrequencyThreshold;
151+
bool ScalePerExecTime;
123152
};
124153

125154
class InputCorpus {
@@ -177,7 +206,8 @@ class InputCorpus {
177206
bool empty() const { return Inputs.empty(); }
178207
const Unit &operator[] (size_t Idx) const { return Inputs[Idx]->U; }
179208
InputInfo *AddToCorpus(const Unit &U, size_t NumFeatures, bool MayDeleteFile,
180-
bool HasFocusFunction,
209+
bool HasFocusFunction, bool NeverReduce,
210+
std::chrono::microseconds TimeOfUnit,
181211
const Vector<uint32_t> &FeatureSet,
182212
const DataFlowTrace &DFT, const InputInfo *BaseII) {
183213
assert(!U.empty());
@@ -187,6 +217,8 @@ class InputCorpus {
187217
InputInfo &II = *Inputs.back();
188218
II.U = U;
189219
II.NumFeatures = NumFeatures;
220+
II.NeverReduce = NeverReduce;
221+
II.TimeOfUnit = TimeOfUnit;
190222
II.MayDeleteFile = MayDeleteFile;
191223
II.UniqFeatureSet = FeatureSet;
192224
II.HasFocusFunction = HasFocusFunction;
@@ -268,6 +300,15 @@ class InputCorpus {
268300
return II;
269301
}
270302

303+
InputInfo &ChooseUnitToCrossOverWith(Random &Rand, bool UniformDist) {
304+
if (!UniformDist) {
305+
return ChooseUnitToMutate(Rand);
306+
}
307+
InputInfo &II = *Inputs[Rand(Inputs.size())];
308+
assert(!II.U.empty());
309+
return II;
310+
}
311+
271312
// Returns an index of random unit from the corpus to mutate.
272313
size_t ChooseUnitIdxToMutate(Random &Rand) {
273314
UpdateCorpusDistribution(Rand);
@@ -460,12 +501,19 @@ class InputCorpus {
460501
Weights.resize(N);
461502
std::iota(Intervals.begin(), Intervals.end(), 0);
462503

504+
std::chrono::microseconds AverageUnitExecutionTime(0);
505+
for (auto II : Inputs) {
506+
AverageUnitExecutionTime += II->TimeOfUnit;
507+
}
508+
AverageUnitExecutionTime /= N;
509+
463510
bool VanillaSchedule = true;
464511
if (Entropic.Enabled) {
465512
for (auto II : Inputs) {
466513
if (II->NeedsEnergyUpdate && II->Energy != 0.0) {
467514
II->NeedsEnergyUpdate = false;
468-
II->UpdateEnergy(RareFeatures.size());
515+
II->UpdateEnergy(RareFeatures.size(), Entropic.ScalePerExecTime,
516+
AverageUnitExecutionTime);
469517
}
470518
}
471519

libfuzzer/FuzzerDataFlowTrace.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath,
253253
return 1;
254254
}
255255

256-
static char DFSanEnv[] = "DFSAN_OPTIONS=fast16labels=1:warn_unimplemented=0";
256+
static char DFSanEnv[] = "DFSAN_OPTIONS=warn_unimplemented=0";
257257
putenv(DFSanEnv);
258258
MkDir(DirPath);
259259
for (auto &F : CorporaFiles) {

libfuzzer/FuzzerDriver.cpp

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,28 @@ static void WorkerThread(const Command &BaseCmd, std::atomic<unsigned> *Counter,
250250
}
251251
}
252252

253+
static void ValidateDirectoryExists(const std::string &Path,
254+
bool CreateDirectory) {
255+
if (Path.empty()) {
256+
Printf("ERROR: Provided directory path is an empty string\n");
257+
exit(1);
258+
}
259+
260+
if (IsDirectory(Path))
261+
return;
262+
263+
if (CreateDirectory) {
264+
if (!MkDirRecursive(Path)) {
265+
Printf("ERROR: Failed to create directory \"%s\"\n", Path.c_str());
266+
exit(1);
267+
}
268+
return;
269+
}
270+
271+
Printf("ERROR: The required directory \"%s\" does not exist\n", Path.c_str());
272+
exit(1);
273+
}
274+
253275
std::string CloneArgsWithoutX(const Vector<std::string> &Args,
254276
const char *X1, const char *X2) {
255277
std::string Cmd;
@@ -299,7 +321,12 @@ int RunOneTest(Fuzzer *F, const char *InputFilePath, size_t MaxLen) {
299321
if (MaxLen && MaxLen < U.size())
300322
U.resize(MaxLen);
301323
F->ExecuteCallback(U.data(), U.size());
302-
F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
324+
if (Flags.print_full_coverage) {
325+
// Leak detection is not needed when collecting full coverage data.
326+
F->TPCUpdateObservedPCs();
327+
} else {
328+
F->TryDetectingAMemoryLeak(U.data(), U.size(), true);
329+
}
303330
return 0;
304331
}
305332

@@ -649,6 +676,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
649676
Options.Verbosity = Flags.verbosity;
650677
Options.MaxLen = Flags.max_len;
651678
Options.LenControl = Flags.len_control;
679+
Options.KeepSeed = Flags.keep_seed;
652680
Options.UnitTimeoutSec = Flags.timeout;
653681
Options.ErrorExitCode = Flags.error_exitcode;
654682
Options.TimeoutExitCode = Flags.timeout_exitcode;
@@ -657,6 +685,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
657685
Options.IgnoreCrashes = Flags.ignore_crashes;
658686
Options.MaxTotalTimeSec = Flags.max_total_time;
659687
Options.DoCrossOver = Flags.cross_over;
688+
Options.CrossOverUniformDist = Flags.cross_over_uniform_dist;
660689
Options.MutateDepth = Flags.mutate_depth;
661690
Options.ReduceDepth = Flags.reduce_depth;
662691
Options.UseCounters = Flags.use_counters;
@@ -678,13 +707,33 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
678707
Options.MallocLimitMb = Options.RssLimitMb;
679708
if (Flags.runs >= 0)
680709
Options.MaxNumberOfRuns = Flags.runs;
681-
if (!Inputs->empty() && !Flags.minimize_crash_internal_step)
682-
Options.OutputCorpus = (*Inputs)[0];
710+
if (!Inputs->empty() && !Flags.minimize_crash_internal_step) {
711+
// Ensure output corpus assumed to be the first arbitrary argument input
712+
// is not a path to an existing file.
713+
std::string OutputCorpusDir = (*Inputs)[0];
714+
if (!IsFile(OutputCorpusDir)) {
715+
Options.OutputCorpus = OutputCorpusDir;
716+
ValidateDirectoryExists(Options.OutputCorpus, Flags.create_missing_dirs);
717+
}
718+
}
683719
Options.ReportSlowUnits = Flags.report_slow_units;
684-
if (Flags.artifact_prefix)
720+
if (Flags.artifact_prefix) {
685721
Options.ArtifactPrefix = Flags.artifact_prefix;
686-
if (Flags.exact_artifact_path)
722+
723+
// Since the prefix could be a full path to a file name prefix, assume
724+
// that if the path ends with the platform's separator that a directory
725+
// is desired
726+
std::string ArtifactPathDir = Options.ArtifactPrefix;
727+
if (!IsSeparator(ArtifactPathDir[ArtifactPathDir.length() - 1])) {
728+
ArtifactPathDir = DirName(ArtifactPathDir);
729+
}
730+
ValidateDirectoryExists(ArtifactPathDir, Flags.create_missing_dirs);
731+
}
732+
if (Flags.exact_artifact_path) {
687733
Options.ExactArtifactPath = Flags.exact_artifact_path;
734+
ValidateDirectoryExists(DirName(Options.ExactArtifactPath),
735+
Flags.create_missing_dirs);
736+
}
688737
Vector<Unit> Dictionary;
689738
if (Flags.dict)
690739
if (!ParseDictionaryFile(FileToString(Flags.dict), &Dictionary))
@@ -699,6 +748,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
699748
Options.PrintFinalStats = Flags.print_final_stats;
700749
Options.PrintCorpusStats = Flags.print_corpus_stats;
701750
Options.PrintCoverage = Flags.print_coverage;
751+
Options.PrintFullCoverage = Flags.print_full_coverage;
702752
if (Flags.exit_on_src_pos)
703753
Options.ExitOnSrcPos = Flags.exit_on_src_pos;
704754
if (Flags.exit_on_item)
@@ -707,8 +757,12 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
707757
Options.FocusFunction = Flags.focus_function;
708758
if (Flags.data_flow_trace)
709759
Options.DataFlowTrace = Flags.data_flow_trace;
710-
if (Flags.features_dir)
760+
if (Flags.features_dir) {
711761
Options.FeaturesDir = Flags.features_dir;
762+
ValidateDirectoryExists(Options.FeaturesDir, Flags.create_missing_dirs);
763+
}
764+
if (Flags.mutation_graph_file)
765+
Options.MutationGraphFile = Flags.mutation_graph_file;
712766
if (Flags.collect_data_flow)
713767
Options.CollectDataFlow = Flags.collect_data_flow;
714768
if (Flags.stop_file)
@@ -718,21 +772,19 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
718772
(size_t)Flags.entropic_feature_frequency_threshold;
719773
Options.EntropicNumberOfRarestFeatures =
720774
(size_t)Flags.entropic_number_of_rarest_features;
721-
if (Options.Entropic) {
722-
if (!Options.FocusFunction.empty()) {
723-
Printf("ERROR: The parameters `--entropic` and `--focus_function` cannot "
724-
"be used together.\n");
725-
exit(1);
726-
}
775+
Options.EntropicScalePerExecTime = Flags.entropic_scale_per_exec_time;
776+
if (!Options.FocusFunction.empty())
777+
Options.Entropic = false; // FocusFunction overrides entropic scheduling.
778+
if (Options.Entropic)
727779
Printf("INFO: Running with entropic power schedule (0x%X, %d).\n",
728780
Options.EntropicFeatureFrequencyThreshold,
729781
Options.EntropicNumberOfRarestFeatures);
730-
}
731782
struct EntropicOptions Entropic;
732783
Entropic.Enabled = Options.Entropic;
733784
Entropic.FeatureFrequencyThreshold =
734785
Options.EntropicFeatureFrequencyThreshold;
735786
Entropic.NumberOfRarestFeatures = Options.EntropicNumberOfRarestFeatures;
787+
Entropic.ScalePerExecTime = Options.EntropicScalePerExecTime;
736788

737789
unsigned Seed = Flags.seed;
738790
// Initialize Seed.
@@ -767,6 +819,7 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
767819
#endif // LIBFUZZER_EMSCRIPTEN
768820

769821
Options.HandleAbrt = Flags.handle_abrt;
822+
Options.HandleAlrm = !Flags.minimize_crash;
770823
Options.HandleBus = Flags.handle_bus;
771824
Options.HandleFpe = Flags.handle_fpe;
772825
Options.HandleIll = Flags.handle_ill;
@@ -776,6 +829,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
776829
Options.HandleXfsz = Flags.handle_xfsz;
777830
Options.HandleUsr1 = Flags.handle_usr1;
778831
Options.HandleUsr2 = Flags.handle_usr2;
832+
Options.HandleWinExcept = Flags.handle_winexcept;
833+
779834
SetSignalHandler(Options);
780835

781836
std::atexit(Fuzzer::StaticExitCallback);
@@ -858,6 +913,12 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
858913
exit(0); // Don't let F destroy itself.
859914
}
860915

916+
extern "C" ATTRIBUTE_INTERFACE int
917+
LLVMFuzzerRunDriver(int *argc, char ***argv,
918+
int (*UserCb)(const uint8_t *Data, size_t Size)) {
919+
return FuzzerDriver(argc, argv, UserCb);
920+
}
921+
861922
// Storage for global ExternalFunctions object.
862923
ExternalFunctions *EF = nullptr;
863924

libfuzzer/FuzzerExtFunctionsWeak.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
//===----------------------------------------------------------------------===//
1414
#include "FuzzerPlatform.h"
1515
#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FUCHSIA || \
16-
LIBFUZZER_FREEBSD || LIBFUZZER_OPENBSD || LIBFUZZER_EMSCRIPTEN
16+
LIBFUZZER_FREEBSD || LIBFUZZER_EMSCRIPTEN
1717

1818
#include "FuzzerExtFunctions.h"
1919
#include "FuzzerIO.h"

libfuzzer/FuzzerExtraCounters.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include <cstdint>
1313

1414
#if LIBFUZZER_LINUX || LIBFUZZER_NETBSD || LIBFUZZER_FREEBSD || \
15-
LIBFUZZER_OPENBSD || LIBFUZZER_FUCHSIA || LIBFUZZER_EMSCRIPTEN
15+
LIBFUZZER_FUCHSIA || LIBFUZZER_EMSCRIPTEN
1616
__attribute__((weak)) extern uint8_t __start___libfuzzer_extra_counters;
1717
__attribute__((weak)) extern uint8_t __stop___libfuzzer_extra_counters;
1818

0 commit comments

Comments
 (0)