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