[llvm] r292646 - [libFuzzer] experimental support for 'equivalance fuzzing'
Kostya Serebryany via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 20 12:57:08 PST 2017
Author: kcc
Date: Fri Jan 20 14:57:07 2017
New Revision: 292646
URL: http://llvm.org/viewvc/llvm-project?rev=292646&view=rev
Log:
[libFuzzer] experimental support for 'equivalance fuzzing'
Added:
llvm/trunk/lib/Fuzzer/FuzzerShmem.h
llvm/trunk/lib/Fuzzer/FuzzerShmemPosix.cpp
llvm/trunk/lib/Fuzzer/test/equivalence.test
Modified:
llvm/trunk/lib/Fuzzer/CMakeLists.txt
llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
llvm/trunk/lib/Fuzzer/FuzzerFlags.def
llvm/trunk/lib/Fuzzer/FuzzerInternal.h
llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
llvm/trunk/lib/Fuzzer/test/EquivalenceATest.cpp
llvm/trunk/lib/Fuzzer/test/EquivalenceBTest.cpp
Modified: llvm/trunk/lib/Fuzzer/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/CMakeLists.txt?rev=292646&r1=292645&r2=292646&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/CMakeLists.txt (original)
+++ llvm/trunk/lib/Fuzzer/CMakeLists.txt Fri Jan 20 14:57:07 2017
@@ -21,6 +21,7 @@ if( LLVM_USE_SANITIZE_COVERAGE )
FuzzerMerge.cpp
FuzzerMutate.cpp
FuzzerSHA1.cpp
+ FuzzerShmemPosix.cpp
FuzzerTracePC.cpp
FuzzerTraceState.cpp
FuzzerUtil.cpp
Modified: llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp?rev=292646&r1=292645&r2=292646&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerDriver.cpp Fri Jan 20 14:57:07 2017
@@ -15,6 +15,7 @@
#include "FuzzerIO.h"
#include "FuzzerMutate.h"
#include "FuzzerRandom.h"
+#include "FuzzerShmem.h"
#include "FuzzerTracePC.h"
#include <algorithm>
#include <atomic>
@@ -474,6 +475,31 @@ int FuzzerDriver(int *argc, char ***argv
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);
Modified: llvm/trunk/lib/Fuzzer/FuzzerFlags.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerFlags.def?rev=292646&r1=292645&r2=292646&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerFlags.def (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerFlags.def Fri Jan 20 14:57:07 2017
@@ -106,6 +106,9 @@ FUZZER_FLAG_STRING(exit_on_item, "Exit i
" 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)
Modified: llvm/trunk/lib/Fuzzer/FuzzerInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerInternal.h?rev=292646&r1=292645&r2=292646&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerInternal.h (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerInternal.h Fri Jan 20 14:57:07 2017
@@ -109,6 +109,7 @@ public:
bool DuringInitialCorpusExecution);
void HandleMalloc(size_t Size);
+ void AnnounceOutput(const uint8_t *Data, size_t Size);
private:
void AlarmCallback();
Modified: llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp?rev=292646&r1=292645&r2=292646&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp (original)
+++ llvm/trunk/lib/Fuzzer/FuzzerLoop.cpp Fri Jan 20 14:57:07 2017
@@ -14,6 +14,7 @@
#include "FuzzerIO.h"
#include "FuzzerMutate.h"
#include "FuzzerRandom.h"
+#include "FuzzerShmem.h"
#include "FuzzerTracePC.h"
#include <algorithm>
#include <cstring>
@@ -42,6 +43,8 @@ static const size_t kMaxUnitSizeToPrint
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",
@@ -531,6 +534,8 @@ size_t Fuzzer::GetCurrentUnitInFuzzingTh
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];
@@ -806,6 +811,29 @@ void Fuzzer::MinimizeCrashLoop(const Uni
}
}
+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" {
@@ -816,5 +844,8 @@ size_t LLVMFuzzerMutate(uint8_t *Data, s
}
// 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"
Added: llvm/trunk/lib/Fuzzer/FuzzerShmem.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerShmem.h?rev=292646&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerShmem.h (added)
+++ llvm/trunk/lib/Fuzzer/FuzzerShmem.h Fri Jan 20 14:57:07 2017
@@ -0,0 +1,69 @@
+//===- 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
Added: llvm/trunk/lib/Fuzzer/FuzzerShmemPosix.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/FuzzerShmemPosix.cpp?rev=292646&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/FuzzerShmemPosix.cpp (added)
+++ llvm/trunk/lib/Fuzzer/FuzzerShmemPosix.cpp Fri Jan 20 14:57:07 2017
@@ -0,0 +1,97 @@
+//===- 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
Modified: llvm/trunk/lib/Fuzzer/test/EquivalenceATest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/EquivalenceATest.cpp?rev=292646&r1=292645&r2=292646&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/EquivalenceATest.cpp (original)
+++ llvm/trunk/lib/Fuzzer/test/EquivalenceATest.cpp Fri Jan 20 14:57:07 2017
@@ -2,12 +2,14 @@
// 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);
Modified: llvm/trunk/lib/Fuzzer/test/EquivalenceBTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/EquivalenceBTest.cpp?rev=292646&r1=292645&r2=292646&view=diff
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/EquivalenceBTest.cpp (original)
+++ llvm/trunk/lib/Fuzzer/test/EquivalenceBTest.cpp Fri Jan 20 14:57:07 2017
@@ -7,18 +7,19 @@
// 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);
Added: llvm/trunk/lib/Fuzzer/test/equivalence.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/test/equivalence.test?rev=292646&view=auto
==============================================================================
--- llvm/trunk/lib/Fuzzer/test/equivalence.test (added)
+++ llvm/trunk/lib/Fuzzer/test/equivalence.test Fri Jan 20 14:57:07 2017
@@ -0,0 +1,5 @@
+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
More information about the llvm-commits
mailing list