2015-05-11 23:16:27 +02:00
|
|
|
//===- FuzzerTraceState.cpp - Trace-based fuzzer mutator ------------------===//
|
2015-03-31 00:09:51 +02:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2016-10-04 08:08:46 +02:00
|
|
|
// Data tracing.
|
2015-03-31 00:09:51 +02:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-09-21 03:50:50 +02:00
|
|
|
#include "FuzzerDictionary.h"
|
2016-11-30 20:06:14 +01:00
|
|
|
#include "FuzzerIO.h"
|
2017-06-06 13:49:48 +02:00
|
|
|
#include "FuzzerInternal.h"
|
2016-09-21 03:50:50 +02:00
|
|
|
#include "FuzzerMutate.h"
|
2016-09-23 02:46:18 +02:00
|
|
|
#include "FuzzerTracePC.h"
|
2015-05-07 23:02:11 +02:00
|
|
|
#include <algorithm>
|
2015-03-31 00:09:51 +02:00
|
|
|
#include <cstring>
|
2016-01-12 03:08:37 +01:00
|
|
|
#include <map>
|
2016-07-16 01:27:19 +02:00
|
|
|
#include <set>
|
2016-11-30 20:06:14 +01:00
|
|
|
#include <thread>
|
2015-03-31 00:09:51 +02:00
|
|
|
|
2015-05-11 22:51:19 +02:00
|
|
|
namespace fuzzer {
|
|
|
|
|
2016-01-15 07:24:05 +01:00
|
|
|
// Declared as static globals for faster checks inside the hooks.
|
2016-07-16 01:27:19 +02:00
|
|
|
static bool RecordingMemmem = false;
|
2016-07-19 20:29:06 +02:00
|
|
|
|
2017-03-31 04:21:28 +02:00
|
|
|
int ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr;
|
2016-01-15 07:24:05 +01:00
|
|
|
|
2015-05-11 23:16:27 +02:00
|
|
|
class TraceState {
|
2016-06-23 22:44:48 +02:00
|
|
|
public:
|
|
|
|
TraceState(MutationDispatcher &MD, const FuzzingOptions &Options,
|
2016-05-27 23:05:35 +02:00
|
|
|
const Fuzzer *F)
|
2016-05-26 23:32:30 +02:00
|
|
|
: MD(MD), Options(Options), F(F) {}
|
2015-03-31 00:09:51 +02:00
|
|
|
|
2015-05-07 23:02:11 +02:00
|
|
|
void StartTraceRecording() {
|
2017-01-18 02:10:18 +01:00
|
|
|
if (!Options.UseMemmem)
|
2016-05-26 23:32:30 +02:00
|
|
|
return;
|
2017-01-18 02:10:18 +01:00
|
|
|
RecordingMemmem = true;
|
2016-07-16 01:27:19 +02:00
|
|
|
InterestingWords.clear();
|
2016-02-13 04:25:16 +01:00
|
|
|
MD.ClearAutoDictionary();
|
2015-05-07 23:02:11 +02:00
|
|
|
}
|
|
|
|
|
2016-01-09 04:08:58 +01:00
|
|
|
void StopTraceRecording() {
|
2017-01-18 02:10:18 +01:00
|
|
|
if (!RecordingMemmem)
|
2016-06-23 22:44:48 +02:00
|
|
|
return;
|
2016-07-16 01:27:19 +02:00
|
|
|
for (auto &W : InterestingWords)
|
|
|
|
MD.AddWordToAutoDictionary({W});
|
2015-05-07 23:02:11 +02:00
|
|
|
}
|
|
|
|
|
2016-07-16 01:27:19 +02:00
|
|
|
void AddInterestingWord(const uint8_t *Data, size_t Size) {
|
|
|
|
if (!RecordingMemmem || !F->InFuzzingThread()) return;
|
|
|
|
if (Size <= 1) return;
|
|
|
|
Size = std::min(Size, Word::GetMaxSize());
|
|
|
|
Word W(Data, Size);
|
|
|
|
InterestingWords.insert(W);
|
|
|
|
}
|
|
|
|
|
2015-03-31 00:09:51 +02:00
|
|
|
private:
|
2016-02-03 00:17:45 +01:00
|
|
|
|
2016-07-16 01:27:19 +02:00
|
|
|
// TODO: std::set is too inefficient, need to have a custom DS here.
|
|
|
|
std::set<Word> InterestingWords;
|
2016-02-13 04:25:16 +01:00
|
|
|
MutationDispatcher &MD;
|
2016-06-23 22:44:48 +02:00
|
|
|
const FuzzingOptions Options;
|
2016-05-26 23:32:30 +02:00
|
|
|
const Fuzzer *F;
|
2015-03-31 00:09:51 +02:00
|
|
|
};
|
|
|
|
|
2015-05-11 23:16:27 +02:00
|
|
|
static TraceState *TS;
|
2015-03-31 00:09:51 +02:00
|
|
|
|
2015-05-07 23:02:11 +02:00
|
|
|
void Fuzzer::StartTraceRecording() {
|
2015-05-11 23:16:27 +02:00
|
|
|
if (!TS) return;
|
|
|
|
TS->StartTraceRecording();
|
2015-05-07 23:02:11 +02:00
|
|
|
}
|
|
|
|
|
2016-01-09 04:08:58 +01:00
|
|
|
void Fuzzer::StopTraceRecording() {
|
|
|
|
if (!TS) return;
|
|
|
|
TS->StopTraceRecording();
|
2015-03-31 00:09:51 +02:00
|
|
|
}
|
|
|
|
|
2015-05-11 23:16:27 +02:00
|
|
|
void Fuzzer::InitializeTraceState() {
|
2017-01-18 02:10:18 +01:00
|
|
|
if (!Options.UseMemmem) return;
|
2016-05-26 23:32:30 +02:00
|
|
|
TS = new TraceState(MD, Options, this);
|
2015-03-31 00:09:51 +02:00
|
|
|
}
|
|
|
|
|
2015-07-30 23:22:22 +02:00
|
|
|
static size_t InternalStrnlen(const char *S, size_t MaxLen) {
|
|
|
|
size_t Len = 0;
|
|
|
|
for (; Len < MaxLen && S[Len]; Len++) {}
|
|
|
|
return Len;
|
|
|
|
}
|
|
|
|
|
2017-03-24 23:19:52 +01:00
|
|
|
// Finds min of (strlen(S1), strlen(S2)).
|
|
|
|
// Needed bacause one of these strings may actually be non-zero terminated.
|
|
|
|
static size_t InternalStrnlen2(const char *S1, const char *S2) {
|
|
|
|
size_t Len = 0;
|
|
|
|
for (; S1[Len] && S2[Len]; Len++) {}
|
|
|
|
return Len;
|
|
|
|
}
|
|
|
|
|
2015-03-31 00:09:51 +02:00
|
|
|
} // namespace fuzzer
|
|
|
|
|
2015-05-11 23:16:27 +02:00
|
|
|
using fuzzer::TS;
|
2015-05-11 22:51:19 +02:00
|
|
|
|
2015-03-31 00:09:51 +02:00
|
|
|
extern "C" {
|
2015-08-05 20:23:01 +02:00
|
|
|
|
2016-01-12 17:50:18 +01:00
|
|
|
// We may need to avoid defining weak hooks to stay compatible with older clang.
|
|
|
|
#ifndef LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
|
|
|
|
# define LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
|
2017-01-18 00:50:21 +01:00
|
|
|
|
2017-02-03 21:26:44 +01:00
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
2015-07-30 03:34:58 +02:00
|
|
|
void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
|
2016-01-12 01:43:42 +01:00
|
|
|
const void *s2, size_t n, int result) {
|
2017-03-31 04:21:28 +02:00
|
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
2016-01-12 01:43:42 +01:00
|
|
|
if (result == 0) return; // No reason to mutate.
|
2016-01-09 02:39:55 +01:00
|
|
|
if (n <= 1) return; // Not interesting.
|
2017-01-18 00:09:05 +01:00
|
|
|
fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/false);
|
2015-07-30 04:33:45 +02:00
|
|
|
}
|
|
|
|
|
2017-02-03 21:26:44 +01:00
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
2015-07-30 04:33:45 +02:00
|
|
|
void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
|
2016-01-12 01:43:42 +01:00
|
|
|
const char *s2, size_t n, int result) {
|
2017-03-31 04:21:28 +02:00
|
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
2016-01-12 01:43:42 +01:00
|
|
|
if (result == 0) return; // No reason to mutate.
|
2015-07-31 19:05:05 +02:00
|
|
|
size_t Len1 = fuzzer::InternalStrnlen(s1, n);
|
|
|
|
size_t Len2 = fuzzer::InternalStrnlen(s2, n);
|
|
|
|
n = std::min(n, Len1);
|
|
|
|
n = std::min(n, Len2);
|
|
|
|
if (n <= 1) return; // Not interesting.
|
2017-01-18 00:09:05 +01:00
|
|
|
fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/true);
|
2015-07-30 03:34:58 +02:00
|
|
|
}
|
|
|
|
|
2017-01-18 00:50:21 +01:00
|
|
|
|
2017-02-03 21:26:44 +01:00
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
2015-08-05 20:23:01 +02:00
|
|
|
void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
|
2016-01-12 01:43:42 +01:00
|
|
|
const char *s2, int result) {
|
2017-03-31 04:21:28 +02:00
|
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
2016-01-12 01:43:42 +01:00
|
|
|
if (result == 0) return; // No reason to mutate.
|
2017-03-24 23:19:52 +01:00
|
|
|
size_t N = fuzzer::InternalStrnlen2(s1, s2);
|
2015-08-05 20:23:01 +02:00
|
|
|
if (N <= 1) return; // Not interesting.
|
2017-01-18 00:09:05 +01:00
|
|
|
fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, N, /*StopAtZero*/true);
|
2015-08-05 20:23:01 +02:00
|
|
|
}
|
|
|
|
|
2017-02-03 21:26:44 +01:00
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
2016-07-16 01:27:19 +02:00
|
|
|
void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1,
|
|
|
|
const char *s2, size_t n, int result) {
|
2017-03-31 04:21:28 +02:00
|
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
2016-07-16 01:27:19 +02:00
|
|
|
return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result);
|
|
|
|
}
|
2017-01-18 00:50:21 +01:00
|
|
|
|
2017-02-03 21:26:44 +01:00
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
2016-07-16 01:27:19 +02:00
|
|
|
void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1,
|
|
|
|
const char *s2, int result) {
|
2017-03-31 04:21:28 +02:00
|
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
2016-07-16 01:27:19 +02:00
|
|
|
return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result);
|
|
|
|
}
|
2017-01-18 00:50:21 +01:00
|
|
|
|
2017-02-03 21:26:44 +01:00
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
2016-07-16 01:27:19 +02:00
|
|
|
void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1,
|
|
|
|
const char *s2, char *result) {
|
2017-03-31 04:21:28 +02:00
|
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
2016-07-16 01:27:19 +02:00
|
|
|
TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
|
|
|
|
}
|
2017-01-18 00:50:21 +01:00
|
|
|
|
2017-02-03 21:26:44 +01:00
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
2016-07-16 01:27:19 +02:00
|
|
|
void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1,
|
|
|
|
const char *s2, char *result) {
|
2017-03-31 04:21:28 +02:00
|
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
2016-07-16 01:27:19 +02:00
|
|
|
TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
|
|
|
|
}
|
2017-01-18 00:50:21 +01:00
|
|
|
|
2017-02-03 21:26:44 +01:00
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
2016-07-16 01:27:19 +02:00
|
|
|
void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1,
|
|
|
|
const void *s2, size_t len2, void *result) {
|
2017-03-31 04:21:28 +02:00
|
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
2016-07-19 20:29:06 +02:00
|
|
|
TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), len2);
|
2016-07-16 01:27:19 +02:00
|
|
|
}
|
|
|
|
|
2016-01-12 17:50:18 +01:00
|
|
|
#endif // LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
|
2015-03-31 00:09:51 +02:00
|
|
|
} // extern "C"
|