1 1.1 kamil //===- FuzzerLoop.cpp - Fuzzer's main loop --------------------------------===// 2 1.1 kamil // 3 1.1 kamil // The LLVM Compiler Infrastructure 4 1.1 kamil // 5 1.1 kamil // This file is distributed under the University of Illinois Open Source 6 1.1 kamil // License. See LICENSE.TXT for details. 7 1.1 kamil // 8 1.1 kamil //===----------------------------------------------------------------------===// 9 1.1 kamil // Fuzzer's main loop. 10 1.1 kamil //===----------------------------------------------------------------------===// 11 1.1 kamil 12 1.1 kamil #include "FuzzerCorpus.h" 13 1.1 kamil #include "FuzzerIO.h" 14 1.1 kamil #include "FuzzerInternal.h" 15 1.1 kamil #include "FuzzerMutate.h" 16 1.1 kamil #include "FuzzerRandom.h" 17 1.1 kamil #include "FuzzerShmem.h" 18 1.1 kamil #include "FuzzerTracePC.h" 19 1.1 kamil #include <algorithm> 20 1.1 kamil #include <cstring> 21 1.1 kamil #include <memory> 22 1.1 kamil #include <mutex> 23 1.1 kamil #include <set> 24 1.1 kamil 25 1.1 kamil #if defined(__has_include) 26 1.1 kamil #if __has_include(<sanitizer / lsan_interface.h>) 27 1.1 kamil #include <sanitizer/lsan_interface.h> 28 1.1 kamil #endif 29 1.1 kamil #endif 30 1.1 kamil 31 1.1 kamil #define NO_SANITIZE_MEMORY 32 1.1 kamil #if defined(__has_feature) 33 1.1 kamil #if __has_feature(memory_sanitizer) 34 1.1 kamil #undef NO_SANITIZE_MEMORY 35 1.1 kamil #define NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) 36 1.1 kamil #endif 37 1.1 kamil #endif 38 1.1 kamil 39 1.1 kamil namespace fuzzer { 40 1.1 kamil static const size_t kMaxUnitSizeToPrint = 256; 41 1.1 kamil 42 1.1 kamil thread_local bool Fuzzer::IsMyThread; 43 1.1 kamil 44 1.1 kamil SharedMemoryRegion SMR; 45 1.1 kamil 46 1.1 kamil bool RunningUserCallback = false; 47 1.1 kamil 48 1.1 kamil // Only one Fuzzer per process. 49 1.1 kamil static Fuzzer *F; 50 1.1 kamil 51 1.1 kamil // Leak detection is expensive, so we first check if there were more mallocs 52 1.1 kamil // than frees (using the sanitizer malloc hooks) and only then try to call lsan. 53 1.1 kamil struct MallocFreeTracer { 54 1.1 kamil void Start(int TraceLevel) { 55 1.1 kamil this->TraceLevel = TraceLevel; 56 1.1 kamil if (TraceLevel) 57 1.1 kamil Printf("MallocFreeTracer: START\n"); 58 1.1 kamil Mallocs = 0; 59 1.1 kamil Frees = 0; 60 1.1 kamil } 61 1.1 kamil // Returns true if there were more mallocs than frees. 62 1.1 kamil bool Stop() { 63 1.1 kamil if (TraceLevel) 64 1.1 kamil Printf("MallocFreeTracer: STOP %zd %zd (%s)\n", Mallocs.load(), 65 1.1 kamil Frees.load(), Mallocs == Frees ? "same" : "DIFFERENT"); 66 1.1 kamil bool Result = Mallocs > Frees; 67 1.1 kamil Mallocs = 0; 68 1.1 kamil Frees = 0; 69 1.1 kamil TraceLevel = 0; 70 1.1 kamil return Result; 71 1.1 kamil } 72 1.1 kamil std::atomic<size_t> Mallocs; 73 1.1 kamil std::atomic<size_t> Frees; 74 1.1 kamil int TraceLevel = 0; 75 1.1 kamil 76 1.1 kamil std::recursive_mutex TraceMutex; 77 1.1 kamil bool TraceDisabled = false; 78 1.1 kamil }; 79 1.1 kamil 80 1.1 kamil static MallocFreeTracer AllocTracer; 81 1.1 kamil 82 1.1 kamil // Locks printing and avoids nested hooks triggered from mallocs/frees in 83 1.1 kamil // sanitizer. 84 1.1 kamil class TraceLock { 85 1.1 kamil public: 86 1.1 kamil TraceLock() : Lock(AllocTracer.TraceMutex) { 87 1.1 kamil AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; 88 1.1 kamil } 89 1.1 kamil ~TraceLock() { AllocTracer.TraceDisabled = !AllocTracer.TraceDisabled; } 90 1.1 kamil 91 1.1 kamil bool IsDisabled() const { 92 1.1 kamil // This is already inverted value. 93 1.1 kamil return !AllocTracer.TraceDisabled; 94 1.1 kamil } 95 1.1 kamil 96 1.1 kamil private: 97 1.1 kamil std::lock_guard<std::recursive_mutex> Lock; 98 1.1 kamil }; 99 1.1 kamil 100 1.1 kamil ATTRIBUTE_NO_SANITIZE_MEMORY 101 1.1 kamil void MallocHook(const volatile void *ptr, size_t size) { 102 1.1 kamil size_t N = AllocTracer.Mallocs++; 103 1.1 kamil F->HandleMalloc(size); 104 1.1 kamil if (int TraceLevel = AllocTracer.TraceLevel) { 105 1.1 kamil TraceLock Lock; 106 1.1 kamil if (Lock.IsDisabled()) 107 1.1 kamil return; 108 1.1 kamil Printf("MALLOC[%zd] %p %zd\n", N, ptr, size); 109 1.1 kamil if (TraceLevel >= 2 && EF) 110 1.1 kamil PrintStackTrace(); 111 1.1 kamil } 112 1.1 kamil } 113 1.1 kamil 114 1.1 kamil ATTRIBUTE_NO_SANITIZE_MEMORY 115 1.1 kamil void FreeHook(const volatile void *ptr) { 116 1.1 kamil size_t N = AllocTracer.Frees++; 117 1.1 kamil if (int TraceLevel = AllocTracer.TraceLevel) { 118 1.1 kamil TraceLock Lock; 119 1.1 kamil if (Lock.IsDisabled()) 120 1.1 kamil return; 121 1.1 kamil Printf("FREE[%zd] %p\n", N, ptr); 122 1.1 kamil if (TraceLevel >= 2 && EF) 123 1.1 kamil PrintStackTrace(); 124 1.1 kamil } 125 1.1 kamil } 126 1.1 kamil 127 1.1 kamil // Crash on a single malloc that exceeds the rss limit. 128 1.1 kamil void Fuzzer::HandleMalloc(size_t Size) { 129 1.1 kamil if (!Options.MallocLimitMb || (Size >> 20) < (size_t)Options.MallocLimitMb) 130 1.1 kamil return; 131 1.1 kamil Printf("==%d== ERROR: libFuzzer: out-of-memory (malloc(%zd))\n", GetPid(), 132 1.1 kamil Size); 133 1.1 kamil Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); 134 1.1 kamil PrintStackTrace(); 135 1.1 kamil DumpCurrentUnit("oom-"); 136 1.1 kamil Printf("SUMMARY: libFuzzer: out-of-memory\n"); 137 1.1 kamil PrintFinalStats(); 138 1.1 kamil _Exit(Options.ErrorExitCode); // Stop right now. 139 1.1 kamil } 140 1.1 kamil 141 1.1 kamil Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, 142 1.1 kamil FuzzingOptions Options) 143 1.1 kamil : CB(CB), Corpus(Corpus), MD(MD), Options(Options) { 144 1.1 kamil if (EF->__sanitizer_set_death_callback) 145 1.1 kamil EF->__sanitizer_set_death_callback(StaticDeathCallback); 146 1.1 kamil assert(!F); 147 1.1 kamil F = this; 148 1.1 kamil TPC.ResetMaps(); 149 1.1 kamil IsMyThread = true; 150 1.1 kamil if (Options.DetectLeaks && EF->__sanitizer_install_malloc_and_free_hooks) 151 1.1 kamil EF->__sanitizer_install_malloc_and_free_hooks(MallocHook, FreeHook); 152 1.1 kamil TPC.SetUseCounters(Options.UseCounters); 153 1.1 kamil TPC.SetUseValueProfileMask(Options.UseValueProfile); 154 1.1 kamil 155 1.1 kamil if (Options.Verbosity) 156 1.1 kamil TPC.PrintModuleInfo(); 157 1.1 kamil if (!Options.OutputCorpus.empty() && Options.ReloadIntervalSec) 158 1.1 kamil EpochOfLastReadOfOutputCorpus = GetEpoch(Options.OutputCorpus); 159 1.1 kamil MaxInputLen = MaxMutationLen = Options.MaxLen; 160 1.1 kamil TmpMaxMutationLen = Max(size_t(4), Corpus.MaxInputSize()); 161 1.1 kamil AllocateCurrentUnitData(); 162 1.1 kamil CurrentUnitSize = 0; 163 1.1 kamil memset(BaseSha1, 0, sizeof(BaseSha1)); 164 1.1 kamil TPC.SetFocusFunction(Options.FocusFunction); 165 1.1 kamil DFT.Init(Options.DataFlowTrace, Options.FocusFunction); 166 1.1 kamil } 167 1.1 kamil 168 1.1 kamil Fuzzer::~Fuzzer() {} 169 1.1 kamil 170 1.1 kamil void Fuzzer::AllocateCurrentUnitData() { 171 1.1 kamil if (CurrentUnitData || MaxInputLen == 0) 172 1.1 kamil return; 173 1.1 kamil CurrentUnitData = new uint8_t[MaxInputLen]; 174 1.1 kamil } 175 1.1 kamil 176 1.1 kamil void Fuzzer::StaticDeathCallback() { 177 1.1 kamil assert(F); 178 1.1 kamil F->DeathCallback(); 179 1.1 kamil } 180 1.1 kamil 181 1.1 kamil void Fuzzer::DumpCurrentUnit(const char *Prefix) { 182 1.1 kamil if (!CurrentUnitData) 183 1.1 kamil return; // Happens when running individual inputs. 184 1.1 kamil ScopedDisableMsanInterceptorChecks S; 185 1.1 kamil MD.PrintMutationSequence(); 186 1.1 kamil Printf("; base unit: %s\n", Sha1ToString(BaseSha1).c_str()); 187 1.1 kamil size_t UnitSize = CurrentUnitSize; 188 1.1 kamil if (UnitSize <= kMaxUnitSizeToPrint) { 189 1.1 kamil PrintHexArray(CurrentUnitData, UnitSize, "\n"); 190 1.1 kamil PrintASCII(CurrentUnitData, UnitSize, "\n"); 191 1.1 kamil } 192 1.1 kamil WriteUnitToFileWithPrefix({CurrentUnitData, CurrentUnitData + UnitSize}, 193 1.1 kamil Prefix); 194 1.1 kamil } 195 1.1 kamil 196 1.1 kamil NO_SANITIZE_MEMORY 197 1.1 kamil void Fuzzer::DeathCallback() { 198 1.1 kamil DumpCurrentUnit("crash-"); 199 1.1 kamil PrintFinalStats(); 200 1.1 kamil } 201 1.1 kamil 202 1.1 kamil void Fuzzer::StaticAlarmCallback() { 203 1.1 kamil assert(F); 204 1.1 kamil F->AlarmCallback(); 205 1.1 kamil } 206 1.1 kamil 207 1.1 kamil void Fuzzer::StaticCrashSignalCallback() { 208 1.1 kamil assert(F); 209 1.1 kamil F->CrashCallback(); 210 1.1 kamil } 211 1.1 kamil 212 1.1 kamil void Fuzzer::StaticExitCallback() { 213 1.1 kamil assert(F); 214 1.1 kamil F->ExitCallback(); 215 1.1 kamil } 216 1.1 kamil 217 1.1 kamil void Fuzzer::StaticInterruptCallback() { 218 1.1 kamil assert(F); 219 1.1 kamil F->InterruptCallback(); 220 1.1 kamil } 221 1.1 kamil 222 1.1 kamil void Fuzzer::StaticGracefulExitCallback() { 223 1.1 kamil assert(F); 224 1.1 kamil F->GracefulExitRequested = true; 225 1.1 kamil Printf("INFO: signal received, trying to exit gracefully\n"); 226 1.1 kamil } 227 1.1 kamil 228 1.1 kamil void Fuzzer::StaticFileSizeExceedCallback() { 229 1.1 kamil Printf("==%lu== ERROR: libFuzzer: file size exceeded\n", GetPid()); 230 1.1 kamil exit(1); 231 1.1 kamil } 232 1.1 kamil 233 1.1 kamil void Fuzzer::CrashCallback() { 234 1.1 kamil if (EF->__sanitizer_acquire_crash_state) 235 1.1 kamil EF->__sanitizer_acquire_crash_state(); 236 1.1 kamil Printf("==%lu== ERROR: libFuzzer: deadly signal\n", GetPid()); 237 1.1 kamil PrintStackTrace(); 238 1.1 kamil Printf("NOTE: libFuzzer has rudimentary signal handlers.\n" 239 1.1 kamil " Combine libFuzzer with AddressSanitizer or similar for better " 240 1.1 kamil "crash reports.\n"); 241 1.1 kamil Printf("SUMMARY: libFuzzer: deadly signal\n"); 242 1.1 kamil DumpCurrentUnit("crash-"); 243 1.1 kamil PrintFinalStats(); 244 1.1 kamil _Exit(Options.ErrorExitCode); // Stop right now. 245 1.1 kamil } 246 1.1 kamil 247 1.1 kamil void Fuzzer::ExitCallback() { 248 1.1 kamil if (!RunningUserCallback) 249 1.1 kamil return; // This exit did not come from the user callback 250 1.1 kamil if (EF->__sanitizer_acquire_crash_state && 251 1.1 kamil !EF->__sanitizer_acquire_crash_state()) 252 1.1 kamil return; 253 1.1 kamil Printf("==%lu== ERROR: libFuzzer: fuzz target exited\n", GetPid()); 254 1.1 kamil PrintStackTrace(); 255 1.1 kamil Printf("SUMMARY: libFuzzer: fuzz target exited\n"); 256 1.1 kamil DumpCurrentUnit("crash-"); 257 1.1 kamil PrintFinalStats(); 258 1.1 kamil _Exit(Options.ErrorExitCode); 259 1.1 kamil } 260 1.1 kamil 261 1.1 kamil void Fuzzer::MaybeExitGracefully() { 262 1.1 kamil if (!GracefulExitRequested) return; 263 1.1 kamil Printf("==%lu== INFO: libFuzzer: exiting as requested\n", GetPid()); 264 1.1 kamil PrintFinalStats(); 265 1.1 kamil _Exit(0); 266 1.1 kamil } 267 1.1 kamil 268 1.1 kamil void Fuzzer::InterruptCallback() { 269 1.1 kamil Printf("==%lu== libFuzzer: run interrupted; exiting\n", GetPid()); 270 1.1 kamil PrintFinalStats(); 271 1.1 kamil _Exit(0); // Stop right now, don't perform any at-exit actions. 272 1.1 kamil } 273 1.1 kamil 274 1.1 kamil NO_SANITIZE_MEMORY 275 1.1 kamil void Fuzzer::AlarmCallback() { 276 1.1 kamil assert(Options.UnitTimeoutSec > 0); 277 1.1 kamil // In Windows Alarm callback is executed by a different thread. 278 1.1 kamil // NetBSD's current behavior needs this change too. 279 1.1 kamil #if !LIBFUZZER_WINDOWS && !LIBFUZZER_NETBSD 280 1.1 kamil if (!InFuzzingThread()) 281 1.1 kamil return; 282 1.1 kamil #endif 283 1.1 kamil if (!RunningUserCallback) 284 1.1 kamil return; // We have not started running units yet. 285 1.1 kamil size_t Seconds = 286 1.1 kamil duration_cast<seconds>(system_clock::now() - UnitStartTime).count(); 287 1.1 kamil if (Seconds == 0) 288 1.1 kamil return; 289 1.1 kamil if (Options.Verbosity >= 2) 290 1.1 kamil Printf("AlarmCallback %zd\n", Seconds); 291 1.1 kamil if (Seconds >= (size_t)Options.UnitTimeoutSec) { 292 1.1 kamil if (EF->__sanitizer_acquire_crash_state && 293 1.1 kamil !EF->__sanitizer_acquire_crash_state()) 294 1.1 kamil return; 295 1.1 kamil Printf("ALARM: working on the last Unit for %zd seconds\n", Seconds); 296 1.1 kamil Printf(" and the timeout value is %d (use -timeout=N to change)\n", 297 1.1 kamil Options.UnitTimeoutSec); 298 1.1 kamil DumpCurrentUnit("timeout-"); 299 1.1 kamil Printf("==%lu== ERROR: libFuzzer: timeout after %d seconds\n", GetPid(), 300 1.1 kamil Seconds); 301 1.1 kamil PrintStackTrace(); 302 1.1 kamil Printf("SUMMARY: libFuzzer: timeout\n"); 303 1.1 kamil PrintFinalStats(); 304 1.1 kamil _Exit(Options.TimeoutExitCode); // Stop right now. 305 1.1 kamil } 306 1.1 kamil } 307 1.1 kamil 308 1.1 kamil void Fuzzer::RssLimitCallback() { 309 1.1 kamil if (EF->__sanitizer_acquire_crash_state && 310 1.1 kamil !EF->__sanitizer_acquire_crash_state()) 311 1.1 kamil return; 312 1.1 kamil Printf( 313 1.1 kamil "==%lu== ERROR: libFuzzer: out-of-memory (used: %zdMb; limit: %zdMb)\n", 314 1.1 kamil GetPid(), GetPeakRSSMb(), Options.RssLimitMb); 315 1.1 kamil Printf(" To change the out-of-memory limit use -rss_limit_mb=<N>\n\n"); 316 1.1 kamil PrintMemoryProfile(); 317 1.1 kamil DumpCurrentUnit("oom-"); 318 1.1 kamil Printf("SUMMARY: libFuzzer: out-of-memory\n"); 319 1.1 kamil PrintFinalStats(); 320 1.1 kamil _Exit(Options.ErrorExitCode); // Stop right now. 321 1.1 kamil } 322 1.1 kamil 323 1.1 kamil void Fuzzer::PrintStats(const char *Where, const char *End, size_t Units) { 324 1.1 kamil size_t ExecPerSec = execPerSec(); 325 1.1 kamil if (!Options.Verbosity) 326 1.1 kamil return; 327 1.1 kamil Printf("#%zd\t%s", TotalNumberOfRuns, Where); 328 1.1 kamil if (size_t N = TPC.GetTotalPCCoverage()) 329 1.1 kamil Printf(" cov: %zd", N); 330 1.1 kamil if (size_t N = Corpus.NumFeatures()) 331 1.1 kamil Printf(" ft: %zd", N); 332 1.1 kamil if (!Corpus.empty()) { 333 1.1 kamil Printf(" corp: %zd", Corpus.NumActiveUnits()); 334 1.1 kamil if (size_t N = Corpus.SizeInBytes()) { 335 1.1 kamil if (N < (1 << 14)) 336 1.1 kamil Printf("/%zdb", N); 337 1.1 kamil else if (N < (1 << 24)) 338 1.1 kamil Printf("/%zdKb", N >> 10); 339 1.1 kamil else 340 1.1 kamil Printf("/%zdMb", N >> 20); 341 1.1 kamil } 342 1.1 kamil if (size_t FF = Corpus.NumInputsThatTouchFocusFunction()) 343 1.1 kamil Printf(" focus: %zd", FF); 344 1.1 kamil } 345 1.1 kamil if (TmpMaxMutationLen) 346 1.1 kamil Printf(" lim: %zd", TmpMaxMutationLen); 347 1.1 kamil if (Units) 348 1.1 kamil Printf(" units: %zd", Units); 349 1.1 kamil 350 1.1 kamil Printf(" exec/s: %zd", ExecPerSec); 351 1.1 kamil Printf(" rss: %zdMb", GetPeakRSSMb()); 352 1.1 kamil Printf("%s", End); 353 1.1 kamil } 354 1.1 kamil 355 1.1 kamil void Fuzzer::PrintFinalStats() { 356 1.1 kamil if (Options.PrintCoverage) 357 1.1 kamil TPC.PrintCoverage(); 358 1.1 kamil if (Options.PrintUnstableStats) 359 1.1 kamil TPC.PrintUnstableStats(); 360 1.1 kamil if (Options.DumpCoverage) 361 1.1 kamil TPC.DumpCoverage(); 362 1.1 kamil if (Options.PrintCorpusStats) 363 1.1 kamil Corpus.PrintStats(); 364 1.1 kamil if (!Options.PrintFinalStats) 365 1.1 kamil return; 366 1.1 kamil size_t ExecPerSec = execPerSec(); 367 1.1 kamil Printf("stat::number_of_executed_units: %zd\n", TotalNumberOfRuns); 368 1.1 kamil Printf("stat::average_exec_per_sec: %zd\n", ExecPerSec); 369 1.1 kamil Printf("stat::new_units_added: %zd\n", NumberOfNewUnitsAdded); 370 1.1 kamil Printf("stat::slowest_unit_time_sec: %zd\n", TimeOfLongestUnitInSeconds); 371 1.1 kamil Printf("stat::peak_rss_mb: %zd\n", GetPeakRSSMb()); 372 1.1 kamil } 373 1.1 kamil 374 1.1 kamil void Fuzzer::SetMaxInputLen(size_t MaxInputLen) { 375 1.1 kamil assert(this->MaxInputLen == 0); // Can only reset MaxInputLen from 0 to non-0. 376 1.1 kamil assert(MaxInputLen); 377 1.1 kamil this->MaxInputLen = MaxInputLen; 378 1.1 kamil this->MaxMutationLen = MaxInputLen; 379 1.1 kamil AllocateCurrentUnitData(); 380 1.1 kamil Printf("INFO: -max_len is not provided; " 381 1.1 kamil "libFuzzer will not generate inputs larger than %zd bytes\n", 382 1.1 kamil MaxInputLen); 383 1.1 kamil } 384 1.1 kamil 385 1.1 kamil void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) { 386 1.1 kamil assert(MaxMutationLen && MaxMutationLen <= MaxInputLen); 387 1.1 kamil this->MaxMutationLen = MaxMutationLen; 388 1.1 kamil } 389 1.1 kamil 390 1.1 kamil void Fuzzer::CheckExitOnSrcPosOrItem() { 391 1.1 kamil if (!Options.ExitOnSrcPos.empty()) { 392 1.1 kamil static auto *PCsSet = new Set<uintptr_t>; 393 1.1 kamil auto HandlePC = [&](uintptr_t PC) { 394 1.1 kamil if (!PCsSet->insert(PC).second) 395 1.1 kamil return; 396 1.1 kamil std::string Descr = DescribePC("%F %L", PC + 1); 397 1.1 kamil if (Descr.find(Options.ExitOnSrcPos) != std::string::npos) { 398 1.1 kamil Printf("INFO: found line matching '%s', exiting.\n", 399 1.1 kamil Options.ExitOnSrcPos.c_str()); 400 1.1 kamil _Exit(0); 401 1.1 kamil } 402 1.1 kamil }; 403 1.1 kamil TPC.ForEachObservedPC(HandlePC); 404 1.1 kamil } 405 1.1 kamil if (!Options.ExitOnItem.empty()) { 406 1.1 kamil if (Corpus.HasUnit(Options.ExitOnItem)) { 407 1.1 kamil Printf("INFO: found item with checksum '%s', exiting.\n", 408 1.1 kamil Options.ExitOnItem.c_str()); 409 1.1 kamil _Exit(0); 410 1.1 kamil } 411 1.1 kamil } 412 1.1 kamil } 413 1.1 kamil 414 1.1 kamil void Fuzzer::RereadOutputCorpus(size_t MaxSize) { 415 1.1 kamil if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec) 416 1.1 kamil return; 417 1.1 kamil Vector<Unit> AdditionalCorpus; 418 1.1 kamil ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus, 419 1.1 kamil &EpochOfLastReadOfOutputCorpus, MaxSize, 420 1.1 kamil /*ExitOnError*/ false); 421 1.1 kamil if (Options.Verbosity >= 2) 422 1.1 kamil Printf("Reload: read %zd new units.\n", AdditionalCorpus.size()); 423 1.1 kamil bool Reloaded = false; 424 1.1 kamil for (auto &U : AdditionalCorpus) { 425 1.1 kamil if (U.size() > MaxSize) 426 1.1 kamil U.resize(MaxSize); 427 1.1 kamil if (!Corpus.HasUnit(U)) { 428 1.1 kamil if (RunOne(U.data(), U.size())) { 429 1.1 kamil CheckExitOnSrcPosOrItem(); 430 1.1 kamil Reloaded = true; 431 1.1 kamil } 432 1.1 kamil } 433 1.1 kamil } 434 1.1 kamil if (Reloaded) 435 1.1 kamil PrintStats("RELOAD"); 436 1.1 kamil } 437 1.1 kamil 438 1.1 kamil void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) { 439 1.1 kamil auto TimeOfUnit = 440 1.1 kamil duration_cast<seconds>(UnitStopTime - UnitStartTime).count(); 441 1.1 kamil if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) && 442 1.1 kamil secondsSinceProcessStartUp() >= 2) 443 1.1 kamil PrintStats("pulse "); 444 1.1 kamil if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 && 445 1.1 kamil TimeOfUnit >= Options.ReportSlowUnits) { 446 1.1 kamil TimeOfLongestUnitInSeconds = TimeOfUnit; 447 1.1 kamil Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds); 448 1.1 kamil WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-"); 449 1.1 kamil } 450 1.1 kamil } 451 1.1 kamil 452 1.1 kamil void Fuzzer::CheckForUnstableCounters(const uint8_t *Data, size_t Size) { 453 1.1 kamil auto CBSetupAndRun = [&]() { 454 1.1 kamil ScopedEnableMsanInterceptorChecks S; 455 1.1 kamil UnitStartTime = system_clock::now(); 456 1.1 kamil TPC.ResetMaps(); 457 1.1 kamil RunningUserCallback = true; 458 1.1 kamil CB(Data, Size); 459 1.1 kamil RunningUserCallback = false; 460 1.1 kamil UnitStopTime = system_clock::now(); 461 1.1 kamil }; 462 1.1 kamil 463 1.1 kamil // Copy original run counters into our unstable counters 464 1.1 kamil TPC.InitializeUnstableCounters(); 465 1.1 kamil 466 1.1 kamil // First Rerun 467 1.1 kamil CBSetupAndRun(); 468 1.1 kamil if (TPC.UpdateUnstableCounters(Options.HandleUnstable)) { 469 1.1 kamil // Second Rerun 470 1.1 kamil CBSetupAndRun(); 471 1.1 kamil TPC.UpdateAndApplyUnstableCounters(Options.HandleUnstable); 472 1.1 kamil } 473 1.1 kamil } 474 1.1 kamil 475 1.1 kamil bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile, 476 1.1 kamil InputInfo *II, bool *FoundUniqFeatures) { 477 1.1 kamil if (!Size) 478 1.1 kamil return false; 479 1.1 kamil 480 1.1 kamil ExecuteCallback(Data, Size); 481 1.1 kamil 482 1.1 kamil UniqFeatureSetTmp.clear(); 483 1.1 kamil size_t FoundUniqFeaturesOfII = 0; 484 1.1 kamil size_t NumUpdatesBefore = Corpus.NumFeatureUpdates(); 485 1.1 kamil bool NewFeaturesUnstable = false; 486 1.1 kamil 487 1.1 kamil if (Options.HandleUnstable || Options.PrintUnstableStats) { 488 1.1 kamil TPC.CollectFeatures([&](size_t Feature) { 489 1.1 kamil if (Corpus.IsFeatureNew(Feature, Size, Options.Shrink)) 490 1.1 kamil NewFeaturesUnstable = true; 491 1.1 kamil }); 492 1.1 kamil if (NewFeaturesUnstable) 493 1.1 kamil CheckForUnstableCounters(Data, Size); 494 1.1 kamil } 495 1.1 kamil 496 1.1 kamil TPC.CollectFeatures([&](size_t Feature) { 497 1.1 kamil if (Corpus.AddFeature(Feature, Size, Options.Shrink)) 498 1.1 kamil UniqFeatureSetTmp.push_back(Feature); 499 1.1 kamil if (Options.ReduceInputs && II) 500 1.1 kamil if (std::binary_search(II->UniqFeatureSet.begin(), 501 1.1 kamil II->UniqFeatureSet.end(), Feature)) 502 1.1 kamil FoundUniqFeaturesOfII++; 503 1.1 kamil }); 504 1.1 kamil 505 1.1 kamil if (FoundUniqFeatures) 506 1.1 kamil *FoundUniqFeatures = FoundUniqFeaturesOfII; 507 1.1 kamil PrintPulseAndReportSlowInput(Data, Size); 508 1.1 kamil size_t NumNewFeatures = Corpus.NumFeatureUpdates() - NumUpdatesBefore; 509 1.1 kamil 510 1.1 kamil if (NumNewFeatures) { 511 1.1 kamil TPC.UpdateObservedPCs(); 512 1.1 kamil Corpus.AddToCorpus({Data, Data + Size}, NumNewFeatures, MayDeleteFile, 513 1.1 kamil TPC.ObservedFocusFunction(), UniqFeatureSetTmp, DFT, II); 514 1.1 kamil return true; 515 1.1 kamil } 516 1.1 kamil if (II && FoundUniqFeaturesOfII && 517 1.1 kamil II->DataFlowTraceForFocusFunction.empty() && 518 1.1 kamil FoundUniqFeaturesOfII == II->UniqFeatureSet.size() && 519 1.1 kamil II->U.size() > Size) { 520 1.1 kamil Corpus.Replace(II, {Data, Data + Size}); 521 1.1 kamil return true; 522 1.1 kamil } 523 1.1 kamil return false; 524 1.1 kamil } 525 1.1 kamil 526 1.1 kamil size_t Fuzzer::GetCurrentUnitInFuzzingThead(const uint8_t **Data) const { 527 1.1 kamil assert(InFuzzingThread()); 528 1.1 kamil *Data = CurrentUnitData; 529 1.1 kamil return CurrentUnitSize; 530 1.1 kamil } 531 1.1 kamil 532 1.1 kamil void Fuzzer::CrashOnOverwrittenData() { 533 1.1 kamil Printf("==%d== ERROR: libFuzzer: fuzz target overwrites it's const input\n", 534 1.1 kamil GetPid()); 535 1.1 kamil DumpCurrentUnit("crash-"); 536 1.1 kamil Printf("SUMMARY: libFuzzer: out-of-memory\n"); 537 1.1 kamil _Exit(Options.ErrorExitCode); // Stop right now. 538 1.1 kamil } 539 1.1 kamil 540 1.1 kamil // Compare two arrays, but not all bytes if the arrays are large. 541 1.1 kamil static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) { 542 1.1 kamil const size_t Limit = 64; 543 1.1 kamil if (Size <= 64) 544 1.1 kamil return !memcmp(A, B, Size); 545 1.1 kamil // Compare first and last Limit/2 bytes. 546 1.1 kamil return !memcmp(A, B, Limit / 2) && 547 1.1 kamil !memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2); 548 1.1 kamil } 549 1.1 kamil 550 1.1 kamil void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) { 551 1.1 kamil TPC.RecordInitialStack(); 552 1.1 kamil TotalNumberOfRuns++; 553 1.1 kamil assert(InFuzzingThread()); 554 1.1 kamil if (SMR.IsClient()) 555 1.1 kamil SMR.WriteByteArray(Data, Size); 556 1.1 kamil // We copy the contents of Unit into a separate heap buffer 557 1.1 kamil // so that we reliably find buffer overflows in it. 558 1.1 kamil uint8_t *DataCopy = new uint8_t[Size]; 559 1.1 kamil memcpy(DataCopy, Data, Size); 560 1.1 kamil if (EF->__msan_unpoison) 561 1.1 kamil EF->__msan_unpoison(DataCopy, Size); 562 1.1 kamil if (CurrentUnitData && CurrentUnitData != Data) 563 1.1 kamil memcpy(CurrentUnitData, Data, Size); 564 1.1 kamil CurrentUnitSize = Size; 565 1.1 kamil { 566 1.1 kamil ScopedEnableMsanInterceptorChecks S; 567 1.1 kamil AllocTracer.Start(Options.TraceMalloc); 568 1.1 kamil UnitStartTime = system_clock::now(); 569 1.1 kamil TPC.ResetMaps(); 570 1.1 kamil RunningUserCallback = true; 571 1.1 kamil int Res = CB(DataCopy, Size); 572 1.1 kamil RunningUserCallback = false; 573 1.1 kamil UnitStopTime = system_clock::now(); 574 1.1 kamil (void)Res; 575 1.1 kamil assert(Res == 0); 576 1.1 kamil HasMoreMallocsThanFrees = AllocTracer.Stop(); 577 1.1 kamil } 578 1.1 kamil if (!LooseMemeq(DataCopy, Data, Size)) 579 1.1 kamil CrashOnOverwrittenData(); 580 1.1 kamil CurrentUnitSize = 0; 581 1.1 kamil delete[] DataCopy; 582 1.1 kamil } 583 1.1 kamil 584 1.1 kamil void Fuzzer::WriteToOutputCorpus(const Unit &U) { 585 1.1 kamil if (Options.OnlyASCII) 586 1.1 kamil assert(IsASCII(U)); 587 1.1 kamil if (Options.OutputCorpus.empty()) 588 1.1 kamil return; 589 1.1 kamil std::string Path = DirPlusFile(Options.OutputCorpus, Hash(U)); 590 1.1 kamil WriteToFile(U, Path); 591 1.1 kamil if (Options.Verbosity >= 2) 592 1.1 kamil Printf("Written %zd bytes to %s\n", U.size(), Path.c_str()); 593 1.1 kamil } 594 1.1 kamil 595 1.1 kamil void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) { 596 1.1 kamil if (!Options.SaveArtifacts) 597 1.1 kamil return; 598 1.1 kamil std::string Path = Options.ArtifactPrefix + Prefix + Hash(U); 599 1.1 kamil if (!Options.ExactArtifactPath.empty()) 600 1.1 kamil Path = Options.ExactArtifactPath; // Overrides ArtifactPrefix. 601 1.1 kamil WriteToFile(U, Path); 602 1.1 kamil Printf("artifact_prefix='%s'; Test unit written to %s\n", 603 1.1 kamil Options.ArtifactPrefix.c_str(), Path.c_str()); 604 1.1 kamil if (U.size() <= kMaxUnitSizeToPrint) 605 1.1 kamil Printf("Base64: %s\n", Base64(U).c_str()); 606 1.1 kamil } 607 1.1 kamil 608 1.1 kamil void Fuzzer::PrintStatusForNewUnit(const Unit &U, const char *Text) { 609 1.1 kamil if (!Options.PrintNEW) 610 1.1 kamil return; 611 1.1 kamil PrintStats(Text, ""); 612 1.1 kamil if (Options.Verbosity) { 613 1.1 kamil Printf(" L: %zd/%zd ", U.size(), Corpus.MaxInputSize()); 614 1.1 kamil MD.PrintMutationSequence(); 615 1.1 kamil Printf("\n"); 616 1.1 kamil } 617 1.1 kamil } 618 1.1 kamil 619 1.1 kamil void Fuzzer::ReportNewCoverage(InputInfo *II, const Unit &U) { 620 1.1 kamil II->NumSuccessfullMutations++; 621 1.1 kamil MD.RecordSuccessfulMutationSequence(); 622 1.1 kamil PrintStatusForNewUnit(U, II->Reduced ? "REDUCE" : "NEW "); 623 1.1 kamil WriteToOutputCorpus(U); 624 1.1 kamil NumberOfNewUnitsAdded++; 625 1.1 kamil CheckExitOnSrcPosOrItem(); // Check only after the unit is saved to corpus. 626 1.1 kamil LastCorpusUpdateRun = TotalNumberOfRuns; 627 1.1 kamil } 628 1.1 kamil 629 1.1 kamil // Tries detecting a memory leak on the particular input that we have just 630 1.1 kamil // executed before calling this function. 631 1.1 kamil void Fuzzer::TryDetectingAMemoryLeak(const uint8_t *Data, size_t Size, 632 1.1 kamil bool DuringInitialCorpusExecution) { 633 1.1 kamil if (!HasMoreMallocsThanFrees) 634 1.1 kamil return; // mallocs==frees, a leak is unlikely. 635 1.1 kamil if (!Options.DetectLeaks) 636 1.1 kamil return; 637 1.1 kamil if (!DuringInitialCorpusExecution && 638 1.1 kamil TotalNumberOfRuns >= Options.MaxNumberOfRuns) 639 1.1 kamil return; 640 1.1 kamil if (!&(EF->__lsan_enable) || !&(EF->__lsan_disable) || 641 1.1 kamil !(EF->__lsan_do_recoverable_leak_check)) 642 1.1 kamil return; // No lsan. 643 1.1 kamil // Run the target once again, but with lsan disabled so that if there is 644 1.1 kamil // a real leak we do not report it twice. 645 1.1 kamil EF->__lsan_disable(); 646 1.1 kamil ExecuteCallback(Data, Size); 647 1.1 kamil EF->__lsan_enable(); 648 1.1 kamil if (!HasMoreMallocsThanFrees) 649 1.1 kamil return; // a leak is unlikely. 650 1.1 kamil if (NumberOfLeakDetectionAttempts++ > 1000) { 651 1.1 kamil Options.DetectLeaks = false; 652 1.1 kamil Printf("INFO: libFuzzer disabled leak detection after every mutation.\n" 653 1.1 kamil " Most likely the target function accumulates allocated\n" 654 1.1 kamil " memory in a global state w/o actually leaking it.\n" 655 1.1 kamil " You may try running this binary with -trace_malloc=[12]" 656 1.1 kamil " to get a trace of mallocs and frees.\n" 657 1.1 kamil " If LeakSanitizer is enabled in this process it will still\n" 658 1.1 kamil " run on the process shutdown.\n"); 659 1.1 kamil return; 660 1.1 kamil } 661 1.1 kamil // Now perform the actual lsan pass. This is expensive and we must ensure 662 1.1 kamil // we don't call it too often. 663 1.1 kamil if (EF->__lsan_do_recoverable_leak_check()) { // Leak is found, report it. 664 1.1 kamil if (DuringInitialCorpusExecution) 665 1.1 kamil Printf("\nINFO: a leak has been found in the initial corpus.\n\n"); 666 1.1 kamil Printf("INFO: to ignore leaks on libFuzzer side use -detect_leaks=0.\n\n"); 667 1.1 kamil CurrentUnitSize = Size; 668 1.1 kamil DumpCurrentUnit("leak-"); 669 1.1 kamil PrintFinalStats(); 670 1.1 kamil _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on. 671 1.1 kamil } 672 1.1 kamil } 673 1.1 kamil 674 1.1 kamil void Fuzzer::MutateAndTestOne() { 675 1.1 kamil MD.StartMutationSequence(); 676 1.1 kamil 677 1.1 kamil auto &II = Corpus.ChooseUnitToMutate(MD.GetRand()); 678 1.1 kamil const auto &U = II.U; 679 1.1 kamil memcpy(BaseSha1, II.Sha1, sizeof(BaseSha1)); 680 1.1 kamil assert(CurrentUnitData); 681 1.1 kamil size_t Size = U.size(); 682 1.1 kamil assert(Size <= MaxInputLen && "Oversized Unit"); 683 1.1 kamil memcpy(CurrentUnitData, U.data(), Size); 684 1.1 kamil 685 1.1 kamil assert(MaxMutationLen > 0); 686 1.1 kamil 687 1.1 kamil size_t CurrentMaxMutationLen = 688 1.1 kamil Min(MaxMutationLen, Max(U.size(), TmpMaxMutationLen)); 689 1.1 kamil assert(CurrentMaxMutationLen > 0); 690 1.1 kamil 691 1.1 kamil for (int i = 0; i < Options.MutateDepth; i++) { 692 1.1 kamil if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) 693 1.1 kamil break; 694 1.1 kamil MaybeExitGracefully(); 695 1.1 kamil size_t NewSize = 0; 696 1.1 kamil if (II.HasFocusFunction && !II.DataFlowTraceForFocusFunction.empty() && 697 1.1 kamil Size <= CurrentMaxMutationLen) 698 1.1 kamil NewSize = MD.MutateWithMask(CurrentUnitData, Size, Size, 699 1.1 kamil II.DataFlowTraceForFocusFunction); 700 1.1 kamil else 701 1.1 kamil NewSize = MD.Mutate(CurrentUnitData, Size, CurrentMaxMutationLen); 702 1.1 kamil assert(NewSize > 0 && "Mutator returned empty unit"); 703 1.1 kamil assert(NewSize <= CurrentMaxMutationLen && "Mutator return oversized unit"); 704 1.1 kamil Size = NewSize; 705 1.1 kamil II.NumExecutedMutations++; 706 1.1 kamil 707 1.1 kamil bool FoundUniqFeatures = false; 708 1.1 kamil bool NewCov = RunOne(CurrentUnitData, Size, /*MayDeleteFile=*/true, &II, 709 1.1 kamil &FoundUniqFeatures); 710 1.1 kamil TryDetectingAMemoryLeak(CurrentUnitData, Size, 711 1.1 kamil /*DuringInitialCorpusExecution*/ false); 712 1.1 kamil if (NewCov) { 713 1.1 kamil ReportNewCoverage(&II, {CurrentUnitData, CurrentUnitData + Size}); 714 1.1 kamil break; // We will mutate this input more in the next rounds. 715 1.1 kamil } 716 1.1 kamil if (Options.ReduceDepth && !FoundUniqFeatures) 717 1.1 kamil break; 718 1.1 kamil } 719 1.1 kamil } 720 1.1 kamil 721 1.1 kamil void Fuzzer::PurgeAllocator() { 722 1.1 kamil if (Options.PurgeAllocatorIntervalSec < 0 || !EF->__sanitizer_purge_allocator) 723 1.1 kamil return; 724 1.1 kamil if (duration_cast<seconds>(system_clock::now() - 725 1.1 kamil LastAllocatorPurgeAttemptTime) 726 1.1 kamil .count() < Options.PurgeAllocatorIntervalSec) 727 1.1 kamil return; 728 1.1 kamil 729 1.1 kamil if (Options.RssLimitMb <= 0 || 730 1.1 kamil GetPeakRSSMb() > static_cast<size_t>(Options.RssLimitMb) / 2) 731 1.1 kamil EF->__sanitizer_purge_allocator(); 732 1.1 kamil 733 1.1 kamil LastAllocatorPurgeAttemptTime = system_clock::now(); 734 1.1 kamil } 735 1.1 kamil 736 1.1 kamil void Fuzzer::ReadAndExecuteSeedCorpora(const Vector<std::string> &CorpusDirs) { 737 1.1 kamil const size_t kMaxSaneLen = 1 << 20; 738 1.1 kamil const size_t kMinDefaultLen = 4096; 739 1.1 kamil Vector<SizedFile> SizedFiles; 740 1.1 kamil size_t MaxSize = 0; 741 1.1 kamil size_t MinSize = -1; 742 1.1 kamil size_t TotalSize = 0; 743 1.1 kamil size_t LastNumFiles = 0; 744 1.1 kamil for (auto &Dir : CorpusDirs) { 745 1.1 kamil GetSizedFilesFromDir(Dir, &SizedFiles); 746 1.1 kamil Printf("INFO: % 8zd files found in %s\n", SizedFiles.size() - LastNumFiles, 747 1.1 kamil Dir.c_str()); 748 1.1 kamil LastNumFiles = SizedFiles.size(); 749 1.1 kamil } 750 1.1 kamil for (auto &File : SizedFiles) { 751 1.1 kamil MaxSize = Max(File.Size, MaxSize); 752 1.1 kamil MinSize = Min(File.Size, MinSize); 753 1.1 kamil TotalSize += File.Size; 754 1.1 kamil } 755 1.1 kamil if (Options.MaxLen == 0) 756 1.1 kamil SetMaxInputLen(std::min(std::max(kMinDefaultLen, MaxSize), kMaxSaneLen)); 757 1.1 kamil assert(MaxInputLen > 0); 758 1.1 kamil 759 1.1 kamil // Test the callback with empty input and never try it again. 760 1.1 kamil uint8_t dummy = 0; 761 1.1 kamil ExecuteCallback(&dummy, 0); 762 1.1 kamil 763 1.1 kamil if (SizedFiles.empty()) { 764 1.1 kamil Printf("INFO: A corpus is not provided, starting from an empty corpus\n"); 765 1.1 kamil Unit U({'\n'}); // Valid ASCII input. 766 1.1 kamil RunOne(U.data(), U.size()); 767 1.1 kamil } else { 768 1.1 kamil Printf("INFO: seed corpus: files: %zd min: %zdb max: %zdb total: %zdb" 769 1.1 kamil " rss: %zdMb\n", 770 1.1 kamil SizedFiles.size(), MinSize, MaxSize, TotalSize, GetPeakRSSMb()); 771 1.1 kamil if (Options.ShuffleAtStartUp) 772 1.1 kamil std::shuffle(SizedFiles.begin(), SizedFiles.end(), MD.GetRand()); 773 1.1 kamil 774 1.1 kamil if (Options.PreferSmall) { 775 1.1 kamil std::stable_sort(SizedFiles.begin(), SizedFiles.end()); 776 1.1 kamil assert(SizedFiles.front().Size <= SizedFiles.back().Size); 777 1.1 kamil } 778 1.1 kamil 779 1.1 kamil // Load and execute inputs one by one. 780 1.1 kamil for (auto &SF : SizedFiles) { 781 1.1 kamil auto U = FileToVector(SF.File, MaxInputLen, /*ExitOnError=*/false); 782 1.1 kamil assert(U.size() <= MaxInputLen); 783 1.1 kamil RunOne(U.data(), U.size()); 784 1.1 kamil CheckExitOnSrcPosOrItem(); 785 1.1 kamil TryDetectingAMemoryLeak(U.data(), U.size(), 786 1.1 kamil /*DuringInitialCorpusExecution*/ true); 787 1.1 kamil } 788 1.1 kamil } 789 1.1 kamil 790 1.1 kamil PrintStats("INITED"); 791 1.1 kamil if (!Options.FocusFunction.empty()) 792 1.1 kamil Printf("INFO: %zd/%zd inputs touch the focus function\n", 793 1.1 kamil Corpus.NumInputsThatTouchFocusFunction(), Corpus.size()); 794 1.1 kamil if (!Options.DataFlowTrace.empty()) 795 1.1 kamil Printf("INFO: %zd/%zd inputs have the Data Flow Trace\n", 796 1.1 kamil Corpus.NumInputsWithDataFlowTrace(), Corpus.size()); 797 1.1 kamil 798 1.1 kamil if (Corpus.empty() && Options.MaxNumberOfRuns) { 799 1.1 kamil Printf("ERROR: no interesting inputs were found. " 800 1.1 kamil "Is the code instrumented for coverage? Exiting.\n"); 801 1.1 kamil exit(1); 802 1.1 kamil } 803 1.1 kamil } 804 1.1 kamil 805 1.1 kamil void Fuzzer::Loop(const Vector<std::string> &CorpusDirs) { 806 1.1 kamil ReadAndExecuteSeedCorpora(CorpusDirs); 807 1.1 kamil DFT.Clear(); // No need for DFT any more. 808 1.1 kamil TPC.SetPrintNewPCs(Options.PrintNewCovPcs); 809 1.1 kamil TPC.SetPrintNewFuncs(Options.PrintNewCovFuncs); 810 1.1 kamil system_clock::time_point LastCorpusReload = system_clock::now(); 811 1.1 kamil if (Options.DoCrossOver) 812 1.1 kamil MD.SetCorpus(&Corpus); 813 1.1 kamil while (true) { 814 1.1 kamil auto Now = system_clock::now(); 815 1.1 kamil if (duration_cast<seconds>(Now - LastCorpusReload).count() >= 816 1.1 kamil Options.ReloadIntervalSec) { 817 1.1 kamil RereadOutputCorpus(MaxInputLen); 818 1.1 kamil LastCorpusReload = system_clock::now(); 819 1.1 kamil } 820 1.1 kamil if (TotalNumberOfRuns >= Options.MaxNumberOfRuns) 821 1.1 kamil break; 822 1.1 kamil if (TimedOut()) 823 1.1 kamil break; 824 1.1 kamil 825 1.1 kamil // Update TmpMaxMutationLen 826 1.1 kamil if (Options.LenControl) { 827 1.1 kamil if (TmpMaxMutationLen < MaxMutationLen && 828 1.1 kamil TotalNumberOfRuns - LastCorpusUpdateRun > 829 1.1 kamil Options.LenControl * Log(TmpMaxMutationLen)) { 830 1.1 kamil TmpMaxMutationLen = 831 1.1 kamil Min(MaxMutationLen, TmpMaxMutationLen + Log(TmpMaxMutationLen)); 832 1.1 kamil LastCorpusUpdateRun = TotalNumberOfRuns; 833 1.1 kamil } 834 1.1 kamil } else { 835 1.1 kamil TmpMaxMutationLen = MaxMutationLen; 836 1.1 kamil } 837 1.1 kamil 838 1.1 kamil // Perform several mutations and runs. 839 1.1 kamil MutateAndTestOne(); 840 1.1 kamil 841 1.1 kamil PurgeAllocator(); 842 1.1 kamil } 843 1.1 kamil 844 1.1 kamil PrintStats("DONE ", "\n"); 845 1.1 kamil MD.PrintRecommendedDictionary(); 846 1.1 kamil } 847 1.1 kamil 848 1.1 kamil void Fuzzer::MinimizeCrashLoop(const Unit &U) { 849 1.1 kamil if (U.size() <= 1) 850 1.1 kamil return; 851 1.1 kamil while (!TimedOut() && TotalNumberOfRuns < Options.MaxNumberOfRuns) { 852 1.1 kamil MD.StartMutationSequence(); 853 1.1 kamil memcpy(CurrentUnitData, U.data(), U.size()); 854 1.1 kamil for (int i = 0; i < Options.MutateDepth; i++) { 855 1.1 kamil size_t NewSize = MD.Mutate(CurrentUnitData, U.size(), MaxMutationLen); 856 1.1 kamil assert(NewSize > 0 && NewSize <= MaxMutationLen); 857 1.1 kamil ExecuteCallback(CurrentUnitData, NewSize); 858 1.1 kamil PrintPulseAndReportSlowInput(CurrentUnitData, NewSize); 859 1.1 kamil TryDetectingAMemoryLeak(CurrentUnitData, NewSize, 860 1.1 kamil /*DuringInitialCorpusExecution*/ false); 861 1.1 kamil } 862 1.1 kamil } 863 1.1 kamil } 864 1.1 kamil 865 1.1 kamil void Fuzzer::AnnounceOutput(const uint8_t *Data, size_t Size) { 866 1.1 kamil if (SMR.IsServer()) { 867 1.1 kamil SMR.WriteByteArray(Data, Size); 868 1.1 kamil } else if (SMR.IsClient()) { 869 1.1 kamil SMR.PostClient(); 870 1.1 kamil SMR.WaitServer(); 871 1.1 kamil size_t OtherSize = SMR.ReadByteArraySize(); 872 1.1 kamil uint8_t *OtherData = SMR.GetByteArray(); 873 1.1 kamil if (Size != OtherSize || memcmp(Data, OtherData, Size) != 0) { 874 1.1 kamil size_t i = 0; 875 1.1 kamil for (i = 0; i < Min(Size, OtherSize); i++) 876 1.1 kamil if (Data[i] != OtherData[i]) 877 1.1 kamil break; 878 1.1 kamil Printf("==%lu== ERROR: libFuzzer: equivalence-mismatch. Sizes: %zd %zd; " 879 1.1 kamil "offset %zd\n", 880 1.1 kamil GetPid(), Size, OtherSize, i); 881 1.1 kamil DumpCurrentUnit("mismatch-"); 882 1.1 kamil Printf("SUMMARY: libFuzzer: equivalence-mismatch\n"); 883 1.1 kamil PrintFinalStats(); 884 1.1 kamil _Exit(Options.ErrorExitCode); 885 1.1 kamil } 886 1.1 kamil } 887 1.1 kamil } 888 1.1 kamil 889 1.1 kamil } // namespace fuzzer 890 1.1 kamil 891 1.1 kamil extern "C" { 892 1.1 kamil 893 1.1 kamil __attribute__((visibility("default"))) size_t 894 1.1 kamil LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) { 895 1.1 kamil assert(fuzzer::F); 896 1.1 kamil return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize); 897 1.1 kamil } 898 1.1 kamil 899 1.1 kamil // Experimental 900 1.1 kamil __attribute__((visibility("default"))) void 901 1.1 kamil LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) { 902 1.1 kamil assert(fuzzer::F); 903 1.1 kamil fuzzer::F->AnnounceOutput(Data, Size); 904 1.1 kamil } 905 1.1 kamil } // extern "C" 906