| 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 | 6f5a804 | 2016-09-21 01:50:50 +0000 | [diff] [blame] | 12 | #include "FuzzerDictionary.h" |
| Zachary Turner | 24a148b | 2016-11-30 19:06:14 +0000 | [diff] [blame] | 13 | #include "FuzzerInternal.h" |
| 14 | #include "FuzzerIO.h" |
| Kostya Serebryany | 6f5a804 | 2016-09-21 01:50:50 +0000 | [diff] [blame] | 15 | #include "FuzzerMutate.h" |
| Kostya Serebryany | ab73c69 | 2016-09-23 00:46:18 +0000 | [diff] [blame] | 16 | #include "FuzzerTracePC.h" |
| Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 17 | #include <algorithm> |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 18 | #include <cstring> |
| Kostya Serebryany | 859e86d | 2016-01-12 02:08:37 +0000 | [diff] [blame] | 19 | #include <map> |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 20 | #include <set> |
| Zachary Turner | 24a148b | 2016-11-30 19:06:14 +0000 | [diff] [blame] | 21 | #include <thread> |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 22 | |
| Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 23 | namespace fuzzer { |
| 24 | |
| Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 25 | // Declared as static globals for faster checks inside the hooks. |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 26 | static bool RecordingMemmem = false; |
| Kostya Serebryany | 6b08be9 | 2016-07-19 18:29:06 +0000 | [diff] [blame] | 27 | static bool DoingMyOwnMemmem = false; |
| 28 | |
| Kostya Serebryany | a5f94fb | 2016-10-14 20:20:33 +0000 | [diff] [blame] | 29 | ScopedDoingMyOwnMemmem::ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = true; } |
| 30 | ScopedDoingMyOwnMemmem::~ScopedDoingMyOwnMemmem() { DoingMyOwnMemmem = false; } |
| Kostya Serebryany | ae5b956 | 2016-01-15 06:24:05 +0000 | [diff] [blame] | 31 | |
| Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 32 | class TraceState { |
| Mike Aizatsky | f0b3e85 | 2016-06-23 20:44:48 +0000 | [diff] [blame] | 33 | public: |
| 34 | TraceState(MutationDispatcher &MD, const FuzzingOptions &Options, |
| Richard Smith | b62e7e3 | 2016-05-27 21:05:35 +0000 | [diff] [blame] | 35 | const Fuzzer *F) |
| Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 36 | : MD(MD), Options(Options), F(F) {} |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 37 | |
| Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 38 | void StartTraceRecording() { |
| Kostya Serebryany | bb91170 | 2017-01-18 01:10:18 +0000 | [diff] [blame] | 39 | if (!Options.UseMemmem) |
| Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 40 | return; |
| Kostya Serebryany | bb91170 | 2017-01-18 01:10:18 +0000 | [diff] [blame] | 41 | RecordingMemmem = true; |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 42 | InterestingWords.clear(); |
| Kostya Serebryany | 7ec0c56 | 2016-02-13 03:25:16 +0000 | [diff] [blame] | 43 | MD.ClearAutoDictionary(); |
| Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 44 | } |
| 45 | |
| Kostya Serebryany | b65805a | 2016-01-09 03:08:58 +0000 | [diff] [blame] | 46 | void StopTraceRecording() { |
| Kostya Serebryany | bb91170 | 2017-01-18 01:10:18 +0000 | [diff] [blame] | 47 | if (!RecordingMemmem) |
| Mike Aizatsky | f0b3e85 | 2016-06-23 20:44:48 +0000 | [diff] [blame] | 48 | return; |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 49 | for (auto &W : InterestingWords) |
| 50 | MD.AddWordToAutoDictionary({W}); |
| Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 51 | } |
| 52 | |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 53 | void AddInterestingWord(const uint8_t *Data, size_t Size) { |
| 54 | if (!RecordingMemmem || !F->InFuzzingThread()) return; |
| 55 | if (Size <= 1) return; |
| 56 | Size = std::min(Size, Word::GetMaxSize()); |
| 57 | Word W(Data, Size); |
| 58 | InterestingWords.insert(W); |
| 59 | } |
| 60 | |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 61 | private: |
| Kostya Serebryany | d88d130 | 2016-02-02 23:17:45 +0000 | [diff] [blame] | 62 | |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 63 | // TODO: std::set is too inefficient, need to have a custom DS here. |
| 64 | std::set<Word> InterestingWords; |
| Kostya Serebryany | 7ec0c56 | 2016-02-13 03:25:16 +0000 | [diff] [blame] | 65 | MutationDispatcher &MD; |
| Mike Aizatsky | f0b3e85 | 2016-06-23 20:44:48 +0000 | [diff] [blame] | 66 | const FuzzingOptions Options; |
| Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 67 | const Fuzzer *F; |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 68 | }; |
| 69 | |
| Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 70 | static TraceState *TS; |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 71 | |
| Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 72 | void Fuzzer::StartTraceRecording() { |
| Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 73 | if (!TS) return; |
| 74 | TS->StartTraceRecording(); |
| Kostya Serebryany | beb24c3 | 2015-05-07 21:02:11 +0000 | [diff] [blame] | 75 | } |
| 76 | |
| Kostya Serebryany | b65805a | 2016-01-09 03:08:58 +0000 | [diff] [blame] | 77 | void Fuzzer::StopTraceRecording() { |
| 78 | if (!TS) return; |
| 79 | TS->StopTraceRecording(); |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 80 | } |
| 81 | |
| Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 82 | void Fuzzer::InitializeTraceState() { |
| Kostya Serebryany | bb91170 | 2017-01-18 01:10:18 +0000 | [diff] [blame] | 83 | if (!Options.UseMemmem) return; |
| Kostya Serebryany | f26017b | 2016-05-26 21:32:30 +0000 | [diff] [blame] | 84 | TS = new TraceState(MD, Options, this); |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 85 | } |
| 86 | |
| Kostya Serebryany | c9dc96b | 2015-07-30 21:22:22 +0000 | [diff] [blame] | 87 | static size_t InternalStrnlen(const char *S, size_t MaxLen) { |
| 88 | size_t Len = 0; |
| 89 | for (; Len < MaxLen && S[Len]; Len++) {} |
| 90 | return Len; |
| 91 | } |
| 92 | |
| Kostya Serebryany | c58982d | 2017-03-24 22:19:52 +0000 | [diff] [blame^] | 93 | // Finds min of (strlen(S1), strlen(S2)). |
| 94 | // Needed bacause one of these strings may actually be non-zero terminated. |
| 95 | static size_t InternalStrnlen2(const char *S1, const char *S2) { |
| 96 | size_t Len = 0; |
| 97 | for (; S1[Len] && S2[Len]; Len++) {} |
| 98 | return Len; |
| 99 | } |
| 100 | |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 101 | } // namespace fuzzer |
| 102 | |
| Kostya Serebryany | 2252625 | 2015-05-11 21:16:27 +0000 | [diff] [blame] | 103 | using fuzzer::TS; |
| Kostya Serebryany | 5a99ecb | 2015-05-11 20:51:19 +0000 | [diff] [blame] | 104 | |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 105 | extern "C" { |
| Kostya Serebryany | 7f4227d | 2015-08-05 18:23:01 +0000 | [diff] [blame] | 106 | |
| Kostya Serebryany | 4b83a4f | 2016-01-12 16:50:18 +0000 | [diff] [blame] | 107 | // We may need to avoid defining weak hooks to stay compatible with older clang. |
| 108 | #ifndef LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS |
| 109 | # define LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS 1 |
| 110 | #endif |
| 111 | |
| 112 | #if LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS |
| Kostya Serebryany | 3344f35 | 2017-01-17 23:50:21 +0000 | [diff] [blame] | 113 | |
| Mike Aizatsky | 1b65812 | 2017-02-03 20:26:44 +0000 | [diff] [blame] | 114 | ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY |
| Kostya Serebryany | 0e776a2 | 2015-07-30 01:34:58 +0000 | [diff] [blame] | 115 | void __sanitizer_weak_hook_memcmp(void *caller_pc, const void *s1, |
| Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 116 | const void *s2, size_t n, int result) { |
| Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 117 | if (result == 0) return; // No reason to mutate. |
| Kostya Serebryany | c573316 | 2016-01-09 01:39:55 +0000 | [diff] [blame] | 118 | if (n <= 1) return; // Not interesting. |
| Kostya Serebryany | 1d8c2ce | 2017-01-17 23:09:05 +0000 | [diff] [blame] | 119 | fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/false); |
| Kostya Serebryany | b74ba42 | 2015-07-30 02:33:45 +0000 | [diff] [blame] | 120 | } |
| 121 | |
| Mike Aizatsky | 1b65812 | 2017-02-03 20:26:44 +0000 | [diff] [blame] | 122 | ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY |
| Kostya Serebryany | b74ba42 | 2015-07-30 02:33:45 +0000 | [diff] [blame] | 123 | void __sanitizer_weak_hook_strncmp(void *caller_pc, const char *s1, |
| Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 124 | const char *s2, size_t n, int result) { |
| Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 125 | if (result == 0) return; // No reason to mutate. |
| Kostya Serebryany | cd6a466 | 2015-07-31 17:05:05 +0000 | [diff] [blame] | 126 | size_t Len1 = fuzzer::InternalStrnlen(s1, n); |
| 127 | size_t Len2 = fuzzer::InternalStrnlen(s2, n); |
| 128 | n = std::min(n, Len1); |
| 129 | n = std::min(n, Len2); |
| 130 | if (n <= 1) return; // Not interesting. |
| Kostya Serebryany | 1d8c2ce | 2017-01-17 23:09:05 +0000 | [diff] [blame] | 131 | fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, n, /*StopAtZero*/true); |
| Kostya Serebryany | 0e776a2 | 2015-07-30 01:34:58 +0000 | [diff] [blame] | 132 | } |
| 133 | |
| Kostya Serebryany | 3344f35 | 2017-01-17 23:50:21 +0000 | [diff] [blame] | 134 | |
| Mike Aizatsky | 1b65812 | 2017-02-03 20:26:44 +0000 | [diff] [blame] | 135 | ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY |
| Kostya Serebryany | 7f4227d | 2015-08-05 18:23:01 +0000 | [diff] [blame] | 136 | void __sanitizer_weak_hook_strcmp(void *caller_pc, const char *s1, |
| Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 137 | const char *s2, int result) { |
| Kostya Serebryany | e358095 | 2016-01-12 00:43:42 +0000 | [diff] [blame] | 138 | if (result == 0) return; // No reason to mutate. |
| Kostya Serebryany | c58982d | 2017-03-24 22:19:52 +0000 | [diff] [blame^] | 139 | size_t N = fuzzer::InternalStrnlen2(s1, s2); |
| Kostya Serebryany | 7f4227d | 2015-08-05 18:23:01 +0000 | [diff] [blame] | 140 | if (N <= 1) return; // Not interesting. |
| Kostya Serebryany | 1d8c2ce | 2017-01-17 23:09:05 +0000 | [diff] [blame] | 141 | fuzzer::TPC.AddValueForMemcmp(caller_pc, s1, s2, N, /*StopAtZero*/true); |
| Kostya Serebryany | 7f4227d | 2015-08-05 18:23:01 +0000 | [diff] [blame] | 142 | } |
| 143 | |
| Mike Aizatsky | 1b65812 | 2017-02-03 20:26:44 +0000 | [diff] [blame] | 144 | ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 145 | void __sanitizer_weak_hook_strncasecmp(void *called_pc, const char *s1, |
| 146 | const char *s2, size_t n, int result) { |
| 147 | return __sanitizer_weak_hook_strncmp(called_pc, s1, s2, n, result); |
| 148 | } |
| Kostya Serebryany | 3344f35 | 2017-01-17 23:50:21 +0000 | [diff] [blame] | 149 | |
| Mike Aizatsky | 1b65812 | 2017-02-03 20:26:44 +0000 | [diff] [blame] | 150 | ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 151 | void __sanitizer_weak_hook_strcasecmp(void *called_pc, const char *s1, |
| 152 | const char *s2, int result) { |
| 153 | return __sanitizer_weak_hook_strcmp(called_pc, s1, s2, result); |
| 154 | } |
| Kostya Serebryany | 3344f35 | 2017-01-17 23:50:21 +0000 | [diff] [blame] | 155 | |
| Mike Aizatsky | 1b65812 | 2017-02-03 20:26:44 +0000 | [diff] [blame] | 156 | ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 157 | void __sanitizer_weak_hook_strstr(void *called_pc, const char *s1, |
| 158 | const char *s2, char *result) { |
| 159 | TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); |
| 160 | } |
| Kostya Serebryany | 3344f35 | 2017-01-17 23:50:21 +0000 | [diff] [blame] | 161 | |
| Mike Aizatsky | 1b65812 | 2017-02-03 20:26:44 +0000 | [diff] [blame] | 162 | ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 163 | void __sanitizer_weak_hook_strcasestr(void *called_pc, const char *s1, |
| 164 | const char *s2, char *result) { |
| 165 | TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), strlen(s2)); |
| 166 | } |
| Kostya Serebryany | 3344f35 | 2017-01-17 23:50:21 +0000 | [diff] [blame] | 167 | |
| Mike Aizatsky | 1b65812 | 2017-02-03 20:26:44 +0000 | [diff] [blame] | 168 | ATTRIBUTE_INTERFACE ATTRIBUTE_NO_SANITIZE_MEMORY |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 169 | void __sanitizer_weak_hook_memmem(void *called_pc, const void *s1, size_t len1, |
| 170 | const void *s2, size_t len2, void *result) { |
| Kostya Serebryany | 6b08be9 | 2016-07-19 18:29:06 +0000 | [diff] [blame] | 171 | if (fuzzer::DoingMyOwnMemmem) return; |
| 172 | TS->AddInterestingWord(reinterpret_cast<const uint8_t *>(s2), len2); |
| Kostya Serebryany | c135b55 | 2016-07-15 23:27:19 +0000 | [diff] [blame] | 173 | } |
| 174 | |
| Kostya Serebryany | 4b83a4f | 2016-01-12 16:50:18 +0000 | [diff] [blame] | 175 | #endif // LLVM_FUZZER_DEFINES_SANITIZER_WEAK_HOOOKS |
| Kostya Serebryany | 16d03bd | 2015-03-30 22:09:51 +0000 | [diff] [blame] | 176 | } // extern "C" |