// Tries detecting a memory leak on the particular input that we have just // executed before calling this function. void Fuzzer::TryDetectingAMemoryLeak(uint8_t *Data, size_t Size) { if (!HasMoreMallocsThanFrees) return; // mallocs==frees, a leak is unlikely. if (!Options.DetectLeaks) return; if (!&__lsan_enable || !&__lsan_disable || !__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. __lsan_disable(); RunOneAndUpdateCorpus(Data, Size); __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" " 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 (__lsan_do_recoverable_leak_check()) { // Leak is found, report it. CurrentUnitData = Data; CurrentUnitSize = Size; DumpCurrentUnit("leak-"); PrintFinalStats(); _Exit(Options.ErrorExitCode); // not exit() to disable lsan further on. } }
void key_destructor(void *arg) { __lsan_disable(); void *p = malloc(1337); // Break optimization. fprintf(stderr, "Test alloc: %p.\n", p); pthread_setspecific(key, 0); __lsan_enable(); }
int main() { void **p; { __lsan_disable(); p = malloc(sizeof(void *)); __lsan_enable(); } *p = malloc(666); void *q = malloc(1337); // Break optimization. fprintf(stderr, "Test alloc: %p.\n", q); return 0; }