mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
eb66b33867
I did this a long time ago with a janky python script, but now clang-format has built-in support for this. I fed clang-format every line with a #include and let it re-sort things according to the precise LLVM rules for include ordering baked into clang-format these days. I've reverted a number of files where the results of sorting includes isn't healthy. Either places where we have legacy code relying on particular include ordering (where possible, I'll fix these separately) or where we have particular formatting around #include lines that I didn't want to disturb in this patch. This patch is *entirely* mechanical. If you get merge conflicts or anything, just ignore the changes in this patch and run clang-format over your #include lines in the files. Sorry for any noise here, but it is important to keep these things stable. I was seeing an increasing number of patches with irrelevant re-ordering of #include lines because clang-format was used. This patch at least isolates that churn, makes it easy to skip when resolving conflicts, and gets us to a clean baseline (again). llvm-svn: 304787
182 lines
5.9 KiB
C++
182 lines
5.9 KiB
C++
//===- FuzzerTraceState.cpp - Trace-based fuzzer mutator ------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// Data tracing.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "FuzzerDictionary.h"
|
|
#include "FuzzerIO.h"
|
|
#include "FuzzerInternal.h"
|
|
#include "FuzzerMutate.h"
|
|
#include "FuzzerTracePC.h"
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
#include <map>
|
|
#include <set>
|
|
#include <thread>
|
|
|
|
namespace fuzzer {
|
|
|
|
// Declared as static globals for faster checks inside the hooks.
|
|
static bool RecordingMemmem = false;
|
|
|
|
int ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr;
|
|
|
|
class TraceState {
|
|
public:
|
|
TraceState(MutationDispatcher &MD, const FuzzingOptions &Options,
|
|
const Fuzzer *F)
|
|
: MD(MD), Options(Options), F(F) {}
|
|
|
|
void StartTraceRecording() {
|
|
if (!Options.UseMemmem)
|
|
return;
|
|
RecordingMemmem = true;
|
|
InterestingWords.clear();
|
|
MD.ClearAutoDictionary();
|
|
}
|
|
|
|
void StopTraceRecording() {
|
|
if (!RecordingMemmem)
|
|
return;
|
|
for (auto &W : InterestingWords)
|
|
MD.AddWordToAutoDictionary({W});
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
private:
|
|
|
|
// TODO: std::set is too inefficient, need to have a custom DS here.
|
|
std::set<Word> InterestingWords;
|
|
MutationDispatcher &MD;
|
|
const FuzzingOptions Options;
|
|
const Fuzzer *F;
|
|
};
|
|
|
|
static TraceState *TS;
|
|
|
|
void Fuzzer::StartTraceRecording() {
|
|
if (!TS) return;
|
|
TS->StartTraceRecording();
|
|
}
|
|
|
|
void Fuzzer::StopTraceRecording() {
|
|
if (!TS) return;
|
|
TS->StopTraceRecording();
|
|
}
|
|
|
|
void Fuzzer::InitializeTraceState() {
|
|
if (!Options.UseMemmem) return;
|
|
TS = new TraceState(MD, Options, this);
|
|
}
|
|
|
|
static size_t InternalStrnlen(const char *S, size_t MaxLen) {
|
|
size_t Len = 0;
|
|
for (; Len < MaxLen && S[Len]; Len++) {}
|
|
return Len;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
} // namespace fuzzer
|
|
|
|
using fuzzer::TS;
|
|
|
|
extern "C" {
|
|
|
|
// 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
|
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
|
void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
|
|
const void *s2, size_t n, int result) {
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
|
if (result == 0) return; // No reason to mutate.
|
|
if (n <= 1) return; // Not interesting.
|
|
fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/false);
|
|
}
|
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
|
void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
|
|
const char *s2, size_t n, int result) {
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
|
if (result == 0) return; // No reason to mutate.
|
|
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.
|
|
fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/true);
|
|
}
|
|
|
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
|
void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
|
|
const char *s2, int result) {
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
|
if (result == 0) return; // No reason to mutate.
|
|
size_t N = fuzzer::InternalStrnlen2(s1, s2);
|
|
if (N <= 1) return; // Not interesting.
|
|
fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, N, /*StopAtZero*/true);
|
|
}
|
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
|
void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1,
|
|
const char *s2, size_t n, int result) {
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
|
return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result);
|
|
}
|
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
|
void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1,
|
|
const char *s2, int result) {
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
|
return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result);
|
|
}
|
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
|
void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1,
|
|
const char *s2, char *result) {
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
|
TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
|
|
}
|
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
|
void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1,
|
|
const char *s2, char *result) {
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
|
TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2));
|
|
}
|
|
|
|
ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY
|
|
void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1,
|
|
const void *s2, size_t len2, void *result) {
|
|
if (fuzzer::ScopedDoingMyOwnMemOrStr::DoingMyOwnMemOrStr) return;
|
|
TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), len2);
|
|
}
|
|
|
|
#endif // LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
|
|
} // extern "C"
|