#include <algorithm>
#include <cstring>
#include <thread>
-#include <unordered_map>
+#include <map>
#if !LLVM_FUZZER_SUPPORTS_DFSAN
// Stubs for dfsan for platforms where dfsan does not exist and weak
RecordingTraces = false;
for (size_t i = 0; i < NumMutations; i++) {
auto &M = Mutations[i];
- USF.GetMD().AddWordToAutoDictionary(Unit(M.Data, M.Data + M.Size), M.Pos);
+ Unit U(M.Data, M.Data + M.Size);
+ if (Options.Verbosity >= 2) {
+ AutoDictUnitCounts[U]++;
+ AutoDictAdds++;
+ if ((AutoDictAdds & (AutoDictAdds - 1)) == 0) {
+ typedef std::pair<size_t, Unit> CU;
+ std::vector<CU> CountedUnits;
+ for (auto &I : AutoDictUnitCounts)
+ CountedUnits.push_back(std::make_pair(I.second, I.first));
+ std::sort(CountedUnits.begin(), CountedUnits.end(),
+ [](const CU &a, const CU &b) { return a.first > b.first; });
+ Printf("AutoDict:\n");
+ for (auto &I : CountedUnits) {
+ Printf(" %zd ", I.first);
+ PrintASCII(I.second);
+ Printf("\n");
+ }
+ }
+ }
+ USF.GetMD().AddWordToAutoDictionary(U, M.Pos);
}
}
UserSuppliedFuzzer &USF;
const Fuzzer::FuzzingOptions &Options;
const Unit &CurrentUnit;
+ std::map<Unit, size_t> AutoDictUnitCounts;
+ size_t AutoDictAdds = 0;
static thread_local bool IsMyThread;
};
void TraceState::TraceCmpCallback(uintptr_t PC, size_t CmpSize, size_t CmpType,
uint64_t Arg1, uint64_t Arg2) {
if (!RecordingTraces || !IsMyThread) return;
+ if ((CmpType == ICMP_EQ || CmpType == ICMP_NE) && Arg1 == Arg2)
+ return; // No reason to mutate.
int Added = 0;
- if (Options.Verbosity >= 3)
- Printf("TraceCmp %zd/%zd: %p %zd %zd\n", CmpSize, CmpType, PC, Arg1, Arg2);
Added += TryToAddDesiredData(Arg1, Arg2, CmpSize);
Added += TryToAddDesiredData(Arg2, Arg1, CmpSize);
if (!Added && CmpSize == 4 && IsTwoByteData(Arg1) && IsTwoByteData(Arg2)) {
Added += TryToAddDesiredData(Arg1, Arg2, 2);
Added += TryToAddDesiredData(Arg2, Arg1, 2);
}
+ if (Options.Verbosity >= 3 && Added)
+ Printf("TraceCmp %zd/%zd: %p %zd %zd\n", CmpSize, CmpType, PC, Arg1, Arg2);
}
void TraceState::TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1,
const uint8_t *Data2) {
if (!RecordingTraces || !IsMyThread) return;
CmpSize = std::min(CmpSize, TraceBasedMutation::kMaxSize);
- TryToAddDesiredData(Data1, Data2, CmpSize);
- TryToAddDesiredData(Data2, Data1, CmpSize);
+ int Added2 = TryToAddDesiredData(Data1, Data2, CmpSize);
+ int Added1 = TryToAddDesiredData(Data2, Data1, CmpSize);
+ if ((Added1 || Added2) && Options.Verbosity >= 3) {
+ Printf("MemCmp Added %d%d: ", Added1, Added2);
+ if (Added1) PrintASCII(Data1, CmpSize);
+ if (Added2) PrintASCII(Data2, CmpSize);
+ Printf("\n");
+ }
}
void TraceState::TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits,
reinterpret_cast<const uint8_t *>(s2), L1, L2);
}
+// 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
void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1,
- const void *s2, size_t n) {
+ const void *s2, size_t n, int result) {
if (!TS) return;
+ if (result == 0) return; // No reason to mutate.
if (n <= 1) return; // Not interesting.
TS->TraceMemcmpCallback(n, reinterpret_cast<const uint8_t *>(s1),
reinterpret_cast<const uint8_t *>(s2));
}
void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1,
- const char *s2, size_t n) {
+ const char *s2, size_t n, int result) {
if (!TS) 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);
}
void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1,
- const char *s2) {
+ const char *s2, int result) {
if (!TS) return;
+ if (result == 0) return; // No reason to mutate.
size_t Len1 = strlen(s1);
size_t Len2 = strlen(s2);
size_t N = std::min(Len1, Len2);
reinterpret_cast<const uint8_t *>(s2));
}
+#endif // LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS
+
__attribute__((visibility("default")))
void __sanitizer_cov_trace_cmp(uint64_t SizeAndType, uint64_t Arg1,
uint64_t Arg2) {