FuzzerMerge.cpp
FuzzerMutate.cpp
FuzzerSHA1.cpp
+ FuzzerShmemPosix.cpp
FuzzerTracePC.cpp
FuzzerTraceState.cpp
FuzzerUtil.cpp
#include "FuzzerIO.h"
#include "FuzzerMutate.h"
#include "FuzzerRandom.h"
+#include "FuzzerShmem.h"
#include "FuzzerTracePC.h"
#include <algorithm>
#include <atomic>
if (Flags.minimize_crash_internal_step)
return MinimizeCrashInputInternalStep(F, Corpus);
+ if (auto Name = Flags.run_equivalence_server) {
+ SMR.Destroy(Name);
+ if (!SMR.Create(Name, 1 << 12)) {
+ Printf("ERROR: can't create shared memory region\n");
+ return 1;
+ }
+ Printf("INFO: EQUIVALENCE SERVER UP\n");
+ while (true) {
+ SMR.WaitClient();
+ size_t Size = SMR.ReadByteArraySize();
+ SMR.WriteByteArray(nullptr, 0);
+ F->RunOne(SMR.GetByteArray(), Size);
+ SMR.PostServer();
+ }
+ return 0;
+ }
+
+ if (auto Name = Flags.use_equivalence_server) {
+ if (!SMR.Open(Name)) {
+ Printf("ERROR: can't open shared memory region\n");
+ return 1;
+ }
+ Printf("INFO: EQUIVALENCE CLIENT UP\n");
+ }
+
if (DoPlainRun) {
Options.SaveArtifacts = false;
int Runs = std::max(1, Flags.runs);
" was added to the corpus. "
"Used primarily for testing libFuzzer itself.")
+FUZZER_FLAG_STRING(run_equivalence_server, "Experimental")
+FUZZER_FLAG_STRING(use_equivalence_server, "Experimental")
+
FUZZER_DEPRECATED_FLAG(exit_on_first)
FUZZER_DEPRECATED_FLAG(save_minimized_corpus)
FUZZER_DEPRECATED_FLAG(sync_command)
bool DuringInitialCorpusExecution);
void HandleMalloc(size_t Size);
+ void AnnounceOutput(const uint8_t *Data, size_t Size);
private:
void AlarmCallback();
#include "FuzzerIO.h"
#include "FuzzerMutate.h"
#include "FuzzerRandom.h"
+#include "FuzzerShmem.h"
#include "FuzzerTracePC.h"
#include <algorithm>
#include <cstring>
thread_local bool Fuzzer::IsMyThread;
+SharedMemoryRegion SMR;
+
static void MissingExternalApiFunction(const char *FnName) {
Printf("ERROR: %s is not defined. Exiting.\n"
"Did you use -fsanitize-coverage=... to build your code?\n",
void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
assert(InFuzzingThread());
+ if (SMR.IsClient())
+ SMR.WriteByteArray(Data, Size);
// 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];
}
}
+void Fuzzer::AnnounceOutput(const uint8_t *Data, size_t Size) {
+ if (SMR.IsServer()) {
+ SMR.WriteByteArray(Data, Size);
+ } else if (SMR.IsClient()) {
+ SMR.PostClient();
+ SMR.WaitServer();
+ size_t OtherSize = SMR.ReadByteArraySize();
+ uint8_t *OtherData = SMR.GetByteArray();
+ if (Size != OtherSize || memcmp(Data, OtherData, Size) != 0) {
+ size_t i = 0;
+ for (i = 0; i < Min(Size, OtherSize); i++)
+ if (Data[i] != OtherData[i])
+ break;
+ Printf("==%lu== ERROR: libFuzzer: equivalence-mismatch. Sizes: %zd %zd; "
+ "offset %zd\n", GetPid(), Size, OtherSize, i);
+ DumpCurrentUnit("mismatch-");
+ Printf("SUMMARY: libFuzzer: equivalence-mismatch\n");
+ PrintFinalStats();
+ _Exit(Options.ErrorExitCode);
+ }
+ }
+}
+
} // namespace fuzzer
extern "C" {
}
// Experimental
-void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) {}
+void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size) {
+ assert(fuzzer::F);
+ fuzzer::F->AnnounceOutput(Data, Size);
+}
} // extern "C"
--- /dev/null
+//===- FuzzerShmem.h - shared memory interface ------------------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// SharedMemoryRegion
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FUZZER_SHMEM_H
+#define LLVM_FUZZER_SHMEM_H
+
+#include <algorithm>
+#include <cstring>
+#include <string>
+
+#include "FuzzerDefs.h"
+
+namespace fuzzer {
+
+class SharedMemoryRegion {
+ public:
+ bool Create(const char *Name, size_t Size);
+ bool Open(const char *Name);
+ bool Destroy(const char *Name);
+ size_t GetSize() const { return Size; }
+ uint8_t *GetData() { return Data; }
+ void PostServer() {Post(0);}
+ void WaitServer() {Wait(0);}
+ void PostClient() {Post(1);}
+ void WaitClient() {Wait(1);}
+
+ size_t WriteByteArray(const uint8_t *Bytes, size_t N) {
+ N = std::min(N, GetSize() - sizeof(N));
+ memcpy(GetData(), &N, sizeof(N));
+ memcpy(GetData() + sizeof(N), Bytes, N);
+ assert(N == ReadByteArraySize());
+ return N;
+ }
+ size_t ReadByteArraySize() {
+ size_t Res;
+ memcpy(&Res, GetData(), sizeof(Res));
+ return Res;
+ }
+ uint8_t *GetByteArray() { return GetData() + sizeof(size_t); }
+
+ bool IsServer() const { return Data && IAmServer; }
+ bool IsClient() const { return Data && !IAmServer; }
+
+private:
+ bool IAmServer;
+ std::string Path(const char *Name);
+ std::string SemName(const char *Name, int Idx);
+ void Post(int Idx);
+ void Wait(int Idx);
+
+ bool Map(int fd);
+ size_t Size = 0;
+ uint8_t *Data = nullptr;
+ void *Semaphore[2];
+};
+
+extern SharedMemoryRegion SMR;
+
+} // namespace fuzzer
+
+#endif // LLVM_FUZZER_SHMEM_H
--- /dev/null
+//===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// SharedMemoryRegion
+//===----------------------------------------------------------------------===//
+#include "FuzzerDefs.h"
+#ifdef LIBFUZZER_POSIX
+
+#include "FuzzerIO.h"
+#include "FuzzerShmem.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <unistd.h>
+
+namespace fuzzer {
+
+std::string SharedMemoryRegion::Path(const char *Name) {
+ return DirPlusFile(TmpDir(), Name);
+}
+
+std::string SharedMemoryRegion::SemName(const char *Name, int Idx) {
+ std::string Res(Name);
+ return Res + (char)('0' + Idx);
+}
+
+bool SharedMemoryRegion::Map(int fd) {
+ Data = (uint8_t *)mmap(0, Size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
+ if (Data == (uint8_t*)-1)
+ return false;
+ return true;
+}
+
+bool SharedMemoryRegion::Create(const char *Name, size_t Size) {
+ int fd = open(Path(Name).c_str(), O_CREAT | O_RDWR, 0777);
+ if (fd < 0) return false;
+ if (ftruncate(fd, Size) < 0) return false;
+ this->Size = Size;
+ if (!Map(fd))
+ return false;
+ for (int i = 0; i < 2; i++) {
+ sem_unlink(SemName(Name, i).c_str());
+ Semaphore[i] = sem_open(SemName(Name, i).c_str(), O_CREAT, 0644, 0);
+ if (Semaphore[i] == (void *)-1)
+ return false;
+ }
+ IAmServer = true;
+ return true;
+}
+
+bool SharedMemoryRegion::Open(const char *Name) {
+ int fd = open(Path(Name).c_str(), O_RDWR);
+ if (fd < 0) return false;
+ struct stat stat_res;
+ if (0 != fstat(fd, &stat_res))
+ return false;
+ Size = stat_res.st_size;
+ if (!Map(fd))
+ return false;
+ for (int i = 0; i < 2; i++) {
+ Semaphore[i] = sem_open(SemName(Name, i).c_str(), 0);
+ if (Semaphore[i] == (void *)-1)
+ return false;
+ }
+ IAmServer = false;
+ return true;
+}
+
+bool SharedMemoryRegion::Destroy(const char *Name) {
+ return 0 == unlink(Path(Name).c_str());
+}
+
+void SharedMemoryRegion::Post(int Idx) {
+ assert(Idx == 0 || Idx == 1);
+ sem_post((sem_t*)Semaphore[Idx]);
+}
+
+void SharedMemoryRegion::Wait(int Idx) {
+ assert(Idx == 0 || Idx == 1);
+ if (sem_wait((sem_t*)Semaphore[Idx])) {
+ Printf("ERROR: sem_wait failed\n");
+ exit(1);
+ }
+}
+
+} // namespace fuzzer
+
+#endif // LIBFUZZER_POSIX
// License. See LICENSE.TXT for details.
#include <stddef.h>
#include <stdint.h>
+#include <stdio.h>
// Test for libFuzzer's "equivalence" fuzzing, part A.
extern "C" void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
- if (Size > 100) return 0;
- uint8_t Result[100];
+ // fprintf(stderr, "A %zd\n", Size);
+ uint8_t Result[50];
+ if (Size > 50) Size = 50;
for (size_t i = 0; i < Size; i++)
Result[Size - i - 1] = Data[i];
LLVMFuzzerAnnounceOutput(Result, Size);
// Test for libFuzzer's "equivalence" fuzzing, part B.
extern "C" void LLVMFuzzerAnnounceOutput(const uint8_t *Data, size_t Size);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
- if (Size > 100) return 0;
- uint8_t Result[100];
+ // fprintf(stderr, "B %zd\n", Size);
+ uint8_t Result[50];
+ if (Size > 50) Size = 50;
for (size_t i = 0; i < Size; i++)
Result[Size - i - 1] = Data[i];
// Be a bit different from EquivalenceATest
- if (Size > 42 && Data[10] == 'B') {
+ if (Size > 10 && Data[5] == 'B' && Data[6] == 'C' && Data[7] == 'D') {
static int c;
if (!c)
fprintf(stderr, "ZZZZZZZ\n");
c = 1;
- Result[42]++;
+ Result[2]++;
}
LLVMFuzzerAnnounceOutput(Result, Size);
--- /dev/null
+RUN: LLVMFuzzer-EquivalenceATest -run_equivalence_server=EQUIV_TEST & export APID=$!
+RUN: not LLVMFuzzer-EquivalenceBTest -use_equivalence_server=EQUIV_TEST 2>&1 | FileCheck %s
+CHECK: ERROR: libFuzzer: equivalence-mismatch. Sizes: {{.*}}; offset 2
+CHECK: SUMMARY: libFuzzer: equivalence-mismatch
+RUN: kill -9 $APID