Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 1 | //===- FuzzerTraceState.cpp - Trace-based fuzzer mutator ------------------===// |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
Kostya Serebryany | 4820cc9 | 2016-10-04 06:08:46 +0000 | [diff] [blame] | 9 | // Data tracing. |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 10 | //===----------------------------------------------------------------------===// |
| 11 | |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 12 | #include "FuzzerInternal.h" |
Kostya Serebryany | 6f5a804 | 2016-09-21 01:50:50 +0000 | [diff] [blame] | 13 | #include "FuzzerDictionary.h" |
| 14 | #include "FuzzerMutate.h" |
| 15 | #include "FuzzerRandom.h" |
Kostya Serebryany | ab73c69 | 2016-09-23 00:46:18 +0000 | [diff] [blame] | 16 | #include "FuzzerTracePC.h" |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 17 | |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 18 | #include <algorithm> |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 19 | #include <cstring> |
Kostya Serebryany | 226b734 | 2016-01-06 00:03:35 +0000 | [diff] [blame] | 20 | #include <thread> |
Kostya Serebryany | 859e86d | 2016-01-12 02:08:37 +0000 | [diff] [blame] | 21 | #include <map> |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 22 | #include <set> |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 23 | |
Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 24 | namespace fuzzer { |
| 25 | |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 26 | // For now, very simple: put Size bytes of Data at position Pos. |
| 27 | struct TraceBasedMutation { |
Kostya Serebryany | 476f0ce | 2016-01-16 03:53:32 +0000 | [diff] [blame] | 28 | uint32_t Pos; |
| 29 | Word W; |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 30 | }; |
| 31 | |
Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 32 | // Declared as static globals for faster checks inside the hooks. |
Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 33 | static bool RecordingMemcmp = false; |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 34 | static bool RecordingMemmem = false; |
Kostya Serebryany | 6b08be9 | 2016-07-19 18:29:06 +0000 | [diff] [blame] | 35 | static bool DoingMyOwnMemmem = false; |
| 36 | |
Kostya Serebryany | a5f94fb | 2016-10-14 20:20:33 +0000 | [diff] [blame^] | 37 | ScopedDoingMyOwnMemmem::ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = true; } |
| 38 | ScopedDoingMyOwnMemmem::~ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = false; } |
Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 39 | |
Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 40 | class TraceState { |
Mike Aizatsky | f0b3e85 | 2016-06-23 20:44:48 +0000 | [diff] [blame] | 41 | public: |
| 42 | TraceState(MutationDispatcher &MD, const FuzzingOptions &Options, |
Richard Smith | b62e7e3 | 2016-05-27 21:05:35 +0000 | [diff] [blame] | 43 | const Fuzzer *F) |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 44 | : MD(MD), Options(Options), F(F) {} |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 45 | |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 46 | void TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1, |
| 47 | const uint8_t *Data2); |
Kostya Serebryany | fb7d8d9 | 2015-07-31 01:33:06 +0000 | [diff] [blame] | 48 | |
| 49 | void TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits, uint64_t Val, |
| 50 | size_t NumCases, uint64_t *Cases); |
Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 51 | int TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData, |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 52 | size_t DataSize); |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 53 | int TryToAddDesiredData(const uint8_t *PresentData, |
| 54 | const uint8_t *DesiredData, size_t DataSize); |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 55 | |
| 56 | void StartTraceRecording() { |
Kostya Serebryany | 5c04bd2 | 2016-09-09 01:17:03 +0000 | [diff] [blame] | 57 | if (!Options.UseMemcmp) |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 58 | return; |
Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 59 | RecordingMemcmp = Options.UseMemcmp; |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 60 | RecordingMemmem = Options.UseMemmem; |
Kostya Serebryany | e7583d2 | 2016-01-09 00:38:40 +0000 | [diff] [blame] | 61 | NumMutations = 0; |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 62 | InterestingWords.clear(); |
Kostya Serebryany | 7ec0c56 | 2016-02-13 03:25:16 +0000 | [diff] [blame] | 63 | MD.ClearAutoDictionary(); |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 64 | } |
| 65 | |
Kostya Serebryany | b65805a | 2016-01-09 03:08:58 +0000 | [diff] [blame] | 66 | void StopTraceRecording() { |
Kostya Serebryany | 5c04bd2 | 2016-09-09 01:17:03 +0000 | [diff] [blame] | 67 | if (!RecordingMemcmp) |
Mike Aizatsky | f0b3e85 | 2016-06-23 20:44:48 +0000 | [diff] [blame] | 68 | return; |
Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 69 | RecordingMemcmp = false; |
Kostya Serebryany | b65805a | 2016-01-09 03:08:58 +0000 | [diff] [blame] | 70 | for (size_t i = 0; i < NumMutations; i++) { |
| 71 | auto &M = Mutations[i]; |
Kostya Serebryany | 859e86d | 2016-01-12 02:08:37 +0000 | [diff] [blame] | 72 | if (Options.Verbosity >= 2) { |
Kostya Serebryany | 476f0ce | 2016-01-16 03:53:32 +0000 | [diff] [blame] | 73 | AutoDictUnitCounts[M.W]++; |
Kostya Serebryany | 859e86d | 2016-01-12 02:08:37 +0000 | [diff] [blame] | 74 | AutoDictAdds++; |
| 75 | if ((AutoDictAdds & (AutoDictAdds - 1)) == 0) { |
Kostya Serebryany | 476f0ce | 2016-01-16 03:53:32 +0000 | [diff] [blame] | 76 | typedef std::pair<size_t, Word> CU; |
Kostya Serebryany | 859e86d | 2016-01-12 02:08:37 +0000 | [diff] [blame] | 77 | std::vector<CU> CountedUnits; |
| 78 | for (auto &I : AutoDictUnitCounts) |
| 79 | CountedUnits.push_back(std::make_pair(I.second, I.first)); |
| 80 | std::sort(CountedUnits.begin(), CountedUnits.end(), |
| 81 | [](const CU &a, const CU &b) { return a.first > b.first; }); |
| 82 | Printf("AutoDict:\n"); |
| 83 | for (auto &I : CountedUnits) { |
| 84 | Printf(" %zd ", I.first); |
Kostya Serebryany | 6f5a804 | 2016-09-21 01:50:50 +0000 | [diff] [blame] | 85 | PrintASCII(I.second.data(), I.second.size()); |
Kostya Serebryany | 859e86d | 2016-01-12 02:08:37 +0000 | [diff] [blame] | 86 | Printf("\n"); |
| 87 | } |
| 88 | } |
| 89 | } |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 90 | MD.AddWordToAutoDictionary({M.W, M.Pos}); |
Kostya Serebryany | b65805a | 2016-01-09 03:08:58 +0000 | [diff] [blame] | 91 | } |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 92 | for (auto &W : InterestingWords) |
| 93 | MD.AddWordToAutoDictionary({W}); |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 94 | } |
| 95 | |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 96 | void AddMutation(uint32_t Pos, uint32_t Size, const uint8_t *Data) { |
Kostya Serebryany | e7583d2 | 2016-01-09 00:38:40 +0000 | [diff] [blame] | 97 | if (NumMutations >= kMaxMutations) return; |
| 98 | auto &M = Mutations[NumMutations++]; |
| 99 | M.Pos = Pos; |
Kostya Serebryany | 476f0ce | 2016-01-16 03:53:32 +0000 | [diff] [blame] | 100 | M.W.Set(Data, Size); |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | void AddMutation(uint32_t Pos, uint32_t Size, uint64_t Data) { |
| 104 | assert(Size <= sizeof(Data)); |
| 105 | AddMutation(Pos, Size, reinterpret_cast<uint8_t*>(&Data)); |
Kostya Serebryany | e7583d2 | 2016-01-09 00:38:40 +0000 | [diff] [blame] | 106 | } |
| 107 | |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 108 | void AddInterestingWord(const uint8_t *Data, size_t Size) { |
| 109 | if (!RecordingMemmem || !F->InFuzzingThread()) return; |
| 110 | if (Size <= 1) return; |
| 111 | Size = std::min(Size, Word::GetMaxSize()); |
| 112 | Word W(Data, Size); |
| 113 | InterestingWords.insert(W); |
| 114 | } |
| 115 | |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 116 | private: |
Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 117 | bool IsTwoByteData(uint64_t Data) { |
| 118 | int64_t Signed = static_cast<int64_t>(Data); |
| 119 | Signed >>= 16; |
| 120 | return Signed == 0 || Signed == -1L; |
| 121 | } |
Kostya Serebryany | d88d130 | 2016-02-02 23:17:45 +0000 | [diff] [blame] | 122 | |
| 123 | // We don't want to create too many trace-based mutations as it is both |
| 124 | // expensive and useless. So after some number of mutations is collected, |
| 125 | // start rejecting some of them. The more there are mutations the more we |
| 126 | // reject. |
| 127 | bool WantToHandleOneMoreMutation() { |
| 128 | const size_t FirstN = 64; |
| 129 | // Gladly handle first N mutations. |
| 130 | if (NumMutations <= FirstN) return true; |
| 131 | size_t Diff = NumMutations - FirstN; |
| 132 | size_t DiffLog = sizeof(long) * 8 - __builtin_clzl((long)Diff); |
| 133 | assert(DiffLog > 0 && DiffLog < 64); |
Kostya Serebryany | 7ec0c56 | 2016-02-13 03:25:16 +0000 | [diff] [blame] | 134 | bool WantThisOne = MD.GetRand()(1 << DiffLog) == 0; // 1 out of DiffLog. |
Kostya Serebryany | d88d130 | 2016-02-02 23:17:45 +0000 | [diff] [blame] | 135 | return WantThisOne; |
| 136 | } |
| 137 | |
Kostya Serebryany | e7583d2 | 2016-01-09 00:38:40 +0000 | [diff] [blame] | 138 | static const size_t kMaxMutations = 1 << 16; |
| 139 | size_t NumMutations; |
| 140 | TraceBasedMutation Mutations[kMaxMutations]; |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 141 | // TODO: std::set is too inefficient, need to have a custom DS here. |
| 142 | std::set<Word> InterestingWords; |
Kostya Serebryany | 7ec0c56 | 2016-02-13 03:25:16 +0000 | [diff] [blame] | 143 | MutationDispatcher &MD; |
Mike Aizatsky | f0b3e85 | 2016-06-23 20:44:48 +0000 | [diff] [blame] | 144 | const FuzzingOptions Options; |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 145 | const Fuzzer *F; |
Kostya Serebryany | 476f0ce | 2016-01-16 03:53:32 +0000 | [diff] [blame] | 146 | std::map<Word, size_t> AutoDictUnitCounts; |
Kostya Serebryany | 859e86d | 2016-01-12 02:08:37 +0000 | [diff] [blame] | 147 | size_t AutoDictAdds = 0; |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 148 | }; |
| 149 | |
Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 150 | int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData, |
Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 151 | size_t DataSize) { |
Kostya Serebryany | d88d130 | 2016-02-02 23:17:45 +0000 | [diff] [blame] | 152 | if (NumMutations >= kMaxMutations || !WantToHandleOneMoreMutation()) return 0; |
Kostya Serebryany | 6b08be9 | 2016-07-19 18:29:06 +0000 | [diff] [blame] | 153 | ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem; |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 154 | const uint8_t *UnitData; |
| 155 | auto UnitSize = F->GetCurrentUnitInFuzzingThead(&UnitData); |
Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 156 | int Res = 0; |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 157 | const uint8_t *Beg = UnitData; |
| 158 | const uint8_t *End = Beg + UnitSize; |
Kostya Serebryany | e641dd6 | 2015-09-04 22:32:25 +0000 | [diff] [blame] | 159 | for (const uint8_t *Cur = Beg; Cur < End; Cur++) { |
Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 160 | Cur = (uint8_t *)memmem(Cur, End - Cur, &PresentData, DataSize); |
| 161 | if (!Cur) |
| 162 | break; |
Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 163 | size_t Pos = Cur - Beg; |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 164 | assert(Pos < UnitSize); |
Kostya Serebryany | e7583d2 | 2016-01-09 00:38:40 +0000 | [diff] [blame] | 165 | AddMutation(Pos, DataSize, DesiredData); |
| 166 | AddMutation(Pos, DataSize, DesiredData + 1); |
| 167 | AddMutation(Pos, DataSize, DesiredData - 1); |
Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 168 | Res++; |
| 169 | } |
| 170 | return Res; |
| 171 | } |
| 172 | |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 173 | int TraceState::TryToAddDesiredData(const uint8_t *PresentData, |
| 174 | const uint8_t *DesiredData, |
| 175 | size_t DataSize) { |
Kostya Serebryany | d88d130 | 2016-02-02 23:17:45 +0000 | [diff] [blame] | 176 | if (NumMutations >= kMaxMutations || !WantToHandleOneMoreMutation()) return 0; |
Kostya Serebryany | 6b08be9 | 2016-07-19 18:29:06 +0000 | [diff] [blame] | 177 | ScopedDoingMyOwnMemmem scoped_doing_my_own_memmem; |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 178 | const uint8_t *UnitData; |
| 179 | auto UnitSize = F->GetCurrentUnitInFuzzingThead(&UnitData); |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 180 | int Res = 0; |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 181 | const uint8_t *Beg = UnitData; |
| 182 | const uint8_t *End = Beg + UnitSize; |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 183 | for (const uint8_t *Cur = Beg; Cur < End; Cur++) { |
| 184 | Cur = (uint8_t *)memmem(Cur, End - Cur, PresentData, DataSize); |
| 185 | if (!Cur) |
| 186 | break; |
| 187 | size_t Pos = Cur - Beg; |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 188 | assert(Pos < UnitSize); |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 189 | AddMutation(Pos, DataSize, DesiredData); |
| 190 | Res++; |
| 191 | } |
| 192 | return Res; |
| 193 | } |
| 194 | |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 195 | void TraceState::TraceMemcmpCallback(size_t CmpSize, const uint8_t *Data1, |
| 196 | const uint8_t *Data2) { |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 197 | if (!RecordingMemcmp || !F->InFuzzingThread()) return; |
Kostya Serebryany | 476f0ce | 2016-01-16 03:53:32 +0000 | [diff] [blame] | 198 | CmpSize = std::min(CmpSize, Word::GetMaxSize()); |
Kostya Serebryany | 1f9c40d | 2016-01-09 03:46:08 +0000 | [diff] [blame] | 199 | int Added2 = TryToAddDesiredData(Data1, Data2, CmpSize); |
| 200 | int Added1 = TryToAddDesiredData(Data2, Data1, CmpSize); |
| 201 | if ((Added1 || Added2) && Options.Verbosity >= 3) { |
| 202 | Printf("MemCmp Added %d%d: ", Added1, Added2); |
Kostya Serebryany | 4174005 | 2016-01-12 02:36:59 +0000 | [diff] [blame] | 203 | if (Added1) PrintASCII(Data1, CmpSize); |
| 204 | if (Added2) PrintASCII(Data2, CmpSize); |
Kostya Serebryany | 1f9c40d | 2016-01-09 03:46:08 +0000 | [diff] [blame] | 205 | Printf("\n"); |
| 206 | } |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 207 | } |
| 208 | |
Kostya Serebryany | fb7d8d9 | 2015-07-31 01:33:06 +0000 | [diff] [blame] | 209 | void TraceState::TraceSwitchCallback(uintptr_t PC, size_t ValSizeInBits, |
| 210 | uint64_t Val, size_t NumCases, |
| 211 | uint64_t *Cases) { |
Kostya Serebryany | 5c04bd2 | 2016-09-09 01:17:03 +0000 | [diff] [blame] | 212 | if (F->InFuzzingThread()) return; |
Kostya Serebryany | fe7e41e | 2015-07-31 20:58:55 +0000 | [diff] [blame] | 213 | size_t ValSize = ValSizeInBits / 8; |
| 214 | bool TryShort = IsTwoByteData(Val); |
Kostya Serebryany | fb7d8d9 | 2015-07-31 01:33:06 +0000 | [diff] [blame] | 215 | for (size_t i = 0; i < NumCases; i++) |
Kostya Serebryany | fe7e41e | 2015-07-31 20:58:55 +0000 | [diff] [blame] | 216 | TryShort &= IsTwoByteData(Cases[i]); |
| 217 | |
| 218 | if (Options.Verbosity >= 3) |
| 219 | Printf("TraceSwitch: %p %zd # %zd; TryShort %d\n", PC, Val, NumCases, |
| 220 | TryShort); |
| 221 | |
| 222 | for (size_t i = 0; i < NumCases; i++) { |
| 223 | TryToAddDesiredData(Val, Cases[i], ValSize); |
| 224 | if (TryShort) |
| 225 | TryToAddDesiredData(Val, Cases[i], 2); |
| 226 | } |
Kostya Serebryany | fb7d8d9 | 2015-07-31 01:33:06 +0000 | [diff] [blame] | 227 | } |
| 228 | |
Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 229 | static TraceState *TS; |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 230 | |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 231 | void Fuzzer::StartTraceRecording() { |
Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 232 | if (!TS) return; |
| 233 | TS->StartTraceRecording(); |
Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 234 | } |
| 235 | |
Kostya Serebryany | b65805a | 2016-01-09 03:08:58 +0000 | [diff] [blame] | 236 | void Fuzzer::StopTraceRecording() { |
| 237 | if (!TS) return; |
| 238 | TS->StopTraceRecording(); |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 239 | } |
| 240 | |
Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 241 | void Fuzzer::InitializeTraceState() { |
Kostya Serebryany | 5c04bd2 | 2016-09-09 01:17:03 +0000 | [diff] [blame] | 242 | if (!Options.UseMemcmp) return; |
Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 243 | TS = new TraceState(MD, Options, this); |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 244 | } |
| 245 | |
Kostya Serebryany | c9dc96b | 2015-07-30 21:22:22 +0000 | [diff] [blame] | 246 | static size_t InternalStrnlen(const char *S, size_t MaxLen) { |
| 247 | size_t Len = 0; |
| 248 | for (; Len < MaxLen && S[Len]; Len++) {} |
| 249 | return Len; |
| 250 | } |
| 251 | |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 252 | } // namespace fuzzer |
| 253 | |
Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 254 | using fuzzer::TS; |
Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 255 | using fuzzer::RecordingMemcmp; |
Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 256 | |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 257 | extern "C" { |
Kostya Serebryany | 7f4227d | 2015-08-05 18:23:01 +0000 | [diff] [blame] | 258 | |
Kostya Serebryany | 4b83a4f | 2016-01-12 16:50:18 +0000 | [diff] [blame] | 259 | // We may need to avoid defining weak hooks to stay compatible with older clang. |
| 260 | #ifndef LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS |
| 261 | # define LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS 1 |
| 262 | #endif |
| 263 | |
| 264 | #if LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS |
Kostya Serebryany | 0e776a2 | 2015-07-30 01:34:58 +0000 | [diff] [blame] | 265 | void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1, |
Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 266 | const void *s2, size_t n, int result) { |
Kostya Serebryany | 379359c | 2016-10-05 01:09:40 +0000 | [diff] [blame] | 267 | fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n); |
Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 268 | if (!RecordingMemcmp) return; |
Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 269 | if (result == 0) return; // No reason to mutate. |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 270 | if (n <= 1) return; // Not interesting. |
| 271 | TS->TraceMemcmpCallback(n, reinterpret_cast<const uint8_t *>(s1), |
| 272 | reinterpret_cast<const uint8_t *>(s2)); |
Kostya Serebryany | b74ba42 | 2015-07-30 02:33:45 +0000 | [diff] [blame] | 273 | } |
| 274 | |
| 275 | void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1, |
Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 276 | const char *s2, size_t n, int result) { |
Kostya Serebryany | 379359c | 2016-10-05 01:09:40 +0000 | [diff] [blame] | 277 | fuzzer::TPC.AddValueForStrcmp(caller_pc, s1, s2, n); |
Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 278 | if (!RecordingMemcmp) return; |
Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 279 | if (result == 0) return; // No reason to mutate. |
Kostya Serebryany | cd6a466 | 2015-07-31 17:05:05 +0000 | [diff] [blame] | 280 | size_t Len1 = fuzzer::InternalStrnlen(s1, n); |
| 281 | size_t Len2 = fuzzer::InternalStrnlen(s2, n); |
| 282 | n = std::min(n, Len1); |
| 283 | n = std::min(n, Len2); |
| 284 | if (n <= 1) return; // Not interesting. |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 285 | TS->TraceMemcmpCallback(n, reinterpret_cast<const uint8_t *>(s1), |
| 286 | reinterpret_cast<const uint8_t *>(s2)); |
Kostya Serebryany | 0e776a2 | 2015-07-30 01:34:58 +0000 | [diff] [blame] | 287 | } |
| 288 | |
Kostya Serebryany | 7f4227d | 2015-08-05 18:23:01 +0000 | [diff] [blame] | 289 | void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1, |
Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 290 | const char *s2, int result) { |
Kostya Serebryany | 379359c | 2016-10-05 01:09:40 +0000 | [diff] [blame] | 291 | fuzzer::TPC.AddValueForStrcmp(caller_pc, s1, s2, 64); |
Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 292 | if (!RecordingMemcmp) return; |
Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 293 | if (result == 0) return; // No reason to mutate. |
Kostya Serebryany | 7f4227d | 2015-08-05 18:23:01 +0000 | [diff] [blame] | 294 | size_t Len1 = strlen(s1); |
| 295 | size_t Len2 = strlen(s2); |
| 296 | size_t N = std::min(Len1, Len2); |
| 297 | if (N <= 1) return; // Not interesting. |
Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 298 | TS->TraceMemcmpCallback(N, reinterpret_cast<const uint8_t *>(s1), |
| 299 | reinterpret_cast<const uint8_t *>(s2)); |
Kostya Serebryany | 7f4227d | 2015-08-05 18:23:01 +0000 | [diff] [blame] | 300 | } |
| 301 | |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 302 | void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, |
| 303 | const char *s2, size_t n, int result) { |
| 304 | return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result); |
| 305 | } |
| 306 | void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, |
| 307 | const char *s2, int result) { |
| 308 | return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); |
| 309 | } |
| 310 | void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, |
| 311 | const char *s2, char *result) { |
| 312 | TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); |
| 313 | } |
| 314 | void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, |
| 315 | const char *s2, char *result) { |
| 316 | TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); |
| 317 | } |
| 318 | void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, |
| 319 | const void *s2, size_t len2, void *result) { |
Kostya Serebryany | 6b08be9 | 2016-07-19 18:29:06 +0000 | [diff] [blame] | 320 | if (fuzzer::DoingMyOwnMemmem) return; |
| 321 | TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), len2); |
Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 322 | } |
| 323 | |
Kostya Serebryany | 4b83a4f | 2016-01-12 16:50:18 +0000 | [diff] [blame] | 324 | #endif // LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS |
Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 325 | } // extern "C" |