1 1.1 kamil //===- FuzzerUtilWindows.cpp - Misc utils for Windows. --------------------===// 2 1.1 kamil // 3 1.1 kamil // The LLVM Compiler Infrastructure 4 1.1 kamil // 5 1.1 kamil // This file is distributed under the University of Illinois Open Source 6 1.1 kamil // License. See LICENSE.TXT for details. 7 1.1 kamil // 8 1.1 kamil //===----------------------------------------------------------------------===// 9 1.1 kamil // Misc utils implementation for Windows. 10 1.1 kamil //===----------------------------------------------------------------------===// 11 1.1 kamil #include "FuzzerDefs.h" 12 1.1 kamil #if LIBFUZZER_WINDOWS 13 1.1 kamil #include "FuzzerCommand.h" 14 1.1 kamil #include "FuzzerIO.h" 15 1.1 kamil #include "FuzzerInternal.h" 16 1.1 kamil #include <cassert> 17 1.1 kamil #include <chrono> 18 1.1 kamil #include <cstring> 19 1.1 kamil #include <errno.h> 20 1.1 kamil #include <iomanip> 21 1.1 kamil #include <signal.h> 22 1.1 kamil #include <stdio.h> 23 1.1 kamil #include <sys/types.h> 24 1.1 kamil #include <windows.h> 25 1.1 kamil 26 1.1 kamil // This must be included after windows.h. 27 1.1 kamil #include <psapi.h> 28 1.1 kamil 29 1.1 kamil namespace fuzzer { 30 1.1 kamil 31 1.1 kamil static const FuzzingOptions* HandlerOpt = nullptr; 32 1.1 kamil 33 1.1 kamil static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo) { 34 1.1 kamil switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { 35 1.1 kamil case EXCEPTION_ACCESS_VIOLATION: 36 1.1 kamil case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: 37 1.1 kamil case EXCEPTION_STACK_OVERFLOW: 38 1.1 kamil if (HandlerOpt->HandleSegv) 39 1.1 kamil Fuzzer::StaticCrashSignalCallback(); 40 1.1 kamil break; 41 1.1 kamil case EXCEPTION_DATATYPE_MISALIGNMENT: 42 1.1 kamil case EXCEPTION_IN_PAGE_ERROR: 43 1.1 kamil if (HandlerOpt->HandleBus) 44 1.1 kamil Fuzzer::StaticCrashSignalCallback(); 45 1.1 kamil break; 46 1.1 kamil case EXCEPTION_ILLEGAL_INSTRUCTION: 47 1.1 kamil case EXCEPTION_PRIV_INSTRUCTION: 48 1.1 kamil if (HandlerOpt->HandleIll) 49 1.1 kamil Fuzzer::StaticCrashSignalCallback(); 50 1.1 kamil break; 51 1.1 kamil case EXCEPTION_FLT_DENORMAL_OPERAND: 52 1.1 kamil case EXCEPTION_FLT_DIVIDE_BY_ZERO: 53 1.1 kamil case EXCEPTION_FLT_INEXACT_RESULT: 54 1.1 kamil case EXCEPTION_FLT_INVALID_OPERATION: 55 1.1 kamil case EXCEPTION_FLT_OVERFLOW: 56 1.1 kamil case EXCEPTION_FLT_STACK_CHECK: 57 1.1 kamil case EXCEPTION_FLT_UNDERFLOW: 58 1.1 kamil case EXCEPTION_INT_DIVIDE_BY_ZERO: 59 1.1 kamil case EXCEPTION_INT_OVERFLOW: 60 1.1 kamil if (HandlerOpt->HandleFpe) 61 1.1 kamil Fuzzer::StaticCrashSignalCallback(); 62 1.1 kamil break; 63 1.1 kamil // TODO: handle (Options.HandleXfsz) 64 1.1 kamil } 65 1.1 kamil return EXCEPTION_CONTINUE_SEARCH; 66 1.1 kamil } 67 1.1 kamil 68 1.1 kamil BOOL WINAPI CtrlHandler(DWORD dwCtrlType) { 69 1.1 kamil switch (dwCtrlType) { 70 1.1 kamil case CTRL_C_EVENT: 71 1.1 kamil if (HandlerOpt->HandleInt) 72 1.1 kamil Fuzzer::StaticInterruptCallback(); 73 1.1 kamil return TRUE; 74 1.1 kamil case CTRL_BREAK_EVENT: 75 1.1 kamil if (HandlerOpt->HandleTerm) 76 1.1 kamil Fuzzer::StaticInterruptCallback(); 77 1.1 kamil return TRUE; 78 1.1 kamil } 79 1.1 kamil return FALSE; 80 1.1 kamil } 81 1.1 kamil 82 1.1 kamil void CALLBACK AlarmHandler(PVOID, BOOLEAN) { 83 1.1 kamil Fuzzer::StaticAlarmCallback(); 84 1.1 kamil } 85 1.1 kamil 86 1.1 kamil class TimerQ { 87 1.1 kamil HANDLE TimerQueue; 88 1.1 kamil public: 89 1.1 kamil TimerQ() : TimerQueue(NULL) {}; 90 1.1 kamil ~TimerQ() { 91 1.1 kamil if (TimerQueue) 92 1.1 kamil DeleteTimerQueueEx(TimerQueue, NULL); 93 1.1 kamil }; 94 1.1 kamil void SetTimer(int Seconds) { 95 1.1 kamil if (!TimerQueue) { 96 1.1 kamil TimerQueue = CreateTimerQueue(); 97 1.1 kamil if (!TimerQueue) { 98 1.1 kamil Printf("libFuzzer: CreateTimerQueue failed.\n"); 99 1.1 kamil exit(1); 100 1.1 kamil } 101 1.1 kamil } 102 1.1 kamil HANDLE Timer; 103 1.1 kamil if (!CreateTimerQueueTimer(&Timer, TimerQueue, AlarmHandler, NULL, 104 1.1 kamil Seconds*1000, Seconds*1000, 0)) { 105 1.1 kamil Printf("libFuzzer: CreateTimerQueueTimer failed.\n"); 106 1.1 kamil exit(1); 107 1.1 kamil } 108 1.1 kamil }; 109 1.1 kamil }; 110 1.1 kamil 111 1.1 kamil static TimerQ Timer; 112 1.1 kamil 113 1.1 kamil static void CrashHandler(int) { Fuzzer::StaticCrashSignalCallback(); } 114 1.1 kamil 115 1.1 kamil void SetSignalHandler(const FuzzingOptions& Options) { 116 1.1 kamil HandlerOpt = &Options; 117 1.1 kamil 118 1.1 kamil if (Options.UnitTimeoutSec > 0) 119 1.1 kamil Timer.SetTimer(Options.UnitTimeoutSec / 2 + 1); 120 1.1 kamil 121 1.1 kamil if (Options.HandleInt || Options.HandleTerm) 122 1.1 kamil if (!SetConsoleCtrlHandler(CtrlHandler, TRUE)) { 123 1.1 kamil DWORD LastError = GetLastError(); 124 1.1 kamil Printf("libFuzzer: SetConsoleCtrlHandler failed (Error code: %lu).\n", 125 1.1 kamil LastError); 126 1.1 kamil exit(1); 127 1.1 kamil } 128 1.1 kamil 129 1.1 kamil if (Options.HandleSegv || Options.HandleBus || Options.HandleIll || 130 1.1 kamil Options.HandleFpe) 131 1.1 kamil SetUnhandledExceptionFilter(ExceptionHandler); 132 1.1 kamil 133 1.1 kamil if (Options.HandleAbrt) 134 1.1 kamil if (SIG_ERR == signal(SIGABRT, CrashHandler)) { 135 1.1 kamil Printf("libFuzzer: signal failed with %d\n", errno); 136 1.1 kamil exit(1); 137 1.1 kamil } 138 1.1 kamil } 139 1.1 kamil 140 1.1 kamil void SleepSeconds(int Seconds) { Sleep(Seconds * 1000); } 141 1.1 kamil 142 1.1 kamil unsigned long GetPid() { return GetCurrentProcessId(); } 143 1.1 kamil 144 1.1 kamil size_t GetPeakRSSMb() { 145 1.1 kamil PROCESS_MEMORY_COUNTERS info; 146 1.1 kamil if (!GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info))) 147 1.1 kamil return 0; 148 1.1 kamil return info.PeakWorkingSetSize >> 20; 149 1.1 kamil } 150 1.1 kamil 151 1.1 kamil FILE *OpenProcessPipe(const char *Command, const char *Mode) { 152 1.1 kamil return _popen(Command, Mode); 153 1.1 kamil } 154 1.1 kamil 155 1.1 kamil int ExecuteCommand(const Command &Cmd) { 156 1.1 kamil std::string CmdLine = Cmd.toString(); 157 1.1 kamil return system(CmdLine.c_str()); 158 1.1 kamil } 159 1.1 kamil 160 1.1 kamil const void *SearchMemory(const void *Data, size_t DataLen, const void *Patt, 161 1.1 kamil size_t PattLen) { 162 1.1 kamil // TODO: make this implementation more efficient. 163 1.1 kamil const char *Cdata = (const char *)Data; 164 1.1 kamil const char *Cpatt = (const char *)Patt; 165 1.1 kamil 166 1.1 kamil if (!Data || !Patt || DataLen == 0 || PattLen == 0 || DataLen < PattLen) 167 1.1 kamil return NULL; 168 1.1 kamil 169 1.1 kamil if (PattLen == 1) 170 1.1 kamil return memchr(Data, *Cpatt, DataLen); 171 1.1 kamil 172 1.1 kamil const char *End = Cdata + DataLen - PattLen + 1; 173 1.1 kamil 174 1.1 kamil for (const char *It = Cdata; It < End; ++It) 175 1.1 kamil if (It[0] == Cpatt[0] && memcmp(It, Cpatt, PattLen) == 0) 176 1.1 kamil return It; 177 1.1 kamil 178 1.1 kamil return NULL; 179 1.1 kamil } 180 1.1 kamil 181 1.1 kamil std::string DisassembleCmd(const std::string &FileName) { 182 1.1 kamil Vector<std::string> command_vector; 183 1.1 kamil command_vector.push_back("dumpbin /summary > nul"); 184 1.1 kamil if (ExecuteCommand(Command(command_vector)) == 0) 185 1.1 kamil return "dumpbin /disasm " + FileName; 186 1.1 kamil Printf("libFuzzer: couldn't find tool to disassemble (dumpbin)\n"); 187 1.1 kamil exit(1); 188 1.1 kamil } 189 1.1 kamil 190 1.1 kamil std::string SearchRegexCmd(const std::string &Regex) { 191 1.1 kamil return "findstr /r \"" + Regex + "\""; 192 1.1 kamil } 193 1.1 kamil 194 1.1 kamil } // namespace fuzzer 195 1.1 kamil 196 1.1 kamil #endif // LIBFUZZER_WINDOWS 197