|
@@ -513,7 +513,7 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
|
|
|
// Largest input length should be INT_MAX.
|
|
|
assert(Size < std::numeric_limits<uint32_t>::max());
|
|
|
|
|
|
- ExecuteCallback(Data, Size);
|
|
|
+ if(!ExecuteCallback(Data, Size)) return false;
|
|
|
auto TimeOfUnit = duration_cast<microseconds>(UnitStopTime - UnitStartTime);
|
|
|
|
|
|
UniqFeatureSetTmp.clear();
|
|
@@ -588,7 +588,7 @@ static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
|
|
|
|
|
|
// This method is not inlined because it would cause a test to fail where it
|
|
|
// is part of the stack unwinding. See D97975 for details.
|
|
|
-ATTRIBUTE_NOINLINE void Fuzzer::ExecuteCallback(const uint8_t *Data,
|
|
|
+ATTRIBUTE_NOINLINE bool Fuzzer::ExecuteCallback(const uint8_t *Data,
|
|
|
size_t Size) {
|
|
|
TPC.RecordInitialStack();
|
|
|
TotalNumberOfRuns++;
|
|
@@ -604,23 +604,24 @@ ATTRIBUTE_NOINLINE void Fuzzer::ExecuteCallback(const uint8_t *Data,
|
|
|
if (CurrentUnitData && CurrentUnitData != Data)
|
|
|
memcpy(CurrentUnitData, Data, Size);
|
|
|
CurrentUnitSize = Size;
|
|
|
+ int CBRes = 0;
|
|
|
{
|
|
|
ScopedEnableMsanInterceptorChecks S;
|
|
|
AllocTracer.Start(Options.TraceMalloc);
|
|
|
UnitStartTime = system_clock::now();
|
|
|
TPC.ResetMaps();
|
|
|
RunningUserCallback = true;
|
|
|
- int Res = CB(DataCopy, Size);
|
|
|
+ CBRes = CB(DataCopy, Size);
|
|
|
RunningUserCallback = false;
|
|
|
UnitStopTime = system_clock::now();
|
|
|
- (void)Res;
|
|
|
- assert(Res == 0);
|
|
|
+ assert(CBRes == 0 || CBRes == -1);
|
|
|
HasMoreMallocsThanFrees = AllocTracer.Stop();
|
|
|
}
|
|
|
if (!LooseMemeq(DataCopy, Data, Size))
|
|
|
CrashOnOverwrittenData();
|
|
|
CurrentUnitSize = 0;
|
|
|
delete[] DataCopy;
|
|
|
+ return CBRes == 0;
|
|
|
}
|
|
|
|
|
|
std::string Fuzzer::WriteToOutputCorpus(const Unit &U) {
|
|
@@ -845,9 +846,16 @@ void Fuzzer::ReadAndExecuteSeedCorpora(std::vector<SizedFile> &CorporaFiles) {
|
|
|
}
|
|
|
|
|
|
if (Corpus.empty() && Options.MaxNumberOfRuns) {
|
|
|
- Printf("ERROR: no interesting inputs were found. "
|
|
|
- "Is the code instrumented for coverage? Exiting.\n");
|
|
|
- exit(1);
|
|
|
+ Printf("WARNING: no interesting inputs were found so far. "
|
|
|
+ "Is the code instrumented for coverage?\n"
|
|
|
+ "This may also happen if the target rejected all inputs we tried so "
|
|
|
+ "far\n");
|
|
|
+ // The remaining logic requires that the corpus is not empty,
|
|
|
+ // so we add one fake input to the in-memory corpus.
|
|
|
+ Corpus.AddToCorpus({'\n'}, /*NumFeatures=*/1, /*MayDeleteFile=*/true,
|
|
|
+ /*HasFocusFunction=*/false, /*NeverReduce=*/false,
|
|
|
+ /*TimeOfUnit=*/duration_cast<microseconds>(0s), {0}, DFT,
|
|
|
+ /*BaseII*/ nullptr);
|
|
|
}
|
|
|
}
|
|
|
|